From c5cd2328e82ef18c5ee14a2fba3cf25eb5dd2ad2 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Sun, 30 May 2004 18:30:03 +0000 Subject: [PATCH] - Implementation of IoQueryDeviceDescription. Patch by Alex Ionescu. svn path=/trunk/; revision=9563 --- reactos/ntoskrnl/io/resource.c | 737 ++++++++++++++++++++++++++++++--- 1 file changed, 689 insertions(+), 48 deletions(-) diff --git a/reactos/ntoskrnl/io/resource.c b/reactos/ntoskrnl/io/resource.c index 1cb892e58cf..216e058d638 100644 --- a/reactos/ntoskrnl/io/resource.c +++ b/reactos/ntoskrnl/io/resource.c @@ -16,12 +16,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: resource.c,v 1.14 2003/12/14 17:44:02 hbirr Exp $ +/* $Id: resource.c,v 1.15 2004/05/30 18:30:03 navaraf Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/io/resource.c * PURPOSE: Hardware resource managment * PROGRAMMER: David Welch (welch@mcmail.com) + * Alex Ionescu (alex@relsoft.net) * UPDATE HISTORY: * Created 22/05/98 */ @@ -30,8 +31,6 @@ #include #include - - #include /* GLOBALS *******************************************************************/ @@ -39,7 +38,633 @@ static CONFIGURATION_INFORMATION SystemConfigurationInformation = {0, 0, 0, 0, 0, 0, 0, FALSE, FALSE}; -/* FUNCTIONS *****************************************************************/ +/* API Parameters to Pass in IopQueryBusDescription */ +typedef struct IO_QUERY { + PINTERFACE_TYPE BusType; + PULONG BusNumber; + PCONFIGURATION_TYPE ControllerType; + PULONG ControllerNumber; + PCONFIGURATION_TYPE PeripheralType; + PULONG PeripheralNumber; + PIO_QUERY_DEVICE_ROUTINE CalloutRoutine; + PVOID Context; +} IO_QUERY, *PIO_QUERY; + +PWSTR ArcTypes[42] = { + L"System", + L"CentralProcessor", + L"FloatingPointProcessor", + L"PrimaryICache", + L"PrimaryDCache", + L"SecondaryICache", + L"SecondaryDCache", + L"SecondaryCache", + L"EisaAdapter", + L"TcAdapter", + L"ScsiAdapter", + L"DtiAdapter", + L"MultifunctionAdapter", + L"DiskController", + L"TapeController", + L"CdRomController", + L"WormController", + L"SerialController", + L"NetworkController", + L"DisplayController", + L"ParallelController", + L"PointerController", + L"KeyboardController", + L"AudioController", + L"OtherController", + L"DiskPeripheral", + L"FloppyDiskPeripheral", + L"TapePeripheral", + L"ModemPeripheral", + L"MonitorPeripheral", + L"PrinterPeripheral", + L"PointerPeripheral", + L"KeyboardPeripheral", + L"TerminalPeripheral", + L"OtherPeripheral", + L"LinePeripheral", + L"NetworkPeripheral", + L"SystemMemory", + L"DockingInformation", + L"RealModeIrqRoutingTable", + L"RealModePCIEnumeration", + L"Undefined" +}; + +#define TAG_IO_RESOURCE TAG('R', 'S', 'R', 'C') + +/* PRIVATE FUNCTIONS **********************************************************/ + +/* + * IopQueryDeviceDescription + * + * FUNCTION: + * Reads and returns Hardware information from the appropriate hardware + * registry key. Helper sub of IopQueryBusDescription. + * + * ARGUMENTS: + * Query - What the parent function wants. + * RootKey - Which key to look in + * RootKeyHandle - Handle to the key + * Bus - Bus Number. + * BusInformation - The Configuration Information Sent + * + * RETURNS: + * Status + */ + +NTSTATUS STDCALL +IopQueryDeviceDescription( + PIO_QUERY Query, + UNICODE_STRING RootKey, + HANDLE RootKeyHandle, + ULONG Bus, + PKEY_VALUE_FULL_INFORMATION *BusInformation) +{ + NTSTATUS Status; + + /* Controller Stuff */ + UNICODE_STRING ControllerString; + UNICODE_STRING ControllerRootRegName = RootKey; + UNICODE_STRING ControllerRegName; + HANDLE ControllerKeyHandle; + PKEY_FULL_INFORMATION ControllerFullInformation; + PKEY_VALUE_FULL_INFORMATION ControllerInformation[3] = {NULL, NULL, NULL}; + ULONG ControllerNumber; + ULONG ControllerLoop; + ULONG MaximumControllerNumber; + + /* Peripheral Stuff */ + UNICODE_STRING PeripheralString; + HANDLE PeripheralKeyHandle; + PKEY_FULL_INFORMATION PeripheralFullInformation; + PKEY_VALUE_FULL_INFORMATION PeripheralInformation[3] = {NULL, NULL, NULL}; + ULONG PeripheralNumber; + ULONG PeripheralLoop; + ULONG MaximumPeripheralNumber; + + /* Global Registry Stuff */ + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG LenFullInformation; + ULONG LenKeyFullInformation; + UNICODE_STRING TempString; + WCHAR TempBuffer[14]; + PWSTR Strings[3] = { + L"Identifier", + L"Configuration Data", + L"Component Information" + }; + + /* Temporary String */ + TempString.MaximumLength = sizeof(TempBuffer); + TempString.Length = 0; + TempString.Buffer = TempBuffer; + + /* Add Controller Name to String */ + RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); + RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]); + + /* Set the Controller Number if specified */ + if (Query->ControllerNumber && *(Query->ControllerNumber)) + { + ControllerNumber = *Query->ControllerNumber; + MaximumControllerNumber = ControllerNumber + 1; + } else { + /* Find out how many Controller Numbers there are */ + InitializeObjectAttributes( + &ObjectAttributes, + &ControllerRootRegName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) + { + /* How much buffer space */ + ZwQueryKey(ControllerKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); + + /* Allocate it */ + ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryKey(ControllerKeyHandle, KeyFullInformation, ControllerFullInformation, LenFullInformation, &LenFullInformation); + ZwClose(ControllerKeyHandle); + ControllerKeyHandle = NULL; + } + + /* No controller was found, go back to function. */ + if (!NT_SUCCESS(Status)) + { + if (ControllerFullInformation != NULL) + ExFreePool(ControllerFullInformation); + return Status; + } + + /* Find out Controller Numbers */ + ControllerNumber = 0; + MaximumControllerNumber = ControllerFullInformation->SubKeys; + + /* Free Memory */ + ExFreePool(ControllerFullInformation); + ControllerFullInformation = NULL; + } + + /* Save String */ + ControllerRegName = ControllerRootRegName; + + /* Loop through controllers */ + for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++) + { + /* Load String */ + ControllerRootRegName = ControllerRegName; + + /* Controller Number to Registry String */ + Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString); + + /* Create String */ + Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); + Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); + + /* Something messed up */ + if (!NT_SUCCESS(Status)) break; + + /* Open the Registry Key */ + InitializeObjectAttributes( + &ObjectAttributes, + &ControllerRootRegName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); + + /* Read the Configuration Data... */ + if (NT_SUCCESS(Status)) + { + for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) + { + /* Identifier String First */ + RtlInitUnicodeString(&ControllerString, Strings[ControllerLoop]); + + /* How much buffer space */ + ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); + + /* Allocate it */ + ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, ControllerInformation[ControllerLoop], LenKeyFullInformation, &LenKeyFullInformation); + } + + /* Clean Up */ + ZwClose(ControllerKeyHandle); + ControllerKeyHandle = NULL; + } + + /* Something messed up */ + if (!NT_SUCCESS(Status)) + goto EndLoop; + + /* We now have Bus *AND* Controller Information.. is it enough? */ + if (!(*Query->PeripheralType)) + { + Status = Query->CalloutRoutine( + Query->Context, + &ControllerRootRegName, + *Query->BusType, + Bus, + BusInformation, + *Query->ControllerType, + ControllerNumber, + ControllerInformation, + 0, + 0, + NULL); + goto EndLoop; + } + + /* Not enough...caller also wants peripheral name */ + Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); + Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]); + + /* Something messed up */ + if (!NT_SUCCESS(Status)) goto EndLoop; + + /* Set the Peripheral Number if specified */ + if (Query->PeripheralNumber && *Query->PeripheralNumber) + { + PeripheralNumber = *Query->PeripheralNumber; + MaximumPeripheralNumber = PeripheralNumber + 1; + } else { + /* Find out how many Peripheral Numbers there are */ + InitializeObjectAttributes( + &ObjectAttributes, + &ControllerRootRegName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); + + if (NT_SUCCESS(Status)) + { + /* How much buffer space */ + ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); + + /* Allocate it */ + PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, PeripheralFullInformation, LenFullInformation, &LenFullInformation); + ZwClose(PeripheralKeyHandle); + PeripheralKeyHandle = NULL; + } + + /* No controller was found, go back to function but clean up first */ + if (!NT_SUCCESS(Status)) + { + Status = STATUS_SUCCESS; + goto EndLoop; + } + + /* Find out Peripheral Number */ + PeripheralNumber = 0; + MaximumPeripheralNumber = PeripheralFullInformation->SubKeys; + + /* Free Memory */ + ExFreePool(PeripheralFullInformation); + PeripheralFullInformation = NULL; + } + + /* Save Name */ + ControllerRegName = ControllerRootRegName; + + /* Loop through Peripherals */ + for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++) + { + /* Restore Name */ + ControllerRootRegName = ControllerRegName; + + /* Peripheral Number to Registry String */ + Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString); + + /* Create String */ + Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); + Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); + + /* Something messed up */ + if (!NT_SUCCESS(Status)) break; + + /* Open the Registry Key */ + InitializeObjectAttributes( + &ObjectAttributes, + &ControllerRootRegName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); + + if (NT_SUCCESS(Status)) + { + for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) + { + /* Identifier String First */ + RtlInitUnicodeString(&PeripheralString, Strings[PeripheralLoop]); + + /* How much buffer space */ + ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); + + /* Allocate it */ + PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, PeripheralInformation[PeripheralLoop], LenKeyFullInformation, &LenKeyFullInformation); + } + + /* Clean Up */ + ZwClose(PeripheralKeyHandle); + PeripheralKeyHandle = NULL; + + /* We now have everything the caller could possibly want */ + if (NT_SUCCESS(Status)) + { +#if 0 + Status = Query->CalloutRoutine( + Query->Context, + &ControllerRootRegName, + *Query->BusType, + Bus, + BusInformation, + *Query->ControllerType, + ControllerNumber, + ControllerInformation, + *Query->PeripheralType, + PeripheralNumber, + PeripheralInformation); +#else + Status = STATUS_SUCCESS; +#endif + } + + /* Free the allocated memory */ + for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) + { + if (PeripheralInformation[PeripheralLoop]) + { + ExFreePool(PeripheralInformation[PeripheralLoop]); + PeripheralInformation[PeripheralLoop] = NULL; + } + } + + /* Something Messed up */ + if (!NT_SUCCESS(Status)) break; + } + } + +EndLoop: + /* Free the allocated memory */ + for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) + { + if (ControllerInformation[ControllerLoop]) + { + ExFreePool(ControllerInformation[ControllerLoop]); + ControllerInformation[ControllerLoop] = NULL; + } + } + + /* Something Messed up */ + if (!NT_SUCCESS(Status)) break; + } + + return Status; +} + +/* + * IopQueryBusDescription + * + * FUNCTION: + * Reads and returns Hardware information from the appropriate hardware + * registry key. Helper sub of IoQueryDeviceDescription. Has two modes + * of operation, either looking for Root Bus Types or for sub-Bus + * information. + * + * ARGUMENTS: + * Query - What the parent function wants. + * RootKey - Which key to look in + * RootKeyHandle - Handle to the key + * Bus - Bus Number. + * KeyIsRoot - Whether we are looking for Root Bus Types or + * information under them. + * + * RETURNS: + * Status + */ + +NTSTATUS STDCALL +IopQueryBusDescription( + PIO_QUERY Query, + UNICODE_STRING RootKey, + HANDLE RootKeyHandle, + PULONG Bus, + BOOLEAN KeyIsRoot) +{ + NTSTATUS Status; + ULONG BusLoop; + UNICODE_STRING SubRootRegName; + UNICODE_STRING BusString; + UNICODE_STRING SubBusString; + ULONG LenBasicInformation; + ULONG LenFullInformation; + ULONG LenKeyFullInformation; + ULONG LenKey; + HANDLE SubRootKeyHandle; + PKEY_FULL_INFORMATION FullInformation; + PKEY_BASIC_INFORMATION BasicInformation; + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_VALUE_FULL_INFORMATION BusInformation[3] = {NULL, NULL, NULL}; + + /* How much buffer space */ + Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); + + if (!NT_SUCCESS(Status)) + return Status; + + /* Allocate it */ + FullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryKey(RootKeyHandle, KeyFullInformation, FullInformation, LenFullInformation, &LenFullInformation); + + /* Everything was fine */ + if (NT_SUCCESS(Status)) + { + /* Buffer needed for all the keys under this one */ + LenBasicInformation = FullInformation->MaxNameLen + sizeof(KEY_BASIC_INFORMATION); + + /* Allocate it */ + BasicInformation = ExAllocatePoolWithTag(PagedPool, LenBasicInformation, TAG_IO_RESOURCE); + } + + /* Deallocate the old Buffer */ + ExFreePool(FullInformation); + + /* Try to find a Bus */ + for (BusLoop = 0; NT_SUCCESS(Status); BusLoop++) + { + /* Bus parameter was passed and number was matched */ + if ((Query->BusNumber) && (*(Query->BusNumber)) == *Bus) break; + + /* Enumerate the Key */ + Status = ZwEnumerateKey( + RootKeyHandle, + BusLoop, + KeyBasicInformation, + BasicInformation, + LenBasicInformation, + &LenKey); + + /* Everything enumerated */ + if (!NT_SUCCESS(Status)) break; + + /* What Bus are we going to go down? (only check if this is a Root Key) */ + if (KeyIsRoot) + { + if (wcsncmp(BasicInformation->Name, L"MultifunctionAdapter", BasicInformation->NameLength / 2) && + wcsncmp(BasicInformation->Name, L"EisaAdapter", BasicInformation->NameLength / 2) && + wcsncmp(BasicInformation->Name, L"TcAdapter", BasicInformation->NameLength / 2)) + { + /* Nothing found, check next */ + continue; + } + } + + /* Enumerate the Bus. */ + BusString.Buffer = BasicInformation->Name; + BusString.Length = BasicInformation->NameLength; + BusString.MaximumLength = BasicInformation->NameLength; + + /* Open a handle to the Root Registry Key */ + InitializeObjectAttributes( + &ObjectAttributes, + &BusString, + OBJ_CASE_INSENSITIVE, + RootKeyHandle, + NULL); + + Status = ZwOpenKey(&SubRootKeyHandle, KEY_READ, &ObjectAttributes); + + /* Go on if we can't */ + if (!NT_SUCCESS(Status)) continue; + + /* Key opened. Create the path */ + SubRootRegName = RootKey; + RtlAppendUnicodeToString(&SubRootRegName, L"\\"); + RtlAppendUnicodeStringToString(&SubRootRegName, &BusString); + + if (!KeyIsRoot) + { + /* Parsing a SubBus-key */ + int SubBusLoop; + PWSTR Strings[3] = { + L"Identifier", + L"Configuration Data", + L"Component Information"}; + + for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++) + { + /* Identifier String First */ + RtlInitUnicodeString(&SubBusString, Strings[SubBusLoop]); + + /* How much buffer space */ + ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); + + /* Allocate it */ + BusInformation[SubBusLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); + + /* Get the Information */ + Status = ZwQueryValueKey(SubRootKeyHandle, &SubBusString, KeyValueFullInformation, BusInformation[SubBusLoop], LenKeyFullInformation, &LenKeyFullInformation); + } + + if (NT_SUCCESS(Status)) + { + /* Do we have something */ + if (BusInformation[1] != NULL && + BusInformation[1]->DataLength != 0 && + /* Does it match what we want? */ + (((PCM_FULL_RESOURCE_DESCRIPTOR)((ULONG_PTR)BusInformation[1] + BusInformation[1]->DataOffset))->InterfaceType == *(Query->BusType))) + { + /* Found a bus */ + (*Bus)++; + + /* Is it the bus we wanted */ + if (Query->BusNumber == NULL || *(Query->BusNumber) == *Bus) + { + /* If we don't want Controller Information, we're done... call the callback */ + if (Query->ControllerType == NULL) + { + Status = Query->CalloutRoutine( + Query->Context, + &SubRootRegName, + *(Query->BusType), + *Bus, + BusInformation, + 0, + 0, + NULL, + 0, + 0, + NULL); + } else { + /* We want Controller Info...get it */ + Status = IopQueryDeviceDescription(Query, SubRootRegName, RootKeyHandle, *Bus, (PKEY_VALUE_FULL_INFORMATION*)BusInformation); + } + } + } + } + + /* Free the allocated memory */ + for (SubBusLoop = 0; SubBusLoop < 3; SubBusLoop++) + { + if (BusInformation[SubBusLoop]) + { + ExFreePool(BusInformation[SubBusLoop]); + BusInformation[SubBusLoop] = NULL; + } + } + + /* Exit the Loop if we found the bus */ + if (Query->BusNumber != NULL && *(Query->BusNumber) == *Bus) + { + ZwClose(SubRootKeyHandle); + SubRootKeyHandle = NULL; + continue; + } + } + + /* Enumerate the buses below us recursively if we haven't found the bus yet */ + Status = IopQueryBusDescription(Query, SubRootRegName, SubRootKeyHandle, Bus, !KeyIsRoot); + + /* Everything enumerated */ + if (Status == STATUS_NO_MORE_ENTRIES) Status = STATUS_SUCCESS; + + ZwClose(SubRootKeyHandle); + SubRootKeyHandle = NULL; + } + + /* Free the last remaining Allocated Memory */ + if (BasicInformation) + ExFreePool(BasicInformation); + + return Status; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ /* * @implemented @@ -106,9 +731,25 @@ IoAssignResources(PUNICODE_STRING RegistryPath, } /* - * @unimplemented + * FUNCTION: + * Reads and returns Hardware information from the appropriate hardware registry key. + * + * ARGUMENTS: + * BusType - MCA, ISA, EISA...specifies the Bus Type + * BusNumber - Which bus of above should be queried + * ControllerType - Specifices the Controller Type + * ControllerNumber - Which of the controllers to query. + * CalloutRoutine - Which function to call for each valid query. + * Context - Value to pass to the callback. + * + * RETURNS: + * Status + * + * STATUS: + * @implemented */ -NTSTATUS STDCALL + +NTSTATUS NTAPI IoQueryDeviceDescription(PINTERFACE_TYPE BusType, PULONG BusNumber, PCONFIGURATION_TYPE ControllerType, @@ -118,51 +759,51 @@ IoQueryDeviceDescription(PINTERFACE_TYPE BusType, PIO_QUERY_DEVICE_ROUTINE CalloutRoutine, PVOID Context) { -#if 0 - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - PWCH BaseKeyName[] = - L"\\Registry\\Machine\\Hardware\\MultifunctionAdapter\\0"; - HANDLE BaseKeyHandle; - ULONG i; - struct - { - KEY_BASIC_INFORMATION BasicInfo; - WCH Name[255]; - } BasicInfo; + NTSTATUS Status; + ULONG BusLoopNumber = -1; /* Root Bus */ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING RootRegKey; + HANDLE RootRegHandle; + WCHAR RootRegString[] = L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\"; + IO_QUERY Query; - BaseKeyName = L"\\Registry\\Machine\\Hardware\\MultifunctionAdapter"; - InitializeObjectAttributes(&ObjectAttributes, - BaseKeyName, - 0, - NULL, - NULL); - Status = ZwOpenKey(&BaseKeyHandle, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEY, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + /* Set up the String */ + RootRegKey.Length = 0; + RootRegKey.MaximumLength = 2048; + RootRegKey.Buffer = ExAllocatePoolWithTag(PagedPool, RootRegKey.MaximumLength, TAG_IO_RESOURCE); + RtlAppendUnicodeToString(&RootRegKey, RootRegString); + + /* Open a handle to the Root Registry Key */ + InitializeObjectAttributes( + &ObjectAttributes, + &RootRegKey, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - i = 0; - for (;;) - { - Status = ZwEnumerateKey(BaseKeyHandle, - i, - KeyBasicInformation, - &BasicInfo, - sizeof(BasicInfo), - &ResultLength); - if (!NT_SUCCESS(Status)) - { - break; - } + Status = ZwOpenKey(&RootRegHandle, KEY_READ, &ObjectAttributes); - - } -#endif - return(STATUS_NOT_IMPLEMENTED); + if (NT_SUCCESS(Status)) + { + /* Use a helper function to loop though this key and get the info */ + Query.BusType = BusType; + Query.BusNumber = BusNumber; + Query.ControllerType = ControllerType; + Query.ControllerNumber = ControllerNumber; + Query.PeripheralType = PeripheralType; + Query.PeripheralNumber = PeripheralNumber; + Query.CalloutRoutine = CalloutRoutine; + Query.Context = Context; + Status = IopQueryBusDescription(&Query, RootRegKey, RootRegHandle, &BusLoopNumber, TRUE); + + /* Close registry */ + ZwClose(RootRegHandle); + } + + /* Free Memory */ + ExFreePool(RootRegKey.Buffer); + + return Status; } /*