/*++ Copyright (C) Microsoft Corporation, 1996 - 1999 Module Name: devcaps.c Abstract: This module contains the implementation for the Microsoft Biometric Device Library Environment: Kernel mode only. Notes: Revision History: - Created December 2002 by Reid Kuhn --*/ #include #include #include #include #include #include "bdlint.h" #define DEVICE_REGISTRY_PATH L"\\Registry\\Machine\\Software\\Microsoft\\BAPI\\BSPs\\Microsoft Kernel BSP\\Devices\\" #define PNPID_VALUE_NAME L"PNP ID" NTSTATUS BDLBuildRegKeyPath ( PDEVICE_OBJECT pPhysicalDeviceObject, PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension, LPWSTR *pwszDeviceRegistryKeyName ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hDevInstRegyKey = NULL; ULONG cbKeyName; UNICODE_STRING ValueName; KEY_VALUE_BASIC_INFORMATION *pKeyValueInformation = NULL; ULONG ResultLength; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLBuildRegKeyPath: Enter\n", __DATE__, __TIME__)) // // Opend the device specific registry location // status = IoOpenDeviceRegistryKey( pPhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &hDevInstRegyKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLBuildRegKeyPath: IoOpenDeviceRegistryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Query the PNP ID from the device specific registry location // RtlInitUnicodeString(&ValueName, PNPID_VALUE_NAME); status = ZwQueryValueKey( hDevInstRegyKey, &ValueName, KeyValueBasicInformation, NULL, 0, &ResultLength); pKeyValueInformation = ExAllocatePoolWithTag(PagedPool, ResultLength, BDL_ULONG_TAG); if (pKeyValueInformation == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLBuildRegKeyPath: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } status = ZwQueryValueKey( hDevInstRegyKey, &ValueName, KeyValueBasicInformation, pKeyValueInformation, ResultLength, &ResultLength); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLBuildRegKeyPath: ZwQueryValueKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } if (pKeyValueInformation->Type != REG_SZ) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLBuildRegKeyPath: PNP ID is not a string type\n", __DATE__, __TIME__)) ASSERT(0); status = STATUS_UNSUCCESSFUL; goto ErrorReturn; } // // Allocate space for the concatenatenation of the base registry name with the // PnP name of the current device and pass that concatenation back // cbKeyName = pKeyValueInformation->NameLength + ((wcslen(DEVICE_REGISTRY_PATH) + 1) * sizeof(WCHAR)); *pwszDeviceRegistryKeyName = ExAllocatePoolWithTag(PagedPool, cbKeyName, BDL_ULONG_TAG); if (*pwszDeviceRegistryKeyName == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLBuildRegKeyPath: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } StringCbCopyW(*pwszDeviceRegistryKeyName, cbKeyName, DEVICE_REGISTRY_PATH); RtlCopyMemory( &((*pwszDeviceRegistryKeyName)[wcslen(DEVICE_REGISTRY_PATH)]), pKeyValueInformation->Name, pKeyValueInformation->NameLength); (*pwszDeviceRegistryKeyName)[cbKeyName / sizeof(WCHAR)] = L'\0'; Return: if (hDevInstRegyKey != NULL) { ZwClose(hDevInstRegyKey); } if (pKeyValueInformation != NULL) { ExFreePoolWithTag(pKeyValueInformation, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLBuildRegKeyPath: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLOpenSubkey ( HANDLE hRegKey, WCHAR *szKey, HANDLE *phSubKey ) { UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES ObjectAttributes; RtlInitUnicodeString(&UnicodeString, szKey); InitializeObjectAttributes( &ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hRegKey, NULL); return (ZwOpenKey( phSubKey, KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes)); } NTSTATUS BDLGetValue ( HANDLE hRegKey, ULONG Type, WCHAR *szValue, ULONG *pULONGValue, WCHAR **pszValue ) { NTSTATUS status = STATUS_SUCCESS; KEY_VALUE_FULL_INFORMATION *pKeyValueFullInformation = NULL; ULONG ResultLength; UNICODE_STRING UnicodeString; ULONG NumChars; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetValue: Enter\n", __DATE__, __TIME__)) RtlInitUnicodeString(&UnicodeString, szValue); status = ZwQueryValueKey( hRegKey, &UnicodeString, KeyValueFullInformation, NULL, 0, &ResultLength); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetValue: ZwQueryValueKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } pKeyValueFullInformation = ExAllocatePoolWithTag(PagedPool, ResultLength, BDL_ULONG_TAG); if (pKeyValueFullInformation == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetValue: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } status = ZwQueryValueKey( hRegKey, &UnicodeString, KeyValueFullInformation, pKeyValueFullInformation, ResultLength, &ResultLength); if (pKeyValueFullInformation->Type != Type) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetValue: %S is not of Type %lx\n", __DATE__, __TIME__, szValue, Type)) ASSERT(0); status = STATUS_UNSUCCESSFUL; goto ErrorReturn; } if (Type == REG_DWORD) { *pULONGValue = *((ULONG *) (((PUCHAR) pKeyValueFullInformation) + pKeyValueFullInformation->DataOffset)); } else { NumChars = pKeyValueFullInformation->DataLength / sizeof(WCHAR); *pszValue = ExAllocatePoolWithTag( PagedPool, (NumChars + 1) * sizeof(WCHAR), BDL_ULONG_TAG); if (*pszValue == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetValue: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } RtlCopyMemory( *pszValue, ((PUCHAR) pKeyValueFullInformation) + pKeyValueFullInformation->DataOffset, pKeyValueFullInformation->DataLength); (*pszValue)[NumChars] = L'\0'; } Return: if (pKeyValueFullInformation != NULL) { ExFreePoolWithTag(pKeyValueFullInformation, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetValue: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetControls ( HANDLE hRegKey, ULONG *pNumControls, BDL_CONTROL **prgControls ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hControlsKey = NULL; UNICODE_STRING UnicodeString; KEY_FULL_INFORMATION ControlsKeyFullInfo; ULONG ReturnedSize; ULONG i; HANDLE hControlIdKey = NULL; KEY_BASIC_INFORMATION *pControlIdKeyBasicInfo = NULL; ULONG KeyBasicInfoSize = 0; ULONG NumericMinimum = 0; ULONG NumericMaximum = 0; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetControls: Enter\n", __DATE__, __TIME__)) *pNumControls = 0; *prgControls = NULL; // // Open the "Controls" key so it can be used to query all subkeys and values // status = BDLOpenSubkey(hRegKey, L"Controls", &hControlsKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Find out how many controls there are // status = ZwQueryKey( hControlsKey, KeyFullInformation, &ControlsKeyFullInfo, sizeof(ControlsKeyFullInfo), &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: ZwQueryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Allocate the array of controls // *prgControls = ExAllocatePoolWithTag( PagedPool, ControlsKeyFullInfo.SubKeys * sizeof(BDL_CONTROL), BDL_ULONG_TAG); if (*prgControls == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } *pNumControls = ControlsKeyFullInfo.SubKeys; RtlZeroMemory(*prgControls, ControlsKeyFullInfo.SubKeys * sizeof(BDL_CONTROL)); // // Allocate a structure for querying key names that is large enough to hold all of them // KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ControlsKeyFullInfo.MaxNameLen; pControlIdKeyBasicInfo = ExAllocatePoolWithTag( PagedPool, KeyBasicInfoSize + 1, BDL_ULONG_TAG); if (pControlIdKeyBasicInfo == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } // // Loop for each Control SubKey and get the relevant info // for (i = 0; i < ControlsKeyFullInfo.SubKeys; i++) { // // Get the name on the key // status = ZwEnumerateKey( hControlsKey, i, KeyBasicInformation, pControlIdKeyBasicInfo, KeyBasicInfoSize, &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: ZwEnumerateKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Change the key string to a value // pControlIdKeyBasicInfo->Name[pControlIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0'; RtlInitUnicodeString(&UnicodeString, pControlIdKeyBasicInfo->Name); RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgControls)[i].ControlId)); // // Open up the key // status = BDLOpenSubkey(hControlsKey, pControlIdKeyBasicInfo->Name, &hControlIdKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get all the values under the key // if ((STATUS_SUCCESS != (status = BDLGetValue( hControlIdKey, REG_DWORD, L"NumericMinimum", &(NumericMinimum), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hControlIdKey, REG_DWORD, L"NumericMaximum", &(NumericMaximum), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hControlIdKey, REG_DWORD, L"NumericGranularity", &((*prgControls)[i].NumericGranularity), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hControlIdKey, REG_DWORD, L"NumericDivisor", &((*prgControls)[i].NumericDivisor), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hControlIdKey, REG_DWORD, L"Flags", &((*prgControls)[i].Flags), NULL)))) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetControls: BDLGetValue failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Convert Min and Max to 32-bit integers // if (NumericMinimum | 0x8000000) { (*prgControls)[i].NumericMinimum = 0 - (((INT32) (((ULONG) 0xFFFFFFFF) - NumericMinimum)) + 1); } else { (*prgControls)[i].NumericMinimum = (INT32) NumericMinimum; } if (NumericMaximum | 0x8000000) { (*prgControls)[i].NumericMaximum = 0 - (((INT32) (((ULONG) 0xFFFFFFFF) - NumericMaximum)) + 1); } else { (*prgControls)[i].NumericMaximum = (INT32) NumericMaximum; } ZwClose(hControlIdKey); hControlIdKey = NULL; } Return: if (hControlsKey != NULL) { ZwClose(hControlsKey); } if (hControlIdKey != NULL) { ZwClose(hControlIdKey); } if (pControlIdKeyBasicInfo != NULL) { ExFreePoolWithTag(pControlIdKeyBasicInfo, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetControls: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetSourceLists ( HANDLE hRegKey, ULONG *pNumSourceLists, BDL_CHANNEL_SOURCE_LIST **prgSourceLists ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hSourcesKey = NULL; UNICODE_STRING UnicodeString; KEY_FULL_INFORMATION SourcesKeyFullInfo; ULONG ReturnedSize; ULONG i; HANDLE hSourceListIndexKey = NULL; KEY_BASIC_INFORMATION *pSourcesListIndexKeyBasicInfo = NULL; ULONG KeyBasicInfoSize = 0; WCHAR *szGUID = NULL; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetSourceLists: Enter\n", __DATE__, __TIME__)) *pNumSourceLists = 0; *prgSourceLists = NULL; // // Open the "Sources" key so it can be used to query all subkeys and values // status = BDLOpenSubkey(hRegKey, L"Sources", &hSourcesKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Find out how many sources lists there are // status = ZwQueryKey( hSourcesKey, KeyFullInformation, &SourcesKeyFullInfo, sizeof(SourcesKeyFullInfo), &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: ZwQueryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Allocate the array of sources lists // *prgSourceLists = ExAllocatePoolWithTag( PagedPool, SourcesKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL_SOURCE_LIST), BDL_ULONG_TAG); if (*prgSourceLists == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } *pNumSourceLists = SourcesKeyFullInfo.SubKeys; RtlZeroMemory(*prgSourceLists, SourcesKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL_SOURCE_LIST)); // // Allocate a structure for querying key names that is large enough to hold all of them // KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + SourcesKeyFullInfo.MaxNameLen; pSourcesListIndexKeyBasicInfo = ExAllocatePoolWithTag( PagedPool, KeyBasicInfoSize + 1, BDL_ULONG_TAG); if (pSourcesListIndexKeyBasicInfo == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } // // Loop for each Source List Index SubKey and get the relevant info // for (i = 0; i < SourcesKeyFullInfo.SubKeys; i++) { // // Get the name of the key // // NOTE: This code does not ensure that the key names progress from "0" to "1" // to "n". The WHQL driver validation ensures proper registry form. // status = ZwEnumerateKey( hSourcesKey, i, KeyBasicInformation, pSourcesListIndexKeyBasicInfo, KeyBasicInfoSize, &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: ZwEnumerateKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Open up the key // status = BDLOpenSubkey( hSourcesKey, pSourcesListIndexKeyBasicInfo->Name, &hSourceListIndexKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get all the values under the key // if ((STATUS_SUCCESS != (status = BDLGetValue( hSourceListIndexKey, REG_SZ, L"Format", NULL, &szGUID))) || (STATUS_SUCCESS != (status = BDLGetValue( hSourceListIndexKey, REG_DWORD, L"Min", &((*prgSourceLists)[i].MinSources), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hSourceListIndexKey, REG_DWORD, L"Max", &((*prgSourceLists)[i].MaxSources), NULL))) || (STATUS_SUCCESS != (status = BDLGetValue( hSourceListIndexKey, REG_DWORD, L"Flags", &((*prgSourceLists)[i].Flags), NULL)))) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetSourceLists: BDLGetValue failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Convert the Format GUID string to an actual GUID // RtlInitUnicodeString(&UnicodeString, szGUID); status = RtlGUIDFromString(&UnicodeString, &((*prgSourceLists)[i].FormatGUID)); ZwClose(hSourceListIndexKey); hSourceListIndexKey = NULL; } Return: if (hSourcesKey != NULL) { ZwClose(hSourcesKey); } if (hSourceListIndexKey != NULL) { ZwClose(hSourceListIndexKey); } if (pSourcesListIndexKeyBasicInfo != NULL) { ExFreePoolWithTag(pSourcesListIndexKeyBasicInfo, BDL_ULONG_TAG); } if (szGUID != NULL) { ExFreePoolWithTag(szGUID, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetSourceLists: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetProducts ( HANDLE hRegKey, ULONG *pNumProducts, BDL_PRODUCT **prgProducts ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hProductsKey = NULL; UNICODE_STRING UnicodeString; KEY_FULL_INFORMATION ProductsKeyFullInfo; ULONG ReturnedSize; ULONG i; HANDLE hProductIndexKey = NULL; KEY_BASIC_INFORMATION *pProductIndexKeyBasicInfo = NULL; ULONG KeyBasicInfoSize = 0; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetProducts: Enter\n", __DATE__, __TIME__)) *pNumProducts = 0; *prgProducts = NULL; // // Open the "Products" key so it can be used to query all subkeys and values // status = BDLOpenSubkey(hRegKey, L"Products", &hProductsKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Find out how many products there are // status = ZwQueryKey( hProductsKey, KeyFullInformation, &ProductsKeyFullInfo, sizeof(ProductsKeyFullInfo), &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: ZwQueryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Allocate the array of products // *prgProducts = ExAllocatePoolWithTag( PagedPool, ProductsKeyFullInfo.SubKeys * sizeof(BDL_PRODUCT), BDL_ULONG_TAG); if (*prgProducts == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } *pNumProducts = ProductsKeyFullInfo.SubKeys; RtlZeroMemory(*prgProducts, ProductsKeyFullInfo.SubKeys * sizeof(BDL_PRODUCT)); // // Allocate a structure for querying key names that is large enough to hold all of them // KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ProductsKeyFullInfo.MaxNameLen; pProductIndexKeyBasicInfo = ExAllocatePoolWithTag( PagedPool, KeyBasicInfoSize + 1, BDL_ULONG_TAG); if (pProductIndexKeyBasicInfo == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } // // Loop for each Source List Index SubKey and get the relevant info // for (i = 0; i < ProductsKeyFullInfo.SubKeys; i++) { // // Get the name of the key // // NOTE: This code does not ensure that the key names progress from "0" to "1" // to "n". The WHQL driver validation ensures proper registry form. // status = ZwEnumerateKey( hProductsKey, i, KeyBasicInformation, pProductIndexKeyBasicInfo, KeyBasicInfoSize, &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: ZwEnumerateKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Open up the key // status = BDLOpenSubkey( hProductsKey, pProductIndexKeyBasicInfo->Name, &hProductIndexKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get all the values under the key // if (STATUS_SUCCESS != (status = BDLGetValue( hProductIndexKey, REG_DWORD, L"Flags", &((*prgProducts)[i].Flags), NULL))) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetProducts: BDLGetValue failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } ZwClose(hProductIndexKey); hProductIndexKey = NULL; } Return: if (hProductsKey != NULL) { ZwClose(hProductsKey); } if (hProductIndexKey != NULL) { ZwClose(hProductIndexKey); } if (pProductIndexKeyBasicInfo != NULL) { ExFreePoolWithTag(pProductIndexKeyBasicInfo, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetProducts: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetChannels ( HANDLE hRegKey, ULONG *pNumChannels, BDL_CHANNEL **prgChannels ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hChannelsKey = NULL; KEY_FULL_INFORMATION ChannelsKeyFullInfo; UNICODE_STRING UnicodeString; ULONG ReturnedSize; ULONG i; HANDLE hChannelIdKey = NULL; KEY_BASIC_INFORMATION *pChannelIdKeyBasicInfo = NULL; ULONG KeyBasicInfoSize = 0; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetChannels: Enter\n", __DATE__, __TIME__)) *pNumChannels = 0; *prgChannels = NULL; // // Open the "Channels" key so it can be used to query all subkeys and values // status = BDLOpenSubkey(hRegKey, L"Channels", &hChannelsKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Find out how many controls there are // status = ZwQueryKey( hChannelsKey, KeyFullInformation, &ChannelsKeyFullInfo, sizeof(ChannelsKeyFullInfo), &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: ZwQueryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Allocate the array of channels // *prgChannels = ExAllocatePoolWithTag( PagedPool, ChannelsKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL), BDL_ULONG_TAG); if (*prgChannels == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } *pNumChannels = ChannelsKeyFullInfo.SubKeys; RtlZeroMemory(*prgChannels, ChannelsKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL)); // // Allocate a structure for querying key names that is large enough to hold all of them // KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ChannelsKeyFullInfo.MaxNameLen; pChannelIdKeyBasicInfo = ExAllocatePoolWithTag( PagedPool, KeyBasicInfoSize + 1, BDL_ULONG_TAG); if (pChannelIdKeyBasicInfo == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } // // Loop for each Channel SubKey and get the relevant info // for (i = 0; i < ChannelsKeyFullInfo.SubKeys; i++) { // // Get the name on the key // status = ZwEnumerateKey( hChannelsKey, i, KeyBasicInformation, pChannelIdKeyBasicInfo, KeyBasicInfoSize, &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: ZwEnumerateKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Change the key string to a value // pChannelIdKeyBasicInfo->Name[pChannelIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0'; RtlInitUnicodeString(&UnicodeString, pChannelIdKeyBasicInfo->Name); RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgChannels)[i].ChannelId)); // // Open up the key // status = BDLOpenSubkey(hChannelsKey, pChannelIdKeyBasicInfo->Name, &hChannelIdKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the Cancelable value // status = BDLGetValue( hChannelIdKey, REG_DWORD, L"Cancelable", (ULONG *) &((*prgChannels)[i].fCancelable), NULL); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLGetValue failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the channel level controls // status = BDLGetControls( hChannelIdKey, &((*prgChannels)[i].NumControls), &((*prgChannels)[i].rgControls)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLGetControls failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the sources lists // status = BDLGetSourceLists( hChannelIdKey, &((*prgChannels)[i].NumSourceLists), &((*prgChannels)[i].rgSourceLists)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLGetSourceLists failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the products // status = BDLGetProducts( hChannelIdKey, &((*prgChannels)[i].NumProducts), &((*prgChannels)[i].rgProducts)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetChannels: BDLGetProductss failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } ZwClose(hChannelIdKey); hChannelIdKey = NULL; } Return: if (hChannelsKey != NULL) { ZwClose(hChannelsKey); } if (hChannelIdKey != NULL) { ZwClose(hChannelIdKey); } if (pChannelIdKeyBasicInfo != NULL) { ExFreePoolWithTag(pChannelIdKeyBasicInfo, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetChannels: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetComponents ( HANDLE hRegKey, ULONG *pNumComponents, BDL_COMPONENT **prgComponents ) { NTSTATUS status = STATUS_SUCCESS; HANDLE hComponentsKey = NULL; UNICODE_STRING UnicodeString; KEY_FULL_INFORMATION ComponentsKeyFullInfo; ULONG ReturnedSize; ULONG i; HANDLE hComponentIdKey = NULL; KEY_BASIC_INFORMATION *pComponentIdKeyBasicInfo = NULL; ULONG KeyBasicInfoSize = 0; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetComponents: Enter\n", __DATE__, __TIME__)) *pNumComponents = 0; *prgComponents = NULL; // // Open the "Components" key so it can be used to query all subkeys and values // status = BDLOpenSubkey(hRegKey, L"Components", &hComponentsKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Find out how many components there are // status = ZwQueryKey( hComponentsKey, KeyFullInformation, &ComponentsKeyFullInfo, sizeof(ComponentsKeyFullInfo), &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: ZwQueryKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Allocate the array of components // *prgComponents = ExAllocatePoolWithTag( PagedPool, ComponentsKeyFullInfo.SubKeys * sizeof(BDL_COMPONENT), BDL_ULONG_TAG); if (*prgComponents == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } *pNumComponents = ComponentsKeyFullInfo.SubKeys; RtlZeroMemory(*prgComponents, ComponentsKeyFullInfo.SubKeys * sizeof(BDL_COMPONENT)); // // Allocate a structure for querying key names that is large enough to hold all of them // KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ComponentsKeyFullInfo.MaxNameLen; pComponentIdKeyBasicInfo = ExAllocatePoolWithTag( PagedPool, KeyBasicInfoSize + 1, BDL_ULONG_TAG); if (pComponentIdKeyBasicInfo == NULL) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: ExAllocatePoolWithTag failed\n", __DATE__, __TIME__)) status = STATUS_NO_MEMORY; goto ErrorReturn; } // // Loop for each Component SubKey and get the relevant info // for (i = 0; i < ComponentsKeyFullInfo.SubKeys; i++) { // // Get the name on the key // status = ZwEnumerateKey( hComponentsKey, i, KeyBasicInformation, pComponentIdKeyBasicInfo, KeyBasicInfoSize, &ReturnedSize); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: ZwEnumerateKey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Change the key string to a value // pComponentIdKeyBasicInfo->Name[pComponentIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0'; RtlInitUnicodeString(&UnicodeString, pComponentIdKeyBasicInfo->Name); RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgComponents)[i].ComponentId)); // // Open up the key // status = BDLOpenSubkey(hComponentsKey, pComponentIdKeyBasicInfo->Name, &hComponentIdKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the component level controls // status = BDLGetControls( hComponentIdKey, &((*prgComponents)[i].NumControls), &((*prgComponents)[i].rgControls)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: BDLGetControls failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the channels in this component // status = BDLGetChannels( hComponentIdKey, &((*prgComponents)[i].NumChannels), &((*prgComponents)[i].rgChannels)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetComponents: BDLGetChannels failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } ZwClose(hComponentIdKey); hComponentIdKey = NULL; } Return: if (hComponentsKey != NULL) { ZwClose(hComponentsKey); } if (hComponentIdKey != NULL) { ZwClose(hComponentIdKey); } if (pComponentIdKeyBasicInfo != NULL) { ExFreePoolWithTag(pComponentIdKeyBasicInfo, BDL_ULONG_TAG); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetControls: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: goto Return; } NTSTATUS BDLGetDeviceCapabilities ( PDEVICE_OBJECT pPhysicalDeviceObject, PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension ) { NTSTATUS status = STATUS_SUCCESS; LPWSTR pwszDeviceRegistryKeyName = NULL; HANDLE hDeviceKey = NULL; BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetDevicesCapabilities: Enter\n", __DATE__, __TIME__)) // // Build the top level registry key name // status = BDLBuildRegKeyPath( pPhysicalDeviceObject, pBDLExtension, &pwszDeviceRegistryKeyName); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetDevicesCapabilities: BDLBuildRegKeyPath failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Open the top level device key so it can be used to query all subkeys and values // status = BDLOpenSubkey(NULL, pwszDeviceRegistryKeyName, &hDeviceKey); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetDevicesCapabilities: BDLOpenSubkey failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the device level controls // status = BDLGetControls( hDeviceKey, &(pBDLExtension->DeviceCapabilities.NumControls), &(pBDLExtension->DeviceCapabilities.rgControls)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetDevicesCapabilities: BDLGetControls failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } // // Get the components // status = BDLGetComponents( hDeviceKey, &(pBDLExtension->DeviceCapabilities.NumComponents), &(pBDLExtension->DeviceCapabilities.rgComponents)); if (status != STATUS_SUCCESS) { BDLDebug( BDL_DEBUG_ERROR, ("%s %s: BDL!BDLGetDevicesCapabilities: BDLGetControls failed with %x\n", __DATE__, __TIME__, status)) goto ErrorReturn; } Return: if (pwszDeviceRegistryKeyName != NULL) { ExFreePoolWithTag(pwszDeviceRegistryKeyName, BDL_ULONG_TAG); } if (hDeviceKey != NULL) { ZwClose(hDeviceKey); } BDLDebug( BDL_DEBUG_TRACE, ("%s %s: BDL!BDLGetDevicesCapabilities: Leave\n", __DATE__, __TIME__)) return (status); ErrorReturn: BDLCleanupDeviceCapabilities(pBDLExtension); goto Return; } VOID BDLCleanupDeviceCapabilities ( PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension ) { BDL_DEVICE_CAPABILITIES *pDeviceCapabilites = &(pBDLExtension->DeviceCapabilities); ULONG i, j; // // Free device level control array // if (pDeviceCapabilites->rgControls != NULL) { ExFreePoolWithTag(pDeviceCapabilites->rgControls, BDL_ULONG_TAG); pDeviceCapabilites->rgControls = NULL; } // // Free component array // if (pDeviceCapabilites->rgComponents != NULL) { // // Free each component // for (i = 0; i < pDeviceCapabilites->NumComponents; i++) { // // Free component level control array // if (pDeviceCapabilites->rgComponents[i].rgControls != NULL) { ExFreePoolWithTag(pDeviceCapabilites->rgComponents[i].rgControls, BDL_ULONG_TAG); } // // Free channel array // if (pDeviceCapabilites->rgComponents[i].rgChannels != NULL) { // // Free each channel // for (j = 0; j < pDeviceCapabilites->rgComponents[i].NumChannels; j++) { // // Free channel level controls, source lists, and products // if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgControls != NULL) { ExFreePoolWithTag( pDeviceCapabilites->rgComponents[i].rgChannels[j].rgControls, BDL_ULONG_TAG); } if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgSourceLists != NULL) { ExFreePoolWithTag( pDeviceCapabilites->rgComponents[i].rgChannels[j].rgSourceLists, BDL_ULONG_TAG); } if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgProducts != NULL) { ExFreePoolWithTag( pDeviceCapabilites->rgComponents[i].rgChannels[j].rgProducts, BDL_ULONG_TAG); } } ExFreePoolWithTag(pDeviceCapabilites->rgComponents[i].rgChannels, BDL_ULONG_TAG); } } ExFreePoolWithTag(pDeviceCapabilites->rgComponents, BDL_ULONG_TAG); pDeviceCapabilites->rgComponents = NULL; } }