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.

3316 lines
95 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. bdl.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 May 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. #ifndef FILE_DEVICE_BIOMETRIC
  21. #define FILE_DEVICE_BIOMETRIC 0x3B
  22. #endif
  23. #define BDL_DRIVER_EXTENSION_ID ((PVOID) 1)
  24. typedef enum _IRP_ACTION
  25. {
  26. Undefined = 0,
  27. SkipRequest,
  28. WaitForCompletion,
  29. CompleteRequest,
  30. MarkPending
  31. } IRP_ACTION;
  32. typedef struct _POWER_IRP_CONTEXT
  33. {
  34. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension;
  35. PIRP pIrp;
  36. UCHAR MinorFunction;
  37. } POWER_IRP_CONTEXT, *PPOWER_IRP_CONTEXT;
  38. VOID BDLControlChangeDpc
  39. (
  40. IN PKDPC pDpc,
  41. IN PVOID pvContext,
  42. IN PVOID pArg1,
  43. IN PVOID pArg2
  44. );
  45. /////////////////////////////////////////////////////////////////////////////////////////
  46. //
  47. // Forward declarations of all the PNP and Power handling functions.
  48. //
  49. NTSTATUS
  50. BDLPnPStart
  51. (
  52. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  53. IN PDEVICE_OBJECT pAttachedDeviceObject,
  54. IN PIRP pIrp,
  55. PIO_STACK_LOCATION pStackLocation
  56. );
  57. NTSTATUS
  58. BDLPnPQueryStop
  59. (
  60. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  61. IN PDEVICE_OBJECT pAttachedDeviceObject,
  62. IN PIRP pIrp
  63. );
  64. NTSTATUS
  65. BDLPnPCancelStop
  66. (
  67. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  68. IN PDEVICE_OBJECT pAttachedDeviceObject,
  69. IN PIRP pIrp
  70. );
  71. NTSTATUS
  72. BDLPnPStop
  73. (
  74. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  75. IN PDEVICE_OBJECT pAttachedDeviceObject,
  76. IN PIRP pIrp
  77. );
  78. NTSTATUS
  79. BDLPnPQueryRemove
  80. (
  81. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  82. IN PDEVICE_OBJECT pAttachedDeviceObject,
  83. IN PIRP pIrp
  84. );
  85. NTSTATUS
  86. BDLPnPCancelRemove
  87. (
  88. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  89. IN PDEVICE_OBJECT pAttachedDeviceObject,
  90. IN PIRP pIrp
  91. );
  92. NTSTATUS
  93. BDLHandleRemove
  94. (
  95. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  96. IN PDEVICE_OBJECT pAttachedDeviceObject,
  97. IN PIRP pIrp
  98. );
  99. NTSTATUS
  100. BDLPnPRemove
  101. (
  102. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  103. IN PDEVICE_OBJECT pDeviceObject,
  104. IN PDEVICE_OBJECT pAttachedDeviceObject,
  105. IN PIRP pIrp
  106. );
  107. NTSTATUS
  108. BDLPnPSurpriseRemoval
  109. (
  110. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  111. IN PDEVICE_OBJECT pAttachedDeviceObject,
  112. IN PIRP pIrp
  113. );
  114. NTSTATUS
  115. BDLSystemQueryPower
  116. (
  117. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  118. IN PIO_STACK_LOCATION pStackLocation,
  119. OUT IRP_ACTION *pIRPAction,
  120. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  121. );
  122. NTSTATUS
  123. BDLSystemSetPower
  124. (
  125. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  126. IN PIO_STACK_LOCATION pStackLocation,
  127. OUT IRP_ACTION *pIRPAction,
  128. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  129. );
  130. NTSTATUS
  131. BDLDeviceQueryPower
  132. (
  133. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  134. IN PIO_STACK_LOCATION pStackLocation,
  135. OUT IRP_ACTION *pIRPAction,
  136. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  137. );
  138. NTSTATUS
  139. BDLDeviceSetPower
  140. (
  141. IN PDEVICE_OBJECT pDeviceObject,
  142. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  143. IN PIO_STACK_LOCATION pStackLocation,
  144. OUT IRP_ACTION *pIRPAction,
  145. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  146. );
  147. #pragma alloc_text(INIT, DriverEntry)
  148. #pragma alloc_text(PAGEABLE, BDLDriverUnload)
  149. #pragma alloc_text(PAGEABLE, BDLAddDevice)
  150. //
  151. // This is the main driver entry point
  152. //
  153. NTSTATUS
  154. DriverEntry
  155. (
  156. IN PDRIVER_OBJECT DriverObject,
  157. IN PUNICODE_STRING RegistryPath
  158. )
  159. {
  160. BDLDebug(
  161. BDL_DEBUG_TRACE,
  162. ("%s %s: BDL!DriverEntry\n",
  163. __DATE__,
  164. __TIME__))
  165. return (STATUS_SUCCESS);
  166. }
  167. /////////////////////////////////////////////////////////////////////////////////////////
  168. //
  169. // These functions are the BDL's entry points for all the major system IRPs
  170. //
  171. //
  172. // BDLDriverUnload()
  173. //
  174. // The driver unload routine. This is called by the I/O system
  175. // when the device is unloaded from memory.
  176. //
  177. // PARAMETERS:
  178. // pDriverObject Pointer to driver object created by system.
  179. //
  180. // RETURNS:
  181. // STATUS_SUCCESS If the BDLDriverUnload call succeeded
  182. //
  183. VOID
  184. BDLDriverUnload
  185. (
  186. IN PDRIVER_OBJECT pDriverObject
  187. )
  188. {
  189. BDLDebug(
  190. BDL_DEBUG_TRACE,
  191. ("%s %s: BDL!BDLDriverUnload: Enter\n",
  192. __DATE__,
  193. __TIME__))
  194. PAGED_CODE();
  195. BDLDebug(
  196. BDL_DEBUG_TRACE,
  197. ("%s %s: BDL!BDLDriverUnload: Leave\n",
  198. __DATE__,
  199. __TIME__))
  200. }
  201. //
  202. // BDLCreate()
  203. //
  204. // This routine is called by the I/O system when the device is opened
  205. //
  206. // PARAMETERS:
  207. // pDeviceObject Pointer to device object for this miniport
  208. // pIrp The IRP that represents this call
  209. //
  210. NTSTATUS
  211. BDLCreate
  212. (
  213. IN PDEVICE_OBJECT pDeviceObject,
  214. IN PIRP pIrp
  215. )
  216. {
  217. NTSTATUS status = STATUS_SUCCESS;
  218. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  219. BDLDebug(
  220. BDL_DEBUG_TRACE,
  221. ("%s %s: BDL!BDLCreate: Enter\n",
  222. __DATE__,
  223. __TIME__))
  224. status = IoAcquireRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'lCrC');
  225. if (status != STATUS_SUCCESS)
  226. {
  227. BDLDebug(
  228. BDL_DEBUG_ERROR,
  229. ("%s %s: BDL!BDLCreate: IoAcquireRemoveLock failed with %lx\n",
  230. __DATE__,
  231. __TIME__,
  232. status))
  233. }
  234. if (InterlockedCompareExchange(&(pBDLExtension->DeviceOpen), TRUE, FALSE) == FALSE)
  235. {
  236. BDLDebug(
  237. BDL_DEBUG_TRACE,
  238. ("%s %s: BDL!BDLCreate: Device opened\n",
  239. __DATE__,
  240. __TIME__))
  241. }
  242. else
  243. {
  244. BDLDebug(
  245. BDL_DEBUG_ERROR,
  246. ("%s %s: BDL!BDLCreate: device is already open\n",
  247. __DATE__,
  248. __TIME__))
  249. //
  250. // The device is already in use, so fail the call
  251. //
  252. status = STATUS_UNSUCCESSFUL;
  253. //
  254. // release the lock since we are failing the call
  255. //
  256. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'lCrC');
  257. }
  258. BDLDebug(
  259. BDL_DEBUG_TRACE,
  260. ("%s %s: BDL!BDLCreate: Leave\n",
  261. __DATE__,
  262. __TIME__))
  263. return (status);
  264. }
  265. //
  266. // BDLClose()
  267. //
  268. // This routine is called by the I/O system when the device is closed
  269. //
  270. NTSTATUS
  271. BDLClose
  272. (
  273. IN PDEVICE_OBJECT pDeviceObject,
  274. IN PIRP pIrp
  275. )
  276. {
  277. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  278. BDLDebug(
  279. BDL_DEBUG_TRACE,
  280. ("%s %s: BDL!BDLClose: Enter\n",
  281. __DATE__,
  282. __TIME__))
  283. //
  284. // Clean up any outstanding notification info and data handles
  285. //
  286. BDLCleanupNotificationStruct(pBDLExtension);
  287. BDLCleanupDataHandles(pBDLExtension);
  288. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'lCrC');
  289. pBDLExtension->DeviceOpen = FALSE;
  290. BDLDebug(
  291. BDL_DEBUG_TRACE,
  292. ("%s %s: BDL!BDLClose: Leave\n",
  293. __DATE__,
  294. __TIME__))
  295. return (STATUS_SUCCESS);
  296. }
  297. //
  298. // BDLCleanup()
  299. //
  300. // This routine is called when the calling application terminates
  301. //
  302. NTSTATUS
  303. BDLCleanup
  304. (
  305. IN PDEVICE_OBJECT pDeviceObject,
  306. IN PIRP pIrp
  307. )
  308. {
  309. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  310. BDLDebug(
  311. BDL_DEBUG_TRACE,
  312. ("%s %s: BDL!BDLCleanup: Enter\n",
  313. __DATE__,
  314. __TIME__))
  315. //
  316. // Clean up any outstanding notification info and data handles
  317. //
  318. BDLCleanupNotificationStruct(pBDLExtension);
  319. BDLCleanupDataHandles(pBDLExtension);
  320. //
  321. // Cancel the notification IRP (probably don't have to do this, since the
  322. // system should call the cancel routine on the applications behalf.
  323. //
  324. BDLCancelGetNotificationIRP(pBDLExtension);
  325. //
  326. // Complete this IRP
  327. //
  328. pIrp->IoStatus.Information = 0;
  329. pIrp->IoStatus.Status = STATUS_SUCCESS;
  330. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  331. BDLDebug(
  332. BDL_DEBUG_TRACE,
  333. ("%s %s: BDL!BDLCleanup: Leave\n",
  334. __DATE__,
  335. __TIME__))
  336. return (STATUS_SUCCESS);
  337. }
  338. //
  339. // BDLDeviceControl()
  340. //
  341. // This routine is called when an IOCTL is made on this device
  342. //
  343. NTSTATUS
  344. BDLDeviceControl
  345. (
  346. IN PDEVICE_OBJECT pDeviceObject,
  347. IN PIRP pIrp
  348. )
  349. {
  350. NTSTATUS status = STATUS_SUCCESS;
  351. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  352. PIO_STACK_LOCATION pStack = NULL;
  353. ULONG cbIn = 0;
  354. ULONG cbOut = 0;
  355. ULONG IOCTLCode = 0;
  356. PVOID pIOBuffer = NULL;
  357. ULONG cbOutUsed = 0;
  358. KIRQL irql;
  359. BDLDebug(
  360. BDL_DEBUG_TRACE,
  361. ("%s %s: BDL!BDLDeviceControl: Enter\n",
  362. __DATE__,
  363. __TIME__))
  364. //
  365. // Do some checking that is valid for all IOCTLs
  366. //
  367. //
  368. // Acquire the remove lock and check to make sure the device wasn't removed
  369. //
  370. status = IoAcquireRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'tCoI');
  371. if (status != STATUS_SUCCESS)
  372. {
  373. //
  374. // The device has been removed, so fail the call.
  375. //
  376. pIrp->IoStatus.Information = 0;
  377. status = STATUS_DEVICE_REMOVED;
  378. goto Return;
  379. }
  380. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  381. //
  382. // If IO count is anything other than 0 than the device must already
  383. // be started so just incremement the IO count. If it is 0, then wait
  384. // on the started event to make sure the device is started.
  385. //
  386. if (pBDLExtension->IoCount == 0)
  387. {
  388. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  389. status = KeWaitForSingleObject(
  390. &(pBDLExtension->DeviceStartedEvent),
  391. Executive,
  392. KernelMode,
  393. FALSE,
  394. NULL);
  395. ASSERT(status == STATUS_SUCCESS);
  396. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  397. }
  398. pBDLExtension->IoCount++;
  399. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  400. //
  401. // If the device has been removed then fail the call. This will happen
  402. // if the device is stopped and the IOCTL is blocked at the above
  403. // KeWaitForSingleObject and then the device gets removed.
  404. //
  405. if (pBDLExtension->fDeviceRemoved == TRUE)
  406. {
  407. status = STATUS_DEVICE_REMOVED;
  408. goto Return;
  409. }
  410. //
  411. // Get the input/output buffer, buffer sizes, and control code
  412. //
  413. pStack = IoGetCurrentIrpStackLocation(pIrp);
  414. cbIn = pStack->Parameters.DeviceIoControl.InputBufferLength;
  415. cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
  416. IOCTLCode = pStack->Parameters.DeviceIoControl.IoControlCode;
  417. pIOBuffer = pIrp->AssociatedIrp.SystemBuffer;
  418. //
  419. // We must run at passive level otherwise IoCompleteRequest won't work properly
  420. //
  421. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  422. //
  423. // Now, do the IOCTL specific processing
  424. //
  425. switch (IOCTLCode)
  426. {
  427. case BDD_IOCTL_STARTUP:
  428. status = BDLIOCTL_Startup(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  429. break;
  430. case BDD_IOCTL_SHUTDOWN:
  431. status = BDLIOCTL_Shutdown(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  432. break;
  433. case BDD_IOCTL_GETDEVICEINFO:
  434. status = BDLIOCTL_GetDeviceInfo(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  435. break;
  436. case BDD_IOCTL_DOCHANNEL:
  437. status = BDLIOCTL_DoChannel(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  438. break;
  439. case BDD_IOCTL_GETCONTROL:
  440. status = BDLIOCTL_GetControl(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  441. break;
  442. case BDD_IOCTL_SETCONTROL:
  443. status = BDLIOCTL_SetControl(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  444. break;
  445. case BDD_IOCTL_CREATEHANDLEFROMDATA:
  446. status = BDLIOCTL_CreateHandleFromData(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  447. break;
  448. case BDD_IOCTL_CLOSEHANDLE:
  449. status = BDLIOCTL_CloseHandle(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  450. break;
  451. case BDD_IOCTL_GETDATAFROMHANDLE:
  452. status = BDLIOCTL_GetDataFromHandle(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  453. break;
  454. case BDD_IOCTL_REGISTERNOTIFY:
  455. status = BDLIOCTL_RegisterNotify(pBDLExtension, cbIn, cbOut, pIOBuffer, &cbOutUsed);
  456. break;
  457. case BDD_IOCTL_GETNOTIFICATION:
  458. status = BDLIOCTL_GetNotification(pBDLExtension, cbIn, cbOut, pIOBuffer, pIrp, &cbOutUsed);
  459. break;
  460. default:
  461. status = STATUS_INVALID_DEVICE_REQUEST;
  462. break;
  463. }
  464. Return:
  465. //
  466. // If the IRP isn't pending, then complete it
  467. //
  468. if (status != STATUS_PENDING)
  469. {
  470. pIrp->IoStatus.Information = cbOutUsed;
  471. pIrp->IoStatus.Status = status;
  472. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  473. }
  474. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  475. pBDLExtension->IoCount--;
  476. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  477. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'tCoI');
  478. BDLDebug(
  479. BDL_DEBUG_TRACE,
  480. ("%s %s: BDL!BDLDeviceControl: Leave\n",
  481. __DATE__,
  482. __TIME__))
  483. return (status);
  484. }
  485. //
  486. // BDLSystemControl()
  487. //
  488. //
  489. //
  490. NTSTATUS
  491. BDLSystemControl
  492. (
  493. IN PDEVICE_OBJECT pDeviceObject,
  494. IN PIRP pIrp
  495. )
  496. {
  497. NTSTATUS status = STATUS_SUCCESS;
  498. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  499. BDLDebug(
  500. BDL_DEBUG_TRACE,
  501. ("%s %s: BDL!BDLSystemControl: Enter\n",
  502. __DATE__,
  503. __TIME__))
  504. //
  505. // Becuase we are not a WMI provider all we have to do is pass this IRP down
  506. //
  507. IoSkipCurrentIrpStackLocation(pIrp);
  508. status = IoCallDriver(pBDLExtension->BdlExtenstion.pAttachedDeviceObject, pIrp);
  509. BDLDebug(
  510. BDL_DEBUG_TRACE,
  511. ("%s %s: BDL!BDLSystemControl: Leave\n",
  512. __DATE__,
  513. __TIME__))
  514. return (status);
  515. }
  516. //
  517. // BDLAddDevice()
  518. //
  519. // This routine creates an object for the physical device specified and
  520. // sets up the deviceExtension.
  521. //
  522. NTSTATUS
  523. BDLAddDevice
  524. (
  525. IN PDRIVER_OBJECT pDriverObject,
  526. IN PDEVICE_OBJECT pPhysicalDeviceObject
  527. )
  528. {
  529. NTSTATUS status = STATUS_SUCCESS;
  530. PDEVICE_OBJECT pDeviceObject = NULL;
  531. PBDL_DRIVER_EXTENSION pDriverExtension = NULL;
  532. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = NULL;
  533. BDSI_ADDDEVICE bdsiAddDeviceParams;
  534. ULONG i;
  535. BDLDebug(
  536. BDL_DEBUG_TRACE,
  537. ("%s %s: BDL!BDLAddDevice: Enter\n",
  538. __DATE__,
  539. __TIME__))
  540. PAGED_CODE();
  541. //
  542. // Get the driver extension
  543. //
  544. pDriverExtension = IoGetDriverObjectExtension(pDriverObject, BDL_DRIVER_EXTENSION_ID);
  545. ASSERT(pDriverExtension != NULL);
  546. //
  547. // Create the device object
  548. //
  549. status = IoCreateDevice(
  550. pDriverObject,
  551. sizeof(BDL_INTERNAL_DEVICE_EXTENSION),
  552. NULL,
  553. FILE_DEVICE_BIOMETRIC,
  554. 0,
  555. TRUE,
  556. &pDeviceObject);
  557. if (status != STATUS_SUCCESS)
  558. {
  559. BDLDebug(
  560. BDL_DEBUG_ERROR,
  561. ("%s %s: BDL!BDLAddDevice: IoCreateDevice failed with %lx\n",
  562. __DATE__,
  563. __TIME__,
  564. status))
  565. goto ErrorReturn;
  566. }
  567. pBDLExtension = pDeviceObject->DeviceExtension;
  568. RtlZeroMemory(pBDLExtension, sizeof(BDL_INTERNAL_DEVICE_EXTENSION));
  569. //
  570. // Attach the device to the stack
  571. //
  572. pBDLExtension->BdlExtenstion.Size = sizeof(BDL_DEVICEEXT);
  573. pBDLExtension->BdlExtenstion.pAttachedDeviceObject = IoAttachDeviceToDeviceStack(
  574. pDeviceObject,
  575. pPhysicalDeviceObject);
  576. if (pBDLExtension->BdlExtenstion.pAttachedDeviceObject == NULL)
  577. {
  578. BDLDebug(
  579. BDL_DEBUG_ERROR,
  580. ("%s %s: BDL!BDLAddDevice: IoAttachDeviceToDeviceStack failed with %lx\n",
  581. __DATE__,
  582. __TIME__,
  583. status))
  584. status = STATUS_UNSUCCESSFUL;
  585. goto ErrorReturn;
  586. }
  587. status = IoRegisterDeviceInterface(
  588. pPhysicalDeviceObject,
  589. &BiometricDeviceGuid,
  590. NULL,
  591. &(pBDLExtension->SymbolicLinkName));
  592. ASSERT(status == STATUS_SUCCESS);
  593. //
  594. // Initialize the rest of the BDL device extension members in order
  595. //
  596. pBDLExtension->pDriverExtension = pDriverExtension;
  597. KeInitializeSpinLock(&(pBDLExtension->SpinLock));
  598. KeInitializeEvent(&(pBDLExtension->DeviceStartedEvent), NotificationEvent, FALSE);
  599. pBDLExtension->IoCount = 0;
  600. IoInitializeRemoveLock(&(pBDLExtension->RemoveLock), BDL_ULONG_TAG, 0, 20);
  601. pBDLExtension->DeviceOpen = FALSE;
  602. status = BDLGetDeviceCapabilities(pPhysicalDeviceObject, pBDLExtension);
  603. if (status != STATUS_SUCCESS)
  604. {
  605. goto ErrorReturn;
  606. }
  607. KeInitializeSpinLock(&(pBDLExtension->ControlChangeStruct.ISRControlChangeLock));
  608. KeInitializeDpc(
  609. &(pBDLExtension->ControlChangeStruct.DpcObject),
  610. BDLControlChangeDpc,
  611. pBDLExtension);
  612. InitializeListHead(&(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue));
  613. for (i = 0; i < CONTROL_CHANGE_POOL_SIZE; i++)
  614. {
  615. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].fUsed = FALSE;
  616. }
  617. KeQueryTickCount(&(pBDLExtension->ControlChangeStruct.StartTime));
  618. pBDLExtension->ControlChangeStruct.NumCalls = 0;
  619. KeInitializeSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock));
  620. InitializeListHead(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue));
  621. pBDLExtension->ControlChangeStruct.pIrp = NULL;
  622. InitializeListHead(&(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList));
  623. pBDLExtension->CurrentPowerState = On;
  624. pBDLExtension->fStartSucceeded = FALSE;
  625. pBDLExtension->fDeviceRemoved = FALSE;
  626. KeInitializeSpinLock(&(pBDLExtension->HandleListLock));
  627. BDLInitializeHandleList(&(pBDLExtension->HandleList));
  628. //
  629. // finally, call the BDD's bdsiAddDevice
  630. //
  631. RtlZeroMemory(&bdsiAddDeviceParams, sizeof(bdsiAddDeviceParams));
  632. bdsiAddDeviceParams.Size = sizeof(bdsiAddDeviceParams);
  633. bdsiAddDeviceParams.pPhysicalDeviceObject = pPhysicalDeviceObject;
  634. bdsiAddDeviceParams.pvBDDExtension = NULL;
  635. status = pDriverExtension->bdsiFunctions.pfbdsiAddDevice(
  636. &(pBDLExtension->BdlExtenstion),
  637. &bdsiAddDeviceParams);
  638. if (status != STATUS_SUCCESS)
  639. {
  640. BDLDebug(
  641. BDL_DEBUG_ERROR,
  642. ("%s %s: BDL!BDLAddDevice: bdsiAddDevice failed with %lx\n",
  643. __DATE__,
  644. __TIME__,
  645. status))
  646. status = STATUS_UNSUCCESSFUL;
  647. goto ErrorReturn;
  648. }
  649. pBDLExtension->BdlExtenstion.pvBDDExtension = bdsiAddDeviceParams.pvBDDExtension;
  650. Return:
  651. BDLDebug(
  652. BDL_DEBUG_TRACE,
  653. ("%s %s: BDL!BDLAddDevice: Leave\n",
  654. __DATE__,
  655. __TIME__))
  656. return (status);
  657. ErrorReturn:
  658. if (pBDLExtension != NULL)
  659. {
  660. BDLCleanupDeviceCapabilities(pBDLExtension);
  661. if (pBDLExtension->BdlExtenstion.pAttachedDeviceObject)
  662. {
  663. IoDetachDevice(pBDLExtension->BdlExtenstion.pAttachedDeviceObject);
  664. }
  665. if (pBDLExtension->SymbolicLinkName.Buffer != NULL)
  666. {
  667. RtlFreeUnicodeString(&(pBDLExtension->SymbolicLinkName));
  668. }
  669. }
  670. if (pDeviceObject != NULL)
  671. {
  672. IoDeleteDevice(pDeviceObject);
  673. }
  674. goto Return;
  675. }
  676. //
  677. // BDLPnP()
  678. //
  679. // This routine is called for all PnP notifications
  680. //
  681. NTSTATUS
  682. BDLPnP
  683. (
  684. IN PDEVICE_OBJECT pDeviceObject,
  685. IN PIRP pIrp
  686. )
  687. {
  688. NTSTATUS status = STATUS_SUCCESS;
  689. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  690. PIO_STACK_LOCATION pStackLocation = NULL;
  691. PDEVICE_OBJECT pAttachedDeviceObject = NULL;
  692. BOOLEAN fCompleteIrp = TRUE;
  693. BDLDebug(
  694. BDL_DEBUG_TRACE,
  695. ("%s %s: BDL!BDLPnP: Enter\n",
  696. __DATE__,
  697. __TIME__))
  698. pAttachedDeviceObject = pBDLExtension->BdlExtenstion.pAttachedDeviceObject;
  699. pStackLocation = IoGetCurrentIrpStackLocation(pIrp);
  700. //
  701. // Acquire the remove lock with the 'Pnp ' tag if this is any IRP other
  702. // than IRP_MN_REMOVE_DEVICE. If it is IRP_MN_REMOVE_DEVICE then acquire
  703. // the lock with the 'Rmv ' tag
  704. //
  705. status = IoAcquireRemoveLock(
  706. &(pBDLExtension->RemoveLock),
  707. (pStackLocation->MinorFunction != IRP_MN_REMOVE_DEVICE)
  708. ? (PVOID) ' PnP' : (PVOID) ' vmR');
  709. if (status != STATUS_SUCCESS)
  710. {
  711. BDLDebug(
  712. BDL_DEBUG_ERROR,
  713. ("%s %s: BDL!BDLPnP: IRP_MN_...%lx - Device Removed!!\n",
  714. __DATE__,
  715. __TIME__,
  716. pStackLocation->MinorFunction))
  717. pIrp->IoStatus.Information = 0;
  718. pIrp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  719. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  720. status = STATUS_DEVICE_REMOVED;
  721. goto Return;
  722. }
  723. switch (pStackLocation->MinorFunction)
  724. {
  725. case IRP_MN_START_DEVICE:
  726. status = BDLPnPStart(
  727. pBDLExtension,
  728. pAttachedDeviceObject,
  729. pIrp,
  730. pStackLocation);
  731. break;
  732. case IRP_MN_QUERY_STOP_DEVICE:
  733. status = BDLPnPQueryStop(
  734. pBDLExtension,
  735. pAttachedDeviceObject,
  736. pIrp);
  737. break;
  738. case IRP_MN_CANCEL_STOP_DEVICE:
  739. status = BDLPnPCancelStop(
  740. pBDLExtension,
  741. pAttachedDeviceObject,
  742. pIrp);
  743. break;
  744. case IRP_MN_STOP_DEVICE:
  745. status = BDLPnPStop(
  746. pBDLExtension,
  747. pAttachedDeviceObject,
  748. pIrp);
  749. break;
  750. case IRP_MN_QUERY_REMOVE_DEVICE:
  751. status = BDLPnPQueryRemove(
  752. pBDLExtension,
  753. pAttachedDeviceObject,
  754. pIrp);
  755. break;
  756. case IRP_MN_CANCEL_REMOVE_DEVICE:
  757. status = BDLPnPCancelRemove(
  758. pBDLExtension,
  759. pAttachedDeviceObject,
  760. pIrp);
  761. break;
  762. case IRP_MN_REMOVE_DEVICE:
  763. status = BDLPnPRemove(
  764. pBDLExtension,
  765. pDeviceObject,
  766. pAttachedDeviceObject,
  767. pIrp);
  768. fCompleteIrp = FALSE;
  769. break;
  770. case IRP_MN_SURPRISE_REMOVAL:
  771. status = BDLPnPSurpriseRemoval(
  772. pBDLExtension,
  773. pAttachedDeviceObject,
  774. pIrp);
  775. fCompleteIrp = FALSE;
  776. break;
  777. default:
  778. //
  779. // This is an Irp that is only useful for underlying drivers
  780. //
  781. BDLDebug(
  782. BDL_DEBUG_TRACE,
  783. ("%s %s: BDL!BDLPnP: IRP_MN_...%lx\n",
  784. __DATE__,
  785. __TIME__,
  786. pStackLocation->MinorFunction))
  787. IoSkipCurrentIrpStackLocation(pIrp);
  788. status = IoCallDriver(pAttachedDeviceObject, pIrp);
  789. fCompleteIrp = FALSE;
  790. break;
  791. }
  792. //
  793. // If we actually processed the IRP and didn't skip it then complete it
  794. //
  795. if (fCompleteIrp == TRUE)
  796. {
  797. pIrp->IoStatus.Status = status;
  798. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  799. }
  800. //
  801. // The BDLPnPRemove() function itself will release the remove lock since it
  802. // has to wait on all the other holders of the lock defore deleting the device
  803. // object. So we don't call IoReleaseRemoveLock() here if this is a
  804. // IRP_MN_REMOVE_DEVICE IRP
  805. //
  806. if (pStackLocation->MinorFunction != IRP_MN_REMOVE_DEVICE)
  807. {
  808. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) ' PnP');
  809. }
  810. Return:
  811. BDLDebug(
  812. BDL_DEBUG_TRACE,
  813. ("%s %s: BDL!BDLPnP: Leave\n",
  814. __DATE__,
  815. __TIME__))
  816. return (status);
  817. }
  818. //
  819. // BDLPower()
  820. //
  821. // This routine is called for all Power notifications
  822. //
  823. NTSTATUS
  824. BDLPower
  825. (
  826. IN PDEVICE_OBJECT pDeviceObject,
  827. IN PIRP pIrp
  828. )
  829. {
  830. NTSTATUS status = STATUS_SUCCESS;
  831. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pDeviceObject->DeviceExtension;
  832. PIO_STACK_LOCATION pStackLocation = NULL;
  833. PDEVICE_OBJECT pAttachedDeviceObject = NULL;
  834. BOOLEAN fCompleteIrp = TRUE;
  835. IRP_ACTION IRPAction = SkipRequest;
  836. PIO_COMPLETION_ROUTINE IoCompletionRoutine = NULL;
  837. POWER_IRP_CONTEXT *pPowerIrpContext = NULL;
  838. BDLDebug(
  839. BDL_DEBUG_TRACE,
  840. ("%s %s: BDL!BDLPower: Enter\n",
  841. __DATE__,
  842. __TIME__))
  843. pAttachedDeviceObject = pBDLExtension->BdlExtenstion.pAttachedDeviceObject;
  844. pStackLocation = IoGetCurrentIrpStackLocation(pIrp);
  845. //
  846. // Acquire the remove lock
  847. //
  848. status = IoAcquireRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  849. if (status != STATUS_SUCCESS)
  850. {
  851. BDLDebug(
  852. BDL_DEBUG_ERROR,
  853. ("%s %s: BDL!BDLPower: IRP_MN_...%lx - Device Removed!!\n",
  854. __DATE__,
  855. __TIME__,
  856. pStackLocation->MinorFunction))
  857. PoStartNextPowerIrp(pIrp);
  858. pIrp->IoStatus.Information = 0;
  859. pIrp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  860. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  861. status = STATUS_DEVICE_REMOVED;
  862. goto Return;
  863. }
  864. switch (pStackLocation->Parameters.Power.Type)
  865. {
  866. case DevicePowerState:
  867. switch (pStackLocation->MinorFunction)
  868. {
  869. case IRP_MN_QUERY_POWER:
  870. status = BDLDeviceQueryPower(
  871. pBDLExtension,
  872. pStackLocation,
  873. &IRPAction,
  874. &IoCompletionRoutine);
  875. break;
  876. case IRP_MN_SET_POWER:
  877. status = BDLDeviceSetPower(
  878. pDeviceObject,
  879. pBDLExtension,
  880. pStackLocation,
  881. &IRPAction,
  882. &IoCompletionRoutine);
  883. break;
  884. default:
  885. ASSERT(FALSE);
  886. break;
  887. } // switch (pStackLocation->MinorFunction)
  888. break;
  889. case SystemPowerState:
  890. switch (pStackLocation->MinorFunction)
  891. {
  892. case IRP_MN_QUERY_POWER:
  893. status = BDLSystemQueryPower(
  894. pBDLExtension,
  895. pStackLocation,
  896. &IRPAction,
  897. &IoCompletionRoutine);
  898. break;
  899. case IRP_MN_SET_POWER:
  900. status = BDLSystemSetPower(
  901. pBDLExtension,
  902. pStackLocation,
  903. &IRPAction,
  904. &IoCompletionRoutine);
  905. break;
  906. default:
  907. ASSERT(FALSE);
  908. break;
  909. } // switch (pStackLocation->MinorFunction)
  910. break;
  911. default:
  912. ASSERT(FALSE);
  913. break;
  914. } // switch (pStackLocation->Parameters.Power.Type)
  915. switch (IRPAction)
  916. {
  917. case SkipRequest:
  918. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  919. PoStartNextPowerIrp(pIrp);
  920. IoSkipCurrentIrpStackLocation(pIrp);
  921. status = PoCallDriver(pAttachedDeviceObject, pIrp);
  922. if (status != STATUS_SUCCESS)
  923. {
  924. BDLDebug(
  925. BDL_DEBUG_ERROR,
  926. ("%s %s: BDL!BDLPower: PoCallDriver failed with %lx\n",
  927. __DATE__,
  928. __TIME__,
  929. status))
  930. goto ErrorReturn;
  931. }
  932. break;
  933. case CompleteRequest:
  934. pIrp->IoStatus.Status = status;
  935. pIrp->IoStatus.Information = 0;
  936. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  937. PoStartNextPowerIrp(pIrp);
  938. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  939. break;
  940. case MarkPending:
  941. //
  942. // Allocate the context struct that all the IRPs use
  943. //
  944. pPowerIrpContext = ExAllocatePoolWithTag(
  945. PagedPool,
  946. sizeof(POWER_IRP_CONTEXT),
  947. BDL_ULONG_TAG);
  948. if (pPowerIrpContext == NULL)
  949. {
  950. BDLDebug(
  951. BDL_DEBUG_ERROR,
  952. ("%s %s: BDL!BDLPower: ExAllocatePoolWithTag failed\n",
  953. __DATE__,
  954. __TIME__))
  955. status = STATUS_NO_MEMORY;
  956. goto ErrorReturn;
  957. }
  958. //
  959. // Fill in the context struct
  960. //
  961. pPowerIrpContext->pBDLExtension = pBDLExtension;
  962. pPowerIrpContext->pIrp = pIrp;
  963. //
  964. // Mark the irp as pending and setup the completion routine, then call the driver
  965. //
  966. IoMarkIrpPending(pIrp);
  967. IoCopyCurrentIrpStackLocationToNext(pIrp);
  968. IoSetCompletionRoutine(pIrp, IoCompletionRoutine, pPowerIrpContext, TRUE, TRUE, TRUE);
  969. status = PoCallDriver(pDeviceObject, pIrp);
  970. ASSERT(status == STATUS_PENDING);
  971. if (status != STATUS_PENDING)
  972. {
  973. BDLDebug(
  974. BDL_DEBUG_ERROR,
  975. ("%s %s: BDL!BDLPower: PoCallDriver should have returned STATUS_PENDING but returned %lx\n",
  976. __DATE__,
  977. __TIME__,
  978. status))
  979. // FIX FIX
  980. //
  981. // I have no idea what can be done to recover in this case
  982. //
  983. }
  984. break;
  985. } // switch (IRPAction)
  986. Return:
  987. BDLDebug(
  988. BDL_DEBUG_TRACE,
  989. ("%s %s: BDL!BDLPower: Leave\n",
  990. __DATE__,
  991. __TIME__))
  992. return (status);
  993. ErrorReturn:
  994. pIrp->IoStatus.Status = status;
  995. pIrp->IoStatus.Information = 0;
  996. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  997. PoStartNextPowerIrp(pIrp);
  998. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  999. goto Return;
  1000. }
  1001. /////////////////////////////////////////////////////////////////////////////////////////
  1002. //
  1003. // These functions are all the handlers for Power events or supporting IoCompletion
  1004. // routines for the handlers
  1005. //
  1006. VOID
  1007. BDLSystemPowerCompleted
  1008. (
  1009. IN PDEVICE_OBJECT pDeviceObject,
  1010. IN UCHAR MinorFunction,
  1011. IN POWER_STATE PowerState,
  1012. IN PVOID Context,
  1013. IN PIO_STATUS_BLOCK pIoStatus
  1014. )
  1015. {
  1016. POWER_IRP_CONTEXT *pPowerIrpContext = (POWER_IRP_CONTEXT *) Context;
  1017. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pPowerIrpContext->pBDLExtension;
  1018. PIRP pIrp = pPowerIrpContext->pIrp;
  1019. BDLDebug(
  1020. BDL_DEBUG_TRACE,
  1021. ("%s %s: BDL!BDLSystemQueryPowerCompleted: Enter\n",
  1022. __DATE__,
  1023. __TIME__))
  1024. //
  1025. // Set the status of the System Power IRP to be the return status of the
  1026. // Device Power IRP that was initiated by calling PoRequestPowerIrp() in
  1027. // BDLSystemPowerIoCompletion()
  1028. //
  1029. pIrp->IoStatus.Status = pIoStatus->Status;
  1030. pIrp->IoStatus.Information = 0;
  1031. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  1032. PoStartNextPowerIrp(pIrp);
  1033. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1034. ExFreePoolWithTag(pPowerIrpContext, BDL_ULONG_TAG);
  1035. BDLDebug(
  1036. BDL_DEBUG_TRACE,
  1037. ("%s %s: BDL!BDLSystemQueryPowerCompleted: Leave\n",
  1038. __DATE__,
  1039. __TIME__))
  1040. }
  1041. NTSTATUS
  1042. BDLSystemPowerIoCompletion
  1043. (
  1044. IN PDEVICE_OBJECT pDeviceObject,
  1045. IN PIRP pIrp,
  1046. IN PVOID Context
  1047. )
  1048. {
  1049. NTSTATUS status = STATUS_SUCCESS;
  1050. POWER_IRP_CONTEXT *pPowerIrpContext = (POWER_IRP_CONTEXT *) Context;
  1051. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pPowerIrpContext->pBDLExtension;
  1052. PIO_STACK_LOCATION pStackLocation = IoGetCurrentIrpStackLocation(pIrp);
  1053. POWER_STATE PowerState;
  1054. BDLDebug(
  1055. BDL_DEBUG_TRACE,
  1056. ("%s %s: BDL!BDLSystemQueryPowerIoCompletion: Enter\n",
  1057. __DATE__,
  1058. __TIME__))
  1059. //
  1060. // If a lower level driver failed the request then just complete the IRP
  1061. // and return the status set by the lower level driver
  1062. //
  1063. if (pIrp->IoStatus.Status != STATUS_SUCCESS)
  1064. {
  1065. status = pIrp->IoStatus.Status;
  1066. BDLDebug(
  1067. BDL_DEBUG_ERROR,
  1068. ("%s %s: BDL!BDLSystemQueryPowerIoCompletion: PoRequestPowerIrp did not return STATUS_PENDING, but returned %lx\n",
  1069. __DATE__,
  1070. __TIME__,
  1071. status))
  1072. goto ErrorReturn;
  1073. }
  1074. //
  1075. // Figure out what device power state to request
  1076. //
  1077. switch (pStackLocation->Parameters.Power.State.SystemState)
  1078. {
  1079. case PowerSystemMaximum:
  1080. case PowerSystemWorking:
  1081. PowerState.DeviceState = PowerDeviceD0;
  1082. break;
  1083. case PowerSystemSleeping1:
  1084. case PowerSystemSleeping2:
  1085. case PowerSystemSleeping3:
  1086. // FIX FIX
  1087. //
  1088. // For now, just fall through and map these system states to the
  1089. // PowerDeviceD3 device state. Ultimately, these system states should
  1090. // map to the PowerDeviceD2 device state
  1091. //
  1092. case PowerSystemHibernate:
  1093. case PowerSystemShutdown:
  1094. PowerState.DeviceState = PowerDeviceD3;
  1095. break;
  1096. default:
  1097. ASSERT(FALSE);
  1098. }
  1099. //
  1100. // Send a query power IRP to the device and pass in a completion routine
  1101. // which will check to see if the device query power IRP was completed
  1102. // successfully or not and will then complete the system query IRP
  1103. //
  1104. status = PoRequestPowerIrp (
  1105. pDeviceObject,
  1106. pStackLocation->MinorFunction,
  1107. PowerState,
  1108. BDLSystemPowerCompleted,
  1109. pPowerIrpContext,
  1110. NULL);
  1111. if (status == STATUS_PENDING)
  1112. {
  1113. status = STATUS_MORE_PROCESSING_REQUIRED;
  1114. }
  1115. else
  1116. {
  1117. pIrp->IoStatus.Status = status;
  1118. pIrp->IoStatus.Information = 0;
  1119. BDLDebug(
  1120. BDL_DEBUG_ERROR,
  1121. ("%s %s: BDL!BDLSystemQueryPowerIoCompletion: PoRequestPowerIrp did not return STATUS_PENDING, but returned %lx\n",
  1122. __DATE__,
  1123. __TIME__,
  1124. status))
  1125. goto ErrorReturn;
  1126. }
  1127. Return:
  1128. BDLDebug(
  1129. BDL_DEBUG_TRACE,
  1130. ("%s %s: BDL!BDLSystemQueryPowerIoCompletion: Leave\n",
  1131. __DATE__,
  1132. __TIME__))
  1133. return (status);
  1134. ErrorReturn:
  1135. //
  1136. // The IRP isn't going to be completed in the device query IRP completion routine,
  1137. // so we need to complete it here
  1138. //
  1139. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  1140. PoStartNextPowerIrp(pIrp);
  1141. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1142. ExFreePoolWithTag(pPowerIrpContext, BDL_ULONG_TAG);
  1143. goto Return;
  1144. }
  1145. NTSTATUS
  1146. BDLSystemQueryPower
  1147. (
  1148. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1149. IN PIO_STACK_LOCATION pStackLocation,
  1150. OUT IRP_ACTION *pIRPAction,
  1151. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  1152. )
  1153. {
  1154. NTSTATUS status = STATUS_SUCCESS;
  1155. KIRQL irql;
  1156. BDLDebug(
  1157. BDL_DEBUG_TRACE,
  1158. ("%s %s: BDL!BDLPowerSystemQuery: Enter\n",
  1159. __DATE__,
  1160. __TIME__))
  1161. //
  1162. // Set these output variables here just in case we mark as pending.
  1163. //
  1164. *pIoCompletionRoutine = BDLSystemPowerIoCompletion;
  1165. switch (pStackLocation->Parameters.Power.State.SystemState)
  1166. {
  1167. case PowerSystemMaximum:
  1168. case PowerSystemWorking:
  1169. //
  1170. // Because we are transitioning into a working state we don't
  1171. // need to check anything... since we can definitely make the
  1172. // transition. Mark as pending and continue processing in
  1173. // completion routine.
  1174. //
  1175. *pIRPAction = MarkPending;
  1176. break;
  1177. case PowerSystemSleeping1:
  1178. case PowerSystemSleeping2:
  1179. case PowerSystemSleeping3:
  1180. case PowerSystemHibernate:
  1181. case PowerSystemShutdown:
  1182. //
  1183. // Since we are going into a low power mode or being shutdown
  1184. // check to see if there are any outstanding IO calls
  1185. //
  1186. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  1187. if (pBDLExtension->IoCount == 0)
  1188. {
  1189. //
  1190. // Block any further IOCTLs
  1191. //
  1192. KeClearEvent(&(pBDLExtension->DeviceStartedEvent));
  1193. //
  1194. // Mark as pending and continue processing in completion routine.
  1195. //
  1196. *pIRPAction = MarkPending;
  1197. }
  1198. else
  1199. {
  1200. //
  1201. // We can't go into sleep mode because the device is busy
  1202. //
  1203. status = STATUS_DEVICE_BUSY;
  1204. *pIRPAction = CompleteRequest;
  1205. }
  1206. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  1207. break;
  1208. case PowerSystemUnspecified:
  1209. ASSERT(FALSE);
  1210. status = STATUS_UNSUCCESSFUL;
  1211. *pIRPAction = CompleteRequest;
  1212. }
  1213. BDLDebug(
  1214. BDL_DEBUG_TRACE,
  1215. ("%s %s: BDL!BDLPowerSystemQuery: Leave\n",
  1216. __DATE__,
  1217. __TIME__))
  1218. return (status);
  1219. }
  1220. NTSTATUS
  1221. BDLSystemSetPower
  1222. (
  1223. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1224. IN PIO_STACK_LOCATION pStackLocation,
  1225. OUT IRP_ACTION *pIRPAction,
  1226. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  1227. )
  1228. {
  1229. NTSTATUS status = STATUS_SUCCESS;
  1230. KIRQL irql;
  1231. BDLDebug(
  1232. BDL_DEBUG_TRACE,
  1233. ("%s %s: BDL!BDLSystemSetPower: Enter\n",
  1234. __DATE__,
  1235. __TIME__))
  1236. //
  1237. // Set the completion routing here just in case we mark as pending.
  1238. //
  1239. *pIoCompletionRoutine = BDLSystemPowerIoCompletion;
  1240. switch (pStackLocation->Parameters.Power.State.SystemState)
  1241. {
  1242. case PowerSystemMaximum:
  1243. case PowerSystemWorking:
  1244. //
  1245. // If we are already in the requested state then skip the request,
  1246. // otherwise mark as pending which will pass the IRP down and continue
  1247. // processing in the completion routine
  1248. //
  1249. if (pBDLExtension->CurrentPowerState == On)
  1250. {
  1251. *pIRPAction = SkipRequest;
  1252. }
  1253. else
  1254. {
  1255. *pIRPAction = MarkPending;
  1256. }
  1257. break;
  1258. case PowerSystemSleeping1:
  1259. case PowerSystemSleeping2:
  1260. case PowerSystemSleeping3:
  1261. // FIX FIX
  1262. //
  1263. // for now just fall through on these
  1264. //
  1265. case PowerSystemHibernate:
  1266. case PowerSystemShutdown:
  1267. //
  1268. // If we are already in the requested state then skip the request,
  1269. // otherwise mark as pending which will pass the IRP down and continue
  1270. // processing in the completion routine
  1271. //
  1272. if (pBDLExtension->CurrentPowerState == Off)
  1273. {
  1274. *pIRPAction = SkipRequest;
  1275. }
  1276. else
  1277. {
  1278. *pIRPAction = MarkPending;
  1279. }
  1280. break;
  1281. case PowerSystemUnspecified:
  1282. ASSERT(FALSE);
  1283. status = STATUS_UNSUCCESSFUL;
  1284. *pIRPAction = CompleteRequest;
  1285. }
  1286. BDLDebug(
  1287. BDL_DEBUG_TRACE,
  1288. ("%s %s: BDL!BDLSystemSetPower: Leave\n",
  1289. __DATE__,
  1290. __TIME__))
  1291. return (status);
  1292. }
  1293. NTSTATUS
  1294. BDLDevicePowerIoCompletion
  1295. (
  1296. IN PDEVICE_OBJECT pDeviceObject,
  1297. IN PIRP pIrp,
  1298. IN PVOID Context
  1299. )
  1300. {
  1301. NTSTATUS status = STATUS_SUCCESS;
  1302. POWER_IRP_CONTEXT *pPowerIrpContext = (POWER_IRP_CONTEXT *) Context;
  1303. PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension = pPowerIrpContext->pBDLExtension;
  1304. PIO_STACK_LOCATION pStackLocation = IoGetCurrentIrpStackLocation(pIrp);
  1305. PBDL_DRIVER_EXTENSION pDriverExtension = pBDLExtension->pDriverExtension;
  1306. BDSI_SETPOWERSTATE bdsiSetPowerStateParams;
  1307. BDLDebug(
  1308. BDL_DEBUG_TRACE,
  1309. ("%s %s: BDL!BDLDevicePowerIoCompletion: Enter\n",
  1310. __DATE__,
  1311. __TIME__))
  1312. //
  1313. // If this is a completion call for an IRP_MN_SET_POWER IRP, AND it is going
  1314. // into a working state, then call the BDD, otherwise just complete the IRP
  1315. // since it is one of the following:
  1316. // 1) a completion for an IRP_MN_SET_POWER IRP that is going into low power/shutdown
  1317. // (in which case the BDD was already called)
  1318. // 2) a completion for an IRP_MN_QUERY_POWER IRP
  1319. //
  1320. if ((pStackLocation->MinorFunction == IRP_MN_SET_POWER) &&
  1321. ( (pStackLocation->Parameters.Power.State.DeviceState == PowerDeviceD0) ||
  1322. (pStackLocation->Parameters.Power.State.DeviceState == PowerDeviceMaximum)))
  1323. {
  1324. RtlZeroMemory(&bdsiSetPowerStateParams, sizeof(bdsiSetPowerStateParams));
  1325. bdsiSetPowerStateParams.Size = sizeof(bdsiSetPowerStateParams);
  1326. bdsiSetPowerStateParams.PowerState = On;
  1327. status = pDriverExtension->bdsiFunctions.pfbdsiSetPowerState(
  1328. &(pBDLExtension->BdlExtenstion),
  1329. &bdsiSetPowerStateParams);
  1330. if (status == STATUS_SUCCESS)
  1331. {
  1332. PoSetPowerState(
  1333. pDeviceObject,
  1334. DevicePowerState,
  1335. pStackLocation->Parameters.Power.State);
  1336. }
  1337. else
  1338. {
  1339. BDLDebug(
  1340. BDL_DEBUG_ERROR,
  1341. ("%s %s: BDL!BDLDevicePowerIoCompletion: pfbdsiSetPowerState failed with %lx\n",
  1342. __DATE__,
  1343. __TIME__,
  1344. status))
  1345. }
  1346. pIrp->IoStatus.Status = status;
  1347. pIrp->IoStatus.Information = 0;
  1348. }
  1349. else
  1350. {
  1351. status = pIrp->IoStatus.Status;
  1352. }
  1353. IoReleaseRemoveLock(&(pBDLExtension->RemoveLock), (PVOID) 'rwoP');
  1354. PoStartNextPowerIrp(pIrp);
  1355. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1356. ExFreePoolWithTag(pPowerIrpContext, BDL_ULONG_TAG);
  1357. BDLDebug(
  1358. BDL_DEBUG_TRACE,
  1359. ("%s %s: BDL!BDLDevicePowerIoCompletion: Leave\n",
  1360. __DATE__,
  1361. __TIME__))
  1362. return (status);
  1363. }
  1364. NTSTATUS
  1365. BDLDeviceQueryPower
  1366. (
  1367. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1368. IN PIO_STACK_LOCATION pStackLocation,
  1369. OUT IRP_ACTION *pIRPAction,
  1370. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  1371. )
  1372. {
  1373. NTSTATUS status = STATUS_SUCCESS;
  1374. KIRQL irql;
  1375. BDLDebug(
  1376. BDL_DEBUG_TRACE,
  1377. ("%s %s: BDL!BDLDeviceQueryPower: Enter\n",
  1378. __DATE__,
  1379. __TIME__))
  1380. //
  1381. // Set the completion routine here just in case we mark as pending.
  1382. //
  1383. *pIoCompletionRoutine = BDLDevicePowerIoCompletion;
  1384. switch (pStackLocation->Parameters.Power.State.DeviceState)
  1385. {
  1386. case PowerDeviceD0:
  1387. case PowerDeviceMaximum:
  1388. //
  1389. // Because we are transitioning into a working state we don't
  1390. // need to check anything... since we can definitely make the
  1391. // transition. Mark as pending and continue processing in
  1392. // completion routine.
  1393. //
  1394. *pIRPAction = MarkPending;
  1395. break;
  1396. case PowerDeviceD2:
  1397. case PowerDeviceD3:
  1398. break;
  1399. //
  1400. // Since we are going into a low power mode or being shutdown
  1401. // check to see if there are any outstanding IO calls
  1402. //
  1403. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  1404. if (pBDLExtension->IoCount == 0)
  1405. {
  1406. //
  1407. // Block any further IOCTLs
  1408. //
  1409. KeClearEvent(&(pBDLExtension->DeviceStartedEvent));
  1410. //
  1411. // Mark as pending and continue processing in completion routine.
  1412. //
  1413. *pIRPAction = MarkPending;
  1414. }
  1415. else
  1416. {
  1417. //
  1418. // We can't go into sleep mode because the device is busy
  1419. //
  1420. status = STATUS_DEVICE_BUSY;
  1421. *pIRPAction = CompleteRequest;
  1422. }
  1423. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  1424. case PowerDeviceD1:
  1425. case PowerDeviceUnspecified:
  1426. //
  1427. // These states are unsupported
  1428. //
  1429. ASSERT(FALSE);
  1430. status = STATUS_UNSUCCESSFUL;
  1431. *pIRPAction = CompleteRequest;
  1432. break;
  1433. }
  1434. BDLDebug(
  1435. BDL_DEBUG_TRACE,
  1436. ("%s %s: BDL!BDLDeviceQueryPower: Leave\n",
  1437. __DATE__,
  1438. __TIME__))
  1439. return (status);
  1440. }
  1441. NTSTATUS
  1442. BDLDeviceSetPower
  1443. (
  1444. IN PDEVICE_OBJECT pDeviceObject,
  1445. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1446. IN PIO_STACK_LOCATION pStackLocation,
  1447. OUT IRP_ACTION *pIRPAction,
  1448. OUT PIO_COMPLETION_ROUTINE *pIoCompletionRoutine
  1449. )
  1450. {
  1451. NTSTATUS status = STATUS_SUCCESS;
  1452. PBDL_DRIVER_EXTENSION pDriverExtension = pBDLExtension->pDriverExtension;
  1453. BDSI_SETPOWERSTATE bdsiSetPowerStateParams;
  1454. BDLDebug(
  1455. BDL_DEBUG_TRACE,
  1456. ("%s %s: BDL!BDLDeviceSetPower: Enter\n",
  1457. __DATE__,
  1458. __TIME__))
  1459. //
  1460. // Set the completion routine here just in case we mark as pending.
  1461. //
  1462. *pIoCompletionRoutine = BDLDevicePowerIoCompletion;
  1463. switch (pStackLocation->Parameters.Power.State.DeviceState)
  1464. {
  1465. case PowerDeviceD0:
  1466. case PowerDeviceMaximum:
  1467. //
  1468. // If we are already in the requested state then skip the request,
  1469. // otherwise mark as pending which will pass the IRP down and continue
  1470. // processing in the completion routine
  1471. //
  1472. if (pBDLExtension->CurrentPowerState == On)
  1473. {
  1474. *pIRPAction = SkipRequest;
  1475. }
  1476. else
  1477. {
  1478. *pIRPAction = MarkPending;
  1479. }
  1480. break;
  1481. case PowerDeviceD2:
  1482. case PowerDeviceD3:
  1483. //
  1484. // If we are already in the requested state then skip the request,
  1485. // otherwise call the BDD and tell it to power down, then mark as
  1486. // pending which will pass the IRP down and then complete the IRP
  1487. // in the completion routine
  1488. //
  1489. if (pBDLExtension->CurrentPowerState == Off)
  1490. {
  1491. *pIRPAction = SkipRequest;
  1492. }
  1493. else
  1494. {
  1495. RtlZeroMemory(&bdsiSetPowerStateParams, sizeof(bdsiSetPowerStateParams));
  1496. bdsiSetPowerStateParams.Size = sizeof(bdsiSetPowerStateParams);
  1497. bdsiSetPowerStateParams.PowerState = Off;
  1498. status = pDriverExtension->bdsiFunctions.pfbdsiSetPowerState(
  1499. &(pBDLExtension->BdlExtenstion),
  1500. &bdsiSetPowerStateParams);
  1501. if (status == STATUS_SUCCESS)
  1502. {
  1503. PoSetPowerState(
  1504. pDeviceObject,
  1505. DevicePowerState,
  1506. pStackLocation->Parameters.Power.State);
  1507. *pIRPAction = MarkPending;
  1508. }
  1509. else
  1510. {
  1511. BDLDebug(
  1512. BDL_DEBUG_ERROR,
  1513. ("%s %s: BDL!BDLDeviceSetPower: pfbdsiSetPowerState failed with %lx\n",
  1514. __DATE__,
  1515. __TIME__,
  1516. status))
  1517. *pIRPAction = CompleteRequest;
  1518. }
  1519. }
  1520. break;
  1521. case PowerDeviceD1:
  1522. case PowerDeviceUnspecified:
  1523. //
  1524. // These states are unsupported
  1525. //
  1526. ASSERT(FALSE);
  1527. status = STATUS_UNSUCCESSFUL;
  1528. *pIRPAction = CompleteRequest;
  1529. break;
  1530. }
  1531. BDLDebug(
  1532. BDL_DEBUG_TRACE,
  1533. ("%s %s: BDL!BDLDeviceSetPower: Leave\n",
  1534. __DATE__,
  1535. __TIME__))
  1536. return (status);
  1537. }
  1538. /////////////////////////////////////////////////////////////////////////////////////////
  1539. //
  1540. // These functions are all the handlers for PNP events
  1541. //
  1542. NTSTATUS
  1543. BDLPnPStart
  1544. (
  1545. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1546. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1547. IN PIRP pIrp,
  1548. PIO_STACK_LOCATION pStackLocation
  1549. )
  1550. {
  1551. NTSTATUS status = STATUS_SUCCESS;
  1552. PBDL_DRIVER_EXTENSION pDriverExtension = pBDLExtension->pDriverExtension;
  1553. BDSI_INITIALIZERESOURCES bdsiInitializeResourcesParams;
  1554. BDLDebug(
  1555. BDL_DEBUG_TRACE,
  1556. ("%s %s: BDL!BDLPnPStartDevice: Enter\n",
  1557. __DATE__,
  1558. __TIME__))
  1559. //
  1560. // We have to call the lower level driver first when starting up
  1561. //
  1562. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1563. if (!NT_SUCCESS(status))
  1564. {
  1565. BDLDebug(
  1566. BDL_DEBUG_ERROR,
  1567. ("%s %s: BDL!BDLPnPStartDevice: BDLCallLowerLevelDriverAndWait failed with %lx\n",
  1568. __DATE__,
  1569. __TIME__,
  1570. status))
  1571. goto Return;
  1572. }
  1573. //
  1574. // Call the BDD's InitializeResources function
  1575. //
  1576. RtlZeroMemory(&bdsiInitializeResourcesParams, sizeof(bdsiInitializeResourcesParams));
  1577. bdsiInitializeResourcesParams.Size = sizeof(bdsiInitializeResourcesParams);
  1578. bdsiInitializeResourcesParams.pAllocatedResources =
  1579. pStackLocation->Parameters.StartDevice.AllocatedResources;
  1580. bdsiInitializeResourcesParams.pAllocatedResourcesTranslated =
  1581. pStackLocation->Parameters.StartDevice.AllocatedResourcesTranslated;
  1582. status = pDriverExtension->bdsiFunctions.pfbdsiInitializeResources(
  1583. &(pBDLExtension->BdlExtenstion),
  1584. &bdsiInitializeResourcesParams);
  1585. if (status != STATUS_SUCCESS)
  1586. {
  1587. BDLDebug(
  1588. BDL_DEBUG_ERROR,
  1589. ("%s %s: BDL!BDLPnPStartDevice: pfbdsiInitializeResources failed with %lx\n",
  1590. __DATE__,
  1591. __TIME__,
  1592. status))
  1593. goto Return;
  1594. }
  1595. //
  1596. // Save the device info
  1597. //
  1598. RtlCopyMemory(
  1599. &(pBDLExtension->wszSerialNumber[0]),
  1600. &(bdsiInitializeResourcesParams.wszSerialNumber[0]),
  1601. sizeof(pBDLExtension->wszSerialNumber));
  1602. pBDLExtension->HWVersionMajor = bdsiInitializeResourcesParams.HWVersionMajor;
  1603. pBDLExtension->HWVersionMinor = bdsiInitializeResourcesParams.HWVersionMinor;
  1604. pBDLExtension->HWBuildNumber = bdsiInitializeResourcesParams.HWBuildNumber;
  1605. pBDLExtension->BDDVersionMajor = bdsiInitializeResourcesParams.BDDVersionMajor;
  1606. pBDLExtension->BDDVersionMinor = bdsiInitializeResourcesParams.BDDVersionMinor;
  1607. pBDLExtension->BDDBuildNumber = bdsiInitializeResourcesParams.BDDBuildNumber;
  1608. //
  1609. // Enable the device interface
  1610. //
  1611. status = IoSetDeviceInterfaceState(&(pBDLExtension->SymbolicLinkName), TRUE);
  1612. if (status != STATUS_SUCCESS)
  1613. {
  1614. BDLDebug(
  1615. BDL_DEBUG_ERROR,
  1616. ("%s %s: BDL!BDLPnPStartDevice: IoSetDeviceInterfaceState failed with %lx\n",
  1617. __DATE__,
  1618. __TIME__,
  1619. status))
  1620. pDriverExtension->bdsiFunctions.pfbdsiReleaseResources(&(pBDLExtension->BdlExtenstion));
  1621. goto Return;
  1622. }
  1623. //
  1624. // This is set here indicating that BDLPnPRemove() should clean up whatever was
  1625. // inizialized during BDLPnPStart(). If this is not set then BDLPnPRemove()
  1626. // should only cleanup what BDLAddDevice() initialized.
  1627. //
  1628. pBDLExtension->fStartSucceeded = TRUE;
  1629. //
  1630. // We are open for business so set the device to started
  1631. //
  1632. KeSetEvent(&(pBDLExtension->DeviceStartedEvent), 0, FALSE);
  1633. Return:
  1634. BDLDebug(
  1635. BDL_DEBUG_TRACE,
  1636. ("%s %s: BDL!BDLPnPStartDevice: Leave\n",
  1637. __DATE__,
  1638. __TIME__))
  1639. return (status);
  1640. }
  1641. NTSTATUS
  1642. BDLPnPQueryStop
  1643. (
  1644. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1645. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1646. IN PIRP pIrp
  1647. )
  1648. {
  1649. NTSTATUS status = STATUS_SUCCESS;
  1650. KIRQL irql;
  1651. BDLDebug(
  1652. BDL_DEBUG_TRACE,
  1653. ("%s %s: BDL!BDLPnPQueryStop: Enter\n",
  1654. __DATE__,
  1655. __TIME__))
  1656. KeAcquireSpinLock(&(pBDLExtension->SpinLock), &irql);
  1657. //
  1658. // Check the IO count to see if we are currently doing anything
  1659. //
  1660. if (pBDLExtension->IoCount > 0)
  1661. {
  1662. //
  1663. // We refuse to stop if we have pending IO
  1664. //
  1665. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  1666. status = STATUS_DEVICE_BUSY;
  1667. }
  1668. else
  1669. {
  1670. //
  1671. // Stop processing IO requests by clearing the device started event
  1672. //
  1673. KeClearEvent(&(pBDLExtension->DeviceStartedEvent));
  1674. KeReleaseSpinLock(&(pBDLExtension->SpinLock), irql);
  1675. //
  1676. // Send to the lower level driver
  1677. //
  1678. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1679. }
  1680. BDLDebug(
  1681. BDL_DEBUG_TRACE,
  1682. ("%s %s: BDL!BDLPnPQueryStop: Leave\n",
  1683. __DATE__,
  1684. __TIME__))
  1685. return (status);
  1686. }
  1687. NTSTATUS
  1688. BDLPnPCancelStop
  1689. (
  1690. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1691. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1692. IN PIRP pIrp
  1693. )
  1694. {
  1695. NTSTATUS status = STATUS_SUCCESS;
  1696. BDLDebug(
  1697. BDL_DEBUG_TRACE,
  1698. ("%s %s: BDL!BDLPnPCancelStop: Enter\n",
  1699. __DATE__,
  1700. __TIME__))
  1701. //
  1702. // Send to the lower level driver
  1703. //
  1704. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1705. if (status != STATUS_SUCCESS)
  1706. {
  1707. BDLDebug(
  1708. BDL_DEBUG_ERROR,
  1709. ("%s %s: BDL!BDLPnPCancelStop: BDLCallLowerLevelDriverAndWait failed with %lx\n",
  1710. __DATE__,
  1711. __TIME__,
  1712. status))
  1713. goto Return;
  1714. }
  1715. //
  1716. // Set the device to started
  1717. //
  1718. KeSetEvent(&(pBDLExtension->DeviceStartedEvent), 0, FALSE);
  1719. Return:
  1720. BDLDebug(
  1721. BDL_DEBUG_TRACE,
  1722. ("%s %s: BDL!BDLPnPCancelStop: Leave\n",
  1723. __DATE__,
  1724. __TIME__))
  1725. return (status);
  1726. }
  1727. NTSTATUS
  1728. BDLPnPStop
  1729. (
  1730. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1731. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1732. IN PIRP pIrp
  1733. )
  1734. {
  1735. NTSTATUS status = STATUS_SUCCESS;
  1736. PBDL_DRIVER_EXTENSION pDriverExtension = pBDLExtension->pDriverExtension;
  1737. BDLDebug(
  1738. BDL_DEBUG_TRACE,
  1739. ("%s %s: BDL!BDLPnPStop: Enter\n",
  1740. __DATE__,
  1741. __TIME__))
  1742. //
  1743. // Disable the device interface (and ignore possible errors)
  1744. //
  1745. IoSetDeviceInterfaceState(&(pBDLExtension->SymbolicLinkName), FALSE);
  1746. //
  1747. // Call the BDD's ReleaseResources
  1748. //
  1749. status = pDriverExtension->bdsiFunctions.pfbdsiReleaseResources(&(pBDLExtension->BdlExtenstion));
  1750. if (status != STATUS_SUCCESS)
  1751. {
  1752. BDLDebug(
  1753. BDL_DEBUG_ERROR,
  1754. ("%s %s: BDL!BDLPnPStop: pfbdsiReleaseResources failed with %lx\n",
  1755. __DATE__,
  1756. __TIME__,
  1757. status))
  1758. goto Return;
  1759. }
  1760. //
  1761. // Set this here indicating the whatever was initialized during BDLPnPStart() has
  1762. // now been cleaned up.
  1763. //
  1764. pBDLExtension->fStartSucceeded = FALSE;
  1765. //
  1766. // Send to the lower level driver
  1767. //
  1768. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1769. if (status != STATUS_SUCCESS)
  1770. {
  1771. BDLDebug(
  1772. BDL_DEBUG_ERROR,
  1773. ("%s %s: BDL!BDLPnPStop: BDLCallLowerLevelDriverAndWait failed with %lx\n",
  1774. __DATE__,
  1775. __TIME__,
  1776. status))
  1777. goto Return;
  1778. }
  1779. Return:
  1780. BDLDebug(
  1781. BDL_DEBUG_TRACE,
  1782. ("%s %s: BDL!BDLPnPStop: Leave\n",
  1783. __DATE__,
  1784. __TIME__))
  1785. return (status);
  1786. }
  1787. NTSTATUS
  1788. BDLPnPQueryRemove
  1789. (
  1790. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1791. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1792. IN PIRP pIrp
  1793. )
  1794. {
  1795. NTSTATUS status = STATUS_SUCCESS;
  1796. BDLDebug(
  1797. BDL_DEBUG_TRACE,
  1798. ("%s %s: BDL!BDLPnPQueryRemove: Enter\n",
  1799. __DATE__,
  1800. __TIME__))
  1801. //
  1802. // Disable the interface (and ignore possible errors)
  1803. //
  1804. IoSetDeviceInterfaceState(&(pBDLExtension->SymbolicLinkName), FALSE);
  1805. //
  1806. // If someone is connected to us then fail the call. We will enable
  1807. // the device interface in IRP_MN_CANCEL_REMOVE_DEVICE again
  1808. //
  1809. if (pBDLExtension->DeviceOpen)
  1810. {
  1811. status = STATUS_UNSUCCESSFUL;
  1812. goto Return;
  1813. }
  1814. //
  1815. // Send to the lower level driver
  1816. //
  1817. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1818. if (status != STATUS_SUCCESS)
  1819. {
  1820. BDLDebug(
  1821. BDL_DEBUG_ERROR,
  1822. ("%s %s: BDL!BDLPnPQueryRemove: BDLCallLowerLevelDriverAndWait failed with %lx\n",
  1823. __DATE__,
  1824. __TIME__,
  1825. status))
  1826. goto Return;
  1827. }
  1828. Return:
  1829. BDLDebug(
  1830. BDL_DEBUG_TRACE,
  1831. ("%s %s: BDL!BDLPnPQueryRemove: Leave\n",
  1832. __DATE__,
  1833. __TIME__))
  1834. return (status);
  1835. }
  1836. NTSTATUS
  1837. BDLPnPCancelRemove
  1838. (
  1839. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1840. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1841. IN PIRP pIrp
  1842. )
  1843. {
  1844. NTSTATUS status = STATUS_SUCCESS;
  1845. BDLDebug(
  1846. BDL_DEBUG_TRACE,
  1847. ("%s %s: BDL!BDLPnPCancelRemove: Enter\n",
  1848. __DATE__,
  1849. __TIME__))
  1850. //
  1851. // Send to the lower level driver first
  1852. //
  1853. status = BDLCallLowerLevelDriverAndWait(pAttachedDeviceObject, pIrp);
  1854. if (status != STATUS_SUCCESS)
  1855. {
  1856. BDLDebug(
  1857. BDL_DEBUG_ERROR,
  1858. ("%s %s: BDL!BDLPnPCancelRemove: BDLCallLowerLevelDriverAndWait failed with %lx\n",
  1859. __DATE__,
  1860. __TIME__,
  1861. status))
  1862. goto Return;
  1863. }
  1864. //
  1865. // Enable the interface
  1866. //
  1867. status = IoSetDeviceInterfaceState(&(pBDLExtension->SymbolicLinkName), TRUE);
  1868. if (status != STATUS_SUCCESS)
  1869. {
  1870. BDLDebug(
  1871. BDL_DEBUG_ERROR,
  1872. ("%s %s: BDL!BDLPnPCancelRemove: IoSetDeviceInterfaceState failed with %lx\n",
  1873. __DATE__,
  1874. __TIME__,
  1875. status))
  1876. goto Return;
  1877. }
  1878. Return:
  1879. BDLDebug(
  1880. BDL_DEBUG_TRACE,
  1881. ("%s %s: BDL!BDLPnPCancelRemove: Leave\n",
  1882. __DATE__,
  1883. __TIME__))
  1884. return (status);
  1885. }
  1886. NTSTATUS
  1887. BDLHandleRemove
  1888. (
  1889. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1890. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1891. IN PIRP pIrp
  1892. )
  1893. {
  1894. NTSTATUS status = STATUS_SUCCESS;
  1895. PBDL_DRIVER_EXTENSION pDriverExtension = pBDLExtension->pDriverExtension;
  1896. BDLDebug(
  1897. BDL_DEBUG_TRACE,
  1898. ("%s %s: BDL!BDLHandleRemove: Enter\n",
  1899. __DATE__,
  1900. __TIME__))
  1901. //
  1902. // Set this event so that any outstanding IOCTLs will be released.
  1903. // It is anti-intuitive to set the started event when the device is
  1904. // removed, but once this event is set, and the IOCTL threads get
  1905. // released, they will all fail when they try to acquire the remove lock.
  1906. //
  1907. // This handles the situation when you have a stopped device, a blocked
  1908. // IOCTL call, and then the device is removed.
  1909. //
  1910. KeSetEvent(&(pBDLExtension->DeviceStartedEvent), 0, FALSE);
  1911. //
  1912. // Disable the interface
  1913. //
  1914. IoSetDeviceInterfaceState(&(pBDLExtension->SymbolicLinkName), FALSE);
  1915. //
  1916. // Clean up any outstanding notification info and data handles
  1917. //
  1918. BDLCleanupNotificationStruct(pBDLExtension);
  1919. BDLCleanupDataHandles(pBDLExtension);
  1920. //
  1921. // If the device is currently started, then stop it.
  1922. //
  1923. if (pBDLExtension->fStartSucceeded == TRUE)
  1924. {
  1925. status = pDriverExtension->bdsiFunctions.pfbdsiReleaseResources(&(pBDLExtension->BdlExtenstion));
  1926. if (status != STATUS_SUCCESS)
  1927. {
  1928. BDLDebug(
  1929. BDL_DEBUG_ERROR,
  1930. ("%s %s: BDL!BDLHandleRemove: pfbdsiReleaseResources failed with %lx\n",
  1931. __DATE__,
  1932. __TIME__,
  1933. status))
  1934. }
  1935. pBDLExtension->fStartSucceeded = FALSE;
  1936. }
  1937. //
  1938. // Tell the BDD to remove the device
  1939. //
  1940. status = pDriverExtension->bdsiFunctions.pfbdsiRemoveDevice(&(pBDLExtension->BdlExtenstion));
  1941. if (status != STATUS_SUCCESS)
  1942. {
  1943. BDLDebug(
  1944. BDL_DEBUG_ERROR,
  1945. ("%s %s: BDL!BDLHandleRemove: pfbdsiRemoveDevice failed with %lx\n",
  1946. __DATE__,
  1947. __TIME__,
  1948. status))
  1949. }
  1950. //
  1951. // Send to the lower level driver
  1952. //
  1953. IoSkipCurrentIrpStackLocation(pIrp);
  1954. status = IoCallDriver(pAttachedDeviceObject, pIrp);
  1955. if (status != STATUS_SUCCESS)
  1956. {
  1957. BDLDebug(
  1958. BDL_DEBUG_ERROR,
  1959. ("%s %s: BDL!BDLHandleRemove: IoCallDriver failed with %lx\n",
  1960. __DATE__,
  1961. __TIME__,
  1962. status))
  1963. }
  1964. BDLDebug(
  1965. BDL_DEBUG_TRACE,
  1966. ("%s %s: BDL!BDLHandleRemove: Leave\n",
  1967. __DATE__,
  1968. __TIME__))
  1969. return (status);
  1970. }
  1971. NTSTATUS
  1972. BDLPnPRemove
  1973. (
  1974. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  1975. IN PDEVICE_OBJECT pDeviceObject,
  1976. IN PDEVICE_OBJECT pAttachedDeviceObject,
  1977. IN PIRP pIrp
  1978. )
  1979. {
  1980. NTSTATUS status = STATUS_SUCCESS;
  1981. BDLDebug(
  1982. BDL_DEBUG_TRACE,
  1983. ("%s %s: BDL!BDLPnPRemove: Enter\n",
  1984. __DATE__,
  1985. __TIME__))
  1986. //
  1987. // If there was a surprise removal then we don't need to cleanup...
  1988. // since the surprise removal already did it
  1989. //
  1990. if (pBDLExtension->fDeviceRemoved == FALSE)
  1991. {
  1992. pBDLExtension->fDeviceRemoved = TRUE;
  1993. BDLHandleRemove(pBDLExtension, pAttachedDeviceObject, pIrp);
  1994. }
  1995. //
  1996. // Wait until there are no more outstanding IRPs
  1997. //
  1998. IoReleaseRemoveLockAndWait(&(pBDLExtension->RemoveLock), (PVOID) ' vmR');
  1999. //
  2000. // cleanup stuff that was initialized in AddDevice
  2001. //
  2002. BDLCleanupDeviceCapabilities(pBDLExtension);
  2003. IoDetachDevice(pAttachedDeviceObject);
  2004. RtlFreeUnicodeString(&(pBDLExtension->SymbolicLinkName));
  2005. IoDeleteDevice(pDeviceObject);
  2006. BDLDebug(
  2007. BDL_DEBUG_TRACE,
  2008. ("%s %s: BDL!BDLPnPRemove: Leave\n",
  2009. __DATE__,
  2010. __TIME__))
  2011. return (status);
  2012. }
  2013. NTSTATUS
  2014. BDLPnPSurpriseRemoval
  2015. (
  2016. IN PBDL_INTERNAL_DEVICE_EXTENSION pBDLExtension,
  2017. IN PDEVICE_OBJECT pAttachedDeviceObject,
  2018. IN PIRP pIrp
  2019. )
  2020. {
  2021. NTSTATUS status = STATUS_SUCCESS;
  2022. BDLDebug(
  2023. BDL_DEBUG_TRACE,
  2024. ("%s %s: BDL!BDLPnPSurpriseRemoval: Enter\n",
  2025. __DATE__,
  2026. __TIME__))
  2027. pBDLExtension->fDeviceRemoved = TRUE;
  2028. //
  2029. // Don't need to check errors, nothing we can do.
  2030. //
  2031. BDLHandleRemove(pBDLExtension, pAttachedDeviceObject, pIrp);
  2032. BDLDebug(
  2033. BDL_DEBUG_TRACE,
  2034. ("%s %s: BDL!BDLPnPSurpriseRemoval: Leave\n",
  2035. __DATE__,
  2036. __TIME__))
  2037. return (status);
  2038. }
  2039. /////////////////////////////////////////////////////////////////////////////////////////
  2040. //
  2041. // These functions are exported by the BDL
  2042. //
  2043. //
  2044. // bdliInitialize()
  2045. //
  2046. // Called in response to the BDD receiving its DriverEntry call. This lets the BDL
  2047. // know that a new BDD has been loaded and allows the BDL to initialize its state so that
  2048. // it can manage the newly loaded BDD.
  2049. //
  2050. // The bdliInitialize call will set the appropriate fields in the DRIVER_OBJECT so that
  2051. // the BDL will receive all the necessary callbacks from the system for PNP events,
  2052. // Power events, and general driver functionality. The BDL will then forward calls that
  2053. // require hardware support to the BDD that called bdliInitialize (it will do so using
  2054. // the BDDI and BDSI APIs). A BDD must call the bdliInitialize call during its
  2055. // DriverEntry function.
  2056. //
  2057. // PARAMETERS:
  2058. // DriverObject This must be the DRIVER_OBJECT pointer that was passed into the
  2059. // BDD's DriverEntry call.
  2060. // RegistryPath This must be the UNICODE_STRING pointer that was passed into the
  2061. // BDD's DriverEntry call.
  2062. // pBDDIFunctions Pointer to a BDLI_BDDIFUNCTIONS structure that is filled in with the
  2063. // entry points that the BDD exports to support the BDDI API set. The
  2064. // pointers themselves are copied by the BDL, as opposed to saving the
  2065. // pBDDIFunctions pointer, so the memory pointed to by pBDDIFunctions
  2066. // need not remain accessible after the bdliInitialize call.
  2067. // pBDSIFunctions Pointer to a BDLI_BDSIFUNCTIONS structure that is filled in with
  2068. // the entry points that the BDD exports to support the BDSI API set.
  2069. // The pointers themselves are copied by the BDL, as opposed to saving
  2070. // the pBDSIFunctions pointer, so the memory pointed to by
  2071. // pBDSIFunctions need not remain accessible after the bdliInitialize
  2072. // call.
  2073. // Flags Unused. Must be 0.
  2074. // pReserved Unused. Must be NULL.
  2075. //
  2076. // RETURNS:
  2077. // STATUS_SUCCESS If the bdliInitialize call succeeded
  2078. //
  2079. NTSTATUS
  2080. bdliInitialize
  2081. (
  2082. IN PDRIVER_OBJECT pDriverObject,
  2083. IN PUNICODE_STRING RegistryPath,
  2084. IN PBDLI_BDDIFUNCTIONS pBDDIFunctions,
  2085. IN PBDLI_BDSIFUNCTIONS pBDSIFunctions,
  2086. IN ULONG Flags,
  2087. IN PVOID pReserved
  2088. )
  2089. {
  2090. NTSTATUS status = STATUS_SUCCESS;
  2091. PBDL_DRIVER_EXTENSION pDriverExtension = NULL;
  2092. BDLDebug(
  2093. BDL_DEBUG_TRACE,
  2094. ("%s %s: BDL!bdliInitialize: Enter\n",
  2095. __DATE__,
  2096. __TIME__))
  2097. //
  2098. // Initialize the Driver Object with the BDL's entry points
  2099. //
  2100. pDriverObject->DriverUnload = BDLDriverUnload;
  2101. pDriverObject->MajorFunction[IRP_MJ_CREATE] = BDLCreate;
  2102. pDriverObject->MajorFunction[IRP_MJ_CLOSE] = BDLClose;
  2103. pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = BDLCleanup;
  2104. pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BDLDeviceControl;
  2105. pDriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = BDLSystemControl;
  2106. pDriverObject->MajorFunction[IRP_MJ_PNP] = BDLPnP;
  2107. pDriverObject->MajorFunction[IRP_MJ_POWER] = BDLPower;
  2108. pDriverObject->DriverExtension->AddDevice = BDLAddDevice;
  2109. //
  2110. // Allocate a slot for the BDL driver extension structure
  2111. //
  2112. status = IoAllocateDriverObjectExtension(
  2113. pDriverObject,
  2114. BDL_DRIVER_EXTENSION_ID,
  2115. sizeof(BDL_DRIVER_EXTENSION),
  2116. &pDriverExtension);
  2117. if (status != STATUS_SUCCESS)
  2118. {
  2119. //
  2120. // This could happen if the BDD stole our slot
  2121. //
  2122. if (status == STATUS_OBJECT_NAME_COLLISION )
  2123. {
  2124. BDLDebug(
  2125. BDL_DEBUG_ERROR,
  2126. ("%s %s: BDL!bdliInitialize: The BDD stole our DriverExtension slot\n",
  2127. __DATE__,
  2128. __TIME__))
  2129. }
  2130. else
  2131. {
  2132. BDLDebug(
  2133. BDL_DEBUG_ERROR,
  2134. ("%s %s: BDL!bdliInitialize: IoAllocateDriverObjectExtension failed with %lx\n",
  2135. __DATE__,
  2136. __TIME__,
  2137. status))
  2138. }
  2139. goto Return;
  2140. }
  2141. //
  2142. // Initialize the driver extension structure
  2143. //
  2144. pDriverExtension->bddiFunctions = *pBDDIFunctions;
  2145. pDriverExtension->bdsiFunctions = *pBDSIFunctions;
  2146. Return:
  2147. BDLDebug(
  2148. BDL_DEBUG_TRACE,
  2149. ("%s %s: BDL!bdliInitialize: Leave\n",
  2150. __DATE__,
  2151. __TIME__))
  2152. return (status);
  2153. }
  2154. //
  2155. // bdliAlloc()
  2156. //
  2157. // Allocates memory that can be returned to the BDL.
  2158. //
  2159. // The BDD must always use this function to allocate memory that it will return to the
  2160. // BDL as an OUT parameter of a BDDI call. Once memory has been returned to the BDL,
  2161. // it will be owned and managed exclusively by the BDL and must not be further referenced
  2162. // by the BDD. (Each BDDI call that requires the use of bdliAlloc will note it).
  2163. //
  2164. // PARAMETERS:
  2165. // pBDLExt Pointer to the BDL_DEVICEEXT structure that was passed into the
  2166. // bdsiAddDevice call.
  2167. // NumBytes The number of bytes to allocate.
  2168. // Flags Unused. Must be 0.
  2169. //
  2170. // RETURNS:
  2171. // Returns a pointer to the allocated memory, or NULL if the function fails.
  2172. //
  2173. void *
  2174. bdliAlloc
  2175. (
  2176. IN PBDL_DEVICEEXT pBDLExt,
  2177. IN ULONG NumBytes,
  2178. IN ULONG Flags
  2179. )
  2180. {
  2181. return (ExAllocatePoolWithTag(PagedPool, NumBytes, BDLI_ULONG_TAG));
  2182. }
  2183. //
  2184. // bdliFree()
  2185. //
  2186. // Frees memory allocated by bdliAlloc.
  2187. //
  2188. // Memory allocated by bdliAlloc is almost always passed to the BDL as a channel product
  2189. // (as a BLOCK-type item) and subsequently freed by the BDL. However, if an error
  2190. // occurs while processing a channel, the BDD may need to call bdliFree to free memory it
  2191. // previous allocated via bdliAlloc.
  2192. //
  2193. // PARAMETERS:
  2194. // pvBlock Block of memory passed in by the BDL.
  2195. //
  2196. // RETURNS:
  2197. // No return value.
  2198. //
  2199. void
  2200. bdliFree
  2201. (
  2202. IN PVOID pvBlock
  2203. )
  2204. {
  2205. ExFreePoolWithTag(pvBlock, BDLI_ULONG_TAG);
  2206. }
  2207. //
  2208. // bdliLogError()
  2209. //
  2210. // Writes an error to the event log.
  2211. //
  2212. // Provides a simple mechanism for BDD writers to write errors to the system event log
  2213. // without the overhead of registering with the event logging subsystem.
  2214. //
  2215. // PARAMETERS:
  2216. // pObject If the error being logged is device specific then this must be a
  2217. // pointer to the BDL_DEVICEEXT structure that was passed into the
  2218. // bdsiAddDevice call when the device was added. If the error being
  2219. // logged is a general BDD error, then this must be same DRIVER_OBJECT
  2220. // structure pointer that was passed into the DriverEntry call of the
  2221. // BDD when the driver was loaded.
  2222. // ErrorCode Error code of the function logging the error.
  2223. // Insertion An insertion string to be written to the event log. Your message file
  2224. // must have a place holder for the insertion. For example, "serial port
  2225. // %2 is either not available or used by another device". In this
  2226. // example, %2 will be replaced by the insertion string. Note that %1 is
  2227. // reserved for the file name.
  2228. // cDumpData The number of bytes pointed to by pbDumpData.
  2229. // pDumpData A data block to be displayed in the data window of the event log.
  2230. // This may be NULL if the caller does not wish to display any dump data.
  2231. // Flags Unused. Must be 0.
  2232. // pReserved Unused. Must be NULL.
  2233. //
  2234. // RETURNS:
  2235. // STATUS_SUCCESS If the bdliLogError call succeeded
  2236. //
  2237. NTSTATUS
  2238. bdliLogError
  2239. (
  2240. IN PVOID pObject,
  2241. IN NTSTATUS ErrorCode,
  2242. IN PUNICODE_STRING Insertion,
  2243. IN ULONG cDumpData,
  2244. IN PUCHAR pDumpData,
  2245. IN ULONG Flags,
  2246. IN PVOID pReserved
  2247. )
  2248. {
  2249. return (STATUS_SUCCESS);
  2250. }
  2251. //
  2252. // bdliControlChange()
  2253. //
  2254. // This function allows BDDs to asynchronously return the values of its controls.
  2255. //
  2256. // bdliControlChange is generally called by the BDD in response to one of its controls
  2257. // changing a value. Specifically, it is most often used in the case of a sensor
  2258. // control that has changed from 0 to 1 indicating that a source is present and a sample
  2259. // can be taken.
  2260. //
  2261. // PARAMETERS:
  2262. // pBDLExt Pointer to the BDL_DEVICEEXT structure that was passed into the
  2263. // bdsiAddDevice call.
  2264. // ComponentId Specifies either the Component ID of the component in which the
  2265. // control or the control's parent channel resides, or '0' to indicate
  2266. // that dwControlId refers to a device control.
  2267. // ChannelId If dwComponentId is not '0', dwChannelId specifies either the Channel
  2268. // ID of the channel in which the control resides, or '0' to indicate
  2269. // that dwControlId refers to a component control.Ignored if
  2270. // dwComponentId is '0'.
  2271. // ControlId ControlId of the changed control.
  2272. // Value Specifies the new value for the control .
  2273. // Flags Unused. Must be 0.
  2274. // pReserved Unused. Must be NULL.
  2275. //
  2276. // RETURNS:
  2277. // STATUS_SUCCESS If the bdliControlChange call succeeded
  2278. //
  2279. NTSTATUS
  2280. bdliControlChange
  2281. (
  2282. IN PBDL_DEVICEEXT pBDLExt,
  2283. IN ULONG ComponentId,
  2284. IN ULONG ChannelId,
  2285. IN ULONG ControlId,
  2286. IN ULONG Value,
  2287. IN ULONG Flags,
  2288. IN PVOID pReserved
  2289. )
  2290. {
  2291. BDL_INTERNAL_DEVICE_EXTENSION *pBDLExtension = (BDL_INTERNAL_DEVICE_EXTENSION *) pBDLExt;
  2292. ULONG i;
  2293. KIRQL irql;
  2294. ULONG TimeInSec = 0;
  2295. LARGE_INTEGER CurrentTime;
  2296. BDLDebug(
  2297. BDL_DEBUG_TRACE,
  2298. ("%s %s: BDL!bdliControlChange: Enter\n",
  2299. __DATE__,
  2300. __TIME__))
  2301. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ISRControlChangeLock), &irql);
  2302. //
  2303. // Save the current IRQ level so that when the DPC routine is executed it
  2304. // knows what level to elevate its IRQL to when getting an item from the
  2305. // ISRControlChangeQueue
  2306. //
  2307. pBDLExtension->ControlChangeStruct.ISRirql = KeGetCurrentIrql();
  2308. //
  2309. // Make sure the BDD isn't call us too often
  2310. //
  2311. if (pBDLExtension->ControlChangeStruct.NumCalls <= 8)
  2312. {
  2313. pBDLExtension->ControlChangeStruct.NumCalls++;
  2314. }
  2315. else
  2316. {
  2317. //
  2318. // FIX FIX - probably need to make this configurable (via registry) at some point
  2319. //
  2320. //
  2321. // We have received 10 notifies, make sure it has been longer than 1 second
  2322. //
  2323. KeQueryTickCount(&(CurrentTime));
  2324. TimeInSec = (ULONG)
  2325. ((pBDLExtension->ControlChangeStruct.StartTime.QuadPart - CurrentTime.QuadPart) *
  2326. KeQueryTimeIncrement() / 10000000);
  2327. if (TimeInSec == 0)
  2328. {
  2329. BDLDebug(
  2330. BDL_DEBUG_ERROR,
  2331. ("%s %s: BDL!bdliControlChange: BDD calling too often\n",
  2332. __DATE__,
  2333. __TIME__))
  2334. goto Return;
  2335. }
  2336. else
  2337. {
  2338. pBDLExtension->ControlChangeStruct.NumCalls = 1;
  2339. KeQueryTickCount(&(pBDLExtension->ControlChangeStruct.StartTime));
  2340. }
  2341. }
  2342. //
  2343. // Get a free item from the pool
  2344. //
  2345. for (i = 0; i < CONTROL_CHANGE_POOL_SIZE; i++)
  2346. {
  2347. if (pBDLExtension->ControlChangeStruct.rgControlChangePool[i].fUsed == FALSE)
  2348. {
  2349. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].fUsed = TRUE;
  2350. //
  2351. // Add the item to the queue
  2352. //
  2353. InsertTailList(
  2354. &(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue),
  2355. &(pBDLExtension->ControlChangeStruct.rgControlChangePool[i].ListEntry));
  2356. break;
  2357. }
  2358. }
  2359. if (i >= CONTROL_CHANGE_POOL_SIZE)
  2360. {
  2361. BDLDebug(
  2362. BDL_DEBUG_ERROR,
  2363. ("%s %s: BDL!bdliControlChange: No free items\n",
  2364. __DATE__,
  2365. __TIME__))
  2366. goto Return;
  2367. }
  2368. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].ComponentId = ComponentId;
  2369. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].ChannelId = ChannelId;
  2370. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].ControlId = ControlId;
  2371. pBDLExtension->ControlChangeStruct.rgControlChangePool[i].Value = Value;
  2372. //
  2373. // Request a DPC. In the DPC we will move this notification from the
  2374. // ISRControlChangeQueue to the IOCTLControlChangeQueue
  2375. //
  2376. KeInsertQueueDpc(&(pBDLExtension->ControlChangeStruct.DpcObject), NULL, NULL);
  2377. Return:
  2378. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ISRControlChangeLock), irql);
  2379. BDLDebug(
  2380. BDL_DEBUG_TRACE,
  2381. ("%s %s: BDL!bdliControlChange: Leave\n",
  2382. __DATE__,
  2383. __TIME__))
  2384. return (STATUS_SUCCESS);
  2385. }
  2386. VOID
  2387. BDLControlChangeDpc
  2388. (
  2389. IN PKDPC pDpc,
  2390. IN BDL_INTERNAL_DEVICE_EXTENSION *pBDLExtension,
  2391. IN PVOID pArg1,
  2392. IN PVOID pArg2
  2393. )
  2394. {
  2395. KIRQL oldIrql, irql;
  2396. BDL_ISR_CONTROL_CHANGE_ITEM *pISRControlChangeItem = NULL;
  2397. PLIST_ENTRY pISRControlChangeEntry = NULL;
  2398. BDL_IOCTL_CONTROL_CHANGE_ITEM *pIOCTLControlChangeItem = NULL;
  2399. PLIST_ENTRY pIOCTLControlChangeEntry = NULL;
  2400. PIRP pIrpToComplete = NULL;
  2401. PUCHAR pv = NULL;
  2402. BDLDebug(
  2403. BDL_DEBUG_TRACE,
  2404. ("%s %s: BDL!BDLControlChangeDpc: Enter\n",
  2405. __DATE__,
  2406. __TIME__))
  2407. //
  2408. // Loop until there are no more items in the ISRControlChangeQueue
  2409. //
  2410. while (1)
  2411. {
  2412. //
  2413. // Allocate a new item to be added to the IOCTLControlChangeQueue
  2414. //
  2415. pIOCTLControlChangeItem = ExAllocatePoolWithTag(
  2416. PagedPool,
  2417. sizeof(BDL_IOCTL_CONTROL_CHANGE_ITEM),
  2418. BDL_ULONG_TAG);
  2419. if (pIOCTLControlChangeItem == NULL)
  2420. {
  2421. BDLDebug(
  2422. BDL_DEBUG_ERROR,
  2423. ("%s %s: BDL!BDLControlChangeDpc: ExAllocatePoolWithTag failed\n",
  2424. __DATE__,
  2425. __TIME__))
  2426. return;
  2427. }
  2428. //
  2429. // Need to raise the IRQL to access the ISRControlChangeQueue
  2430. //
  2431. KeRaiseIrql(pBDLExtension->ControlChangeStruct.ISRirql, &oldIrql);
  2432. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ISRControlChangeLock), &irql);
  2433. //
  2434. // Check to see if the ISRControlChangeQueue has any items
  2435. //
  2436. if (!IsListEmpty(&(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue)))
  2437. {
  2438. //
  2439. // There is at least one item, so get the head of the queue
  2440. //
  2441. pISRControlChangeEntry =
  2442. RemoveHeadList(&(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue));
  2443. pISRControlChangeItem = CONTAINING_RECORD(
  2444. pISRControlChangeEntry,
  2445. BDL_ISR_CONTROL_CHANGE_ITEM,
  2446. ListEntry);
  2447. pIOCTLControlChangeItem->ComponentId = pISRControlChangeItem->ComponentId;
  2448. pIOCTLControlChangeItem->ChannelId = pISRControlChangeItem->ChannelId;
  2449. pIOCTLControlChangeItem->ControlId = pISRControlChangeItem->ControlId;
  2450. pIOCTLControlChangeItem->Value = pISRControlChangeItem->Value;
  2451. pISRControlChangeItem->fUsed = FALSE;
  2452. }
  2453. else
  2454. {
  2455. //
  2456. // There aren't any items in ISRControlChangeQueue, so set pIOCTLControlChangeItem
  2457. // to NULL which will indicate we are done with the loop
  2458. //
  2459. ExFreePoolWithTag(pIOCTLControlChangeItem, BDL_ULONG_TAG);
  2460. pIOCTLControlChangeItem = NULL;
  2461. }
  2462. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ISRControlChangeLock), irql);
  2463. KeLowerIrql(oldIrql);
  2464. if (pIOCTLControlChangeItem == NULL)
  2465. {
  2466. break;
  2467. }
  2468. //
  2469. // Add the head of the ISRControlChangeQueue to the tail of the IOCTLControlChangeQueue
  2470. //
  2471. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  2472. InsertTailList(
  2473. &(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue),
  2474. &(pIOCTLControlChangeItem->ListEntry));
  2475. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  2476. }
  2477. //
  2478. // Now, if there is an item in the IOCTLControlChangeQueue and the GetNotification IRP
  2479. // is pending, complete the IRP with the head of the IOCTLControlChangeQueue
  2480. //
  2481. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  2482. if ((!IsListEmpty(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue))) &&
  2483. (pBDLExtension->ControlChangeStruct.pIrp != NULL))
  2484. {
  2485. pIOCTLControlChangeEntry =
  2486. RemoveHeadList(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue));
  2487. pIOCTLControlChangeItem = CONTAINING_RECORD(
  2488. pIOCTLControlChangeEntry,
  2489. BDL_IOCTL_CONTROL_CHANGE_ITEM,
  2490. ListEntry);
  2491. pIrpToComplete = pBDLExtension->ControlChangeStruct.pIrp;
  2492. pBDLExtension->ControlChangeStruct.pIrp = NULL;
  2493. }
  2494. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  2495. if (pIrpToComplete != NULL)
  2496. {
  2497. pv = pIrpToComplete->AssociatedIrp.SystemBuffer;
  2498. *((ULONG *) pv) = pIOCTLControlChangeItem->ComponentId;
  2499. pv += sizeof(ULONG);
  2500. *((ULONG *) pv) = pIOCTLControlChangeItem->ChannelId;
  2501. pv += sizeof(ULONG);
  2502. *((ULONG *) pv) = pIOCTLControlChangeItem->ControlId;
  2503. pv += sizeof(ULONG);
  2504. *((ULONG *) pv) = pIOCTLControlChangeItem->Value;
  2505. ExFreePoolWithTag(pIOCTLControlChangeItem, BDL_ULONG_TAG);
  2506. pIrpToComplete->IoStatus.Information = SIZEOF_GETNOTIFICATION_OUTPUTBUFFER;
  2507. pIrpToComplete->IoStatus.Status = STATUS_SUCCESS;
  2508. IoCompleteRequest(pIrpToComplete, IO_NO_INCREMENT);
  2509. }
  2510. BDLDebug(
  2511. BDL_DEBUG_TRACE,
  2512. ("%s %s: BDL!BDLControlChangeDpc: Leave\n",
  2513. __DATE__,
  2514. __TIME__))
  2515. }
  2516. VOID
  2517. BDLCleanupNotificationStruct
  2518. (
  2519. IN BDL_INTERNAL_DEVICE_EXTENSION *pBDLExtension
  2520. )
  2521. {
  2522. KIRQL OldIrql, irql;
  2523. BDL_ISR_CONTROL_CHANGE_ITEM *pISRControlChangeItem = NULL;
  2524. PLIST_ENTRY pISRControlChangeEntry = NULL;
  2525. BDL_IOCTL_CONTROL_CHANGE_ITEM *pIOCTLControlChangeItem = NULL;
  2526. PLIST_ENTRY pIOCTLControlChangeEntry = NULL;
  2527. BDL_CONTROL_CHANGE_REGISTRATION *pControlChangeRegistration = NULL;
  2528. PLIST_ENTRY pRegistrationListEntry = NULL;
  2529. BDDI_PARAMS_REGISTERNOTIFY bddiRegisterNotifyParams;
  2530. NTSTATUS status;
  2531. BDLDebug(
  2532. BDL_DEBUG_TRACE,
  2533. ("%s %s: BDL!BDLCleanupNotificationStruct: Enter\n",
  2534. __DATE__,
  2535. __TIME__))
  2536. bddiRegisterNotifyParams.fRegister = FALSE;
  2537. //
  2538. // Clean up all the registered control changes
  2539. //
  2540. while (1)
  2541. {
  2542. //
  2543. // Note that we must raise the irql to dispatch level because we are synchronizing
  2544. // with a dispatch routine (BDLControlChangeDpc) that adds items to the queue at
  2545. // dispatch level
  2546. //
  2547. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  2548. KeAcquireSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), &irql);
  2549. if (IsListEmpty(&(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList)))
  2550. {
  2551. //
  2552. // the lock we are currently holding will be released below
  2553. //
  2554. break;
  2555. }
  2556. pRegistrationListEntry =
  2557. RemoveHeadList(&(pBDLExtension->ControlChangeStruct.ControlChangeRegistrationList));
  2558. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  2559. KeLowerIrql(OldIrql);
  2560. pControlChangeRegistration = CONTAINING_RECORD(
  2561. pRegistrationListEntry,
  2562. BDL_CONTROL_CHANGE_REGISTRATION,
  2563. ListEntry);
  2564. bddiRegisterNotifyParams.ComponentId = pControlChangeRegistration->ComponentId;
  2565. bddiRegisterNotifyParams.ChannelId = pControlChangeRegistration->ChannelId;
  2566. bddiRegisterNotifyParams.ControlId = pControlChangeRegistration->ControlId;
  2567. ExFreePoolWithTag(pControlChangeRegistration, BDL_ULONG_TAG);
  2568. //
  2569. // Call the BDD
  2570. //
  2571. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiRegisterNotify(
  2572. &(pBDLExtension->BdlExtenstion),
  2573. &bddiRegisterNotifyParams);
  2574. if (status != STATUS_SUCCESS)
  2575. {
  2576. BDLDebug(
  2577. BDL_DEBUG_ERROR,
  2578. ("%s %s: BDL!BDLCleanupNotificationStruct: pfbddiRegisterNotify failed with %lx\n",
  2579. __DATE__,
  2580. __TIME__,
  2581. status))
  2582. //
  2583. // Just continue... nothing else we can do
  2584. //
  2585. }
  2586. }
  2587. //
  2588. // Note: we are still holding the lock at this point
  2589. //
  2590. //
  2591. // Since we know there are no registered callbacks we should be able to clear up
  2592. // the ISRControlChangeQueue even though we are only running at dispatch level.
  2593. //
  2594. while (!IsListEmpty(&(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue)))
  2595. {
  2596. pISRControlChangeEntry =
  2597. RemoveHeadList(&(pBDLExtension->ControlChangeStruct.ISRControlChangeQueue));
  2598. pISRControlChangeItem = CONTAINING_RECORD(
  2599. pISRControlChangeEntry,
  2600. BDL_ISR_CONTROL_CHANGE_ITEM,
  2601. ListEntry);
  2602. pISRControlChangeItem->fUsed = FALSE;
  2603. }
  2604. //
  2605. // Clean up IOCTLControlChangeQueue
  2606. //
  2607. while (!IsListEmpty(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue)))
  2608. {
  2609. pIOCTLControlChangeEntry =
  2610. RemoveHeadList(&(pBDLExtension->ControlChangeStruct.IOCTLControlChangeQueue));
  2611. pIOCTLControlChangeItem = CONTAINING_RECORD(
  2612. pIOCTLControlChangeEntry,
  2613. BDL_IOCTL_CONTROL_CHANGE_ITEM,
  2614. ListEntry);
  2615. ExFreePoolWithTag(pIOCTLControlChangeItem, BDL_ULONG_TAG);
  2616. }
  2617. KeReleaseSpinLock(&(pBDLExtension->ControlChangeStruct.ControlChangeLock), irql);
  2618. KeLowerIrql(OldIrql);
  2619. BDLDebug(
  2620. BDL_DEBUG_TRACE,
  2621. ("%s %s: BDL!BDLCleanupNotificationStruct: Leave\n",
  2622. __DATE__,
  2623. __TIME__))
  2624. }
  2625. VOID
  2626. BDLCleanupDataHandles
  2627. (
  2628. IN BDL_INTERNAL_DEVICE_EXTENSION *pBDLExtension
  2629. )
  2630. {
  2631. NTSTATUS status;
  2632. BDDI_ITEM *pBDDIItem = NULL;
  2633. BDD_DATA_HANDLE bddDataHandle;
  2634. BDDI_PARAMS_CLOSEHANDLE bddiCloseHandleParams;
  2635. KIRQL irql;
  2636. BDLDebug(
  2637. BDL_DEBUG_TRACE,
  2638. ("%s %s: BDL!BDLCleanupDataHandles: Enter\n",
  2639. __DATE__,
  2640. __TIME__))
  2641. bddiCloseHandleParams.Size = sizeof(bddiCloseHandleParams);
  2642. BDLLockHandleList(pBDLExtension, &irql);
  2643. //
  2644. // Go through each handle in the list and clean it up
  2645. //
  2646. while(BDLGetFirstHandle(&(pBDLExtension->HandleList), &bddDataHandle) == TRUE)
  2647. {
  2648. BDLRemoveHandleFromList(&(pBDLExtension->HandleList), bddDataHandle);
  2649. pBDDIItem = (BDDI_ITEM *) bddDataHandle;
  2650. //
  2651. // If this is a local handle then just clean it up, otherwise call the BDD
  2652. //
  2653. if (pBDDIItem->Type == BIO_ITEMTYPE_BLOCK)
  2654. {
  2655. bdliFree(pBDDIItem->Data.Block.pBuffer);
  2656. }
  2657. else
  2658. {
  2659. bddiCloseHandleParams.hData = pBDDIItem->Data.Handle;
  2660. //
  2661. // Call the BDD
  2662. //
  2663. status = pBDLExtension->pDriverExtension->bddiFunctions.pfbddiCloseHandle(
  2664. &(pBDLExtension->BdlExtenstion),
  2665. &bddiCloseHandleParams);
  2666. if (status != STATUS_SUCCESS)
  2667. {
  2668. BDLDebug(
  2669. BDL_DEBUG_ERROR,
  2670. ("%s %s: BDL!BDLCleanupDataHandles: pfbddiCloseHandle failed with %lx\n",
  2671. __DATE__,
  2672. __TIME__,
  2673. status))
  2674. //
  2675. // Nothing we can do, just continue
  2676. //
  2677. }
  2678. }
  2679. ExFreePoolWithTag(pBDDIItem, BDL_ULONG_TAG);
  2680. }
  2681. BDLReleaseHandleList(pBDLExtension, irql);
  2682. BDLDebug(
  2683. BDL_DEBUG_TRACE,
  2684. ("%s %s: BDL!BDLCleanupDataHandles: Leave\n",
  2685. __DATE__,
  2686. __TIME__))
  2687. }