Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1809 lines
52 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. devcaps.c
  5. Abstract:
  6. This module contains the implementation for the
  7. Microsoft Biometric Device Library
  8. Environment:
  9. Kernel mode only.
  10. Notes:
  11. Revision History:
  12. - Created December 2002 by Reid Kuhn
  13. --*/
  14. #include <stdarg.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <strsafe.h>
  18. #include <wdm.h>
  19. #include "bdlint.h"
  20. #define DEVICE_REGISTRY_PATH L"\\Registry\\Machine\\Software\\Microsoft\\BAPI\\BSPs\\Microsoft Kernel BSP\\Devices\\"
  21. #define PNPID_VALUE_NAME L"PNP ID"
  22. NTSTATUS
  23. BDLBuildRegKeyPath
  24. (
  25. PDEVICE_OBJECT pPhysicalDeviceObject,
  26. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  27. LPWSTR *pwszDeviceRegistryKeyName
  28. )
  29. {
  30. NTSTATUS status = STATUS_SUCCESS;
  31. HANDLE hDevInstRegyKey = NULL;
  32. ULONG cbKeyName;
  33. UNICODE_STRING ValueName;
  34. KEY_VALUE_BASIC_INFORMATION *pKeyValueInformation = NULL;
  35. ULONG ResultLength;
  36. BDLDebug(
  37. BDL_DEBUG_TRACE,
  38. ("%s %s: BDL!BDLBuildRegKeyPath: Enter\n",
  39. __DATE__,
  40. __TIME__))
  41. //
  42. // Opend the device specific registry location
  43. //
  44. status = IoOpenDeviceRegistryKey(
  45. pPhysicalDeviceObject,
  46. PLUGPLAY_REGKEY_DEVICE,
  47. KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  48. &hDevInstRegyKey);
  49. if (status != STATUS_SUCCESS)
  50. {
  51. BDLDebug(
  52. BDL_DEBUG_ERROR,
  53. ("%s %s: BDL!BDLBuildRegKeyPath: IoOpenDeviceRegistryKey failed with %x\n",
  54. __DATE__,
  55. __TIME__,
  56. status))
  57. goto ErrorReturn;
  58. }
  59. //
  60. // Query the PNP ID from the device specific registry location
  61. //
  62. RtlInitUnicodeString(&ValueName, PNPID_VALUE_NAME);
  63. status = ZwQueryValueKey(
  64. hDevInstRegyKey,
  65. &ValueName,
  66. KeyValueBasicInformation,
  67. NULL,
  68. 0,
  69. &ResultLength);
  70. pKeyValueInformation = ExAllocatePoolWithTag(PagedPool, ResultLength, BDL_ULONG_TAG);
  71. if (pKeyValueInformation == NULL)
  72. {
  73. BDLDebug(
  74. BDL_DEBUG_ERROR,
  75. ("%s %s: BDL!BDLBuildRegKeyPath: ExAllocatePoolWithTag failed\n",
  76. __DATE__,
  77. __TIME__))
  78. status = STATUS_NO_MEMORY;
  79. goto ErrorReturn;
  80. }
  81. status = ZwQueryValueKey(
  82. hDevInstRegyKey,
  83. &ValueName,
  84. KeyValueBasicInformation,
  85. pKeyValueInformation,
  86. ResultLength,
  87. &ResultLength);
  88. if (status != STATUS_SUCCESS)
  89. {
  90. BDLDebug(
  91. BDL_DEBUG_ERROR,
  92. ("%s %s: BDL!BDLBuildRegKeyPath: ZwQueryValueKey failed with %x\n",
  93. __DATE__,
  94. __TIME__,
  95. status))
  96. goto ErrorReturn;
  97. }
  98. if (pKeyValueInformation->Type != REG_SZ)
  99. {
  100. BDLDebug(
  101. BDL_DEBUG_ERROR,
  102. ("%s %s: BDL!BDLBuildRegKeyPath: PNP ID is not a string type\n",
  103. __DATE__,
  104. __TIME__))
  105. ASSERT(0);
  106. status = STATUS_UNSUCCESSFUL;
  107. goto ErrorReturn;
  108. }
  109. //
  110. // Allocate space for the concatenatenation of the base registry name with the
  111. // PnP name of the current device and pass that concatenation back
  112. //
  113. cbKeyName = pKeyValueInformation->NameLength + ((wcslen(DEVICE_REGISTRY_PATH) + 1) * sizeof(WCHAR));
  114. *pwszDeviceRegistryKeyName = ExAllocatePoolWithTag(PagedPool, cbKeyName, BDL_ULONG_TAG);
  115. if (*pwszDeviceRegistryKeyName == NULL)
  116. {
  117. BDLDebug(
  118. BDL_DEBUG_ERROR,
  119. ("%s %s: BDL!BDLBuildRegKeyPath: ExAllocatePoolWithTag failed\n",
  120. __DATE__,
  121. __TIME__))
  122. status = STATUS_NO_MEMORY;
  123. goto ErrorReturn;
  124. }
  125. StringCbCopyW(*pwszDeviceRegistryKeyName, cbKeyName, DEVICE_REGISTRY_PATH);
  126. RtlCopyMemory(
  127. &((*pwszDeviceRegistryKeyName)[wcslen(DEVICE_REGISTRY_PATH)]),
  128. pKeyValueInformation->Name,
  129. pKeyValueInformation->NameLength);
  130. (*pwszDeviceRegistryKeyName)[cbKeyName / sizeof(WCHAR)] = L'\0';
  131. Return:
  132. if (hDevInstRegyKey != NULL)
  133. {
  134. ZwClose(hDevInstRegyKey);
  135. }
  136. if (pKeyValueInformation != NULL)
  137. {
  138. ExFreePoolWithTag(pKeyValueInformation, BDL_ULONG_TAG);
  139. }
  140. BDLDebug(
  141. BDL_DEBUG_TRACE,
  142. ("%s %s: BDL!BDLBuildRegKeyPath: Leave\n",
  143. __DATE__,
  144. __TIME__))
  145. return (status);
  146. ErrorReturn:
  147. goto Return;
  148. }
  149. NTSTATUS
  150. BDLOpenSubkey
  151. (
  152. HANDLE hRegKey,
  153. WCHAR *szKey,
  154. HANDLE *phSubKey
  155. )
  156. {
  157. UNICODE_STRING UnicodeString;
  158. OBJECT_ATTRIBUTES ObjectAttributes;
  159. RtlInitUnicodeString(&UnicodeString, szKey);
  160. InitializeObjectAttributes(
  161. &ObjectAttributes,
  162. &UnicodeString,
  163. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  164. hRegKey,
  165. NULL);
  166. return (ZwOpenKey(
  167. phSubKey,
  168. KEY_READ | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  169. &ObjectAttributes));
  170. }
  171. NTSTATUS
  172. BDLGetValue
  173. (
  174. HANDLE hRegKey,
  175. ULONG Type,
  176. WCHAR *szValue,
  177. ULONG *pULONGValue,
  178. WCHAR **pszValue
  179. )
  180. {
  181. NTSTATUS status = STATUS_SUCCESS;
  182. KEY_VALUE_FULL_INFORMATION *pKeyValueFullInformation = NULL;
  183. ULONG ResultLength;
  184. UNICODE_STRING UnicodeString;
  185. ULONG NumChars;
  186. BDLDebug(
  187. BDL_DEBUG_TRACE,
  188. ("%s %s: BDL!BDLGetValue: Enter\n",
  189. __DATE__,
  190. __TIME__))
  191. RtlInitUnicodeString(&UnicodeString, szValue);
  192. status = ZwQueryValueKey(
  193. hRegKey,
  194. &UnicodeString,
  195. KeyValueFullInformation,
  196. NULL,
  197. 0,
  198. &ResultLength);
  199. if (status != STATUS_SUCCESS)
  200. {
  201. BDLDebug(
  202. BDL_DEBUG_ERROR,
  203. ("%s %s: BDL!BDLGetValue: ZwQueryValueKey failed with %x\n",
  204. __DATE__,
  205. __TIME__,
  206. status))
  207. goto ErrorReturn;
  208. }
  209. pKeyValueFullInformation = ExAllocatePoolWithTag(PagedPool, ResultLength, BDL_ULONG_TAG);
  210. if (pKeyValueFullInformation == NULL)
  211. {
  212. BDLDebug(
  213. BDL_DEBUG_ERROR,
  214. ("%s %s: BDL!BDLGetValue: ExAllocatePoolWithTag failed\n",
  215. __DATE__,
  216. __TIME__))
  217. status = STATUS_NO_MEMORY;
  218. goto ErrorReturn;
  219. }
  220. status = ZwQueryValueKey(
  221. hRegKey,
  222. &UnicodeString,
  223. KeyValueFullInformation,
  224. pKeyValueFullInformation,
  225. ResultLength,
  226. &ResultLength);
  227. if (pKeyValueFullInformation->Type != Type)
  228. {
  229. BDLDebug(
  230. BDL_DEBUG_ERROR,
  231. ("%s %s: BDL!BDLGetValue: %S is not of Type %lx\n",
  232. __DATE__,
  233. __TIME__,
  234. szValue,
  235. Type))
  236. ASSERT(0);
  237. status = STATUS_UNSUCCESSFUL;
  238. goto ErrorReturn;
  239. }
  240. if (Type == REG_DWORD)
  241. {
  242. *pULONGValue = *((ULONG *)
  243. (((PUCHAR) pKeyValueFullInformation) + pKeyValueFullInformation->DataOffset));
  244. }
  245. else
  246. {
  247. NumChars = pKeyValueFullInformation->DataLength / sizeof(WCHAR);
  248. *pszValue = ExAllocatePoolWithTag(
  249. PagedPool,
  250. (NumChars + 1) * sizeof(WCHAR),
  251. BDL_ULONG_TAG);
  252. if (*pszValue == NULL)
  253. {
  254. BDLDebug(
  255. BDL_DEBUG_ERROR,
  256. ("%s %s: BDL!BDLGetValue: ExAllocatePoolWithTag failed\n",
  257. __DATE__,
  258. __TIME__))
  259. status = STATUS_NO_MEMORY;
  260. goto ErrorReturn;
  261. }
  262. RtlCopyMemory(
  263. *pszValue,
  264. ((PUCHAR) pKeyValueFullInformation) + pKeyValueFullInformation->DataOffset,
  265. pKeyValueFullInformation->DataLength);
  266. (*pszValue)[NumChars] = L'\0';
  267. }
  268. Return:
  269. if (pKeyValueFullInformation != NULL)
  270. {
  271. ExFreePoolWithTag(pKeyValueFullInformation, BDL_ULONG_TAG);
  272. }
  273. BDLDebug(
  274. BDL_DEBUG_TRACE,
  275. ("%s %s: BDL!BDLGetValue: Leave\n",
  276. __DATE__,
  277. __TIME__))
  278. return (status);
  279. ErrorReturn:
  280. goto Return;
  281. }
  282. NTSTATUS
  283. BDLGetControls
  284. (
  285. HANDLE hRegKey,
  286. ULONG *pNumControls,
  287. BDL_CONTROL **prgControls
  288. )
  289. {
  290. NTSTATUS status = STATUS_SUCCESS;
  291. HANDLE hControlsKey = NULL;
  292. UNICODE_STRING UnicodeString;
  293. KEY_FULL_INFORMATION ControlsKeyFullInfo;
  294. ULONG ReturnedSize;
  295. ULONG i;
  296. HANDLE hControlIdKey = NULL;
  297. KEY_BASIC_INFORMATION *pControlIdKeyBasicInfo = NULL;
  298. ULONG KeyBasicInfoSize = 0;
  299. ULONG NumericMinimum = 0;
  300. ULONG NumericMaximum = 0;
  301. BDLDebug(
  302. BDL_DEBUG_TRACE,
  303. ("%s %s: BDL!BDLGetControls: Enter\n",
  304. __DATE__,
  305. __TIME__))
  306. *pNumControls = 0;
  307. *prgControls = NULL;
  308. //
  309. // Open the "Controls" key so it can be used to query all subkeys and values
  310. //
  311. status = BDLOpenSubkey(hRegKey, L"Controls", &hControlsKey);
  312. if (status != STATUS_SUCCESS)
  313. {
  314. BDLDebug(
  315. BDL_DEBUG_ERROR,
  316. ("%s %s: BDL!BDLGetControls: BDLOpenSubkey failed with %x\n",
  317. __DATE__,
  318. __TIME__,
  319. status))
  320. goto ErrorReturn;
  321. }
  322. //
  323. // Find out how many controls there are
  324. //
  325. status = ZwQueryKey(
  326. hControlsKey,
  327. KeyFullInformation,
  328. &ControlsKeyFullInfo,
  329. sizeof(ControlsKeyFullInfo),
  330. &ReturnedSize);
  331. if (status != STATUS_SUCCESS)
  332. {
  333. BDLDebug(
  334. BDL_DEBUG_ERROR,
  335. ("%s %s: BDL!BDLGetControls: ZwQueryKey failed with %x\n",
  336. __DATE__,
  337. __TIME__,
  338. status))
  339. goto ErrorReturn;
  340. }
  341. //
  342. // Allocate the array of controls
  343. //
  344. *prgControls = ExAllocatePoolWithTag(
  345. PagedPool,
  346. ControlsKeyFullInfo.SubKeys * sizeof(BDL_CONTROL),
  347. BDL_ULONG_TAG);
  348. if (*prgControls == NULL)
  349. {
  350. BDLDebug(
  351. BDL_DEBUG_ERROR,
  352. ("%s %s: BDL!BDLGetControls: ExAllocatePoolWithTag failed\n",
  353. __DATE__,
  354. __TIME__))
  355. status = STATUS_NO_MEMORY;
  356. goto ErrorReturn;
  357. }
  358. *pNumControls = ControlsKeyFullInfo.SubKeys;
  359. RtlZeroMemory(*prgControls, ControlsKeyFullInfo.SubKeys * sizeof(BDL_CONTROL));
  360. //
  361. // Allocate a structure for querying key names that is large enough to hold all of them
  362. //
  363. KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ControlsKeyFullInfo.MaxNameLen;
  364. pControlIdKeyBasicInfo = ExAllocatePoolWithTag(
  365. PagedPool,
  366. KeyBasicInfoSize + 1,
  367. BDL_ULONG_TAG);
  368. if (pControlIdKeyBasicInfo == NULL)
  369. {
  370. BDLDebug(
  371. BDL_DEBUG_ERROR,
  372. ("%s %s: BDL!BDLGetControls: ExAllocatePoolWithTag failed\n",
  373. __DATE__,
  374. __TIME__))
  375. status = STATUS_NO_MEMORY;
  376. goto ErrorReturn;
  377. }
  378. //
  379. // Loop for each Control SubKey and get the relevant info
  380. //
  381. for (i = 0; i < ControlsKeyFullInfo.SubKeys; i++)
  382. {
  383. //
  384. // Get the name on the <Control Id> key
  385. //
  386. status = ZwEnumerateKey(
  387. hControlsKey,
  388. i,
  389. KeyBasicInformation,
  390. pControlIdKeyBasicInfo,
  391. KeyBasicInfoSize,
  392. &ReturnedSize);
  393. if (status != STATUS_SUCCESS)
  394. {
  395. BDLDebug(
  396. BDL_DEBUG_ERROR,
  397. ("%s %s: BDL!BDLGetControls: ZwEnumerateKey failed with %x\n",
  398. __DATE__,
  399. __TIME__,
  400. status))
  401. goto ErrorReturn;
  402. }
  403. //
  404. // Change the <Control ID> key string to a value
  405. //
  406. pControlIdKeyBasicInfo->Name[pControlIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0';
  407. RtlInitUnicodeString(&UnicodeString, pControlIdKeyBasicInfo->Name);
  408. RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgControls)[i].ControlId));
  409. //
  410. // Open up the <Control ID> key
  411. //
  412. status = BDLOpenSubkey(hControlsKey, pControlIdKeyBasicInfo->Name, &hControlIdKey);
  413. if (status != STATUS_SUCCESS)
  414. {
  415. BDLDebug(
  416. BDL_DEBUG_ERROR,
  417. ("%s %s: BDL!BDLGetControls: BDLOpenSubkey failed with %x\n",
  418. __DATE__,
  419. __TIME__,
  420. status))
  421. goto ErrorReturn;
  422. }
  423. //
  424. // Get all the values under the key
  425. //
  426. if ((STATUS_SUCCESS != (status = BDLGetValue(
  427. hControlIdKey,
  428. REG_DWORD,
  429. L"NumericMinimum",
  430. &(NumericMinimum),
  431. NULL))) ||
  432. (STATUS_SUCCESS != (status = BDLGetValue(
  433. hControlIdKey,
  434. REG_DWORD,
  435. L"NumericMaximum",
  436. &(NumericMaximum),
  437. NULL))) ||
  438. (STATUS_SUCCESS != (status = BDLGetValue(
  439. hControlIdKey,
  440. REG_DWORD,
  441. L"NumericGranularity",
  442. &((*prgControls)[i].NumericGranularity),
  443. NULL))) ||
  444. (STATUS_SUCCESS != (status = BDLGetValue(
  445. hControlIdKey,
  446. REG_DWORD,
  447. L"NumericDivisor",
  448. &((*prgControls)[i].NumericDivisor),
  449. NULL))) ||
  450. (STATUS_SUCCESS != (status = BDLGetValue(
  451. hControlIdKey,
  452. REG_DWORD,
  453. L"Flags",
  454. &((*prgControls)[i].Flags),
  455. NULL))))
  456. {
  457. BDLDebug(
  458. BDL_DEBUG_ERROR,
  459. ("%s %s: BDL!BDLGetControls: BDLGetValue failed with %x\n",
  460. __DATE__,
  461. __TIME__,
  462. status))
  463. goto ErrorReturn;
  464. }
  465. //
  466. // Convert Min and Max to 32-bit integers
  467. //
  468. if (NumericMinimum | 0x8000000)
  469. {
  470. (*prgControls)[i].NumericMinimum =
  471. 0 - (((INT32) (((ULONG) 0xFFFFFFFF) - NumericMinimum)) + 1);
  472. }
  473. else
  474. {
  475. (*prgControls)[i].NumericMinimum = (INT32) NumericMinimum;
  476. }
  477. if (NumericMaximum | 0x8000000)
  478. {
  479. (*prgControls)[i].NumericMaximum =
  480. 0 - (((INT32) (((ULONG) 0xFFFFFFFF) - NumericMaximum)) + 1);
  481. }
  482. else
  483. {
  484. (*prgControls)[i].NumericMaximum = (INT32) NumericMaximum;
  485. }
  486. ZwClose(hControlIdKey);
  487. hControlIdKey = NULL;
  488. }
  489. Return:
  490. if (hControlsKey != NULL)
  491. {
  492. ZwClose(hControlsKey);
  493. }
  494. if (hControlIdKey != NULL)
  495. {
  496. ZwClose(hControlIdKey);
  497. }
  498. if (pControlIdKeyBasicInfo != NULL)
  499. {
  500. ExFreePoolWithTag(pControlIdKeyBasicInfo, BDL_ULONG_TAG);
  501. }
  502. BDLDebug(
  503. BDL_DEBUG_TRACE,
  504. ("%s %s: BDL!BDLGetControls: Leave\n",
  505. __DATE__,
  506. __TIME__))
  507. return (status);
  508. ErrorReturn:
  509. goto Return;
  510. }
  511. NTSTATUS
  512. BDLGetSourceLists
  513. (
  514. HANDLE hRegKey,
  515. ULONG *pNumSourceLists,
  516. BDL_CHANNEL_SOURCE_LIST **prgSourceLists
  517. )
  518. {
  519. NTSTATUS status = STATUS_SUCCESS;
  520. HANDLE hSourcesKey = NULL;
  521. UNICODE_STRING UnicodeString;
  522. KEY_FULL_INFORMATION SourcesKeyFullInfo;
  523. ULONG ReturnedSize;
  524. ULONG i;
  525. HANDLE hSourceListIndexKey = NULL;
  526. KEY_BASIC_INFORMATION *pSourcesListIndexKeyBasicInfo = NULL;
  527. ULONG KeyBasicInfoSize = 0;
  528. WCHAR *szGUID = NULL;
  529. BDLDebug(
  530. BDL_DEBUG_TRACE,
  531. ("%s %s: BDL!BDLGetSourceLists: Enter\n",
  532. __DATE__,
  533. __TIME__))
  534. *pNumSourceLists = 0;
  535. *prgSourceLists = NULL;
  536. //
  537. // Open the "Sources" key so it can be used to query all subkeys and values
  538. //
  539. status = BDLOpenSubkey(hRegKey, L"Sources", &hSourcesKey);
  540. if (status != STATUS_SUCCESS)
  541. {
  542. BDLDebug(
  543. BDL_DEBUG_ERROR,
  544. ("%s %s: BDL!BDLGetSourceLists: BDLOpenSubkey failed with %x\n",
  545. __DATE__,
  546. __TIME__,
  547. status))
  548. goto ErrorReturn;
  549. }
  550. //
  551. // Find out how many sources lists there are
  552. //
  553. status = ZwQueryKey(
  554. hSourcesKey,
  555. KeyFullInformation,
  556. &SourcesKeyFullInfo,
  557. sizeof(SourcesKeyFullInfo),
  558. &ReturnedSize);
  559. if (status != STATUS_SUCCESS)
  560. {
  561. BDLDebug(
  562. BDL_DEBUG_ERROR,
  563. ("%s %s: BDL!BDLGetSourceLists: ZwQueryKey failed with %x\n",
  564. __DATE__,
  565. __TIME__,
  566. status))
  567. goto ErrorReturn;
  568. }
  569. //
  570. // Allocate the array of sources lists
  571. //
  572. *prgSourceLists = ExAllocatePoolWithTag(
  573. PagedPool,
  574. SourcesKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL_SOURCE_LIST),
  575. BDL_ULONG_TAG);
  576. if (*prgSourceLists == NULL)
  577. {
  578. BDLDebug(
  579. BDL_DEBUG_ERROR,
  580. ("%s %s: BDL!BDLGetSourceLists: ExAllocatePoolWithTag failed\n",
  581. __DATE__,
  582. __TIME__))
  583. status = STATUS_NO_MEMORY;
  584. goto ErrorReturn;
  585. }
  586. *pNumSourceLists = SourcesKeyFullInfo.SubKeys;
  587. RtlZeroMemory(*prgSourceLists, SourcesKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL_SOURCE_LIST));
  588. //
  589. // Allocate a structure for querying key names that is large enough to hold all of them
  590. //
  591. KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + SourcesKeyFullInfo.MaxNameLen;
  592. pSourcesListIndexKeyBasicInfo = ExAllocatePoolWithTag(
  593. PagedPool,
  594. KeyBasicInfoSize + 1,
  595. BDL_ULONG_TAG);
  596. if (pSourcesListIndexKeyBasicInfo == NULL)
  597. {
  598. BDLDebug(
  599. BDL_DEBUG_ERROR,
  600. ("%s %s: BDL!BDLGetSourceLists: ExAllocatePoolWithTag failed\n",
  601. __DATE__,
  602. __TIME__))
  603. status = STATUS_NO_MEMORY;
  604. goto ErrorReturn;
  605. }
  606. //
  607. // Loop for each Source List Index SubKey and get the relevant info
  608. //
  609. for (i = 0; i < SourcesKeyFullInfo.SubKeys; i++)
  610. {
  611. //
  612. // Get the name of the <Source List Index> key
  613. //
  614. // NOTE: This code does not ensure that the key names progress from "0" to "1"
  615. // to "n". The WHQL driver validation ensures proper registry form.
  616. //
  617. status = ZwEnumerateKey(
  618. hSourcesKey,
  619. i,
  620. KeyBasicInformation,
  621. pSourcesListIndexKeyBasicInfo,
  622. KeyBasicInfoSize,
  623. &ReturnedSize);
  624. if (status != STATUS_SUCCESS)
  625. {
  626. BDLDebug(
  627. BDL_DEBUG_ERROR,
  628. ("%s %s: BDL!BDLGetSourceLists: ZwEnumerateKey failed with %x\n",
  629. __DATE__,
  630. __TIME__,
  631. status))
  632. goto ErrorReturn;
  633. }
  634. //
  635. // Open up the <Source List Index> key
  636. //
  637. status = BDLOpenSubkey(
  638. hSourcesKey,
  639. pSourcesListIndexKeyBasicInfo->Name,
  640. &hSourceListIndexKey);
  641. if (status != STATUS_SUCCESS)
  642. {
  643. BDLDebug(
  644. BDL_DEBUG_ERROR,
  645. ("%s %s: BDL!BDLGetSourceLists: BDLOpenSubkey failed with %x\n",
  646. __DATE__,
  647. __TIME__,
  648. status))
  649. goto ErrorReturn;
  650. }
  651. //
  652. // Get all the values under the key
  653. //
  654. if ((STATUS_SUCCESS != (status = BDLGetValue(
  655. hSourceListIndexKey,
  656. REG_SZ,
  657. L"Format",
  658. NULL,
  659. &szGUID))) ||
  660. (STATUS_SUCCESS != (status = BDLGetValue(
  661. hSourceListIndexKey,
  662. REG_DWORD,
  663. L"Min",
  664. &((*prgSourceLists)[i].MinSources),
  665. NULL))) ||
  666. (STATUS_SUCCESS != (status = BDLGetValue(
  667. hSourceListIndexKey,
  668. REG_DWORD,
  669. L"Max",
  670. &((*prgSourceLists)[i].MaxSources),
  671. NULL))) ||
  672. (STATUS_SUCCESS != (status = BDLGetValue(
  673. hSourceListIndexKey,
  674. REG_DWORD,
  675. L"Flags",
  676. &((*prgSourceLists)[i].Flags),
  677. NULL))))
  678. {
  679. BDLDebug(
  680. BDL_DEBUG_ERROR,
  681. ("%s %s: BDL!BDLGetSourceLists: BDLGetValue failed with %x\n",
  682. __DATE__,
  683. __TIME__,
  684. status))
  685. goto ErrorReturn;
  686. }
  687. //
  688. // Convert the Format GUID string to an actual GUID
  689. //
  690. RtlInitUnicodeString(&UnicodeString, szGUID);
  691. status = RtlGUIDFromString(&UnicodeString, &((*prgSourceLists)[i].FormatGUID));
  692. ZwClose(hSourceListIndexKey);
  693. hSourceListIndexKey = NULL;
  694. }
  695. Return:
  696. if (hSourcesKey != NULL)
  697. {
  698. ZwClose(hSourcesKey);
  699. }
  700. if (hSourceListIndexKey != NULL)
  701. {
  702. ZwClose(hSourceListIndexKey);
  703. }
  704. if (pSourcesListIndexKeyBasicInfo != NULL)
  705. {
  706. ExFreePoolWithTag(pSourcesListIndexKeyBasicInfo, BDL_ULONG_TAG);
  707. }
  708. if (szGUID != NULL)
  709. {
  710. ExFreePoolWithTag(szGUID, BDL_ULONG_TAG);
  711. }
  712. BDLDebug(
  713. BDL_DEBUG_TRACE,
  714. ("%s %s: BDL!BDLGetSourceLists: Leave\n",
  715. __DATE__,
  716. __TIME__))
  717. return (status);
  718. ErrorReturn:
  719. goto Return;
  720. }
  721. NTSTATUS
  722. BDLGetProducts
  723. (
  724. HANDLE hRegKey,
  725. ULONG *pNumProducts,
  726. BDL_PRODUCT **prgProducts
  727. )
  728. {
  729. NTSTATUS status = STATUS_SUCCESS;
  730. HANDLE hProductsKey = NULL;
  731. UNICODE_STRING UnicodeString;
  732. KEY_FULL_INFORMATION ProductsKeyFullInfo;
  733. ULONG ReturnedSize;
  734. ULONG i;
  735. HANDLE hProductIndexKey = NULL;
  736. KEY_BASIC_INFORMATION *pProductIndexKeyBasicInfo = NULL;
  737. ULONG KeyBasicInfoSize = 0;
  738. BDLDebug(
  739. BDL_DEBUG_TRACE,
  740. ("%s %s: BDL!BDLGetProducts: Enter\n",
  741. __DATE__,
  742. __TIME__))
  743. *pNumProducts = 0;
  744. *prgProducts = NULL;
  745. //
  746. // Open the "Products" key so it can be used to query all subkeys and values
  747. //
  748. status = BDLOpenSubkey(hRegKey, L"Products", &hProductsKey);
  749. if (status != STATUS_SUCCESS)
  750. {
  751. BDLDebug(
  752. BDL_DEBUG_ERROR,
  753. ("%s %s: BDL!BDLGetProducts: BDLOpenSubkey failed with %x\n",
  754. __DATE__,
  755. __TIME__,
  756. status))
  757. goto ErrorReturn;
  758. }
  759. //
  760. // Find out how many products there are
  761. //
  762. status = ZwQueryKey(
  763. hProductsKey,
  764. KeyFullInformation,
  765. &ProductsKeyFullInfo,
  766. sizeof(ProductsKeyFullInfo),
  767. &ReturnedSize);
  768. if (status != STATUS_SUCCESS)
  769. {
  770. BDLDebug(
  771. BDL_DEBUG_ERROR,
  772. ("%s %s: BDL!BDLGetProducts: ZwQueryKey failed with %x\n",
  773. __DATE__,
  774. __TIME__,
  775. status))
  776. goto ErrorReturn;
  777. }
  778. //
  779. // Allocate the array of products
  780. //
  781. *prgProducts = ExAllocatePoolWithTag(
  782. PagedPool,
  783. ProductsKeyFullInfo.SubKeys * sizeof(BDL_PRODUCT),
  784. BDL_ULONG_TAG);
  785. if (*prgProducts == NULL)
  786. {
  787. BDLDebug(
  788. BDL_DEBUG_ERROR,
  789. ("%s %s: BDL!BDLGetProducts: ExAllocatePoolWithTag failed\n",
  790. __DATE__,
  791. __TIME__))
  792. status = STATUS_NO_MEMORY;
  793. goto ErrorReturn;
  794. }
  795. *pNumProducts = ProductsKeyFullInfo.SubKeys;
  796. RtlZeroMemory(*prgProducts, ProductsKeyFullInfo.SubKeys * sizeof(BDL_PRODUCT));
  797. //
  798. // Allocate a structure for querying key names that is large enough to hold all of them
  799. //
  800. KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ProductsKeyFullInfo.MaxNameLen;
  801. pProductIndexKeyBasicInfo = ExAllocatePoolWithTag(
  802. PagedPool,
  803. KeyBasicInfoSize + 1,
  804. BDL_ULONG_TAG);
  805. if (pProductIndexKeyBasicInfo == NULL)
  806. {
  807. BDLDebug(
  808. BDL_DEBUG_ERROR,
  809. ("%s %s: BDL!BDLGetProducts: ExAllocatePoolWithTag failed\n",
  810. __DATE__,
  811. __TIME__))
  812. status = STATUS_NO_MEMORY;
  813. goto ErrorReturn;
  814. }
  815. //
  816. // Loop for each Source List Index SubKey and get the relevant info
  817. //
  818. for (i = 0; i < ProductsKeyFullInfo.SubKeys; i++)
  819. {
  820. //
  821. // Get the name of the <Product Index> key
  822. //
  823. // NOTE: This code does not ensure that the key names progress from "0" to "1"
  824. // to "n". The WHQL driver validation ensures proper registry form.
  825. //
  826. status = ZwEnumerateKey(
  827. hProductsKey,
  828. i,
  829. KeyBasicInformation,
  830. pProductIndexKeyBasicInfo,
  831. KeyBasicInfoSize,
  832. &ReturnedSize);
  833. if (status != STATUS_SUCCESS)
  834. {
  835. BDLDebug(
  836. BDL_DEBUG_ERROR,
  837. ("%s %s: BDL!BDLGetProducts: ZwEnumerateKey failed with %x\n",
  838. __DATE__,
  839. __TIME__,
  840. status))
  841. goto ErrorReturn;
  842. }
  843. //
  844. // Open up the <Product Index> key
  845. //
  846. status = BDLOpenSubkey(
  847. hProductsKey,
  848. pProductIndexKeyBasicInfo->Name,
  849. &hProductIndexKey);
  850. if (status != STATUS_SUCCESS)
  851. {
  852. BDLDebug(
  853. BDL_DEBUG_ERROR,
  854. ("%s %s: BDL!BDLGetProducts: BDLOpenSubkey failed with %x\n",
  855. __DATE__,
  856. __TIME__,
  857. status))
  858. goto ErrorReturn;
  859. }
  860. //
  861. // Get all the values under the key
  862. //
  863. if (STATUS_SUCCESS != (status = BDLGetValue(
  864. hProductIndexKey,
  865. REG_DWORD,
  866. L"Flags",
  867. &((*prgProducts)[i].Flags),
  868. NULL)))
  869. {
  870. BDLDebug(
  871. BDL_DEBUG_ERROR,
  872. ("%s %s: BDL!BDLGetProducts: BDLGetValue failed with %x\n",
  873. __DATE__,
  874. __TIME__,
  875. status))
  876. goto ErrorReturn;
  877. }
  878. ZwClose(hProductIndexKey);
  879. hProductIndexKey = NULL;
  880. }
  881. Return:
  882. if (hProductsKey != NULL)
  883. {
  884. ZwClose(hProductsKey);
  885. }
  886. if (hProductIndexKey != NULL)
  887. {
  888. ZwClose(hProductIndexKey);
  889. }
  890. if (pProductIndexKeyBasicInfo != NULL)
  891. {
  892. ExFreePoolWithTag(pProductIndexKeyBasicInfo, BDL_ULONG_TAG);
  893. }
  894. BDLDebug(
  895. BDL_DEBUG_TRACE,
  896. ("%s %s: BDL!BDLGetProducts: Leave\n",
  897. __DATE__,
  898. __TIME__))
  899. return (status);
  900. ErrorReturn:
  901. goto Return;
  902. }
  903. NTSTATUS
  904. BDLGetChannels
  905. (
  906. HANDLE hRegKey,
  907. ULONG *pNumChannels,
  908. BDL_CHANNEL **prgChannels
  909. )
  910. {
  911. NTSTATUS status = STATUS_SUCCESS;
  912. HANDLE hChannelsKey = NULL;
  913. KEY_FULL_INFORMATION ChannelsKeyFullInfo;
  914. UNICODE_STRING UnicodeString;
  915. ULONG ReturnedSize;
  916. ULONG i;
  917. HANDLE hChannelIdKey = NULL;
  918. KEY_BASIC_INFORMATION *pChannelIdKeyBasicInfo = NULL;
  919. ULONG KeyBasicInfoSize = 0;
  920. BDLDebug(
  921. BDL_DEBUG_TRACE,
  922. ("%s %s: BDL!BDLGetChannels: Enter\n",
  923. __DATE__,
  924. __TIME__))
  925. *pNumChannels = 0;
  926. *prgChannels = NULL;
  927. //
  928. // Open the "Channels" key so it can be used to query all subkeys and values
  929. //
  930. status = BDLOpenSubkey(hRegKey, L"Channels", &hChannelsKey);
  931. if (status != STATUS_SUCCESS)
  932. {
  933. BDLDebug(
  934. BDL_DEBUG_ERROR,
  935. ("%s %s: BDL!BDLGetChannels: BDLOpenSubkey failed with %x\n",
  936. __DATE__,
  937. __TIME__,
  938. status))
  939. goto ErrorReturn;
  940. }
  941. //
  942. // Find out how many controls there are
  943. //
  944. status = ZwQueryKey(
  945. hChannelsKey,
  946. KeyFullInformation,
  947. &ChannelsKeyFullInfo,
  948. sizeof(ChannelsKeyFullInfo),
  949. &ReturnedSize);
  950. if (status != STATUS_SUCCESS)
  951. {
  952. BDLDebug(
  953. BDL_DEBUG_ERROR,
  954. ("%s %s: BDL!BDLGetChannels: ZwQueryKey failed with %x\n",
  955. __DATE__,
  956. __TIME__,
  957. status))
  958. goto ErrorReturn;
  959. }
  960. //
  961. // Allocate the array of channels
  962. //
  963. *prgChannels = ExAllocatePoolWithTag(
  964. PagedPool,
  965. ChannelsKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL),
  966. BDL_ULONG_TAG);
  967. if (*prgChannels == NULL)
  968. {
  969. BDLDebug(
  970. BDL_DEBUG_ERROR,
  971. ("%s %s: BDL!BDLGetChannels: ExAllocatePoolWithTag failed\n",
  972. __DATE__,
  973. __TIME__))
  974. status = STATUS_NO_MEMORY;
  975. goto ErrorReturn;
  976. }
  977. *pNumChannels = ChannelsKeyFullInfo.SubKeys;
  978. RtlZeroMemory(*prgChannels, ChannelsKeyFullInfo.SubKeys * sizeof(BDL_CHANNEL));
  979. //
  980. // Allocate a structure for querying key names that is large enough to hold all of them
  981. //
  982. KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ChannelsKeyFullInfo.MaxNameLen;
  983. pChannelIdKeyBasicInfo = ExAllocatePoolWithTag(
  984. PagedPool,
  985. KeyBasicInfoSize + 1,
  986. BDL_ULONG_TAG);
  987. if (pChannelIdKeyBasicInfo == NULL)
  988. {
  989. BDLDebug(
  990. BDL_DEBUG_ERROR,
  991. ("%s %s: BDL!BDLGetChannels: ExAllocatePoolWithTag failed\n",
  992. __DATE__,
  993. __TIME__))
  994. status = STATUS_NO_MEMORY;
  995. goto ErrorReturn;
  996. }
  997. //
  998. // Loop for each Channel SubKey and get the relevant info
  999. //
  1000. for (i = 0; i < ChannelsKeyFullInfo.SubKeys; i++)
  1001. {
  1002. //
  1003. // Get the name on the <Channel Id> key
  1004. //
  1005. status = ZwEnumerateKey(
  1006. hChannelsKey,
  1007. i,
  1008. KeyBasicInformation,
  1009. pChannelIdKeyBasicInfo,
  1010. KeyBasicInfoSize,
  1011. &ReturnedSize);
  1012. if (status != STATUS_SUCCESS)
  1013. {
  1014. BDLDebug(
  1015. BDL_DEBUG_ERROR,
  1016. ("%s %s: BDL!BDLGetChannels: ZwEnumerateKey failed with %x\n",
  1017. __DATE__,
  1018. __TIME__,
  1019. status))
  1020. goto ErrorReturn;
  1021. }
  1022. //
  1023. // Change the <Channel ID> key string to a value
  1024. //
  1025. pChannelIdKeyBasicInfo->Name[pChannelIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0';
  1026. RtlInitUnicodeString(&UnicodeString, pChannelIdKeyBasicInfo->Name);
  1027. RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgChannels)[i].ChannelId));
  1028. //
  1029. // Open up the <Channel ID> key
  1030. //
  1031. status = BDLOpenSubkey(hChannelsKey, pChannelIdKeyBasicInfo->Name, &hChannelIdKey);
  1032. if (status != STATUS_SUCCESS)
  1033. {
  1034. BDLDebug(
  1035. BDL_DEBUG_ERROR,
  1036. ("%s %s: BDL!BDLGetChannels: BDLOpenSubkey failed with %x\n",
  1037. __DATE__,
  1038. __TIME__,
  1039. status))
  1040. goto ErrorReturn;
  1041. }
  1042. //
  1043. // Get the Cancelable value
  1044. //
  1045. status = BDLGetValue(
  1046. hChannelIdKey,
  1047. REG_DWORD,
  1048. L"Cancelable",
  1049. (ULONG *) &((*prgChannels)[i].fCancelable),
  1050. NULL);
  1051. if (status != STATUS_SUCCESS)
  1052. {
  1053. BDLDebug(
  1054. BDL_DEBUG_ERROR,
  1055. ("%s %s: BDL!BDLGetChannels: BDLGetValue failed with %x\n",
  1056. __DATE__,
  1057. __TIME__,
  1058. status))
  1059. goto ErrorReturn;
  1060. }
  1061. //
  1062. // Get the channel level controls
  1063. //
  1064. status = BDLGetControls(
  1065. hChannelIdKey,
  1066. &((*prgChannels)[i].NumControls),
  1067. &((*prgChannels)[i].rgControls));
  1068. if (status != STATUS_SUCCESS)
  1069. {
  1070. BDLDebug(
  1071. BDL_DEBUG_ERROR,
  1072. ("%s %s: BDL!BDLGetChannels: BDLGetControls failed with %x\n",
  1073. __DATE__,
  1074. __TIME__,
  1075. status))
  1076. goto ErrorReturn;
  1077. }
  1078. //
  1079. // Get the sources lists
  1080. //
  1081. status = BDLGetSourceLists(
  1082. hChannelIdKey,
  1083. &((*prgChannels)[i].NumSourceLists),
  1084. &((*prgChannels)[i].rgSourceLists));
  1085. if (status != STATUS_SUCCESS)
  1086. {
  1087. BDLDebug(
  1088. BDL_DEBUG_ERROR,
  1089. ("%s %s: BDL!BDLGetChannels: BDLGetSourceLists failed with %x\n",
  1090. __DATE__,
  1091. __TIME__,
  1092. status))
  1093. goto ErrorReturn;
  1094. }
  1095. //
  1096. // Get the products
  1097. //
  1098. status = BDLGetProducts(
  1099. hChannelIdKey,
  1100. &((*prgChannels)[i].NumProducts),
  1101. &((*prgChannels)[i].rgProducts));
  1102. if (status != STATUS_SUCCESS)
  1103. {
  1104. BDLDebug(
  1105. BDL_DEBUG_ERROR,
  1106. ("%s %s: BDL!BDLGetChannels: BDLGetProductss failed with %x\n",
  1107. __DATE__,
  1108. __TIME__,
  1109. status))
  1110. goto ErrorReturn;
  1111. }
  1112. ZwClose(hChannelIdKey);
  1113. hChannelIdKey = NULL;
  1114. }
  1115. Return:
  1116. if (hChannelsKey != NULL)
  1117. {
  1118. ZwClose(hChannelsKey);
  1119. }
  1120. if (hChannelIdKey != NULL)
  1121. {
  1122. ZwClose(hChannelIdKey);
  1123. }
  1124. if (pChannelIdKeyBasicInfo != NULL)
  1125. {
  1126. ExFreePoolWithTag(pChannelIdKeyBasicInfo, BDL_ULONG_TAG);
  1127. }
  1128. BDLDebug(
  1129. BDL_DEBUG_TRACE,
  1130. ("%s %s: BDL!BDLGetChannels: Leave\n",
  1131. __DATE__,
  1132. __TIME__))
  1133. return (status);
  1134. ErrorReturn:
  1135. goto Return;
  1136. }
  1137. NTSTATUS
  1138. BDLGetComponents
  1139. (
  1140. HANDLE hRegKey,
  1141. ULONG *pNumComponents,
  1142. BDL_COMPONENT **prgComponents
  1143. )
  1144. {
  1145. NTSTATUS status = STATUS_SUCCESS;
  1146. HANDLE hComponentsKey = NULL;
  1147. UNICODE_STRING UnicodeString;
  1148. KEY_FULL_INFORMATION ComponentsKeyFullInfo;
  1149. ULONG ReturnedSize;
  1150. ULONG i;
  1151. HANDLE hComponentIdKey = NULL;
  1152. KEY_BASIC_INFORMATION *pComponentIdKeyBasicInfo = NULL;
  1153. ULONG KeyBasicInfoSize = 0;
  1154. BDLDebug(
  1155. BDL_DEBUG_TRACE,
  1156. ("%s %s: BDL!BDLGetComponents: Enter\n",
  1157. __DATE__,
  1158. __TIME__))
  1159. *pNumComponents = 0;
  1160. *prgComponents = NULL;
  1161. //
  1162. // Open the "Components" key so it can be used to query all subkeys and values
  1163. //
  1164. status = BDLOpenSubkey(hRegKey, L"Components", &hComponentsKey);
  1165. if (status != STATUS_SUCCESS)
  1166. {
  1167. BDLDebug(
  1168. BDL_DEBUG_ERROR,
  1169. ("%s %s: BDL!BDLGetComponents: BDLOpenSubkey failed with %x\n",
  1170. __DATE__,
  1171. __TIME__,
  1172. status))
  1173. goto ErrorReturn;
  1174. }
  1175. //
  1176. // Find out how many components there are
  1177. //
  1178. status = ZwQueryKey(
  1179. hComponentsKey,
  1180. KeyFullInformation,
  1181. &ComponentsKeyFullInfo,
  1182. sizeof(ComponentsKeyFullInfo),
  1183. &ReturnedSize);
  1184. if (status != STATUS_SUCCESS)
  1185. {
  1186. BDLDebug(
  1187. BDL_DEBUG_ERROR,
  1188. ("%s %s: BDL!BDLGetComponents: ZwQueryKey failed with %x\n",
  1189. __DATE__,
  1190. __TIME__,
  1191. status))
  1192. goto ErrorReturn;
  1193. }
  1194. //
  1195. // Allocate the array of components
  1196. //
  1197. *prgComponents = ExAllocatePoolWithTag(
  1198. PagedPool,
  1199. ComponentsKeyFullInfo.SubKeys * sizeof(BDL_COMPONENT),
  1200. BDL_ULONG_TAG);
  1201. if (*prgComponents == NULL)
  1202. {
  1203. BDLDebug(
  1204. BDL_DEBUG_ERROR,
  1205. ("%s %s: BDL!BDLGetComponents: ExAllocatePoolWithTag failed\n",
  1206. __DATE__,
  1207. __TIME__))
  1208. status = STATUS_NO_MEMORY;
  1209. goto ErrorReturn;
  1210. }
  1211. *pNumComponents = ComponentsKeyFullInfo.SubKeys;
  1212. RtlZeroMemory(*prgComponents, ComponentsKeyFullInfo.SubKeys * sizeof(BDL_COMPONENT));
  1213. //
  1214. // Allocate a structure for querying key names that is large enough to hold all of them
  1215. //
  1216. KeyBasicInfoSize = sizeof(KEY_BASIC_INFORMATION) + ComponentsKeyFullInfo.MaxNameLen;
  1217. pComponentIdKeyBasicInfo = ExAllocatePoolWithTag(
  1218. PagedPool,
  1219. KeyBasicInfoSize + 1,
  1220. BDL_ULONG_TAG);
  1221. if (pComponentIdKeyBasicInfo == NULL)
  1222. {
  1223. BDLDebug(
  1224. BDL_DEBUG_ERROR,
  1225. ("%s %s: BDL!BDLGetComponents: ExAllocatePoolWithTag failed\n",
  1226. __DATE__,
  1227. __TIME__))
  1228. status = STATUS_NO_MEMORY;
  1229. goto ErrorReturn;
  1230. }
  1231. //
  1232. // Loop for each Component SubKey and get the relevant info
  1233. //
  1234. for (i = 0; i < ComponentsKeyFullInfo.SubKeys; i++)
  1235. {
  1236. //
  1237. // Get the name on the <Component Id> key
  1238. //
  1239. status = ZwEnumerateKey(
  1240. hComponentsKey,
  1241. i,
  1242. KeyBasicInformation,
  1243. pComponentIdKeyBasicInfo,
  1244. KeyBasicInfoSize,
  1245. &ReturnedSize);
  1246. if (status != STATUS_SUCCESS)
  1247. {
  1248. BDLDebug(
  1249. BDL_DEBUG_ERROR,
  1250. ("%s %s: BDL!BDLGetComponents: ZwEnumerateKey failed with %x\n",
  1251. __DATE__,
  1252. __TIME__,
  1253. status))
  1254. goto ErrorReturn;
  1255. }
  1256. //
  1257. // Change the <Component ID> key string to a value
  1258. //
  1259. pComponentIdKeyBasicInfo->Name[pComponentIdKeyBasicInfo->NameLength / sizeof(WCHAR)] = L'\0';
  1260. RtlInitUnicodeString(&UnicodeString, pComponentIdKeyBasicInfo->Name);
  1261. RtlUnicodeStringToInteger(&UnicodeString, 16, &((*prgComponents)[i].ComponentId));
  1262. //
  1263. // Open up the <Component ID> key
  1264. //
  1265. status = BDLOpenSubkey(hComponentsKey, pComponentIdKeyBasicInfo->Name, &hComponentIdKey);
  1266. if (status != STATUS_SUCCESS)
  1267. {
  1268. BDLDebug(
  1269. BDL_DEBUG_ERROR,
  1270. ("%s %s: BDL!BDLGetComponents: BDLOpenSubkey failed with %x\n",
  1271. __DATE__,
  1272. __TIME__,
  1273. status))
  1274. goto ErrorReturn;
  1275. }
  1276. //
  1277. // Get the component level controls
  1278. //
  1279. status = BDLGetControls(
  1280. hComponentIdKey,
  1281. &((*prgComponents)[i].NumControls),
  1282. &((*prgComponents)[i].rgControls));
  1283. if (status != STATUS_SUCCESS)
  1284. {
  1285. BDLDebug(
  1286. BDL_DEBUG_ERROR,
  1287. ("%s %s: BDL!BDLGetComponents: BDLGetControls failed with %x\n",
  1288. __DATE__,
  1289. __TIME__,
  1290. status))
  1291. goto ErrorReturn;
  1292. }
  1293. //
  1294. // Get the channels in this component
  1295. //
  1296. status = BDLGetChannels(
  1297. hComponentIdKey,
  1298. &((*prgComponents)[i].NumChannels),
  1299. &((*prgComponents)[i].rgChannels));
  1300. if (status != STATUS_SUCCESS)
  1301. {
  1302. BDLDebug(
  1303. BDL_DEBUG_ERROR,
  1304. ("%s %s: BDL!BDLGetComponents: BDLGetChannels failed with %x\n",
  1305. __DATE__,
  1306. __TIME__,
  1307. status))
  1308. goto ErrorReturn;
  1309. }
  1310. ZwClose(hComponentIdKey);
  1311. hComponentIdKey = NULL;
  1312. }
  1313. Return:
  1314. if (hComponentsKey != NULL)
  1315. {
  1316. ZwClose(hComponentsKey);
  1317. }
  1318. if (hComponentIdKey != NULL)
  1319. {
  1320. ZwClose(hComponentIdKey);
  1321. }
  1322. if (pComponentIdKeyBasicInfo != NULL)
  1323. {
  1324. ExFreePoolWithTag(pComponentIdKeyBasicInfo, BDL_ULONG_TAG);
  1325. }
  1326. BDLDebug(
  1327. BDL_DEBUG_TRACE,
  1328. ("%s %s: BDL!BDLGetControls: Leave\n",
  1329. __DATE__,
  1330. __TIME__))
  1331. return (status);
  1332. ErrorReturn:
  1333. goto Return;
  1334. }
  1335. NTSTATUS
  1336. BDLGetDeviceCapabilities
  1337. (
  1338. PDEVICE_OBJECT pPhysicalDeviceObject,
  1339. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension
  1340. )
  1341. {
  1342. NTSTATUS status = STATUS_SUCCESS;
  1343. LPWSTR pwszDeviceRegistryKeyName = NULL;
  1344. HANDLE hDeviceKey = NULL;
  1345. BDLDebug(
  1346. BDL_DEBUG_TRACE,
  1347. ("%s %s: BDL!BDLGetDevicesCapabilities: Enter\n",
  1348. __DATE__,
  1349. __TIME__))
  1350. //
  1351. // Build the top level registry key name
  1352. //
  1353. status = BDLBuildRegKeyPath(
  1354. pPhysicalDeviceObject,
  1355. pBDLExtension,
  1356. &pwszDeviceRegistryKeyName);
  1357. if (status != STATUS_SUCCESS)
  1358. {
  1359. BDLDebug(
  1360. BDL_DEBUG_ERROR,
  1361. ("%s %s: BDL!BDLGetDevicesCapabilities: BDLBuildRegKeyPath failed with %x\n",
  1362. __DATE__,
  1363. __TIME__,
  1364. status))
  1365. goto ErrorReturn;
  1366. }
  1367. //
  1368. // Open the top level device key so it can be used to query all subkeys and values
  1369. //
  1370. status = BDLOpenSubkey(NULL, pwszDeviceRegistryKeyName, &hDeviceKey);
  1371. if (status != STATUS_SUCCESS)
  1372. {
  1373. BDLDebug(
  1374. BDL_DEBUG_ERROR,
  1375. ("%s %s: BDL!BDLGetDevicesCapabilities: BDLOpenSubkey failed with %x\n",
  1376. __DATE__,
  1377. __TIME__,
  1378. status))
  1379. goto ErrorReturn;
  1380. }
  1381. //
  1382. // Get the device level controls
  1383. //
  1384. status = BDLGetControls(
  1385. hDeviceKey,
  1386. &(pBDLExtension->DeviceCapabilities.NumControls),
  1387. &(pBDLExtension->DeviceCapabilities.rgControls));
  1388. if (status != STATUS_SUCCESS)
  1389. {
  1390. BDLDebug(
  1391. BDL_DEBUG_ERROR,
  1392. ("%s %s: BDL!BDLGetDevicesCapabilities: BDLGetControls failed with %x\n",
  1393. __DATE__,
  1394. __TIME__,
  1395. status))
  1396. goto ErrorReturn;
  1397. }
  1398. //
  1399. // Get the components
  1400. //
  1401. status = BDLGetComponents(
  1402. hDeviceKey,
  1403. &(pBDLExtension->DeviceCapabilities.NumComponents),
  1404. &(pBDLExtension->DeviceCapabilities.rgComponents));
  1405. if (status != STATUS_SUCCESS)
  1406. {
  1407. BDLDebug(
  1408. BDL_DEBUG_ERROR,
  1409. ("%s %s: BDL!BDLGetDevicesCapabilities: BDLGetControls failed with %x\n",
  1410. __DATE__,
  1411. __TIME__,
  1412. status))
  1413. goto ErrorReturn;
  1414. }
  1415. Return:
  1416. if (pwszDeviceRegistryKeyName != NULL)
  1417. {
  1418. ExFreePoolWithTag(pwszDeviceRegistryKeyName, BDL_ULONG_TAG);
  1419. }
  1420. if (hDeviceKey != NULL)
  1421. {
  1422. ZwClose(hDeviceKey);
  1423. }
  1424. BDLDebug(
  1425. BDL_DEBUG_TRACE,
  1426. ("%s %s: BDL!BDLGetDevicesCapabilities: Leave\n",
  1427. __DATE__,
  1428. __TIME__))
  1429. return (status);
  1430. ErrorReturn:
  1431. BDLCleanupDeviceCapabilities(pBDLExtension);
  1432. goto Return;
  1433. }
  1434. VOID
  1435. BDLCleanupDeviceCapabilities
  1436. (
  1437. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension
  1438. )
  1439. {
  1440. BDL_DEVICE_CAPABILITIES *pDeviceCapabilites = &(pBDLExtension->DeviceCapabilities);
  1441. ULONG i, j;
  1442. //
  1443. // Free device level control array
  1444. //
  1445. if (pDeviceCapabilites->rgControls != NULL)
  1446. {
  1447. ExFreePoolWithTag(pDeviceCapabilites->rgControls, BDL_ULONG_TAG);
  1448. pDeviceCapabilites->rgControls = NULL;
  1449. }
  1450. //
  1451. // Free component array
  1452. //
  1453. if (pDeviceCapabilites->rgComponents != NULL)
  1454. {
  1455. //
  1456. // Free each component
  1457. //
  1458. for (i = 0; i < pDeviceCapabilites->NumComponents; i++)
  1459. {
  1460. //
  1461. // Free component level control array
  1462. //
  1463. if (pDeviceCapabilites->rgComponents[i].rgControls != NULL)
  1464. {
  1465. ExFreePoolWithTag(pDeviceCapabilites->rgComponents[i].rgControls, BDL_ULONG_TAG);
  1466. }
  1467. //
  1468. // Free channel array
  1469. //
  1470. if (pDeviceCapabilites->rgComponents[i].rgChannels != NULL)
  1471. {
  1472. //
  1473. // Free each channel
  1474. //
  1475. for (j = 0; j < pDeviceCapabilites->rgComponents[i].NumChannels; j++)
  1476. {
  1477. //
  1478. // Free channel level controls, source lists, and products
  1479. //
  1480. if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgControls != NULL)
  1481. {
  1482. ExFreePoolWithTag(
  1483. pDeviceCapabilites->rgComponents[i].rgChannels[j].rgControls,
  1484. BDL_ULONG_TAG);
  1485. }
  1486. if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgSourceLists != NULL)
  1487. {
  1488. ExFreePoolWithTag(
  1489. pDeviceCapabilites->rgComponents[i].rgChannels[j].rgSourceLists,
  1490. BDL_ULONG_TAG);
  1491. }
  1492. if (pDeviceCapabilites->rgComponents[i].rgChannels[j].rgProducts != NULL)
  1493. {
  1494. ExFreePoolWithTag(
  1495. pDeviceCapabilites->rgComponents[i].rgChannels[j].rgProducts,
  1496. BDL_ULONG_TAG);
  1497. }
  1498. }
  1499. ExFreePoolWithTag(pDeviceCapabilites->rgComponents[i].rgChannels, BDL_ULONG_TAG);
  1500. }
  1501. }
  1502. ExFreePoolWithTag(pDeviceCapabilites->rgComponents, BDL_ULONG_TAG);
  1503. pDeviceCapabilites->rgComponents = NULL;
  1504. }
  1505. }