Source code of Windows XP (NT5)
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.

300 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract: NULL filter driver -- boilerplate code
  6. Environment:
  7. Kernel mode
  8. Revision History:
  9. --*/
  10. #include <WDM.H>
  11. #include "filter.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE, VA_PnP)
  14. #pragma alloc_text(PAGE, GetDeviceCapabilities)
  15. #endif
  16. NTSTATUS VA_PnP(struct DEVICE_EXTENSION *devExt, PIRP irp)
  17. /*++
  18. Routine Description:
  19. Dispatch routine for PnP IRPs (MajorFunction == IRP_MJ_PNP)
  20. Arguments:
  21. devExt - device extension for the targetted device object
  22. irp - IO Request Packet
  23. Return Value:
  24. NT status code
  25. --*/
  26. {
  27. PIO_STACK_LOCATION irpSp;
  28. NTSTATUS status = STATUS_SUCCESS;
  29. BOOLEAN completeIrpHere = FALSE;
  30. BOOLEAN justReturnStatus = FALSE;
  31. PAGED_CODE();
  32. irpSp = IoGetCurrentIrpStackLocation(irp);
  33. DBGOUT(("VA_PnP, minorFunc = %d ", (ULONG)irpSp->MinorFunction));
  34. switch (irpSp->MinorFunction){
  35. case IRP_MN_START_DEVICE:
  36. DBGOUT(("START_DEVICE"));
  37. devExt->state = STATE_STARTING;
  38. /*
  39. * First, send the START_DEVICE irp down the stack
  40. * synchronously to start the lower stack.
  41. * We cannot do anything with our device object
  42. * before propagating the START_DEVICE this way.
  43. */
  44. IoCopyCurrentIrpStackLocationToNext(irp);
  45. status = CallNextDriverSync(devExt, irp);
  46. if (NT_SUCCESS(status)){
  47. //
  48. // Here is were we have an opportunity to run any
  49. // offline diagnostics that may have been queued up
  50. //
  51. FilterPerformOfflineDiags(devExt);
  52. /*
  53. * Now that the lower stack is started,
  54. * do any initialization required by this device object.
  55. */
  56. status = GetDeviceCapabilities(devExt);
  57. if (NT_SUCCESS(status)){
  58. devExt->state = STATE_STARTED;
  59. /*
  60. * Now that device is started, register with WMI
  61. */
  62. IoWMIRegistrationControl(devExt->filterDevObj,
  63. WMIREG_ACTION_REGISTER);
  64. }
  65. else {
  66. devExt->state = STATE_START_FAILED;
  67. }
  68. }
  69. else {
  70. devExt->state = STATE_START_FAILED;
  71. }
  72. completeIrpHere = TRUE;
  73. break;
  74. case IRP_MN_QUERY_STOP_DEVICE:
  75. break;
  76. case IRP_MN_STOP_DEVICE:
  77. if (devExt->state == STATE_SUSPENDED){
  78. status = STATUS_DEVICE_POWER_FAILURE;
  79. completeIrpHere = TRUE;
  80. }
  81. else {
  82. /*
  83. * Only set state to STOPPED if the device was
  84. * previously started successfully.
  85. */
  86. if (devExt->state == STATE_STARTED){
  87. devExt->state = STATE_STOPPED;
  88. }
  89. }
  90. break;
  91. case IRP_MN_QUERY_REMOVE_DEVICE:
  92. /*
  93. * We will pass this IRP down the driver stack.
  94. * However, we need to change the default status
  95. * from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
  96. */
  97. irp->IoStatus.Status = STATUS_SUCCESS;
  98. break;
  99. case IRP_MN_SURPRISE_REMOVAL:
  100. DBGOUT(("SURPRISE_REMOVAL"));
  101. /*
  102. * We will pass this IRP down the driver stack.
  103. * However, we need to change the default status
  104. * from STATUS_NOT_SUPPORTED to STATUS_SUCCESS.
  105. */
  106. irp->IoStatus.Status = STATUS_SUCCESS;
  107. /*
  108. * For now just set the STATE_REMOVING state so that
  109. * we don't do any more IO. We are guaranteed to get
  110. * IRP_MN_REMOVE_DEVICE soon; we'll do the rest of
  111. * the remove processing there.
  112. */
  113. devExt->state = STATE_REMOVING;
  114. break;
  115. case IRP_MN_REMOVE_DEVICE:
  116. /*
  117. * Check the current state to guard against multiple
  118. * REMOVE_DEVICE IRPs.
  119. */
  120. DBGOUT(("REMOVE_DEVICE"));
  121. if (devExt->state != STATE_REMOVED){
  122. devExt->state = STATE_REMOVED;
  123. /*
  124. * Send the REMOVE IRP down the stack asynchronously.
  125. * Do not synchronize sending down the REMOVE_DEVICE
  126. * IRP, because the REMOVE_DEVICE IRP must be sent
  127. * down and completed all the way back up to the sender
  128. * before we continue.
  129. */
  130. IoCopyCurrentIrpStackLocationToNext(irp);
  131. status = IoCallDriver(devExt->physicalDevObj, irp);
  132. justReturnStatus = TRUE;
  133. DBGOUT(("REMOVE_DEVICE - waiting for %d irps to complete...",
  134. devExt->pendingActionCount));
  135. /*
  136. * We must for all outstanding IO to complete before
  137. * completing the REMOVE_DEVICE IRP.
  138. *
  139. * First do an extra decrement on the pendingActionCount.
  140. * This will cause pendingActionCount to eventually
  141. * go to -1 once all asynchronous actions on this
  142. * device object are complete.
  143. * Then wait on the event that gets set when the
  144. * pendingActionCount actually reaches -1.
  145. */
  146. DecrementPendingActionCount(devExt);
  147. KeWaitForSingleObject( &devExt->removeEvent,
  148. Executive, // wait reason
  149. KernelMode,
  150. FALSE, // not alertable
  151. NULL ); // no timeout
  152. DBGOUT(("REMOVE_DEVICE - ... DONE waiting. "));
  153. /*
  154. * Now that the device is going away unregister with WMI
  155. * Note that we wait until all WMI irps are completed
  156. * before unregistering since unregistering will block
  157. * until all WMI irps are completed.
  158. */
  159. IoWMIRegistrationControl(devExt->filterDevObj,
  160. WMIREG_ACTION_DEREGISTER);
  161. /*
  162. * Detach our device object from the lower
  163. * device object stack.
  164. */
  165. IoDetachDevice(devExt->topDevObj);
  166. /*
  167. * Delete our device object.
  168. * This will also delete the associated device extension.
  169. */
  170. IoDeleteDevice(devExt->filterDevObj);
  171. }
  172. break;
  173. case IRP_MN_QUERY_DEVICE_RELATIONS:
  174. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  175. default:
  176. break;
  177. }
  178. if (justReturnStatus){
  179. /*
  180. * We've already sent this IRP down the stack asynchronously.
  181. */
  182. }
  183. else if (completeIrpHere){
  184. irp->IoStatus.Status = status;
  185. IoCompleteRequest(irp, IO_NO_INCREMENT);
  186. }
  187. else {
  188. IoCopyCurrentIrpStackLocationToNext(irp);
  189. status = IoCallDriver(devExt->physicalDevObj, irp);
  190. }
  191. return status;
  192. }
  193. NTSTATUS GetDeviceCapabilities(struct DEVICE_EXTENSION *devExt)
  194. /*++
  195. Routine Description:
  196. Function retrieves the DEVICE_CAPABILITIES descriptor from the device
  197. Arguments:
  198. devExt - device extension for targetted device object
  199. Return Value:
  200. NT status code
  201. --*/
  202. {
  203. NTSTATUS status;
  204. PIRP irp;
  205. PAGED_CODE();
  206. irp = IoAllocateIrp(devExt->physicalDevObj->StackSize, FALSE);
  207. if (irp){
  208. PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(irp);
  209. nextSp->MajorFunction = IRP_MJ_PNP;
  210. nextSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  211. RtlZeroMemory( &devExt->deviceCapabilities,
  212. sizeof(DEVICE_CAPABILITIES));
  213. nextSp->Parameters.DeviceCapabilities.Capabilities =
  214. &devExt->deviceCapabilities;
  215. /*
  216. * For any IRP you create, you must set the default status
  217. * to STATUS_NOT_SUPPORTED before sending it.
  218. */
  219. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  220. status = CallNextDriverSync(devExt, irp);
  221. IoFreeIrp(irp);
  222. }
  223. else {
  224. status = STATUS_INSUFFICIENT_RESOURCES;
  225. }
  226. ASSERT(NT_SUCCESS(status));
  227. return status;
  228. }