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(a)volny.cz)
* Matthew Brace (ismarc(a)austin.rr.com)
- * HervÚ Poussineau (hpoussin(a)reactos.com)
+ * HervÚ Poussineau (hpoussin(a)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(a)volny.cz)
- * HervÚ Poussineau (hpoussin(a)reactos.com)
+ * HervÚ Poussineau (hpoussin(a)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;