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.

305 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. util.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, CallNextDriverSync)
  16. #pragma alloc_text(PAGE, CallDriverSync)
  17. #endif
  18. NTSTATUS CallNextDriverSync(struct DEVICE_EXTENSION *devExt, PIRP irp)
  19. /*++
  20. Routine Description:
  21. Pass the IRP down to the next device object in the stack
  22. synchronously, and bump the pendingActionCount around
  23. the call to prevent the current device object from getting
  24. removed before the IRP completes.
  25. Arguments:
  26. devExt - device extension of one of our device objects
  27. irp - Io Request Packet
  28. Return Value:
  29. NT status code, indicates result returned by lower driver for this IRP.
  30. --*/
  31. {
  32. NTSTATUS status;
  33. PAGED_CODE();
  34. IncrementPendingActionCount(devExt);
  35. status = CallDriverSync(devExt->physicalDevObj, irp);
  36. DecrementPendingActionCount(devExt);
  37. return status;
  38. }
  39. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp)
  40. /*++
  41. Routine Description:
  42. Call IoCallDriver to send the irp to the device object;
  43. then, synchronize with the completion routine.
  44. When CallDriverSync returns, the action has completed
  45. and the irp again belongs to the current driver.
  46. NOTE: In order to keep the device object from getting freed
  47. while this IRP is pending, you should call
  48. IncrementPendingActionCount() and
  49. DecrementPendingActionCount()
  50. around the CallDriverSync call.
  51. Arguments:
  52. devObj - targetted device object
  53. irp - Io Request Packet
  54. Return Value:
  55. NT status code, indicates result returned by lower driver for this IRP.
  56. --*/
  57. {
  58. KEVENT event;
  59. NTSTATUS status;
  60. PAGED_CODE();
  61. KeInitializeEvent(&event, NotificationEvent, FALSE);
  62. IoSetCompletionRoutine( irp,
  63. CallDriverSyncCompletion,
  64. &event, // context
  65. TRUE, TRUE, TRUE);
  66. status = IoCallDriver(devObj, irp);
  67. KeWaitForSingleObject( &event,
  68. Executive, // wait reason
  69. KernelMode,
  70. FALSE, // not alertable
  71. NULL ); // no timeout
  72. status = irp->IoStatus.Status;
  73. ASSERT(NT_SUCCESS(status));
  74. return status;
  75. }
  76. NTSTATUS CallDriverSyncCompletion(
  77. IN PDEVICE_OBJECT devObjOrNULL,
  78. IN PIRP irp,
  79. IN PVOID context)
  80. /*++
  81. Routine Description:
  82. Completion routine for CallDriverSync.
  83. Arguments:
  84. devObjOrNULL -
  85. Usually, this is this driver's device object.
  86. However, if this driver created the IRP,
  87. there is no stack location in the IRP for this driver;
  88. so the kernel has no place to store the device object;
  89. ** so devObj will be NULL in this case **.
  90. irp - completed Io Request Packet
  91. context - context passed to IoSetCompletionRoutine by CallDriverSync.
  92. Return Value:
  93. NT status code, indicates result returned by lower driver for this IRP.
  94. --*/
  95. {
  96. PKEVENT event = context;
  97. ASSERT(irp->IoStatus.Status != STATUS_IO_TIMEOUT);
  98. KeSetEvent(event, 0, FALSE);
  99. return STATUS_MORE_PROCESSING_REQUIRED;
  100. }
  101. VOID IncrementPendingActionCount(struct DEVICE_EXTENSION *devExt)
  102. /*++
  103. Routine Description:
  104. Increment the pendingActionCount for a device object.
  105. This keeps the device object from getting freed before
  106. the action is completed.
  107. Arguments:
  108. devExt - device extension of device object
  109. Return Value:
  110. VOID
  111. --*/
  112. {
  113. ASSERT(devExt->pendingActionCount >= 0);
  114. InterlockedIncrement(&devExt->pendingActionCount);
  115. }
  116. VOID DecrementPendingActionCount(struct DEVICE_EXTENSION *devExt)
  117. /*++
  118. Routine Description:
  119. Decrement the pendingActionCount for a device object.
  120. This is called when an asynchronous action is completed
  121. AND ALSO when we get the REMOVE_DEVICE IRP.
  122. If the pendingActionCount goes to -1, that means that all
  123. actions are completed and we've gotten the REMOVE_DEVICE IRP;
  124. in this case, set the removeEvent event so we can finish
  125. unloading.
  126. Arguments:
  127. devExt - device extension of device object
  128. Return Value:
  129. VOID
  130. --*/
  131. {
  132. ASSERT(devExt->pendingActionCount >= 0);
  133. InterlockedDecrement(&devExt->pendingActionCount);
  134. if (devExt->pendingActionCount < 0){
  135. /*
  136. * All pending actions have completed and we've gotten
  137. * the REMOVE_DEVICE IRP.
  138. * Set the removeEvent so we'll stop waiting on REMOVE_DEVICE.
  139. */
  140. ASSERT((devExt->state == STATE_REMOVING) ||
  141. (devExt->state == STATE_REMOVED));
  142. KeSetEvent(&devExt->removeEvent, 0, FALSE);
  143. }
  144. }
  145. VOID RegistryAccessSample(PDEVICE_OBJECT devObj)
  146. /*++
  147. Routine Description:
  148. SAMPLE showing how to access the device-specific registry key
  149. Arguments:
  150. devObj - device object pointer
  151. NOTE: This must not be the functional device object
  152. created by this filter driver, because that
  153. device object does not have a devnode area
  154. in the registry; pass the device object of
  155. the device object for which this driver is
  156. a filter. This is the device object passed
  157. to VA_AddDevice.
  158. Return Value:
  159. VOID
  160. --*/
  161. {
  162. NTSTATUS status;
  163. HANDLE hRegDevice;
  164. status = IoOpenDeviceRegistryKey( devObj,
  165. PLUGPLAY_REGKEY_DEVICE,
  166. KEY_READ,
  167. &hRegDevice);
  168. if (NT_SUCCESS(status)){
  169. UNICODE_STRING keyName;
  170. PKEY_VALUE_FULL_INFORMATION keyValueInfo;
  171. ULONG keyValueTotalSize, actualLength;
  172. RtlInitUnicodeString(&keyName, L"SampleFilterParam");
  173. keyValueTotalSize = sizeof(KEY_VALUE_FULL_INFORMATION) +
  174. keyName.Length*sizeof(WCHAR) +
  175. sizeof(ULONG);
  176. keyValueInfo = ExAllocatePoolWithTag( PagedPool,
  177. keyValueTotalSize,
  178. FILTER_TAG);
  179. if (keyValueInfo){
  180. status = ZwQueryValueKey( hRegDevice,
  181. &keyName,
  182. KeyValueFullInformation,
  183. keyValueInfo,
  184. keyValueTotalSize,
  185. &actualLength);
  186. if (NT_SUCCESS(status)){
  187. ULONG value;
  188. ASSERT(keyValueInfo->Type == REG_DWORD);
  189. ASSERT(keyValueInfo->DataLength == sizeof(ULONG));
  190. value = *((PULONG)(((PCHAR)keyValueInfo)+keyValueInfo->DataOffset));
  191. DBGOUT(("RegistryAccessSample: value is %xh.", value));
  192. }
  193. else {
  194. DBGOUT(("ZwQueryValueKey failed with %xh.", status));
  195. }
  196. ExFreePool(keyValueInfo);
  197. }
  198. else {
  199. ASSERT(keyValueInfo);
  200. }
  201. ZwClose(hRegDevice);
  202. }
  203. else {
  204. DBGOUT(("IoOpenDeviceRegistryKey failed with %xh.", status));
  205. }
  206. }