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.

297 lines
8.4 KiB

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