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.

298 lines
8.7 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. FilterWmiCleanup(devExt);
  157. IoWMIRegistrationControl(devExt->filterDevObj,
  158. WMIREG_ACTION_DEREGISTER);
  159. /*
  160. * Detach our device object from the lower
  161. * device object stack.
  162. */
  163. IoDetachDevice(devExt->topDevObj);
  164. /*
  165. * Delete our device object.
  166. * This will also delete the associated device extension.
  167. */
  168. IoDeleteDevice(devExt->filterDevObj);
  169. }
  170. break;
  171. case IRP_MN_QUERY_DEVICE_RELATIONS:
  172. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  173. default:
  174. break;
  175. }
  176. if (justReturnStatus){
  177. /*
  178. * We've already sent this IRP down the stack asynchronously.
  179. */
  180. }
  181. else if (completeIrpHere){
  182. irp->IoStatus.Status = status;
  183. IoCompleteRequest(irp, IO_NO_INCREMENT);
  184. }
  185. else {
  186. IoCopyCurrentIrpStackLocationToNext(irp);
  187. status = IoCallDriver(devExt->physicalDevObj, irp);
  188. }
  189. return status;
  190. }
  191. NTSTATUS GetDeviceCapabilities(struct DEVICE_EXTENSION *devExt)
  192. /*++
  193. Routine Description:
  194. Function retrieves the DEVICE_CAPABILITIES descriptor from the device
  195. Arguments:
  196. devExt - device extension for targetted device object
  197. Return Value:
  198. NT status code
  199. --*/
  200. {
  201. NTSTATUS status;
  202. PIRP irp;
  203. PAGED_CODE();
  204. irp = IoAllocateIrp(devExt->physicalDevObj->StackSize, FALSE);
  205. if (irp){
  206. PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(irp);
  207. nextSp->MajorFunction = IRP_MJ_PNP;
  208. nextSp->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
  209. RtlZeroMemory( &devExt->deviceCapabilities,
  210. sizeof(DEVICE_CAPABILITIES));
  211. nextSp->Parameters.DeviceCapabilities.Capabilities =
  212. &devExt->deviceCapabilities;
  213. /*
  214. * For any IRP you create, you must set the default status
  215. * to STATUS_NOT_SUPPORTED before sending it.
  216. */
  217. irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  218. status = CallNextDriverSync(devExt, irp);
  219. IoFreeIrp(irp);
  220. }
  221. else {
  222. status = STATUS_INSUFFICIENT_RESOURCES;
  223. }
  224. ASSERT(NT_SUCCESS(status));
  225. return status;
  226. }