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.

2380 lines
72 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 <winerror.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <strsafe.h>
  19. #include <wdm.h>
  20. #include "bdlint.h"
  21. #define PRODUCT_NOT_REQUESTED 0
  22. #define PRODUCT_HANDLE_REQUESTED 1
  23. #define PRODUCT_BLOCK_REQUESTED 2
  24. NTSTATUS
  25. BDLRegisteredCancelGetNotificationIRP
  26. (
  27. IN PDEVICE_OBJECT pDeviceObject,
  28. IN PIRP pIrp
  29. );
  30. //
  31. // Supporting functions for checking ID's
  32. //
  33. //
  34. BOOLEAN
  35. BDLCheckComponentId
  36. (
  37. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  38. IN ULONG ComponentId,
  39. OUT ULONG *pComponentIndex
  40. )
  41. {
  42. ULONG i;
  43. for (i = 0; i < pBDLExtension->DeviceCapabilities.NumComponents; i++)
  44. {
  45. if (pBDLExtension->DeviceCapabilities.rgComponents[i].ComponentId == ComponentId)
  46. {
  47. break;
  48. }
  49. }
  50. if (i >= pBDLExtension->DeviceCapabilities.NumComponents)
  51. {
  52. return (FALSE);
  53. }
  54. *pComponentIndex = i;
  55. return (TRUE);
  56. }
  57. BOOLEAN
  58. BDLCheckChannelId
  59. (
  60. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  61. IN ULONG ComponentIndex,
  62. IN ULONG ChannelId,
  63. OUT ULONG *pChannelIndex
  64. )
  65. {
  66. ULONG i;
  67. for (i = 0;
  68. i < pBDLExtension->DeviceCapabilities.rgComponents[ComponentIndex].NumChannels;
  69. i++)
  70. {
  71. if (pBDLExtension->DeviceCapabilities.rgComponents[ComponentIndex].rgChannels[i].ChannelId ==
  72. ChannelId)
  73. {
  74. break;
  75. }
  76. }
  77. if (i >= pBDLExtension->DeviceCapabilities.rgComponents[ComponentIndex].NumChannels)
  78. {
  79. return (FALSE);
  80. }
  81. *pChannelIndex = i;
  82. return (TRUE);
  83. }
  84. BOOLEAN
  85. BDLCheckControlIdInArray
  86. (
  87. IN BDL_CONTROL *rgControls,
  88. IN ULONG NumControls,
  89. IN ULONG ControlId,
  90. OUT BDL_CONTROL **ppBDLControl
  91. )
  92. {
  93. ULONG i;
  94. for (i = 0; i < NumControls; i++)
  95. {
  96. if (rgControls[i].ControlId == ControlId)
  97. {
  98. break;
  99. }
  100. }
  101. if (i >= NumControls)
  102. {
  103. return (FALSE);
  104. }
  105. *ppBDLControl = &(rgControls[i]);
  106. return (TRUE);
  107. }
  108. BOOLEAN
  109. BDLCheckControlId
  110. (
  111. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  112. IN ULONG ComponentId,
  113. IN ULONG ChannelId,
  114. IN ULONG ControlId,
  115. OUT BDL_CONTROL **ppBDLControl
  116. )
  117. {
  118. ULONG i, j;
  119. *ppBDLControl = NULL;
  120. //
  121. // If ComponentId is 0 then it is a device level control
  122. //
  123. if (ComponentId == 0)
  124. {
  125. //
  126. // Check device level control ID
  127. //
  128. if (BDLCheckControlIdInArray(
  129. pBDLExtension->DeviceCapabilities.rgControls,
  130. pBDLExtension->DeviceCapabilities.NumControls,
  131. ControlId,
  132. ppBDLControl) == FALSE)
  133. {
  134. BDLDebug(
  135. BDL_DEBUG_ERROR,
  136. ("%s %s: BDL!BDLCheckControlId: Bad Device level ControlId\n",
  137. __DATE__,
  138. __TIME__))
  139. return (FALSE);
  140. }
  141. }
  142. else
  143. {
  144. //
  145. // Check the ComponentId
  146. //
  147. if (BDLCheckComponentId(pBDLExtension, ComponentId, &i) == FALSE)
  148. {
  149. BDLDebug(
  150. BDL_DEBUG_ERROR,
  151. ("%s %s: BDL!BDLCheckControlId: Bad ComponentId\n",
  152. __DATE__,
  153. __TIME__))
  154. return (FALSE);
  155. }
  156. if (ChannelId == 0)
  157. {
  158. //
  159. // Check Component level control ID
  160. //
  161. if (BDLCheckControlIdInArray(
  162. pBDLExtension->DeviceCapabilities.rgComponents[i].rgControls,
  163. pBDLExtension->DeviceCapabilities.rgComponents[i].NumControls,
  164. ControlId,
  165. ppBDLControl) == FALSE)
  166. {
  167. BDLDebug(
  168. BDL_DEBUG_ERROR,
  169. ("%s %s: BDL!BDLCheckControlId: Bad Component level ControlId\n",
  170. __DATE__,
  171. __TIME__))
  172. return (FALSE);
  173. }
  174. }
  175. else
  176. {
  177. //
  178. // Check channel ID
  179. //
  180. if (BDLCheckChannelId(pBDLExtension, i, ChannelId, &j) == FALSE)
  181. {
  182. BDLDebug(
  183. BDL_DEBUG_ERROR,
  184. ("%s %s: BDL!BDLCheckControlId: Bad ChannelId\n",
  185. __DATE__,
  186. __TIME__))
  187. return (FALSE);
  188. }
  189. //
  190. // Check channel level control ID
  191. //
  192. if (BDLCheckControlIdInArray(
  193. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].rgControls,
  194. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].NumControls,
  195. ControlId,
  196. ppBDLControl) == FALSE)
  197. {
  198. BDLDebug(
  199. BDL_DEBUG_ERROR,
  200. ("%s %s: BDL!BDLCheckControlId: Bad channel level ControlId\n",
  201. __DATE__,
  202. __TIME__))
  203. return (FALSE);
  204. }
  205. }
  206. }
  207. return (TRUE);
  208. }
  209. NTSTATUS
  210. BDLIOCTL_Startup
  211. (
  212. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  213. IN ULONG InpuBufferLength,
  214. IN ULONG OutputBufferLength,
  215. IN PVOID pBuffer,
  216. OUT ULONG *pOutputBufferUsed
  217. )
  218. {
  219. NTSTATUS status = STATUS_SUCCESS;
  220. BDLDebug(
  221. BDL_DEBUG_TRACE,
  222. ("%s %s: BDL!BDLIOCTL_Startup: Enter\n",
  223. __DATE__,
  224. __TIME__))
  225. //
  226. // Call the BDD
  227. //
  228. status = pBDLExtension->pDriverExtension->bdsiFunctions.pfbdsiStartup(
  229. &(pBDLExtension->BdlExtenstion));
  230. if (status != STATUS_SUCCESS)
  231. {
  232. BDLDebug(
  233. BDL_DEBUG_ERROR,
  234. ("%s %s: BDL!BDLIOCTL_Startup: pfbdsiStartup failed with %lx\n",
  235. __DATE__,
  236. __TIME__,
  237. status))
  238. }
  239. //
  240. // Set the number of bytes used
  241. //
  242. *pOutputBufferUsed = 0;
  243. BDLDebug(
  244. BDL_DEBUG_TRACE,
  245. ("%s %s: BDL!BDLIOCTL_Startup: Leave\n",
  246. __DATE__,
  247. __TIME__))
  248. return (status);
  249. }
  250. NTSTATUS
  251. BDLIOCTL_Shutdown
  252. (
  253. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  254. IN ULONG InpuBufferLength,
  255. IN ULONG OutputBufferLength,
  256. IN PVOID pBuffer,
  257. OUT ULONG *pOutputBufferUsed
  258. )
  259. {
  260. NTSTATUS status = STATUS_SUCCESS;
  261. BDLDebug(
  262. BDL_DEBUG_TRACE,
  263. ("%s %s: BDL!BDLIOCTL_Shutdown: Enter\n",
  264. __DATE__,
  265. __TIME__))
  266. //
  267. // Call the BDD
  268. //
  269. status = pBDLExtension->pDriverExtension->bdsiFunctions.pfbdsiShutdown(
  270. &(pBDLExtension->BdlExtenstion));
  271. if (status != STATUS_SUCCESS)
  272. {
  273. BDLDebug(
  274. BDL_DEBUG_ERROR,
  275. ("%s %s: BDL!BDLIOCTL_Shutdown: pfbdsiShutdown failed with %lx\n",
  276. __DATE__,
  277. __TIME__,
  278. status))
  279. }
  280. //
  281. // Set the number of bytes used
  282. //
  283. *pOutputBufferUsed = 0;
  284. BDLDebug(
  285. BDL_DEBUG_TRACE,
  286. ("%s %s: BDL!BDLIOCTL_Shutdown: Leave\n",
  287. __DATE__,
  288. __TIME__))
  289. return (status);
  290. }
  291. NTSTATUS
  292. BDLIOCTL_GetDeviceInfo
  293. (
  294. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  295. IN ULONG InpuBufferLength,
  296. IN ULONG OutputBufferLength,
  297. IN PVOID pBuffer,
  298. OUT ULONG *pOutputBufferUsed
  299. )
  300. {
  301. NTSTATUS status = STATUS_SUCCESS;
  302. ULONG RequiredOutputSize = 0;
  303. PUCHAR pv = pBuffer;
  304. BDLDebug(
  305. BDL_DEBUG_TRACE,
  306. ("%s %s: BDL!BDLIOCTL_GetDeviceInfo: Enter\n",
  307. __DATE__,
  308. __TIME__))
  309. //
  310. // Make sure there is enough space for the return buffer
  311. //
  312. RequiredOutputSize = SIZEOF_GETDEVICEINFO_OUTPUTBUFFER;
  313. if (RequiredOutputSize > OutputBufferLength)
  314. {
  315. BDLDebug(
  316. BDL_DEBUG_ERROR,
  317. ("%s %s: BDL!BDLIOCTL_GetDeviceInfo: Output buffer is too small\n",
  318. __DATE__,
  319. __TIME__))
  320. status = STATUS_BUFFER_TOO_SMALL;
  321. goto Return;
  322. }
  323. //
  324. // Write the device info to the output buffer
  325. //
  326. pv = pBuffer;
  327. RtlCopyMemory(
  328. pv,
  329. &(pBDLExtension->wszSerialNumber[0]),
  330. sizeof(pBDLExtension->wszSerialNumber));
  331. pv += sizeof(pBDLExtension->wszSerialNumber);
  332. *((ULONG *) pv) = pBDLExtension->HWVersionMajor;
  333. pv += sizeof(ULONG);
  334. *((ULONG *) pv) = pBDLExtension->HWVersionMinor;
  335. pv += sizeof(ULONG);
  336. *((ULONG *) pv) = pBDLExtension->HWBuildNumber;
  337. pv += sizeof(ULONG);
  338. *((ULONG *) pv) = pBDLExtension->BDDVersionMajor;
  339. pv += sizeof(ULONG);
  340. *((ULONG *) pv) = pBDLExtension->BDDVersionMinor;
  341. pv += sizeof(ULONG);
  342. *((ULONG *) pv) = pBDLExtension->BDDBuildNumber;
  343. //
  344. // Set the number of bytes used
  345. //
  346. *pOutputBufferUsed = RequiredOutputSize;
  347. Return:
  348. BDLDebug(
  349. BDL_DEBUG_TRACE,
  350. ("%s %s: BDL!BDLIOCTL_GetDeviceInfo: Leave\n",
  351. __DATE__,
  352. __TIME__))
  353. return (status);
  354. }
  355. NTSTATUS
  356. BDLIOCTL_DoChannel
  357. (
  358. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  359. IN ULONG InpuBufferLength,
  360. IN ULONG OutputBufferLength,
  361. IN PVOID pBuffer,
  362. OUT ULONG *pOutputBufferUsed
  363. )
  364. {
  365. NTSTATUS status = STATUS_SUCCESS;
  366. ULONG NumProducts = 0;
  367. ULONG NumSourceLists = 0;
  368. ULONG NumSources = 0;
  369. PUCHAR pv = pBuffer;
  370. BDDI_PARAMS_DOCHANNEL bddiDoChannelParams;
  371. ULONG i, j, x, y;
  372. ULONG ProductCreationType;
  373. ULONG RequiredInputSize = 0;
  374. ULONG RequiredOutputSize = 0;
  375. HANDLE hCancelEvent = NULL;
  376. KIRQL irql;
  377. BOOLEAN fHandleListLocked = FALSE;
  378. BDDI_PARAMS_CLOSEHANDLE bddiCloseHandleParams;
  379. BDLDebug(
  380. BDL_DEBUG_TRACE,
  381. ("%s %s: BDL!BDLIOCTL_DoChannel: Enter\n",
  382. __DATE__,
  383. __TIME__))
  384. //
  385. // Initialize the DoChannelParams struct
  386. //
  387. RtlZeroMemory(&bddiDoChannelParams, sizeof(bddiDoChannelParams));
  388. bddiDoChannelParams.Size = sizeof(bddiDoChannelParams);
  389. //
  390. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  391. // spec for details)
  392. //
  393. RequiredInputSize = SIZEOF_DOCHANNEL_INPUTBUFFER;
  394. if (InpuBufferLength < RequiredInputSize)
  395. {
  396. BDLDebug(
  397. BDL_DEBUG_ERROR,
  398. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad input buffer\n",
  399. __DATE__,
  400. __TIME__))
  401. status = STATUS_INVALID_PARAMETER;
  402. goto ErrorReturn;
  403. }
  404. //
  405. // Get all of the minimum input parameters (put the ones that are used
  406. // in the DoChannel call directly into the DoChannelParams struct
  407. //
  408. bddiDoChannelParams.ComponentId = *((ULONG *) pv);
  409. pv += sizeof(ULONG);
  410. bddiDoChannelParams.ChannelId = *((ULONG *) pv);
  411. pv += sizeof(ULONG);
  412. hCancelEvent = *((HANDLE *) pv);
  413. pv += sizeof(HANDLE);
  414. bddiDoChannelParams.hStateData = *((BDD_DATA_HANDLE *) pv);
  415. pv += sizeof(BDD_DATA_HANDLE);
  416. NumProducts = *((ULONG *) pv);
  417. pv += sizeof(ULONG);
  418. NumSourceLists = *((ULONG *) pv);
  419. pv += sizeof(ULONG);
  420. //
  421. // Check the size of the input buffer to make sure it is large enough
  422. // so that we don't run off the end when getting the products array and
  423. // sources lists array
  424. //
  425. // Note that this only checks based on each source list being 0 length,
  426. // so we need to check again before getting each source list.
  427. //
  428. RequiredInputSize += (NumProducts * sizeof(ULONG)) + (NumSourceLists * sizeof(ULONG));
  429. if (InpuBufferLength < RequiredInputSize)
  430. {
  431. BDLDebug(
  432. BDL_DEBUG_ERROR,
  433. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad input buffer\n",
  434. __DATE__,
  435. __TIME__))
  436. status = STATUS_INVALID_PARAMETER;
  437. goto ErrorReturn;
  438. }
  439. //
  440. // Check the size of the output buffer to make sure it is large enough
  441. // to accommodate the standard output + all the products
  442. //
  443. RequiredOutputSize = SIZEOF_DOCHANNEL_OUTPUTBUFFER + (sizeof(BDD_HANDLE) * NumProducts);
  444. if (OutputBufferLength < RequiredOutputSize)
  445. {
  446. BDLDebug(
  447. BDL_DEBUG_ERROR,
  448. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad input buffer\n",
  449. __DATE__,
  450. __TIME__))
  451. status = STATUS_BUFFER_TOO_SMALL;
  452. goto ErrorReturn;
  453. }
  454. //
  455. // Check the ComponentId and ChannelId
  456. //
  457. if (BDLCheckComponentId(pBDLExtension, bddiDoChannelParams.ComponentId, &i) == FALSE)
  458. {
  459. BDLDebug(
  460. BDL_DEBUG_ERROR,
  461. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad ComponentId\n",
  462. __DATE__,
  463. __TIME__))
  464. status = STATUS_INVALID_PARAMETER;
  465. goto ErrorReturn;
  466. }
  467. if (BDLCheckChannelId(pBDLExtension, i, bddiDoChannelParams.ChannelId, &j) == FALSE)
  468. {
  469. BDLDebug(
  470. BDL_DEBUG_ERROR,
  471. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad ChannelId\n",
  472. __DATE__,
  473. __TIME__))
  474. status = STATUS_INVALID_PARAMETER;
  475. goto ErrorReturn;
  476. }
  477. //
  478. // Check to make sure the NumProducts and NumSourceLists are correct
  479. //
  480. if (NumProducts !=
  481. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].NumProducts)
  482. {
  483. BDLDebug(
  484. BDL_DEBUG_ERROR,
  485. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad number of Source Lists\n",
  486. __DATE__,
  487. __TIME__))
  488. status = STATUS_INVALID_PARAMETER;
  489. goto ErrorReturn;
  490. }
  491. if (NumSourceLists !=
  492. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].NumSourceLists)
  493. {
  494. BDLDebug(
  495. BDL_DEBUG_ERROR,
  496. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad number of Source Lists\n",
  497. __DATE__,
  498. __TIME__))
  499. status = STATUS_INVALID_PARAMETER;
  500. goto ErrorReturn;
  501. }
  502. //
  503. // Allocate the space for the product pointer array then get each product
  504. // request type from the input block
  505. //
  506. bddiDoChannelParams.rgpProducts = ExAllocatePoolWithTag(
  507. PagedPool,
  508. sizeof(PBDDI_ITEM) * NumProducts,
  509. BDL_ULONG_TAG);
  510. RtlZeroMemory(bddiDoChannelParams.rgpProducts, sizeof(PBDDI_ITEM) * NumProducts);
  511. for (x = 0; x < NumProducts; x++)
  512. {
  513. ProductCreationType = *((ULONG *) pv);
  514. pv += sizeof(ULONG);
  515. switch (ProductCreationType)
  516. {
  517. case PRODUCT_NOT_REQUESTED:
  518. bddiDoChannelParams.rgpProducts[x] = NULL;
  519. break;
  520. case PRODUCT_HANDLE_REQUESTED:
  521. //
  522. // Make sure the channel supports handle type return
  523. //
  524. if (!(BIO_ITEMTYPE_HANDLE &
  525. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].rgProducts[x].Flags))
  526. {
  527. BDLDebug(
  528. BDL_DEBUG_ERROR,
  529. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad product type request\n",
  530. __DATE__,
  531. __TIME__))
  532. status = STATUS_INVALID_PARAMETER;
  533. goto ErrorReturn;
  534. }
  535. bddiDoChannelParams.rgpProducts[x] = ExAllocatePoolWithTag(
  536. PagedPool,
  537. sizeof(BDDI_ITEM),
  538. BDL_ULONG_TAG);
  539. if (bddiDoChannelParams.rgpProducts[x] == NULL)
  540. {
  541. BDLDebug(
  542. BDL_DEBUG_ERROR,
  543. ("%s %s: BDL!BDLIOCTL_DoChannel:ExAllocatePoolWithTag failed\n",
  544. __DATE__,
  545. __TIME__))
  546. status = STATUS_NO_MEMORY;
  547. goto ErrorReturn;
  548. }
  549. bddiDoChannelParams.rgpProducts[x]->Type = BIO_ITEMTYPE_HANDLE;
  550. bddiDoChannelParams.rgpProducts[x]->Data.Handle = NULL;
  551. break;
  552. case PRODUCT_BLOCK_REQUESTED:
  553. //
  554. // Make sure the channel supports handle type return
  555. //
  556. if (!(BIO_ITEMTYPE_BLOCK &
  557. pBDLExtension->DeviceCapabilities.rgComponents[i].rgChannels[j].rgProducts[x].Flags))
  558. {
  559. BDLDebug(
  560. BDL_DEBUG_ERROR,
  561. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad product type request\n",
  562. __DATE__,
  563. __TIME__))
  564. status = STATUS_INVALID_PARAMETER;
  565. goto ErrorReturn;
  566. }
  567. bddiDoChannelParams.rgpProducts[x] = ExAllocatePoolWithTag(
  568. PagedPool,
  569. sizeof(BDDI_ITEM),
  570. BDL_ULONG_TAG);
  571. if (bddiDoChannelParams.rgpProducts[x] == NULL)
  572. {
  573. BDLDebug(
  574. BDL_DEBUG_ERROR,
  575. ("%s %s: BDL!BDLIOCTL_DoChannel:ExAllocatePoolWithTag failed\n",
  576. __DATE__,
  577. __TIME__))
  578. status = STATUS_NO_MEMORY;
  579. goto ErrorReturn;
  580. }
  581. bddiDoChannelParams.rgpProducts[x]->Type = BIO_ITEMTYPE_BLOCK;
  582. bddiDoChannelParams.rgpProducts[x]->Data.Block.pBuffer = NULL;
  583. bddiDoChannelParams.rgpProducts[x]->Data.Block.cBuffer = 0;
  584. break;
  585. default:
  586. BDLDebug(
  587. BDL_DEBUG_ERROR,
  588. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad Product Request\n",
  589. __DATE__,
  590. __TIME__))
  591. status = STATUS_INVALID_PARAMETER;
  592. goto ErrorReturn;
  593. break;
  594. }
  595. }
  596. //
  597. // Allocate space for the source lists
  598. //
  599. bddiDoChannelParams.rgSourceLists = ExAllocatePoolWithTag(
  600. PagedPool,
  601. sizeof(BDDI_SOURCELIST) * NumSourceLists,
  602. BDL_ULONG_TAG);
  603. RtlZeroMemory(bddiDoChannelParams.rgSourceLists, sizeof(BDDI_SOURCELIST) * NumSourceLists);
  604. //
  605. // We are going to start messing with the handle list, so lock it
  606. //
  607. BDLLockHandleList(pBDLExtension, &irql);
  608. fHandleListLocked = TRUE;
  609. //
  610. // Get each source list from input buffer
  611. //
  612. for (x = 0; x < NumSourceLists; x++)
  613. {
  614. NumSources = *((ULONG *) pv);
  615. pv += sizeof(ULONG);
  616. //
  617. // Check the size of the input buffer to make sure it is large enough
  618. // so that we don't run off the end when getting this source lists
  619. //
  620. RequiredInputSize += NumSources * sizeof(BDD_HANDLE);
  621. if (InpuBufferLength < RequiredInputSize)
  622. {
  623. BDLDebug(
  624. BDL_DEBUG_ERROR,
  625. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad input buffer\n",
  626. __DATE__,
  627. __TIME__))
  628. status = STATUS_INVALID_PARAMETER;
  629. goto ErrorReturn;
  630. }
  631. //
  632. // Allocate the array of sources and then get each source in the list
  633. //
  634. bddiDoChannelParams.rgSourceLists[x].rgpSources = ExAllocatePoolWithTag(
  635. PagedPool,
  636. sizeof(PBDDI_ITEM) * NumSources,
  637. BDL_ULONG_TAG);
  638. if (bddiDoChannelParams.rgpProducts[x] == NULL)
  639. {
  640. BDLDebug(
  641. BDL_DEBUG_ERROR,
  642. ("%s %s: BDL!BDLIOCTL_DoChannel:ExAllocatePoolWithTag failed\n",
  643. __DATE__,
  644. __TIME__))
  645. status = STATUS_NO_MEMORY;
  646. goto ErrorReturn;
  647. }
  648. bddiDoChannelParams.rgSourceLists[x].NumSources = NumSources;
  649. for (y = 0; y < NumSources; y++)
  650. {
  651. bddiDoChannelParams.rgSourceLists[x].rgpSources[y] = *((BDD_HANDLE *) pv);
  652. pv += sizeof(BDD_HANDLE);
  653. if (BDLValidateHandleIsInList(
  654. &(pBDLExtension->HandleList),
  655. bddiDoChannelParams.rgSourceLists[x].rgpSources[y]) == FALSE)
  656. {
  657. BDLDebug(
  658. BDL_DEBUG_ERROR,
  659. ("%s %s: BDL!BDLIOCTL_DoChannel: Bad input handle\n",
  660. __DATE__,
  661. __TIME__))
  662. status = STATUS_INVALID_PARAMETER;
  663. goto ErrorReturn;
  664. }
  665. }
  666. }
  667. //
  668. // If there is a cancel event then get the kernel mode event pointer
  669. // from the user mode event handle
  670. //
  671. if (hCancelEvent != NULL)
  672. {
  673. status = ObReferenceObjectByHandle(
  674. hCancelEvent,
  675. EVENT_QUERY_STATE | EVENT_MODIFY_STATE,
  676. NULL,
  677. KernelMode,
  678. &(bddiDoChannelParams.CancelEvent),
  679. NULL);
  680. if (status != STATUS_SUCCESS)
  681. {
  682. BDLDebug(
  683. BDL_DEBUG_ERROR,
  684. ("%s %s: BDL!BDLIOCTL_DoChannel: ObReferenceObjectByHandle failed with %lx\n",
  685. __DATE__,
  686. __TIME__,
  687. status))
  688. goto ErrorReturn;
  689. }
  690. }
  691. //
  692. // Call the BDD
  693. //
  694. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiDoChannel(
  695. &(pBDLExtension->BdlExtenstion),
  696. &bddiDoChannelParams);
  697. if (status != STATUS_SUCCESS)
  698. {
  699. BDLDebug(
  700. BDL_DEBUG_ERROR,
  701. ("%s %s: BDL!BDLIOCTL_DoChannel: pfbddiDoChannel failed with %lx\n",
  702. __DATE__,
  703. __TIME__,
  704. status))
  705. goto ErrorReturn;
  706. }
  707. //
  708. // Write the output data to the output buffer
  709. //
  710. pv = pBuffer;
  711. *((ULONG *) pv) = bddiDoChannelParams.BIOReturnCode;
  712. pv += sizeof(ULONG);
  713. *((BDD_DATA_HANDLE *) pv) = bddiDoChannelParams.hStateData;
  714. pv += sizeof(BDD_DATA_HANDLE);
  715. //
  716. // Add all the product handles to the output buffer and to the handle list
  717. //
  718. for (x = 0; x < NumProducts; x++)
  719. {
  720. *((BDD_HANDLE *) pv) = bddiDoChannelParams.rgpProducts[x];
  721. pv += sizeof(BDD_HANDLE);
  722. if (bddiDoChannelParams.rgpProducts[x] != NULL)
  723. {
  724. status = BDLAddHandleToList(
  725. &(pBDLExtension->HandleList),
  726. bddiDoChannelParams.rgpProducts[x]);
  727. if (status != STATUS_SUCCESS)
  728. {
  729. //
  730. // Remove the handles that were already added to the handle list
  731. //
  732. for (y = 0; y < x; y++)
  733. {
  734. BDLRemoveHandleFromList(
  735. &(pBDLExtension->HandleList),
  736. bddiDoChannelParams.rgpProducts[y]);
  737. }
  738. BDLDebug(
  739. BDL_DEBUG_ERROR,
  740. ("%s %s: BDL!BDLIOCTL_DoChannel: BDLAddHandleToList failed with %lx\n",
  741. __DATE__,
  742. __TIME__,
  743. status))
  744. goto ErrorReturn;
  745. }
  746. }
  747. }
  748. *pOutputBufferUsed = RequiredOutputSize;
  749. Return:
  750. if (fHandleListLocked == TRUE)
  751. {
  752. BDLReleaseHandleList(pBDLExtension, irql);
  753. }
  754. if (bddiDoChannelParams.rgpProducts != NULL)
  755. {
  756. ExFreePoolWithTag(bddiDoChannelParams.rgpProducts, BDL_ULONG_TAG);
  757. }
  758. if (bddiDoChannelParams.rgSourceLists != NULL)
  759. {
  760. for (x = 0; x < NumSourceLists; x++)
  761. {
  762. if (bddiDoChannelParams.rgSourceLists[x].rgpSources != NULL)
  763. {
  764. ExFreePoolWithTag(bddiDoChannelParams.rgSourceLists[x].rgpSources, BDL_ULONG_TAG);
  765. }
  766. }
  767. ExFreePoolWithTag(bddiDoChannelParams.rgSourceLists, BDL_ULONG_TAG);
  768. }
  769. if (bddiDoChannelParams.CancelEvent != NULL)
  770. {
  771. ObDereferenceObject(bddiDoChannelParams.CancelEvent);
  772. }
  773. BDLDebug(
  774. BDL_DEBUG_TRACE,
  775. ("%s %s: BDL!BDLIOCTL_DoChannel: Leave\n",
  776. __DATE__,
  777. __TIME__))
  778. return (status);
  779. ErrorReturn:
  780. for (x = 0; x < NumProducts; x++)
  781. {
  782. if (bddiDoChannelParams.rgpProducts[x] != NULL)
  783. {
  784. if (bddiDoChannelParams.rgpProducts[x]->Type == BIO_ITEMTYPE_HANDLE)
  785. {
  786. if (bddiDoChannelParams.rgpProducts[x]->Data.Handle != NULL)
  787. {
  788. bddiCloseHandleParams.Size = sizeof(bddiCloseHandleParams);
  789. bddiCloseHandleParams.hData = bddiDoChannelParams.rgpProducts[x]->Data.Handle;
  790. pBDLExtension->pDriverExtension->bddiFunctions.pfbddiCloseHandle(
  791. &(pBDLExtension->BdlExtenstion),
  792. &bddiCloseHandleParams);
  793. }
  794. }
  795. else
  796. {
  797. if (bddiDoChannelParams.rgpProducts[x]->Data.Block.pBuffer != NULL)
  798. {
  799. bdliFree(bddiDoChannelParams.rgpProducts[x]->Data.Block.pBuffer);
  800. }
  801. }
  802. ExFreePoolWithTag(bddiDoChannelParams.rgpProducts[x], BDL_ULONG_TAG);
  803. }
  804. }
  805. goto Return;
  806. }
  807. NTSTATUS
  808. BDLIOCTL_GetControl
  809. (
  810. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  811. IN ULONG InpuBufferLength,
  812. IN ULONG OutputBufferLength,
  813. IN PVOID pBuffer,
  814. OUT ULONG *pOutputBufferUsed
  815. )
  816. {
  817. NTSTATUS status = STATUS_SUCCESS;
  818. ULONG RequiredOutputSize = 0;
  819. BDDI_PARAMS_GETCONTROL bddiGetControlParams;
  820. PUCHAR pv = pBuffer;
  821. ULONG i, j;
  822. BDL_CONTROL *pBDLControl = NULL;
  823. BDLDebug(
  824. BDL_DEBUG_TRACE,
  825. ("%s %s: BDL!BDLIOCTL_GetControl: Enter\n",
  826. __DATE__,
  827. __TIME__))
  828. //
  829. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  830. // spec for details)
  831. //
  832. if (InpuBufferLength < SIZEOF_GETCONTROL_INPUTBUFFER)
  833. {
  834. BDLDebug(
  835. BDL_DEBUG_ERROR,
  836. ("%s %s: BDL!BDLIOCTL_GetControl: Bad input buffer size\n",
  837. __DATE__,
  838. __TIME__))
  839. status = STATUS_INVALID_PARAMETER;
  840. goto Return;
  841. }
  842. //
  843. // Make sure there is enough space for the return buffer
  844. //
  845. RequiredOutputSize = SIZEOF_GETCONTROL_OUTPUTBUFFER;
  846. if (RequiredOutputSize > OutputBufferLength)
  847. {
  848. BDLDebug(
  849. BDL_DEBUG_ERROR,
  850. ("%s %s: BDL!BDLIOCTL_GetControl: Output buffer is too small\n",
  851. __DATE__,
  852. __TIME__))
  853. status = STATUS_BUFFER_TOO_SMALL;
  854. goto Return;
  855. }
  856. //
  857. // Initialize the BDD struct
  858. //
  859. RtlZeroMemory(&bddiGetControlParams, sizeof(bddiGetControlParams));
  860. bddiGetControlParams.Size = sizeof(bddiGetControlParams);
  861. //
  862. // Get the input parameters from the buffer
  863. //
  864. bddiGetControlParams.ComponentId = *((ULONG *) pv);
  865. pv += sizeof(ULONG);
  866. bddiGetControlParams.ChannelId = *((ULONG *) pv);
  867. pv += sizeof(ULONG);
  868. bddiGetControlParams.ControlId = *((ULONG *) pv);
  869. //
  870. // Check control ID
  871. //
  872. if (BDLCheckControlId(
  873. pBDLExtension,
  874. bddiGetControlParams.ComponentId,
  875. bddiGetControlParams.ChannelId,
  876. bddiGetControlParams.ControlId,
  877. &pBDLControl) == FALSE)
  878. {
  879. BDLDebug(
  880. BDL_DEBUG_ERROR,
  881. ("%s %s: BDL!BDLIOCTL_GetControl: Bad ControlId\n",
  882. __DATE__,
  883. __TIME__))
  884. status = STATUS_INVALID_PARAMETER;
  885. goto Return;
  886. }
  887. //
  888. // Call the BDD
  889. //
  890. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiGetControl(
  891. &(pBDLExtension->BdlExtenstion),
  892. &bddiGetControlParams);
  893. if (status != STATUS_SUCCESS)
  894. {
  895. BDLDebug(
  896. BDL_DEBUG_ERROR,
  897. ("%s %s: BDL!BDLIOCTL_GetControl: pfbddiGetControl failed with %lx\n",
  898. __DATE__,
  899. __TIME__,
  900. status))
  901. goto Return;
  902. }
  903. //
  904. // Write the output info to the output buffer
  905. //
  906. pv = pBuffer;
  907. *((ULONG *) pv) = bddiGetControlParams.Value;
  908. pv += sizeof(ULONG);
  909. RtlCopyMemory(pv, bddiGetControlParams.wszString, sizeof(bddiGetControlParams.wszString));
  910. //
  911. // Set the number of bytes used
  912. //
  913. *pOutputBufferUsed = RequiredOutputSize;
  914. Return:
  915. BDLDebug(
  916. BDL_DEBUG_TRACE,
  917. ("%s %s: BDL!BDLIOCTL_GetControl: Leave\n",
  918. __DATE__,
  919. __TIME__))
  920. return (status);
  921. }
  922. NTSTATUS
  923. BDLIOCTL_SetControl
  924. (
  925. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  926. IN ULONG InpuBufferLength,
  927. IN ULONG OutputBufferLength,
  928. IN PVOID pBuffer,
  929. OUT ULONG *pOutputBufferUsed
  930. )
  931. {
  932. NTSTATUS status = STATUS_SUCCESS;
  933. BDDI_PARAMS_SETCONTROL bddiSetControlParams;
  934. PUCHAR pv = pBuffer;
  935. ULONG i, j;
  936. BDL_CONTROL *pBDLControl = NULL;
  937. BDLDebug(
  938. BDL_DEBUG_TRACE,
  939. ("%s %s: BDL!BDLIOCTL_SetControl: Enter\n",
  940. __DATE__,
  941. __TIME__))
  942. //
  943. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  944. // spec for details)
  945. //
  946. if (InpuBufferLength < SIZEOF_SETCONTROL_INPUTBUFFER)
  947. {
  948. BDLDebug(
  949. BDL_DEBUG_ERROR,
  950. ("%s %s: BDL!BDLIOCTL_SetControl: Bad input buffer size\n",
  951. __DATE__,
  952. __TIME__))
  953. status = STATUS_INVALID_PARAMETER;
  954. goto Return;
  955. }
  956. //
  957. // Initialize the BDD struct
  958. //
  959. RtlZeroMemory(&bddiSetControlParams, sizeof(bddiSetControlParams));
  960. bddiSetControlParams.Size = sizeof(bddiSetControlParams);
  961. //
  962. // Get the input parameters from the buffer
  963. //
  964. bddiSetControlParams.ComponentId = *((ULONG *) pv);
  965. pv += sizeof(ULONG);
  966. bddiSetControlParams.ChannelId = *((ULONG *) pv);
  967. pv += sizeof(ULONG);
  968. bddiSetControlParams.ControlId = *((ULONG *) pv);
  969. pv += sizeof(ULONG);
  970. bddiSetControlParams.Value = *((ULONG *) pv);
  971. pv += sizeof(ULONG);
  972. RtlCopyMemory(
  973. &(bddiSetControlParams.wszString[0]),
  974. pv,
  975. sizeof(bddiSetControlParams.wszString));
  976. //
  977. // Check control ID
  978. //
  979. if (BDLCheckControlId(
  980. pBDLExtension,
  981. bddiSetControlParams.ComponentId,
  982. bddiSetControlParams.ChannelId,
  983. bddiSetControlParams.ControlId,
  984. &pBDLControl) == FALSE)
  985. {
  986. BDLDebug(
  987. BDL_DEBUG_ERROR,
  988. ("%s %s: BDL!BDLIOCTL_SetControl: Bad ControlId\n",
  989. __DATE__,
  990. __TIME__))
  991. status = STATUS_INVALID_PARAMETER;
  992. goto Return;
  993. }
  994. //
  995. // First make sure this isn't a read only value, then validate the
  996. // actual value
  997. //
  998. if (pBDLControl->Flags & BIO_CONTROL_FLAG_READONLY)
  999. {
  1000. BDLDebug(
  1001. BDL_DEBUG_ERROR,
  1002. ("%s %s: BDL!BDLIOCTL_SetControl: trying to set a read only control\n",
  1003. __DATE__,
  1004. __TIME__))
  1005. status = STATUS_INVALID_PARAMETER;
  1006. goto Return;
  1007. }
  1008. if ((bddiSetControlParams.Value < pBDLControl->NumericMinimum) ||
  1009. (bddiSetControlParams.Value > pBDLControl->NumericMaximum) ||
  1010. (((bddiSetControlParams.Value - pBDLControl->NumericMinimum)
  1011. % pBDLControl->NumericDivisor) != 0 ))
  1012. {
  1013. BDLDebug(
  1014. BDL_DEBUG_ERROR,
  1015. ("%s %s: BDL!BDLIOCTL_SetControl: trying to set an invalid value\n",
  1016. __DATE__,
  1017. __TIME__))
  1018. status = STATUS_INVALID_PARAMETER;
  1019. goto Return;
  1020. }
  1021. //
  1022. // Call the BDD
  1023. //
  1024. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiSetControl(
  1025. &(pBDLExtension->BdlExtenstion),
  1026. &bddiSetControlParams);
  1027. if (status != STATUS_SUCCESS)
  1028. {
  1029. BDLDebug(
  1030. BDL_DEBUG_ERROR,
  1031. ("%s %s: BDL!BDLIOCTL_SetControl: pfbddiSetControl failed with %lx\n",
  1032. __DATE__,
  1033. __TIME__,
  1034. status))
  1035. goto Return;
  1036. }
  1037. //
  1038. // Set the number of bytes used
  1039. //
  1040. *pOutputBufferUsed = 0;
  1041. Return:
  1042. BDLDebug(
  1043. BDL_DEBUG_TRACE,
  1044. ("%s %s: BDL!BDLIOCTL_SetControl: Leave\n",
  1045. __DATE__,
  1046. __TIME__))
  1047. return (status);
  1048. }
  1049. NTSTATUS
  1050. BDLIOCTL_CreateHandleFromData
  1051. (
  1052. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1053. IN ULONG InpuBufferLength,
  1054. IN ULONG OutputBufferLength,
  1055. IN PVOID pBuffer,
  1056. OUT ULONG *pOutputBufferUsed
  1057. )
  1058. {
  1059. NTSTATUS status = STATUS_SUCCESS;
  1060. ULONG RequiredOutputSize = 0;
  1061. BDDI_PARAMS_CREATEHANDLE_FROMDATA bddiCreateHandleFromDataParams;
  1062. PUCHAR pv = pBuffer;
  1063. ULONG RequiredInputSize = 0;
  1064. ULONG fTempHandle;
  1065. BDDI_ITEM *pNewItem = NULL;
  1066. KIRQL irql;
  1067. BDLDebug(
  1068. BDL_DEBUG_TRACE,
  1069. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: Enter\n",
  1070. __DATE__,
  1071. __TIME__))
  1072. //
  1073. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  1074. // spec for details)
  1075. //
  1076. RequiredInputSize = SIZEOF_CREATEHANDLEFROMDATA_INPUTBUFFER;
  1077. if (InpuBufferLength < RequiredInputSize)
  1078. {
  1079. BDLDebug(
  1080. BDL_DEBUG_ERROR,
  1081. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: Bad input buffer size\n",
  1082. __DATE__,
  1083. __TIME__))
  1084. status = STATUS_INVALID_PARAMETER;
  1085. goto ErrorReturn;
  1086. }
  1087. //
  1088. // Make sure there is enough space for the return buffer
  1089. //
  1090. RequiredOutputSize = SIZEOF_CREATEHANDLEFROMDATA_OUTPUTBUFFER;
  1091. if (RequiredOutputSize > OutputBufferLength)
  1092. {
  1093. BDLDebug(
  1094. BDL_DEBUG_ERROR,
  1095. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: Output buffer is too small\n",
  1096. __DATE__,
  1097. __TIME__))
  1098. status = STATUS_BUFFER_TOO_SMALL;
  1099. goto ErrorReturn;
  1100. }
  1101. //
  1102. // Initialize the BDD struct
  1103. //
  1104. RtlZeroMemory(&bddiCreateHandleFromDataParams, sizeof(bddiCreateHandleFromDataParams));
  1105. bddiCreateHandleFromDataParams.Size = sizeof(bddiCreateHandleFromDataParams);
  1106. //
  1107. // Get the input parameters from the buffer
  1108. //
  1109. RtlCopyMemory(&(bddiCreateHandleFromDataParams.guidFormatId), pv, sizeof(GUID));
  1110. pv += sizeof(GUID);
  1111. fTempHandle = *((ULONG *) pv);
  1112. pv += sizeof(ULONG);
  1113. bddiCreateHandleFromDataParams.cBuffer = *((ULONG *) pv);
  1114. pv += sizeof(ULONG);
  1115. bddiCreateHandleFromDataParams.pBuffer = pv;
  1116. //
  1117. // Check to make sure size of pBuffer isn't too large
  1118. //
  1119. RequiredInputSize += bddiCreateHandleFromDataParams.cBuffer;
  1120. if (InpuBufferLength < RequiredInputSize)
  1121. {
  1122. BDLDebug(
  1123. BDL_DEBUG_ERROR,
  1124. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: Bad input buffer size\n",
  1125. __DATE__,
  1126. __TIME__))
  1127. status = STATUS_INVALID_PARAMETER;
  1128. goto ErrorReturn;
  1129. }
  1130. //
  1131. // Create the new item
  1132. //
  1133. pNewItem = ExAllocatePoolWithTag(PagedPool, sizeof(BDDI_ITEM), BDL_ULONG_TAG);
  1134. if (pNewItem == NULL)
  1135. {
  1136. BDLDebug(
  1137. BDL_DEBUG_ERROR,
  1138. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: ExAllocatePoolWithTag failed\n",
  1139. __DATE__,
  1140. __TIME__))
  1141. status = STATUS_NO_MEMORY;
  1142. goto ErrorReturn;
  1143. }
  1144. //
  1145. // If this is a temp handle then create it locally, otherwise call the BDD
  1146. //
  1147. if (fTempHandle)
  1148. {
  1149. pNewItem->Type = BIO_ITEMTYPE_BLOCK;
  1150. pNewItem->Data.Block.pBuffer = bdliAlloc(
  1151. &(pBDLExtension->BdlExtenstion),
  1152. bddiCreateHandleFromDataParams.cBuffer,
  1153. 0);
  1154. if (pNewItem->Data.Block.pBuffer == NULL)
  1155. {
  1156. BDLDebug(
  1157. BDL_DEBUG_ERROR,
  1158. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: bdliAlloc failed\n",
  1159. __DATE__,
  1160. __TIME__))
  1161. status = STATUS_NO_MEMORY;
  1162. goto ErrorReturn;
  1163. }
  1164. pNewItem->Data.Block.cBuffer = bddiCreateHandleFromDataParams.cBuffer;
  1165. RtlCopyMemory(
  1166. pNewItem->Data.Block.pBuffer,
  1167. pv,
  1168. bddiCreateHandleFromDataParams.cBuffer);
  1169. }
  1170. else
  1171. {
  1172. pNewItem->Type = BIO_ITEMTYPE_HANDLE;
  1173. //
  1174. // Call the BDD
  1175. //
  1176. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiCreateHandleFromData(
  1177. &(pBDLExtension->BdlExtenstion),
  1178. &bddiCreateHandleFromDataParams);
  1179. if (status != STATUS_SUCCESS)
  1180. {
  1181. BDLDebug(
  1182. BDL_DEBUG_ERROR,
  1183. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: pfbddiCreateHandleFromData failed with %lx\n",
  1184. __DATE__,
  1185. __TIME__,
  1186. status))
  1187. goto ErrorReturn;
  1188. }
  1189. pNewItem->Data.Handle = bddiCreateHandleFromDataParams.hData;
  1190. }
  1191. //
  1192. // Add this handle to the list
  1193. //
  1194. BDLLockHandleList(pBDLExtension, &irql);
  1195. status = BDLAddHandleToList(&(pBDLExtension->HandleList), pNewItem);
  1196. BDLReleaseHandleList(pBDLExtension, irql);
  1197. if (status != STATUS_SUCCESS)
  1198. {
  1199. BDLDebug(
  1200. BDL_DEBUG_ERROR,
  1201. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: BDLAddHandleToList failed with %lx\n",
  1202. __DATE__,
  1203. __TIME__,
  1204. status))
  1205. goto ErrorReturn;
  1206. }
  1207. //
  1208. // Write the output info to the output buffer
  1209. //
  1210. pv = pBuffer;
  1211. *((BDD_HANDLE *) pv) = pNewItem;
  1212. //
  1213. // Set the number of bytes used
  1214. //
  1215. *pOutputBufferUsed = RequiredOutputSize;
  1216. Return:
  1217. BDLDebug(
  1218. BDL_DEBUG_TRACE,
  1219. ("%s %s: BDL!BDLIOCTL_CreateHandleFromData: Leave\n",
  1220. __DATE__,
  1221. __TIME__))
  1222. return (status);
  1223. ErrorReturn:
  1224. if (pNewItem != NULL)
  1225. {
  1226. if ((pNewItem->Type == BIO_ITEMTYPE_BLOCK) && (pNewItem->Data.Block.pBuffer != NULL))
  1227. {
  1228. bdliFree(pNewItem->Data.Block.pBuffer);
  1229. }
  1230. ExFreePoolWithTag(pNewItem, BDL_ULONG_TAG);
  1231. }
  1232. goto Return;
  1233. }
  1234. NTSTATUS
  1235. BDLIOCTL_CloseHandle
  1236. (
  1237. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1238. IN ULONG InpuBufferLength,
  1239. IN ULONG OutputBufferLength,
  1240. IN PVOID pBuffer,
  1241. OUT ULONG *pOutputBufferUsed
  1242. )
  1243. {
  1244. NTSTATUS status = STATUS_SUCCESS;
  1245. BDDI_PARAMS_CLOSEHANDLE bddiCloseHandleParams;
  1246. ULONG RequiredInputSize = 0;
  1247. KIRQL irql;
  1248. BDDI_ITEM *pBDDIItem = NULL;
  1249. BOOLEAN fItemInList = FALSE;
  1250. BDLDebug(
  1251. BDL_DEBUG_TRACE,
  1252. ("%s %s: BDL!BDLIOCTL_CloseHandle: Enter\n",
  1253. __DATE__,
  1254. __TIME__))
  1255. //
  1256. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  1257. // spec for details)
  1258. //
  1259. RequiredInputSize = SIZEOF_CLOSEHANDLE_INPUTBUFFER;
  1260. if (InpuBufferLength < RequiredInputSize)
  1261. {
  1262. BDLDebug(
  1263. BDL_DEBUG_ERROR,
  1264. ("%s %s: BDL!BDLIOCTL_CloseHandle: Bad input buffer size\n",
  1265. __DATE__,
  1266. __TIME__))
  1267. status = STATUS_INVALID_PARAMETER;
  1268. goto Return;
  1269. }
  1270. //
  1271. // Initialize the BDD struct
  1272. //
  1273. RtlZeroMemory(&bddiCloseHandleParams, sizeof(bddiCloseHandleParams));
  1274. bddiCloseHandleParams.Size = sizeof(bddiCloseHandleParams);
  1275. //
  1276. // Get the input parameters from the buffer
  1277. //
  1278. pBDDIItem = *((BDD_HANDLE *) pBuffer);
  1279. //
  1280. // Validate the handle is in the list
  1281. //
  1282. BDLLockHandleList(pBDLExtension, &irql);
  1283. fItemInList = BDLRemoveHandleFromList(&(pBDLExtension->HandleList), pBDDIItem);
  1284. BDLReleaseHandleList(pBDLExtension, irql);
  1285. if (fItemInList == FALSE)
  1286. {
  1287. BDLDebug(
  1288. BDL_DEBUG_ERROR,
  1289. ("%s %s: BDL!BDLIOCTL_CloseHandle: Bad handle\n",
  1290. __DATE__,
  1291. __TIME__))
  1292. status = STATUS_INVALID_PARAMETER;
  1293. goto Return;
  1294. }
  1295. //
  1296. // If this is a local handle then just clean it up, otherwise call the BDD
  1297. //
  1298. if (pBDDIItem->Type == BIO_ITEMTYPE_BLOCK)
  1299. {
  1300. bdliFree(pBDDIItem->Data.Block.pBuffer);
  1301. }
  1302. else
  1303. {
  1304. bddiCloseHandleParams.hData = pBDDIItem->Data.Handle;
  1305. //
  1306. // Call the BDD
  1307. //
  1308. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiCloseHandle(
  1309. &(pBDLExtension->BdlExtenstion),
  1310. &bddiCloseHandleParams);
  1311. if (status != STATUS_SUCCESS)
  1312. {
  1313. BDLDebug(
  1314. BDL_DEBUG_ERROR,
  1315. ("%s %s: BDL!BDLIOCTL_CloseHandle: pfbddiCloseHandle failed with %lx\n",
  1316. __DATE__,
  1317. __TIME__,
  1318. status))
  1319. goto Return;
  1320. }
  1321. }
  1322. ExFreePoolWithTag(pBDDIItem, BDL_ULONG_TAG);
  1323. //
  1324. // Set the number of bytes used
  1325. //
  1326. *pOutputBufferUsed = 0;
  1327. Return:
  1328. BDLDebug(
  1329. BDL_DEBUG_TRACE,
  1330. ("%s %s: BDL!BDLIOCTL_CloseHandle: Leave\n",
  1331. __DATE__,
  1332. __TIME__))
  1333. return (status);
  1334. }
  1335. NTSTATUS
  1336. BDLIOCTL_GetDataFromHandle
  1337. (
  1338. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1339. IN ULONG InpuBufferLength,
  1340. IN ULONG OutputBufferLength,
  1341. IN PVOID pBuffer,
  1342. OUT ULONG *pOutputBufferUsed
  1343. )
  1344. {
  1345. NTSTATUS status = STATUS_SUCCESS;
  1346. ULONG RequiredOutputSize = 0;
  1347. BDDI_PARAMS_GETDATA_FROMHANDLE bddiGetDataFromHandleParams;
  1348. BDDI_PARAMS_CLOSEHANDLE bddiCloseHandleParams;
  1349. PUCHAR pv = pBuffer;
  1350. ULONG RequiredInputSize = 0;
  1351. ULONG RemainingBufferSize = 0;
  1352. KIRQL irql;
  1353. BDDI_ITEM *pBDDIItem = NULL;
  1354. BOOLEAN fItemInList = FALSE;
  1355. BOOLEAN fCloseHandle = FALSE;
  1356. BDLDebug(
  1357. BDL_DEBUG_TRACE,
  1358. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: Enter\n",
  1359. __DATE__,
  1360. __TIME__))
  1361. //
  1362. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  1363. // spec for details)
  1364. //
  1365. RequiredInputSize = SIZEOF_GETDATAFROMHANDLE_INPUTBUFFER;
  1366. if (InpuBufferLength < RequiredInputSize)
  1367. {
  1368. BDLDebug(
  1369. BDL_DEBUG_ERROR,
  1370. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: Bad input buffer size\n",
  1371. __DATE__,
  1372. __TIME__))
  1373. status = STATUS_INVALID_PARAMETER;
  1374. goto Return;
  1375. }
  1376. //
  1377. // Make sure there is enough space for the return buffer
  1378. //
  1379. RequiredOutputSize = SIZEOF_GETDATAFROMHANDLE_OUTPUTBUFFER;
  1380. if (RequiredOutputSize > OutputBufferLength)
  1381. {
  1382. BDLDebug(
  1383. BDL_DEBUG_ERROR,
  1384. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: Output buffer is too small\n",
  1385. __DATE__,
  1386. __TIME__))
  1387. status = STATUS_BUFFER_TOO_SMALL;
  1388. goto Return;
  1389. }
  1390. //
  1391. // Calculate the size remaining in the output buffer
  1392. //
  1393. RemainingBufferSize = OutputBufferLength - RequiredOutputSize;
  1394. //
  1395. // Initialize the BDD struct
  1396. //
  1397. RtlZeroMemory(&bddiGetDataFromHandleParams, sizeof(bddiGetDataFromHandleParams));
  1398. bddiGetDataFromHandleParams.Size = sizeof(bddiGetDataFromHandleParams);
  1399. //
  1400. // Get the input parameters from the buffer
  1401. //
  1402. pBDDIItem = *((BDD_HANDLE *) pv);
  1403. pv += sizeof(BDD_HANDLE);
  1404. if (*((ULONG *) pv) == 1)
  1405. {
  1406. fCloseHandle = TRUE;
  1407. }
  1408. {
  1409. fCloseHandle = FALSE;
  1410. }
  1411. //
  1412. // Validate the handle is in the list
  1413. //
  1414. BDLLockHandleList(pBDLExtension, &irql);
  1415. if (fCloseHandle)
  1416. {
  1417. fItemInList = BDLRemoveHandleFromList(&(pBDLExtension->HandleList), pBDDIItem);
  1418. }
  1419. else
  1420. {
  1421. fItemInList = BDLValidateHandleIsInList(&(pBDLExtension->HandleList), pBDDIItem);
  1422. }
  1423. BDLReleaseHandleList(pBDLExtension, irql);
  1424. if (fItemInList == FALSE)
  1425. {
  1426. BDLDebug(
  1427. BDL_DEBUG_ERROR,
  1428. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: Bad handle\n",
  1429. __DATE__,
  1430. __TIME__))
  1431. status = STATUS_INVALID_PARAMETER;
  1432. goto Return;
  1433. }
  1434. pv = pBuffer;
  1435. //
  1436. // If this is a local handle then just hand back the data, otherwise call the BDD
  1437. //
  1438. if (pBDDIItem->Type == BIO_ITEMTYPE_BLOCK)
  1439. {
  1440. //
  1441. // See if the output buffer is large enough
  1442. //
  1443. if (pBDDIItem->Data.Block.cBuffer > RemainingBufferSize)
  1444. {
  1445. bddiGetDataFromHandleParams.pBuffer = NULL;
  1446. bddiGetDataFromHandleParams.BIOReturnCode = BIO_BUFFER_TOO_SMALL;
  1447. }
  1448. else
  1449. {
  1450. //
  1451. // Set the output buffer to be the IOCTL output buffer + the offset
  1452. // of the other output params which preceed the output data buffer
  1453. //
  1454. bddiGetDataFromHandleParams.pBuffer = pv + RequiredOutputSize;
  1455. //
  1456. // Copy the data
  1457. //
  1458. RtlCopyMemory(
  1459. bddiGetDataFromHandleParams.pBuffer,
  1460. pBDDIItem->Data.Block.pBuffer,
  1461. pBDDIItem->Data.Block.cBuffer);
  1462. bddiGetDataFromHandleParams.BIOReturnCode = ERROR_SUCCESS;
  1463. }
  1464. bddiGetDataFromHandleParams.cBuffer = pBDDIItem->Data.Block.cBuffer;
  1465. if (fCloseHandle)
  1466. {
  1467. bdliFree(pBDDIItem->Data.Block.pBuffer);
  1468. }
  1469. }
  1470. else
  1471. {
  1472. bddiGetDataFromHandleParams.hData = pBDDIItem->Data.Handle;
  1473. bddiGetDataFromHandleParams.cBuffer = RemainingBufferSize;
  1474. if (RemainingBufferSize == 0)
  1475. {
  1476. bddiGetDataFromHandleParams.pBuffer = NULL;
  1477. }
  1478. else
  1479. {
  1480. //
  1481. // Set the output buffer to be the IOCTL output buffer + the offset
  1482. // of the other output params which preceed the output data buffer
  1483. //
  1484. bddiGetDataFromHandleParams.pBuffer = pv + RequiredOutputSize;
  1485. }
  1486. //
  1487. // Call the BDD
  1488. //
  1489. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiGetDataFromHandle(
  1490. &(pBDLExtension->BdlExtenstion),
  1491. &bddiGetDataFromHandleParams);
  1492. if (status != STATUS_SUCCESS)
  1493. {
  1494. BDLDebug(
  1495. BDL_DEBUG_ERROR,
  1496. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: pfbddiCloseHandle failed with %lx\n",
  1497. __DATE__,
  1498. __TIME__,
  1499. status))
  1500. goto Return;
  1501. }
  1502. if (fCloseHandle)
  1503. {
  1504. RtlZeroMemory(&bddiCloseHandleParams, sizeof(bddiCloseHandleParams));
  1505. bddiCloseHandleParams.Size = sizeof(bddiCloseHandleParams);
  1506. bddiCloseHandleParams.hData = pBDDIItem->Data.Handle;
  1507. //
  1508. // Call the BDD to close the handle - don't check the return status because
  1509. // we really don't want to fail the operation if just closing the handle fails
  1510. //
  1511. pBDLExtension->pDriverExtension->bddiFunctions.pfbddiCloseHandle(
  1512. &(pBDLExtension->BdlExtenstion),
  1513. &bddiCloseHandleParams);
  1514. }
  1515. }
  1516. if (fCloseHandle)
  1517. {
  1518. ExFreePoolWithTag(pBDDIItem, BDL_ULONG_TAG);
  1519. }
  1520. //
  1521. // Write the return info to the output buffer
  1522. //
  1523. pv = pBuffer;
  1524. *((ULONG *) pv) = bddiGetDataFromHandleParams.BIOReturnCode;
  1525. pv += sizeof(ULONG);
  1526. *((ULONG *) pv) = bddiGetDataFromHandleParams.cBuffer;
  1527. //
  1528. // Set the number of bytes used
  1529. //
  1530. *pOutputBufferUsed = RequiredOutputSize;
  1531. if (bddiGetDataFromHandleParams.pBuffer != NULL)
  1532. {
  1533. *pOutputBufferUsed += bddiGetDataFromHandleParams.cBuffer;
  1534. }
  1535. Return:
  1536. BDLDebug(
  1537. BDL_DEBUG_TRACE,
  1538. ("%s %s: BDL!BDLIOCTL_GetDataFromHandle: Leave\n",
  1539. __DATE__,
  1540. __TIME__))
  1541. return (status);
  1542. }
  1543. NTSTATUS
  1544. BDLIOCTL_RegisterNotify
  1545. (
  1546. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1547. IN ULONG InpuBufferLength,
  1548. IN ULONG OutputBufferLength,
  1549. IN PVOID pBuffer,
  1550. OUT ULONG *pOutputBufferUsed
  1551. )
  1552. {
  1553. NTSTATUS status = STATUS_SUCCESS;
  1554. BDDI_PARAMS_REGISTERNOTIFY bddiRegisterNotifyParams;
  1555. PUCHAR pv = pBuffer;
  1556. ULONG RequiredInputSize = 0;
  1557. BDL_CONTROL *pBDLControl = NULL;
  1558. KIRQL irql, OldIrql;
  1559. PLIST_ENTRY pRegistrationListEntry = NULL;
  1560. PLIST_ENTRY pControlChangeEntry = NULL;
  1561. BDL_CONTROL_CHANGE_REGISTRATION *pControlChangeRegistration = NULL;
  1562. BDL_IOCTL_CONTROL_CHANGE_ITEM *pControlChangeItem = NULL;
  1563. BOOLEAN fLockAcquired = FALSE;
  1564. BOOLEAN fRegistrationFound = FALSE;
  1565. PLIST_ENTRY pTemp = NULL;
  1566. PIRP pIrpToComplete = NULL;
  1567. BDLDebug(
  1568. BDL_DEBUG_TRACE,
  1569. ("%s %s: BDL!BDLIOCTL_RegisterNotify: Enter\n",
  1570. __DATE__,
  1571. __TIME__))
  1572. //
  1573. // Make sure the input buffer is at least the minimum size (see BDDIOCTL
  1574. // spec for details)
  1575. //
  1576. RequiredInputSize = SIZEOF_REGISTERNOTIFY_INPUTBUFFER;
  1577. if (InpuBufferLength < RequiredInputSize)
  1578. {
  1579. BDLDebug(
  1580. BDL_DEBUG_ERROR,
  1581. ("%s %s: BDL!BDLIOCTL_RegisterNotify: Bad input buffer size\n",
  1582. __DATE__,
  1583. __TIME__))
  1584. status = STATUS_INVALID_PARAMETER;
  1585. goto Return;
  1586. }
  1587. //
  1588. // Initialize the BDD struct
  1589. //
  1590. RtlZeroMemory(&bddiRegisterNotifyParams, sizeof(bddiRegisterNotifyParams));
  1591. bddiRegisterNotifyParams.Size = sizeof(bddiRegisterNotifyParams);
  1592. //
  1593. // Get the input parameters from the buffer
  1594. //
  1595. bddiRegisterNotifyParams.fRegister = *((ULONG *) pv) == 1;
  1596. pv += sizeof(ULONG);
  1597. bddiRegisterNotifyParams.ComponentId = *((ULONG *) pv);
  1598. pv += sizeof(ULONG);
  1599. bddiRegisterNotifyParams.ChannelId = *((ULONG *) pv);
  1600. pv += sizeof(ULONG);
  1601. bddiRegisterNotifyParams.ControlId = *((ULONG *) pv);
  1602. //
  1603. // Check control ID
  1604. //
  1605. if (BDLCheckControlId(
  1606. pBDLExtension,
  1607. bddiRegisterNotifyParams.ComponentId,
  1608. bddiRegisterNotifyParams.ChannelId,
  1609. bddiRegisterNotifyParams.ControlId,
  1610. &pBDLControl) == FALSE)
  1611. {
  1612. BDLDebug(
  1613. BDL_DEBUG_ERROR,
  1614. ("%s %s: BDL!BDLIOCTL_RegisterNotify: Bad ControlId\n",
  1615. __DATE__,
  1616. __TIME__))
  1617. status = STATUS_INVALID_PARAMETER;
  1618. goto Return;
  1619. }
  1620. //
  1621. // Make sure this is an async control
  1622. //
  1623. if (!(pBDLControl->Flags | BIO_CONTROL_FLAG_ASYNCHRONOUS))
  1624. {
  1625. BDLDebug(
  1626. BDL_DEBUG_ERROR,
  1627. ("%s %s: BDL!BDLIOCTL_RegisterNotify: trying to register for a non async control\n",
  1628. __DATE__,
  1629. __TIME__))
  1630. status = STATUS_INVALID_PARAMETER;
  1631. goto Return;
  1632. }
  1633. //
  1634. // Note that we must raise the irql to dispatch level because we are synchronizing
  1635. // with a dispatch routine (BDLControlChangeDpc) that adds items to the queue at
  1636. // dispatch level
  1637. //
  1638. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1639. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  1640. fLockAcquired = TRUE;
  1641. //
  1642. // Check to see if this notification registration exists (must exist for unregister, must not
  1643. // exist for register).
  1644. //
  1645. pRegistrationListEntry = pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList.Flink;
  1646. while (pRegistrationListEntry->Flink !=
  1647. pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList.Flink)
  1648. {
  1649. pControlChangeRegistration = CONTAINING_RECORD(
  1650. pRegistrationListEntry,
  1651. BDL_CONTROL_CHANGE_REGISTRATION,
  1652. ListEntry);
  1653. if ((pControlChangeRegistration->ComponentId == bddiRegisterNotifyParams.ComponentId) &&
  1654. (pControlChangeRegistration->ChannelId == bddiRegisterNotifyParams.ChannelId) &&
  1655. (pControlChangeRegistration->ControlId == bddiRegisterNotifyParams.ControlId))
  1656. {
  1657. fRegistrationFound = TRUE;
  1658. //
  1659. // The notification registration does exist, so if this is a register call then fail
  1660. //
  1661. if (bddiRegisterNotifyParams.fRegister == TRUE)
  1662. {
  1663. BDLDebug(
  1664. BDL_DEBUG_ERROR,
  1665. ("%s %s: BDL!BDLIOCTL_RegisterNotify: trying to re-register\n",
  1666. __DATE__,
  1667. __TIME__))
  1668. status = STATUS_INVALID_PARAMETER;
  1669. goto Return;
  1670. }
  1671. //
  1672. // Remove the notification registration from the list
  1673. //
  1674. RemoveEntryList(pRegistrationListEntry);
  1675. ExFreePoolWithTag(pControlChangeRegistration, BDL_ULONG_TAG);
  1676. //
  1677. // Remove any pending notifications for the control which is being unregistered
  1678. //
  1679. pControlChangeEntry = pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue.Flink;
  1680. while (pControlChangeEntry->Flink !=
  1681. pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue.Flink)
  1682. {
  1683. pControlChangeItem = CONTAINING_RECORD(
  1684. pControlChangeEntry,
  1685. BDL_IOCTL_CONTROL_CHANGE_ITEM,
  1686. ListEntry);
  1687. pTemp = pControlChangeEntry;
  1688. pControlChangeEntry = pControlChangeEntry->Flink;
  1689. if ((pControlChangeItem->ComponentId == bddiRegisterNotifyParams.ComponentId) &&
  1690. (pControlChangeItem->ChannelId == bddiRegisterNotifyParams.ChannelId) &&
  1691. (pControlChangeItem->ControlId == bddiRegisterNotifyParams.ControlId))
  1692. {
  1693. RemoveEntryList(pTemp);
  1694. ExFreePoolWithTag(pControlChangeItem, BDL_ULONG_TAG);
  1695. }
  1696. }
  1697. //
  1698. // If the last notification registration just got removed, then complete
  1699. // the pending get notification IRP (if one exists) after releasing the lock.
  1700. //
  1701. if (IsListEmpty(&(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList)) &&
  1702. (pBDLExtension->ControlChangeStruct.pIrp != NULL))
  1703. {
  1704. pIrpToComplete = pBDLExtension->ControlChangeStruct.pIrp;
  1705. pBDLExtension->ControlChangeStruct.pIrp = NULL;
  1706. }
  1707. break;
  1708. }
  1709. pRegistrationListEntry = pRegistrationListEntry->Flink;
  1710. }
  1711. //
  1712. // If the registration was not found, and this is an unregister, return an error
  1713. //
  1714. if ((fRegistrationFound == FALSE) && (bddiRegisterNotifyParams.fRegister == FALSE))
  1715. {
  1716. BDLDebug(
  1717. BDL_DEBUG_ERROR,
  1718. ("%s %s: BDL!BDLIOCTL_RegisterNotify: trying to re-register\n",
  1719. __DATE__,
  1720. __TIME__))
  1721. status = STATUS_INVALID_PARAMETER;
  1722. goto Return;
  1723. }
  1724. //
  1725. // Add the notification to the list if this is a registration
  1726. //
  1727. if (bddiRegisterNotifyParams.fRegister == TRUE)
  1728. {
  1729. pControlChangeRegistration = ExAllocatePoolWithTag(
  1730. PagedPool,
  1731. sizeof(BDL_CONTROL_CHANGE_REGISTRATION),
  1732. BDL_ULONG_TAG);
  1733. if (pControlChangeRegistration == NULL)
  1734. {
  1735. BDLDebug(
  1736. BDL_DEBUG_ERROR,
  1737. ("%s %s: BDL!BDLIOCTL_RegisterNotify: ExAllocatePoolWithTag failed\n",
  1738. __DATE__,
  1739. __TIME__))
  1740. status = STATUS_NO_MEMORY;
  1741. goto Return;
  1742. }
  1743. pControlChangeRegistration->ComponentId = bddiRegisterNotifyParams.ComponentId;
  1744. pControlChangeRegistration->ChannelId = bddiRegisterNotifyParams.ChannelId;
  1745. pControlChangeRegistration->ControlId = bddiRegisterNotifyParams.ControlId;
  1746. InsertHeadList(
  1747. &(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList),
  1748. &(pControlChangeRegistration->ListEntry));
  1749. }
  1750. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  1751. KeLowerIrql(OldIrql);
  1752. fLockAcquired = FALSE;
  1753. if (pIrpToComplete != NULL)
  1754. {
  1755. pIrpToComplete->IoStatus.Information = 0;
  1756. pIrpToComplete->IoStatus.Status = STATUS_NO_MORE_ENTRIES;
  1757. IoCompleteRequest(pIrpToComplete, IO_NO_INCREMENT);
  1758. }
  1759. //
  1760. // Call the BDD
  1761. //
  1762. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiRegisterNotify(
  1763. &(pBDLExtension->BdlExtenstion),
  1764. &bddiRegisterNotifyParams);
  1765. if (status != STATUS_SUCCESS)
  1766. {
  1767. BDLDebug(
  1768. BDL_DEBUG_ERROR,
  1769. ("%s %s: BDL!BDLIOCTL_RegisterNotify: pfbddiRegisterNotify failed with %lx\n",
  1770. __DATE__,
  1771. __TIME__,
  1772. status))
  1773. //
  1774. // FIX FIX - if this fails and it is a register then we need to remove the
  1775. // registration from the list of registrations... since it was already added
  1776. // above.
  1777. //
  1778. ASSERT(0);
  1779. goto Return;
  1780. }
  1781. //
  1782. // Set the number of bytes used
  1783. //
  1784. *pOutputBufferUsed = 0;
  1785. Return:
  1786. if (fLockAcquired == TRUE)
  1787. {
  1788. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  1789. KeLowerIrql(OldIrql);
  1790. }
  1791. BDLDebug(
  1792. BDL_DEBUG_TRACE,
  1793. ("%s %s: BDL!BDLIOCTL_RegisterNotify: Leave\n",
  1794. __DATE__,
  1795. __TIME__))
  1796. return (status);
  1797. }
  1798. NTSTATUS
  1799. BDLIOCTL_GetNotification
  1800. (
  1801. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1802. IN ULONG InpuBufferLength,
  1803. IN ULONG OutputBufferLength,
  1804. IN PVOID pBuffer,
  1805. IN PIRP pIrp,
  1806. OUT ULONG *pOutputBufferUsed
  1807. )
  1808. {
  1809. NTSTATUS status = STATUS_SUCCESS;
  1810. ULONG RequiredOutputSize = 0;
  1811. PUCHAR pv = pBuffer;
  1812. KIRQL irql, OldIrql;
  1813. PLIST_ENTRY pListEntry = NULL;
  1814. BDL_IOCTL_CONTROL_CHANGE_ITEM *pControlChangeItem = NULL;
  1815. BOOLEAN fLockAcquired = FALSE;
  1816. BDLDebug(
  1817. BDL_DEBUG_TRACE,
  1818. ("%s %s: BDL!BDLIOCTL_GetNotification: Enter\n",
  1819. __DATE__,
  1820. __TIME__))
  1821. //
  1822. // Make sure there is enough space for the return buffer
  1823. //
  1824. RequiredOutputSize = SIZEOF_GETNOTIFICATION_OUTPUTBUFFER;
  1825. if (RequiredOutputSize > OutputBufferLength)
  1826. {
  1827. BDLDebug(
  1828. BDL_DEBUG_ERROR,
  1829. ("%s %s: BDL!BDLIOCTL_GetNotification: Output buffer is too small\n",
  1830. __DATE__,
  1831. __TIME__))
  1832. status = STATUS_BUFFER_TOO_SMALL;
  1833. goto Return;
  1834. }
  1835. //
  1836. // Lock the notification queue and see if there are any outstanding notifications.
  1837. // Note that we must raise the irql to dispatch level because we are synchronizing
  1838. // with a DPC routine (BDLControlChangeDpc) that adds items to the queue at
  1839. // dispatch level
  1840. //
  1841. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1842. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  1843. fLockAcquired = TRUE;
  1844. //
  1845. // If there is already an IRP posted then that is a bug in the BSP
  1846. //
  1847. if (pBDLExtension->ControlChangeStruct.pIrp != NULL)
  1848. {
  1849. BDLDebug(
  1850. BDL_DEBUG_ERROR,
  1851. ("%s %s: BDL!BDLIOCTL_GetNotification: Output buffer is too small\n",
  1852. __DATE__,
  1853. __TIME__))
  1854. status = STATUS_INVALID_DEVICE_STATE;
  1855. goto Return;
  1856. }
  1857. if (IsListEmpty(&(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList)))
  1858. {
  1859. //
  1860. // There are no change notifications registered, so complete the IRP with the
  1861. // special status that indicates that
  1862. //
  1863. BDLDebug(
  1864. BDL_DEBUG_TRACE,
  1865. ("%s %s: BDL!BDLIOCTL_GetNotification: ControlChangeRegistrationList empty\n",
  1866. __DATE__,
  1867. __TIME__))
  1868. status = STATUS_NO_MORE_ENTRIES;
  1869. goto Return;
  1870. }
  1871. else if (IsListEmpty(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue)))
  1872. {
  1873. //
  1874. // There are currently no control changes in the list, so just save this Irp
  1875. // and return STATUS_PENDING
  1876. //
  1877. BDLDebug(
  1878. BDL_DEBUG_TRACE,
  1879. ("%s %s: BDL!BDLIOCTL_GetNotification: ControlChanges empty\n",
  1880. __DATE__,
  1881. __TIME__))
  1882. //
  1883. // Set up the cancel routine for this IRP
  1884. //
  1885. if (IoSetCancelRoutine(pIrp, BDLRegisteredCancelGetNotificationIRP) != NULL)
  1886. {
  1887. BDLDebug(
  1888. BDL_DEBUG_ERROR,
  1889. ("%s %s: BDL!BDLIOCTL_GetNotification: pCancel was not NULL\n",
  1890. __DATE__,
  1891. __TIME__))
  1892. }
  1893. pBDLExtension->ControlChangeStruct.pIrp = pIrp;
  1894. status = STATUS_PENDING;
  1895. goto Return;
  1896. }
  1897. else
  1898. {
  1899. //
  1900. // Grab the first control change item in the queue
  1901. //
  1902. pListEntry = RemoveHeadList(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue));
  1903. pControlChangeItem = CONTAINING_RECORD(pListEntry, BDL_IOCTL_CONTROL_CHANGE_ITEM, ListEntry);
  1904. }
  1905. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  1906. KeLowerIrql(OldIrql);
  1907. fLockAcquired = FALSE;
  1908. //
  1909. // We are here because there is currently a control change to report, so write the return
  1910. // info to the output buffer
  1911. //
  1912. pv = pBuffer;
  1913. *((ULONG *) pv) = pControlChangeItem->ComponentId;
  1914. pv += sizeof(ULONG);
  1915. *((ULONG *) pv) = pControlChangeItem->ChannelId;
  1916. pv += sizeof(ULONG);
  1917. *((ULONG *) pv) = pControlChangeItem->ControlId;
  1918. pv += sizeof(ULONG);
  1919. *((ULONG *) pv) = pControlChangeItem->Value;
  1920. //
  1921. // Free up the change item
  1922. //
  1923. ExFreePoolWithTag(pControlChangeItem, BDL_ULONG_TAG);
  1924. //
  1925. // Set the number of bytes used
  1926. //
  1927. *pOutputBufferUsed = RequiredOutputSize;
  1928. Return:
  1929. if (fLockAcquired)
  1930. {
  1931. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  1932. KeLowerIrql(OldIrql);
  1933. }
  1934. BDLDebug(
  1935. BDL_DEBUG_TRACE,
  1936. ("%s %s: BDL!BDLIOCTL_GetNotification: Leave\n",
  1937. __DATE__,
  1938. __TIME__))
  1939. return (status);
  1940. }
  1941. VOID
  1942. BDLCancelGetNotificationIRP
  1943. (
  1944. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension
  1945. )
  1946. {
  1947. PIRP pIrpToCancel = NULL;
  1948. KIRQL irql, OldIrql;
  1949. BDLDebug(
  1950. BDL_DEBUG_TRACE,
  1951. ("%s %s: BDL!BDLCancelGetNotificationIRP: Enter\n",
  1952. __DATE__,
  1953. __TIME__))
  1954. //
  1955. // Remove the GetNotification IRP from the the ControlChangeStruct.
  1956. // Need to make sure the IRP is still there, since theoretically we
  1957. // could be trying to complete it at the same time it is cancelled.
  1958. //
  1959. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  1960. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  1961. if (pBDLExtension->ControlChangeStruct.pIrp != NULL)
  1962. {
  1963. pIrpToCancel = pBDLExtension->ControlChangeStruct.pIrp;
  1964. pBDLExtension->ControlChangeStruct.pIrp = NULL;
  1965. }
  1966. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  1967. KeLowerIrql(OldIrql);
  1968. //
  1969. // Complete the GetNotification IRP as cancelled
  1970. //
  1971. if (pIrpToCancel != NULL)
  1972. {
  1973. pIrpToCancel->IoStatus.Information = 0;
  1974. pIrpToCancel->IoStatus.Status = STATUS_CANCELLED;
  1975. IoCompleteRequest(pIrpToCancel, IO_NO_INCREMENT);
  1976. }
  1977. BDLDebug(
  1978. BDL_DEBUG_TRACE,
  1979. ("%s %s: BDL!BDLCancelGetNotificationIRP: Leave\n",
  1980. __DATE__,
  1981. __TIME__))
  1982. }
  1983. NTSTATUS
  1984. BDLRegisteredCancelGetNotificationIRP
  1985. (
  1986. IN PDEVICE_OBJECT pDeviceObject,
  1987. IN PIRP pIrp
  1988. )
  1989. {
  1990. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  1991. BDLDebug(
  1992. BDL_DEBUG_TRACE,
  1993. ("%s %s: BDL!BDLRegisteredCancelGetNotificationIRP: Enter\n",
  1994. __DATE__,
  1995. __TIME__))
  1996. ASSERT(pIrp == pBDLExtension->ControlChangeStruct.pIrp);
  1997. //
  1998. // Since this function is called already holding the CancelSpinLock
  1999. // we need to release it
  2000. //
  2001. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  2002. //
  2003. // Cancel the IRP
  2004. //
  2005. BDLCancelGetNotificationIRP(pBDLExtension);
  2006. BDLDebug(
  2007. BDL_DEBUG_TRACE,
  2008. ("%s %s: BDL!BDLRegisteredCancelGetNotificationIRP: Leave\n",
  2009. __DATE__,
  2010. __TIME__))
  2011. return (STATUS_CANCELLED);
  2012. }