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.

355 lines
8.4 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. kmcancel.c
  5. Abstract:
  6. This module contains code to verify handling of IRP cancelation requests.
  7. Author:
  8. Abolade Gbadegesin (aboladeg) 05-June-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define THREAD_COUNT 10
  14. #define REQUEST_COUNT 50
  15. #define DD_TARGET_DEVICE_NAME DD_IP_DEVICE_NAME
  16. #define TARGET_IO_CONTROL_CODE IOCTL_IP_RTCHANGE_NOTIFY_REQUEST
  17. //
  18. // Target driver state.
  19. //
  20. PDEVICE_OBJECT TargetDeviceObject = NULL;
  21. PFILE_OBJECT TargetFileObject = NULL;
  22. //
  23. // Thread-management state.
  24. //
  25. ULONG KmcThreadCount;
  26. KEVENT KmcStopEvent;
  27. KSEMAPHORE KmcStopSemaphore;
  28. //
  29. // FUNCTION PROTOTYPES (alphabetically)
  30. //
  31. NTSTATUS
  32. DriverEntry(
  33. IN PDRIVER_OBJECT DriverObject,
  34. IN PUNICODE_STRING RegistryPath
  35. );
  36. NTSTATUS
  37. KmcRequestCompletionRoutine(
  38. PDEVICE_OBJECT DeviceObject,
  39. PIRP Irp,
  40. PVOID Context
  41. );
  42. VOID
  43. KmcRequestThread(
  44. PVOID Context
  45. );
  46. VOID
  47. KmcUnloadDriver(
  48. IN PDRIVER_OBJECT DriverObject
  49. );
  50. VOID
  51. KmcUpdateThread(
  52. PVOID Context
  53. );
  54. NTSTATUS
  55. DriverEntry(
  56. IN PDRIVER_OBJECT DriverObject,
  57. IN PUNICODE_STRING RegistryPath
  58. )
  59. {
  60. ULONG i;
  61. NTSTATUS Status;
  62. HANDLE ThreadHandle;
  63. UNICODE_STRING UnicodeString;
  64. KdPrint(("DriverEntry\n"));
  65. DriverObject->DriverUnload = KmcUnloadDriver;
  66. KmcThreadCount = 0;
  67. KeInitializeEvent(&KmcStopEvent, NotificationEvent, FALSE);
  68. KeInitializeSemaphore(&KmcStopSemaphore, 0, MAXLONG);
  69. //
  70. // Obtain the target driver's device-object
  71. //
  72. RtlInitUnicodeString(&UnicodeString, DD_TARGET_DEVICE_NAME);
  73. Status =
  74. IoGetDeviceObjectPointer(
  75. &UnicodeString,
  76. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  77. &TargetFileObject,
  78. &TargetDeviceObject
  79. );
  80. if (!NT_SUCCESS(Status)) {
  81. KdPrint(("DriverEntry: error %x getting IP object\n", Status));
  82. return Status;
  83. }
  84. ObReferenceObject(TargetDeviceObject);
  85. //
  86. // Start the request/update threads.
  87. // The request threads are responsible for issuing the I/O control
  88. // whose cancelation is being verified, and the update threads are
  89. // responsible for triggering completion of those I/O control requests
  90. // in order to highlight any potential race-conditions.
  91. //
  92. for (i = 0; i < THREAD_COUNT; i++) {
  93. Status =
  94. PsCreateSystemThread(
  95. &ThreadHandle,
  96. GENERIC_ALL,
  97. NULL,
  98. NULL,
  99. NULL,
  100. KmcUpdateThread,
  101. NULL
  102. );
  103. if (NT_SUCCESS(Status)) {
  104. ZwClose(ThreadHandle);
  105. ++KmcThreadCount;
  106. }
  107. Status =
  108. PsCreateSystemThread(
  109. &ThreadHandle,
  110. GENERIC_ALL,
  111. NULL,
  112. NULL,
  113. NULL,
  114. KmcRequestThread,
  115. NULL
  116. );
  117. if (NT_SUCCESS(Status)) {
  118. ZwClose(ThreadHandle);
  119. ++KmcThreadCount;
  120. }
  121. }
  122. return STATUS_SUCCESS;
  123. } // DriverEntry
  124. typedef struct _KMC_REQUEST {
  125. IO_STATUS_BLOCK IoStatus;
  126. PIRP Irp;
  127. ULONG ReferenceCount;
  128. } KMC_REQUEST, *PKMC_REQUEST;
  129. NTSTATUS
  130. KmcRequestCompletionRoutine(
  131. PDEVICE_OBJECT DeviceObject,
  132. PIRP Irp,
  133. PVOID Context
  134. )
  135. {
  136. PKMC_REQUEST Request = (PKMC_REQUEST)Context;
  137. if (InterlockedDecrement(&Request->ReferenceCount) == 0) {
  138. IoFreeIrp(Request->Irp);
  139. ExFreePool(Request);
  140. }
  141. return STATUS_MORE_PROCESSING_REQUIRED;
  142. } // KmcCompletionRoutine
  143. VOID
  144. KmcRequestThread(
  145. PVOID Context
  146. )
  147. {
  148. ULONG i, Index;
  149. LARGE_INTEGER Interval;
  150. PIRP Irp;
  151. PIO_STACK_LOCATION IrpSp;
  152. KIRQL OldIrql;
  153. PKMC_REQUEST Request, RequestArray[REQUEST_COUNT];
  154. for (; !KeReadStateEvent(&KmcStopEvent); ) {
  155. //
  156. // Queue a series of requests to the driver.
  157. //
  158. Index = 0;
  159. RtlZeroMemory(RequestArray, sizeof(RequestArray));
  160. for (i = 0; i < REQUEST_COUNT; i++) {
  161. Request = ExAllocatePool(NonPagedPool, sizeof(*Request));
  162. if (!Request) {
  163. continue;
  164. }
  165. RtlZeroMemory(Request, sizeof(*Request));
  166. Irp = IoAllocateIrp(TargetDeviceObject->StackSize, FALSE);
  167. if (!Irp) {
  168. continue;
  169. }
  170. Request->Irp = Irp;
  171. Irp->RequestorMode = KernelMode;
  172. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  173. Irp->Tail.Overlay.OriginalFileObject = TargetFileObject;
  174. IoSetCompletionRoutine(
  175. Irp,
  176. KmcRequestCompletionRoutine,
  177. Request,
  178. TRUE,
  179. TRUE,
  180. TRUE
  181. );
  182. IrpSp = IoGetNextIrpStackLocation(Irp);
  183. IrpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  184. IrpSp->Parameters.DeviceIoControl.IoControlCode =
  185. TARGET_IO_CONTROL_CODE;
  186. IrpSp->DeviceObject = TargetDeviceObject;
  187. IrpSp->FileObject = TargetFileObject;
  188. Request->ReferenceCount = 2;
  189. RequestArray[Index++] = Request;
  190. IoCallDriver(TargetDeviceObject, Request->Irp);
  191. }
  192. //
  193. // Delay execution for a short interval, and cancel the requests.
  194. //
  195. Interval.QuadPart = -10 * 1000 * 50;
  196. KeDelayExecutionThread(KernelMode, FALSE, &Interval);
  197. for (i = 0; i < REQUEST_COUNT; i++) {
  198. if (Request = RequestArray[i]) {
  199. IoCancelIrp(Request->Irp);
  200. if (InterlockedDecrement(&Request->ReferenceCount) == 0) {
  201. IoFreeIrp(Request->Irp);
  202. ExFreePool(Request);
  203. }
  204. }
  205. }
  206. }
  207. KeReleaseSemaphore(&KmcStopSemaphore, 0, 1, FALSE);
  208. } // KmcRequestThread
  209. VOID
  210. KmcUnloadDriver(
  211. IN PDRIVER_OBJECT DriverObject
  212. )
  213. {
  214. KdPrint(("KmcUnloadDriver\n"));
  215. //
  216. // Signal all threads to stop, and wait for them to exit.
  217. //
  218. KeSetEvent(&KmcStopEvent, 0, FALSE);
  219. while (KmcThreadCount--) {
  220. KeWaitForSingleObject(
  221. &KmcStopSemaphore, Executive, KernelMode, FALSE, NULL
  222. );
  223. }
  224. //
  225. // Release references to the IP device object
  226. //
  227. ObDereferenceObject(TargetFileObject);
  228. ObDereferenceObject(TargetDeviceObject);
  229. } // KmcUnloadDriver
  230. extern
  231. VOID
  232. LookupRoute(
  233. IPRouteLookupData* RouteLookupData,
  234. IPRouteEntry* RouteEntry
  235. );
  236. VOID
  237. KmcUpdateThread(
  238. PVOID Context
  239. )
  240. {
  241. KEVENT Event;
  242. LARGE_INTEGER Interval;
  243. IO_STATUS_BLOCK IoStatus;
  244. PIRP Irp;
  245. IPRouteEntry RouteEntry;
  246. IPRouteLookupData RouteLookupData;
  247. NTSTATUS Status;
  248. //
  249. // Retrieve information from IP for use in triggering route-changes.
  250. //
  251. RtlZeroMemory(&RouteEntry, sizeof(RouteEntry));
  252. RouteLookupData.Version = 0;
  253. RouteLookupData.SrcAdd = 0;
  254. RouteLookupData.DestAdd = 0x100000a; // 10.0.0.1
  255. LookupRoute(&RouteLookupData, &RouteEntry);
  256. RouteEntry.ire_dest = 0x100000a; // 10.0.0.1
  257. RouteEntry.ire_mask = 0xffffffff;
  258. RouteEntry.ire_proto = IRE_PROTO_NETMGMT;
  259. //
  260. // Repeatedly issue changes to the IP routing table, until told to exit.
  261. //
  262. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  263. for (; !KeReadStateEvent(&KmcStopEvent); ) {
  264. Interval.QuadPart = -10 * 1000 * 50;
  265. KeDelayExecutionThread(KernelMode, FALSE, &Interval);
  266. Irp =
  267. IoBuildDeviceIoControlRequest(
  268. IOCTL_IP_SET_ROUTEWITHREF,
  269. TargetDeviceObject,
  270. &RouteEntry,
  271. sizeof(RouteEntry),
  272. NULL,
  273. 0,
  274. FALSE,
  275. &Event,
  276. &IoStatus
  277. );
  278. if (!Irp) { continue; }
  279. Status = IoCallDriver(TargetDeviceObject, Irp);
  280. if (Status == STATUS_PENDING) {
  281. KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
  282. }
  283. }
  284. KeReleaseSemaphore(&KmcStopSemaphore, 0, 1, FALSE);
  285. } // KmcUpdateThread