Windows2003-3790/drivers/bio/bdl/devcaps.c
2020-09-30 16:53:55 +02:00

1810 lines
52 KiB
C

/*++
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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <strsafe.h>
#include <wdm.h>
#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 <Control Id> 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 <Control ID> 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 <Control ID> 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 <Source List Index> 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 <Source List Index> 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 <Product Index> 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 <Product Index> 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 <Channel Id> 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 <Channel ID> 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 <Channel ID> 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 <Component Id> 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 <Component ID> 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 <Component ID> 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;
}
}