Rewrite IoGetDeviceInterfaces: no more memory leaks, be ready to handle PhysicalDeviceObject and Flags parameters, less stack usage IoRegisterPlugPlayNotification: notify caller for already registered interfaces Modified: trunk/reactos/ntoskrnl/include/internal/io.h Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h Modified: trunk/reactos/ntoskrnl/io/deviface.c Modified: trunk/reactos/ntoskrnl/io/pnpnotify.c _____
Modified: trunk/reactos/ntoskrnl/include/internal/io.h --- trunk/reactos/ntoskrnl/include/internal/io.h 2006-01-11 21:59:52 UTC (rev 20790) +++ trunk/reactos/ntoskrnl/include/internal/io.h 2006-01-11 22:13:02 UTC (rev 20791) @@ -218,7 +218,7 @@
IopNotifyPlugPlayNotification( IN PDEVICE_OBJECT DeviceObject, IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, - IN GUID* Event, + IN LPCGUID Event, IN PVOID EventCategoryData1, IN PVOID EventCategoryData2 ); _____
Modified: trunk/reactos/ntoskrnl/include/ntoskrnl.h --- trunk/reactos/ntoskrnl/include/ntoskrnl.h 2006-01-11 21:59:52 UTC (rev 20790) +++ trunk/reactos/ntoskrnl/include/ntoskrnl.h 2006-01-11 22:13:02 UTC (rev 20791) @@ -17,6 +17,9 @@
#include <ntddk.h> #include <wdmguid.h> #include <ndk/ntndk.h> +#undef TEXT +#define TEXT(s) L##s +#include <regstr.h>
/* FIXME: Temporary until CC Ros is gone */ #include <ccros.h> _____
Modified: trunk/reactos/ntoskrnl/io/deviface.c --- trunk/reactos/ntoskrnl/io/deviface.c 2006-01-11 21:59:52 UTC (rev 20790) +++ trunk/reactos/ntoskrnl/io/deviface.c 2006-01-11 22:13:02 UTC (rev 20791) @@ -1,5 +1,4 @@
-/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/deviface.c @@ -7,7 +6,7 @@ * * PROGRAMMERS: Filip Navara (xnavara@volny.cz) * Matthew Brace (ismarc@austin.rr.com) - * HervÚ Poussineau (hpoussin@reactos.com) + * HervÚ Poussineau (hpoussin@reactos.org) */
/* INCLUDES ******************************************************************/ @@ -47,6 +46,93 @@ return STATUS_NOT_IMPLEMENTED; }
+static NTSTATUS +IopOpenInterfaceKey( + IN CONST GUID *InterfaceClassGuid, + IN ACCESS_MASK DesiredAccess, + OUT HANDLE *pInterfaceKey) +{ + UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\Registry\Machine\"); + UNICODE_STRING GuidString; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE InterfaceKey = INVALID_HANDLE_VALUE; + NTSTATUS Status; + + GuidString.Buffer = KeyName.Buffer = NULL; + + Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + KeyName.Length = 0; + KeyName.MaximumLength = LocalMachine.Length + (wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length; + KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength); + if (!KeyName.Buffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = RtlAppendUnicodeStringToString(&KeyName, &LocalMachine); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeToString(&KeyName, REGSTR_PATH_DEVICE_CLASSES); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeToString(&KeyName, L"\"); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + Status = RtlAppendUnicodeStringToString(&KeyName, &GuidString); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + InitializeObjectAttributes( + &ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey( + &InterfaceKey, + DesiredAccess, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + + *pInterfaceKey = InterfaceKey; + Status = STATUS_SUCCESS; + +cleanup: + if (!NT_SUCCESS(Status)) + { + if (InterfaceKey != INVALID_HANDLE_VALUE) + ZwClose(InterfaceKey); + } + RtlFreeUnicodeString(&GuidString); + RtlFreeUnicodeString(&KeyName); + return Status; +} + /* * IoGetDeviceInterfaces * @@ -81,9 +167,6 @@ * Status * @implemented * - * The parameters PhysicalDeviceObject and Flags aren't correctly - * processed. Rest of the cases was tested under Windows(R) XP and - * the function worked correctly. */
NTSTATUS STDCALL @@ -93,472 +176,341 @@ IN ULONG Flags, OUT PWSTR *SymbolicLinkList) { - PWCHAR BaseInterfaceString = L"\Registry\Machine\System\CurrentControlSet\Services\"; - UNICODE_STRING GuidString; - UNICODE_STRING BaseKeyName; - UNICODE_STRING AliasKeyName; - UNICODE_STRING SymbolicLink; - UNICODE_STRING Control; - UNICODE_STRING SubKeyName; - UNICODE_STRING SymbolicLinkKeyName; - UNICODE_STRING ControlKeyName; - UNICODE_STRING TempString; - HANDLE InterfaceKey; - HANDLE SubKey; - HANDLE SymbolicLinkKey; - PKEY_FULL_INFORMATION fip; - PKEY_FULL_INFORMATION bfip = NULL; - PKEY_BASIC_INFORMATION bip; - PKEY_VALUE_PARTIAL_INFORMATION vpip = NULL; - PWCHAR SymLinkList = NULL; - ULONG SymLinkListSize = 0; - NTSTATUS Status; - ULONG Size = 0; - ULONG i = 0; - ULONG j = 0; + UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); + UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); + HANDLE InterfaceKey = INVALID_HANDLE_VALUE; + HANDLE DeviceKey = INVALID_HANDLE_VALUE; + HANDLE ReferenceKey = INVALID_HANDLE_VALUE; + HANDLE ControlKey = INVALID_HANDLE_VALUE; + PKEY_BASIC_INFORMATION DeviceBi = NULL; + PKEY_BASIC_INFORMATION ReferenceBi = NULL; + PKEY_VALUE_PARTIAL_INFORMATION bip = NULL; + UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; + BOOLEAN FoundRightPDO = FALSE; + ULONG i = 0, j, Size; + UNICODE_STRING ReturnBuffer = {0,}; + NTSTATUS Status;
- ASSERT_IRQL(PASSIVE_LEVEL); + PAGED_CODE();
- Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); + Status = IopOpenInterfaceKey(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, &InterfaceKey); if (!NT_SUCCESS(Status)) { - DPRINT("RtlStringFromGUID() Failed.\n"); - return STATUS_INVALID_HANDLE; + DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status); + goto cleanup; }
- RtlInitUnicodeString(&AliasKeyName, BaseInterfaceString); - RtlInitUnicodeString(&SymbolicLink, L"SymbolicLink"); - RtlInitUnicodeString(&Control, L"\Control"); - BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); - BaseKeyName.MaximumLength = BaseKeyName.Length + (38 * sizeof(WCHAR)); - BaseKeyName.Buffer = ExAllocatePool( - PagedPool, - BaseKeyName.MaximumLength); - ASSERT(BaseKeyName.Buffer != NULL); - wcscpy(BaseKeyName.Buffer, BaseKeyString); - RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); - - if (PhysicalDeviceObject) + /* Enumerate subkeys (ie the different device objets) */ + while (TRUE) { - WCHAR GuidBuffer[40]; - UNICODE_STRING PdoGuidString; - - RtlFreeUnicodeString(&BaseKeyName); - - IoGetDeviceProperty( - PhysicalDeviceObject, - DevicePropertyClassGuid, - sizeof(GuidBuffer), - GuidBuffer, + Status = ZwEnumerateKey( + InterfaceKey, + i, + KeyBasicInformation, + NULL, + 0, &Size); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + }
- RtlInitUnicodeString(&PdoGuidString, GuidBuffer); - if (RtlCompareUnicodeString(&GuidString, &PdoGuidString, TRUE)) + DeviceBi = ExAllocatePool(PagedPool, Size); + if (!DeviceBi) { - DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n"); - return STATUS_INVALID_HANDLE; + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; } + Status = ZwEnumerateKey( + InterfaceKey, + i++, + KeyBasicInformation, + DeviceBi, + Size, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; + }
- DPRINT("IoGetDeviceInterfaces() called with PDO, not implemented.\n"); - return STATUS_NOT_IMPLEMENTED; - } - else - { + /* Open device key */ + KeyName.Length = KeyName.MaximumLength = DeviceBi->NameLength; + KeyName.Buffer = DeviceBi->Name; InitializeObjectAttributes( &ObjectAttributes, - &BaseKeyName, + &KeyName, OBJ_CASE_INSENSITIVE, - NULL, + InterfaceKey, NULL); - Status = ZwOpenKey( - &InterfaceKey, - KEY_READ, + &DeviceKey, + KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); - if (!NT_SUCCESS(Status)) { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - RtlFreeUnicodeString(&BaseKeyName); - return Status; + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; }
- Status = ZwQueryKey( - InterfaceKey, - KeyFullInformation, - NULL, - 0, - &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) + if (PhysicalDeviceObject) { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; + /* Check if we are on the right physical device object, + * by reading the DeviceInstance string + */ + DPRINT1("PhysicalDeviceObject != NULL. Case not implemented.\n"); + //FoundRightPDO = TRUE; + Status = STATUS_NOT_IMPLEMENTED; + goto cleanup; }
- fip = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, Size); - ASSERT(fip != NULL); - - Status = ZwQueryKey( - InterfaceKey, - KeyFullInformation, - fip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) + /* Enumerate subkeys (ie the different reference strings) */ + j = 0; + while (TRUE) { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; - } - - for (; i < fip->SubKeys; i++) - { Status = ZwEnumerateKey( - InterfaceKey, - i, + DeviceKey, + j, KeyBasicInformation, NULL, 0, &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; }
- bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, Size); - ASSERT(bip != NULL); - + ReferenceBi = ExAllocatePool(PagedPool, Size); + if (!ReferenceBi) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } Status = ZwEnumerateKey( - InterfaceKey, - i, + DeviceKey, + j++, KeyBasicInformation, - bip, + ReferenceBi, Size, &Size); - if (!NT_SUCCESS(Status)) { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; + DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); + goto cleanup; }
- SubKeyName.Length = 0; - SubKeyName.MaximumLength = BaseKeyName.Length + bip->NameLength + sizeof(WCHAR); - SubKeyName.Buffer = ExAllocatePool(PagedPool, SubKeyName.MaximumLength); - ASSERT(SubKeyName.Buffer != NULL); - TempString.Length = TempString.MaximumLength = bip->NameLength; - TempString.Buffer = bip->Name; - RtlCopyUnicodeString(&SubKeyName, &BaseKeyName); - RtlAppendUnicodeToString(&SubKeyName, L"\"); - RtlAppendUnicodeStringToString(&SubKeyName, &TempString); + KeyName.Length = KeyName.MaximumLength = ReferenceBi->NameLength; + KeyName.Buffer = ReferenceBi->Name; + if (RtlEqualUnicodeString(&KeyName, &Control, TRUE)) + { + /* Skip Control subkey */ + goto NextReferenceString; + }
- ExFreePool(bip); - + /* Open reference key */ InitializeObjectAttributes( &ObjectAttributes, - &SubKeyName, + &KeyName, OBJ_CASE_INSENSITIVE, - NULL, + DeviceKey, NULL); - Status = ZwOpenKey( - &SubKey, - KEY_READ, + &ReferenceKey, + KEY_QUERY_VALUE, &ObjectAttributes); - if (!NT_SUCCESS(Status)) { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - return Status; + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; }
- Status = ZwQueryKey( - SubKey, - KeyFullInformation, - NULL, - 0, - &Size); - - if (Status != STATUS_BUFFER_TOO_SMALL) + if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&BaseKeyName); - RtlFreeUnicodeString(&SubKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - bfip = (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, Size); - ASSERT(bfip != NULL); - - Status = ZwQueryKey( - SubKey, - KeyFullInformation, - bfip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - for(j = 0; j < bfip->SubKeys; j++) - { - Status = ZwEnumerateKey( - SubKey, - j, - KeyBasicInformation, - NULL, - 0, - &Size); - - if (Status == STATUS_NO_MORE_ENTRIES) - continue; - - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(bfip); - ExFreePool(fip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, Size); - ASSERT(bip != NULL); - - Status = ZwEnumerateKey( - SubKey, - j, - KeyBasicInformation, - bip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - ExFreePool(bip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - if (!wcsncmp(bip->Name, L"Control", bip->NameLength)) - { - continue; - } - - SymbolicLinkKeyName.Length = 0; - SymbolicLinkKeyName.MaximumLength = SubKeyName.Length + bip->NameLength + sizeof(WCHAR); - SymbolicLinkKeyName.Buffer = ExAllocatePool(PagedPool, SymbolicLinkKeyName.MaximumLength); - ASSERT(SymbolicLinkKeyName.Buffer != NULL); - TempString.Length = TempString.MaximumLength = bip->NameLength; - TempString.Buffer = bip->Name; - RtlCopyUnicodeString(&SymbolicLinkKeyName, &SubKeyName); - RtlAppendUnicodeToString(&SymbolicLinkKeyName, L"\"); - RtlAppendUnicodeStringToString(&SymbolicLinkKeyName, &TempString); - - ControlKeyName.Length = 0; - ControlKeyName.MaximumLength = SymbolicLinkKeyName.Length + Control.Length + sizeof(WCHAR); - ControlKeyName.Buffer = ExAllocatePool(PagedPool, ControlKeyName.MaximumLength); - ASSERT(ControlKeyName.Buffer != NULL); - RtlCopyUnicodeString(&ControlKeyName, &SymbolicLinkKeyName); - RtlAppendUnicodeStringToString(&ControlKeyName, &Control); - - ExFreePool(bip); - + /* We have to check if the interface is enabled, by + * reading the Linked value in the Control subkey + */ InitializeObjectAttributes( &ObjectAttributes, - &SymbolicLinkKeyName, + &Control, OBJ_CASE_INSENSITIVE, - NULL, + ReferenceKey, NULL); - Status = ZwOpenKey( - &SymbolicLinkKey, - KEY_READ, + &ControlKey, + KEY_QUERY_VALUE, &ObjectAttributes); - - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; - } - - Status = ZwQueryValueKey( - SymbolicLinkKey, - &SymbolicLink, - KeyValuePartialInformation, - NULL, - 0, - &Size); - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - continue; - - if (Status != STATUS_BUFFER_TOO_SMALL) { - DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SymbolicLinkKey); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; + /* That's OK. The key doesn't exist (yet) because + * the interface is not activated. + */ + goto NextReferenceString; } - - vpip = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(PagedPool, Size); - ASSERT(vpip != NULL); - - Status = ZwQueryValueKey( - SymbolicLinkKey, - &SymbolicLink, - KeyValuePartialInformation, - vpip, - Size, - &Size); - - if (!NT_SUCCESS(Status)) + else if (!NT_SUCCESS(Status)) { - DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status); - ExFreePool(fip); - ExFreePool(bfip); - ExFreePool(vpip); - if (SymLinkList != NULL) - ExFreePool(SymLinkList); - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&SubKeyName); - RtlFreeUnicodeString(&BaseKeyName); - ZwClose(SymbolicLinkKey); - ZwClose(SubKey); - ZwClose(InterfaceKey); - return Status; + DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); + goto cleanup; } + /* FIXME: Read the Linked value + * If it doesn't exist => ERROR + * If it is not a REG_DWORD or Size != sizeof(ULONG) => ERROR + * If its value is 0, go to NextReferenceString + * At the moment, do as if it is active... + */ + DPRINT1("Checking if device is enabled is not implemented yet!\n"); + }
- Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ControlKeyName.Buffer); + /* Read the SymbolicLink string and add it into SymbolicLinkList */ + Status = ZwQueryValueKey( + ReferenceKey, + &SymbolicLink, + KeyValuePartialInformation, + NULL, + 0, + &Size); + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + bip = ExAllocatePool(PagedPool, Size); + if (!bip) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + Status = ZwQueryValueKey( + ReferenceKey, + &SymbolicLink, + KeyValuePartialInformation, + bip, + Size, + &Size); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); + goto cleanup; + } + else if (bip->Type != REG_SZ) + { + DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ); + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + else if (bip->DataLength < 5 * sizeof(WCHAR)) + { + DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength < 5 * sizeof(WCHAR)); + Status = STATUS_UNSUCCESSFUL; + goto cleanup; + } + KeyName.Length = KeyName.MaximumLength = bip->DataLength - 4 * sizeof(WCHAR); + KeyName.Buffer = &((PWSTR)bip->Data)[4]; + if (KeyName.Length && KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] == UNICODE_NULL) + /* Remove trailing NULL */ + KeyName.Length -= sizeof(WCHAR);
- if (NT_SUCCESS(Status)) + /* Add new symbolic link to symbolic link list */ + if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength) + { + PWSTR NewBuffer; + ReturnBuffer.MaximumLength = max(ReturnBuffer.MaximumLength * 2, ReturnBuffer.Length + KeyName.Length + 2 * sizeof(WCHAR)); + NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); + if (!NewBuffer) { - /* Put the name in the string here */ - if (SymLinkList == NULL) - { - SymLinkListSize = vpip->DataLength; - SymLinkList = ExAllocatePool(PagedPool, SymLinkListSize + sizeof(WCHAR)); - ASSERT(SymLinkList != NULL); - RtlCopyMemory(SymLinkList, vpip->Data, vpip->DataLength); - SymLinkList[vpip->DataLength / sizeof(WCHAR)] = 0; - SymLinkList[1] = '?'; - } - else - { - PWCHAR OldSymLinkList; - ULONG OldSymLinkListSize; - PWCHAR SymLinkListPtr; - - OldSymLinkList = SymLinkList; - OldSymLinkListSize = SymLinkListSize; - SymLinkListSize += vpip->DataLength; - SymLinkList = ExAllocatePool(PagedPool, SymLinkListSize + sizeof(WCHAR)); - ASSERT(SymLinkList != NULL); - RtlCopyMemory(SymLinkList, OldSymLinkList, OldSymLinkListSize); - ExFreePool(OldSymLinkList); - SymLinkListPtr = SymLinkList + (OldSymLinkListSize / sizeof(WCHAR)); - RtlCopyMemory(SymLinkListPtr, vpip->Data, vpip->DataLength); - SymLinkListPtr[vpip->DataLength / sizeof(WCHAR)] = 0; - SymLinkListPtr[1] = '?'; - } + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; } - - RtlFreeUnicodeString(&SymbolicLinkKeyName); - RtlFreeUnicodeString(&ControlKeyName); - ZwClose(SymbolicLinkKey); + RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); + ExFreePool(ReturnBuffer.Buffer); + ReturnBuffer.Buffer = NewBuffer; } + DPRINT("Adding symbolic link %wZ\n", &KeyName); + Status = RtlAppendUnicodeStringToString(&ReturnBuffer, &KeyName); + if (!NT_SUCCESS(Status)) + { + DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); + goto cleanup; + } + /* RtlAppendUnicodeStringToString added a NULL at the end of the + * destination string, but didn't increase the Length field. + * Do it for it. + */ + ReturnBuffer.Length += sizeof(WCHAR);
- ExFreePool(vpip); - RtlFreeUnicodeString(&SubKeyName); - ZwClose(SubKey); +NextReferenceString: + ExFreePool(ReferenceBi); + ReferenceBi = NULL; + ExFreePool(bip); + bip = NULL; + if (ReferenceKey != INVALID_HANDLE_VALUE) + { + ZwClose(ReferenceKey); + ReferenceKey = INVALID_HANDLE_VALUE; + } + if (ControlKey != INVALID_HANDLE_VALUE) + { + ZwClose(ControlKey); + ControlKey = INVALID_HANDLE_VALUE; + } } - - if (SymLinkList != NULL) + if (FoundRightPDO) { - SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0; + /* No need to go further, as we already have found what we searched */ + break; } - else - { - SymLinkList = ExAllocatePool(PagedPool, 2 * sizeof(WCHAR)); - SymLinkList[0] = 0; - }
- *SymbolicLinkList = SymLinkList; + ExFreePool(DeviceBi); + DeviceBi = NULL; + ZwClose(DeviceKey); + DeviceKey = INVALID_HANDLE_VALUE; + }
- RtlFreeUnicodeString(&BaseKeyName); - ZwClose(InterfaceKey); - ExFreePool(bfip); - ExFreePool(fip); + /* Add final NULL to ReturnBuffer */ + if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength) + { + PWSTR NewBuffer; + ReturnBuffer.MaximumLength += sizeof(WCHAR); + NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); + if (!NewBuffer) + { + DPRINT("ExAllocatePool() failed\n"); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); + ExFreePool(ReturnBuffer.Buffer); + ReturnBuffer.Buffer = NewBuffer; } + ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL; + *SymbolicLinkList = ReturnBuffer.Buffer; + Status = STATUS_SUCCESS;
- return STATUS_SUCCESS; +cleanup: + if (!NT_SUCCESS(Status)) + ExFreePool(ReturnBuffer.Buffer); + if (InterfaceKey != INVALID_HANDLE_VALUE) + ZwClose(InterfaceKey); + if (DeviceKey != INVALID_HANDLE_VALUE) + ZwClose(DeviceKey); + if (ReferenceKey != INVALID_HANDLE_VALUE) + ZwClose(ReferenceKey); + if (ControlKey != INVALID_HANDLE_VALUE) + ZwClose(ControlKey); + ExFreePool(DeviceBi); + ExFreePool(ReferenceBi); + ExFreePool(bip); + return Status; }
/* @@ -882,7 +834,7 @@ PWCHAR StartPosition; PWCHAR EndPosition; NTSTATUS Status; - GUID EventGuid; + LPCGUID EventGuid;
if (SymbolicLinkName == NULL) return STATUS_INVALID_PARAMETER_1; @@ -918,11 +870,11 @@ return Status; }
- EventGuid = Enable ? GUID_DEVICE_INTERFACE_ARRIVAL : GUID_DEVICE_INTERFACE_REMOVAL; + EventGuid = Enable ? &GUID_DEVICE_INTERFACE_ARRIVAL : &GUID_DEVICE_INTERFACE_REMOVAL; IopNotifyPlugPlayNotification( PhysicalDeviceObject, EventCategoryDeviceInterfaceChange, - &EventGuid, + EventGuid, &GuidString, (PVOID)SymbolicLinkName);
_____
Modified: trunk/reactos/ntoskrnl/io/pnpnotify.c --- trunk/reactos/ntoskrnl/io/pnpnotify.c 2006-01-11 21:59:52 UTC (rev 20790) +++ trunk/reactos/ntoskrnl/io/pnpnotify.c 2006-01-11 22:13:02 UTC (rev 20791) @@ -1,12 +1,11 @@
-/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/pnpnotify.c * PURPOSE: Plug & Play notification functions * * PROGRAMMERS: Filip Navara (xnavara@volny.cz) - * HervÚ Poussineau (hpoussin@reactos.com) + * HervÚ Poussineau (hpoussin@reactos.org) */
/* INCLUDES ******************************************************************/ @@ -92,9 +91,13 @@ return STATUS_INSUFFICIENT_RESOURCES; }
- if (EventCategory == EventCategoryTargetDeviceChange + if (EventCategory == EventCategoryDeviceInterfaceChange && EventCategoryFlags & PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES) { + DEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationInfos; + UNICODE_STRING SymbolicLinkU; + PWSTR SymbolicLink; + Status = IoGetDeviceInterfaces( (LPGUID)EventCategoryData, NULL, /* PhysicalDeviceObject OPTIONAL */ @@ -107,8 +110,18 @@ ObDereferenceObject(DriverObject); return Status; } - /* FIXME: enumerate SymbolicLinkList */ - DPRINT1("IoRegisterPlugPlayNotification(): need to send notifications for existing interfaces!\n"); + /* Enumerate SymbolicLinkList */ + NotificationInfos.Version = 1; + NotificationInfos.Size = sizeof(DEVICE_INTERFACE_CHANGE_NOTIFICATION); + RtlCopyMemory(&NotificationInfos.Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)); + RtlCopyMemory(&NotificationInfos.InterfaceClassGuid, EventCategoryData, sizeof(GUID)); + NotificationInfos.SymbolicLinkName = &SymbolicLinkU; + for (SymbolicLink = SymbolicLinkList; *SymbolicLink; SymbolicLink += wcslen(SymbolicLink) + 1) + { + RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink); + DPRINT("Calling callback routine for %S\n", SymbolicLink); + (*CallbackRoutine)(&NotificationInfos, Context); + } ExFreePool(SymbolicLinkList); }
@@ -184,7 +197,7 @@ IopNotifyPlugPlayNotification( IN PDEVICE_OBJECT DeviceObject, IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory, - IN GUID* Event, + IN LPCGUID Event, IN PVOID EventCategoryData1, IN PVOID EventCategoryData2) { @@ -253,7 +266,7 @@ * list to find those that meet some criteria. */
- LIST_FOR_EACH(ChangeEntry,&PnpNotifyListHead, PNP_NOTIFY_ENTRY, PnpNotifyList) + LIST_FOR_EACH(ChangeEntry,&PnpNotifyListHead, PNP_NOTIFY_ENTRY, PnpNotifyList) { CallCurrentEntry = FALSE;