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.

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