- Make IoGetDeviceInterfaces more compatible with the native version. Patch by Matthew Brace.

svn path=/trunk/; revision=8701
This commit is contained in:
Filip Navara 2004-03-14 09:43:12 +00:00
parent 89265e0151
commit b0b55220e6

View file

@ -18,6 +18,7 @@ DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325, 0x11CE, 0xBF, 0xC1
#endif #endif
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#define ASSERT assert
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -99,13 +100,16 @@ IoGetDeviceInterfaces(
UNICODE_STRING BaseKeyName; UNICODE_STRING BaseKeyName;
UNICODE_STRING AliasKeyName; UNICODE_STRING AliasKeyName;
UNICODE_STRING SymbolicLink; UNICODE_STRING SymbolicLink;
UNICODE_STRING Control;
UNICODE_STRING SubKeyName; UNICODE_STRING SubKeyName;
UNICODE_STRING SymbolicLinkKeyName; UNICODE_STRING SymbolicLinkKeyName;
UNICODE_STRING ControlKeyName;
UNICODE_STRING TempString; UNICODE_STRING TempString;
HANDLE InterfaceKey; HANDLE InterfaceKey;
HANDLE SubKey; HANDLE SubKey;
HANDLE SymbolicLinkKey; HANDLE SymbolicLinkKey;
PKEY_FULL_INFORMATION fip; PKEY_FULL_INFORMATION fip;
PKEY_FULL_INFORMATION bfip;
PKEY_BASIC_INFORMATION bip; PKEY_BASIC_INFORMATION bip;
PKEY_VALUE_PARTIAL_INFORMATION vpip; PKEY_VALUE_PARTIAL_INFORMATION vpip;
PWCHAR SymLinkList = NULL; PWCHAR SymLinkList = NULL;
@ -113,6 +117,7 @@ IoGetDeviceInterfaces(
NTSTATUS Status; NTSTATUS Status;
ULONG Size = 0; ULONG Size = 0;
ULONG i = 0; ULONG i = 0;
ULONG j = 0;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString);
@ -124,33 +129,34 @@ IoGetDeviceInterfaces(
RtlInitUnicodeString(&AliasKeyName, BaseInterfaceString); RtlInitUnicodeString(&AliasKeyName, BaseInterfaceString);
RtlInitUnicodeString(&SymbolicLink, L"SymbolicLink"); RtlInitUnicodeString(&SymbolicLink, L"SymbolicLink");
RtlInitUnicodeString(&Control, L"\\Control");
BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR); BaseKeyName.Length = wcslen(BaseKeyString) * sizeof(WCHAR);
BaseKeyName.MaximumLength = BaseKeyName.Length + (38 * sizeof(WCHAR)); BaseKeyName.MaximumLength = BaseKeyName.Length + (38 * sizeof(WCHAR));
BaseKeyName.Buffer = ExAllocatePool( BaseKeyName.Buffer = ExAllocatePool(
NonPagedPool, NonPagedPool,
BaseKeyName.MaximumLength); BaseKeyName.MaximumLength);
assert(BaseKeyName.Buffer != NULL); ASSERT(BaseKeyName.Buffer != NULL);
wcscpy(BaseKeyName.Buffer, BaseKeyString); wcscpy(BaseKeyName.Buffer, BaseKeyString);
RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString);
if (PhysicalDeviceObject) if (PhysicalDeviceObject)
{ {
WCHAR GuidBuffer[32]; WCHAR GuidBuffer[40];
UNICODE_STRING PdoGuidString; UNICODE_STRING PdoGuidString;
RtlFreeUnicodeString(&BaseKeyName); RtlFreeUnicodeString(&BaseKeyName);
IoGetDeviceProperty( IoGetDeviceProperty(
PhysicalDeviceObject, PhysicalDeviceObject,
DevicePropertyClassGuid, DevicePropertyClassGuid,
sizeof(GuidBuffer), sizeof(GuidBuffer),
GuidBuffer, GuidBuffer,
&Size); &Size);
RtlInitUnicodeString(&PdoGuidString, GuidBuffer); RtlInitUnicodeString(&PdoGuidString, GuidBuffer);
if (RtlCompareUnicodeString(&GuidString, &PdoGuidString, TRUE)) if (RtlCompareUnicodeString(&GuidString, &PdoGuidString, TRUE))
{ {
DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n"); DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n");
return STATUS_INVALID_HANDLE; return STATUS_INVALID_HANDLE;
} }
@ -180,7 +186,7 @@ IoGetDeviceInterfaces(
Status = ZwQueryKey( Status = ZwQueryKey(
InterfaceKey, InterfaceKey,
KeyFullInformation, KeyFullInformation,
NULL, NULL,
0, 0,
&Size); &Size);
@ -194,14 +200,14 @@ IoGetDeviceInterfaces(
} }
fip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size); fip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(fip != NULL); ASSERT(fip != NULL);
Status = ZwQueryKey( Status = ZwQueryKey(
InterfaceKey, InterfaceKey,
KeyFullInformation, KeyFullInformation,
fip, fip,
Size, Size,
&Size); &Size);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -216,15 +222,15 @@ IoGetDeviceInterfaces(
{ {
Status = ZwEnumerateKey( Status = ZwEnumerateKey(
InterfaceKey, InterfaceKey,
i, i,
KeyBasicInformation, KeyBasicInformation,
NULL, NULL,
0, 0,
&Size); &Size);
if (Status != STATUS_BUFFER_TOO_SMALL) if (Status != STATUS_BUFFER_TOO_SMALL)
{ {
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status); DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status);
ExFreePool(fip); ExFreePool(fip);
if (SymLinkList != NULL) if (SymLinkList != NULL)
ExFreePool(SymLinkList); ExFreePool(SymLinkList);
@ -234,7 +240,7 @@ IoGetDeviceInterfaces(
} }
bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size); bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(bip != NULL); ASSERT(bip != NULL);
Status = ZwEnumerateKey( Status = ZwEnumerateKey(
InterfaceKey, InterfaceKey,
@ -246,7 +252,7 @@ IoGetDeviceInterfaces(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status); DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status);
ExFreePool(fip); ExFreePool(fip);
ExFreePool(bip); ExFreePool(bip);
if (SymLinkList != NULL) if (SymLinkList != NULL)
@ -255,11 +261,11 @@ IoGetDeviceInterfaces(
ZwClose(InterfaceKey); ZwClose(InterfaceKey);
return Status; return Status;
} }
SubKeyName.Length = 0; SubKeyName.Length = 0;
SubKeyName.MaximumLength = BaseKeyName.Length + bip->NameLength + sizeof(WCHAR); SubKeyName.MaximumLength = BaseKeyName.Length + bip->NameLength + sizeof(WCHAR);
SubKeyName.Buffer = ExAllocatePool(NonPagedPool, SubKeyName.MaximumLength); SubKeyName.Buffer = ExAllocatePool(NonPagedPool, SubKeyName.MaximumLength);
assert(SubKeyName.Buffer != NULL); ASSERT(SubKeyName.Buffer != NULL);
TempString.Length = TempString.MaximumLength = bip->NameLength; TempString.Length = TempString.MaximumLength = bip->NameLength;
TempString.Buffer = bip->Name; TempString.Buffer = bip->Name;
RtlCopyUnicodeString(&SubKeyName, &BaseKeyName); RtlCopyUnicodeString(&SubKeyName, &BaseKeyName);
@ -292,181 +298,263 @@ IoGetDeviceInterfaces(
return Status; return Status;
} }
Status = ZwEnumerateKey( Status = ZwQueryKey(
SubKey, SubKey,
0, KeyFullInformation,
KeyBasicInformation,
NULL, NULL,
0, 0,
&Size); &Size);
if (Status != STATUS_BUFFER_TOO_SMALL) if (Status != STATUS_BUFFER_TOO_SMALL)
{ {
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status); DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
ExFreePool(fip); ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName); RtlFreeUnicodeString(&BaseKeyName);
RtlFreeUnicodeString(&SubKeyName);
ZwClose(SubKey); ZwClose(SubKey);
ZwClose(InterfaceKey); ZwClose(InterfaceKey);
return Status; return Status;
} }
bip = (PKEY_BASIC_INFORMATION)ExAllocatePool(NonPagedPool, Size); bfip = (PKEY_FULL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(bip != NULL); ASSERT(bfip != NULL);
Status = ZwEnumerateKey( Status = ZwQueryKey(
SubKey, SubKey,
0, KeyFullInformation,
KeyBasicInformation, bfip,
bip,
Size, Size,
&Size); &Size);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("ZwEnumerateKey() Failed. (0x%X)\n", Status); DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status);
ExFreePool(fip); 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(NonPagedPool, 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(NonPagedPool, 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(NonPagedPool, ControlKeyName.MaximumLength);
ASSERT(ControlKeyName.Buffer != NULL);
RtlCopyUnicodeString(&ControlKeyName, &SymbolicLinkKeyName);
RtlAppendUnicodeStringToString(&ControlKeyName, &Control);
ExFreePool(bip); ExFreePool(bip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
SymbolicLinkKeyName.Length = 0; InitializeObjectAttributes(
SymbolicLinkKeyName.MaximumLength = SubKeyName.Length + bip->NameLength + sizeof(WCHAR); &ObjectAttributes,
SymbolicLinkKeyName.Buffer = ExAllocatePool(NonPagedPool, SymbolicLinkKeyName.MaximumLength); &SymbolicLinkKeyName,
assert(SymbolicLinkKeyName.Buffer != NULL); OBJ_CASE_INSENSITIVE,
TempString.Length = TempString.MaximumLength = bip->NameLength; NULL,
TempString.Buffer = bip->Name; NULL);
RtlCopyUnicodeString(&SymbolicLinkKeyName, &SubKeyName);
RtlAppendUnicodeToString(&SymbolicLinkKeyName, L"\\"); Status = ZwOpenKey(
RtlAppendUnicodeStringToString(&SymbolicLinkKeyName, &TempString); &SymbolicLinkKey,
KEY_READ,
&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;
ExFreePool(bip); 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;
}
InitializeObjectAttributes( vpip = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
&ObjectAttributes, ASSERT(vpip != NULL);
&SymbolicLinkKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey( Status = ZwQueryValueKey(
&SymbolicLinkKey, SymbolicLinkKey,
KEY_READ, &SymbolicLink,
&ObjectAttributes); KeyValuePartialInformation,
vpip,
Size,
&Size);
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;
}
Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ControlKeyName.Buffer);
if (NT_SUCCESS(Status))
{
/* Put the name in the string here */
if (SymLinkList == NULL)
{
SymLinkListSize = vpip->DataLength;
SymLinkList = ExAllocatePool(NonPagedPool, 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(NonPagedPool, 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] = '?';
}
}
if (!NT_SUCCESS(Status))
{
DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName); RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName); RtlFreeUnicodeString(&ControlKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
Status = ZwQueryValueKey(
SymbolicLinkKey,
&SymbolicLink,
KeyValuePartialInformation,
NULL,
0,
&Size);
if (Status != STATUS_BUFFER_TOO_SMALL)
{
DPRINT("ZwQueryValueKey() Failed. (0x%X)\n", Status);
ExFreePool(fip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SymbolicLinkKey); ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
} }
vpip = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePool(NonPagedPool, Size);
assert(vpip != NULL);
Status = ZwQueryValueKey(
SymbolicLinkKey,
&SymbolicLink,
KeyValuePartialInformation,
vpip,
Size,
&Size);
if (!NT_SUCCESS(Status))
{
ExFreePool(fip);
ExFreePool(vpip);
if (SymLinkList != NULL)
ExFreePool(SymLinkList);
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
RtlFreeUnicodeString(&BaseKeyName);
ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ZwClose(InterfaceKey);
return Status;
}
/* Put the name in the string here */
if (SymLinkList == NULL)
{
SymLinkListSize = vpip->DataLength;
SymLinkList = ExAllocatePool(NonPagedPool, 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(NonPagedPool, 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] = '?';
}
RtlFreeUnicodeString(&SymbolicLinkKeyName);
RtlFreeUnicodeString(&SubKeyName);
ZwClose(SymbolicLinkKey);
ZwClose(SubKey);
ExFreePool(vpip); ExFreePool(vpip);
RtlFreeUnicodeString(&SubKeyName);
ZwClose(SubKey);
} }
if (SymLinkList != NULL) if (SymLinkList != NULL)
{
SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0; SymLinkList[SymLinkListSize / sizeof(WCHAR)] = 0;
}
else
{
SymLinkList = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
SymLinkList[0] = 0;
}
*SymbolicLinkList = SymLinkList; *SymbolicLinkList = SymLinkList;
RtlFreeUnicodeString(&BaseKeyName); RtlFreeUnicodeString(&BaseKeyName);
ZwClose(InterfaceKey); ZwClose(InterfaceKey);
ExFreePool(bfip);
ExFreePool(fip); ExFreePool(fip);
} }