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.

1136 lines
32 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ioverifier.c
  5. Abstract:
  6. This module contains the routines to verify suspect drivers.
  7. Author:
  8. Narayanan Ganapathy (narg) 8-Jan-1999
  9. Revision History:
  10. Adrian J. Oney (AdriaO) 28-Feb-1999
  11. - merge in special irp code.
  12. --*/
  13. #include "iomgr.h"
  14. #include "malloc.h"
  15. #include "..\verifier\vfdeadlock.h"
  16. #if (( defined(_X86_) ) && ( FPO ))
  17. #pragma optimize( "y", off ) // disable FPO for consistent stack traces
  18. #endif
  19. #define IO_FREE_IRP_TYPE_INVALID 1
  20. #define IO_FREE_IRP_NOT_ASSOCIATED_WITH_THREAD 2
  21. #define IO_CALL_DRIVER_IRP_TYPE_INVALID 3
  22. #define IO_CALL_DRIVER_INVALID_DEVICE_OBJECT 4
  23. #define IO_CALL_DRIVER_IRQL_NOT_EQUAL 5
  24. #define IO_COMPLETE_REQUEST_INVALID_STATUS 6
  25. #define IO_COMPLETE_REQUEST_CANCEL_ROUTINE_SET 7
  26. #define IO_BUILD_FSD_REQUEST_EXCEPTION 8
  27. #define IO_BUILD_IOCTL_REQUEST_EXCEPTION 9
  28. #define IO_REINITIALIZING_TIMER_OBJECT 10
  29. #define IO_INVALID_HANDLE 11
  30. #define IO_INVALID_STACK_IOSB 12
  31. #define IO_INVALID_STACK_EVENT 13
  32. #define IO_COMPLETE_REQUEST_INVALID_IRQL 14
  33. #define IO_CALL_DRIVER_ISSUING_INVALID_CREATE_REQUEST 15
  34. //
  35. // 0x200 and up are defined in ioassert.c
  36. //
  37. #ifdef IOV_KD_PRINT
  38. #define IovpKdPrint(x) KdPrint(x)
  39. #else
  40. #define IovpKdPrint(x)
  41. #endif
  42. BOOLEAN
  43. IovpValidateDeviceObject(
  44. IN PDEVICE_OBJECT DeviceObject
  45. );
  46. VOID
  47. IovFreeIrpPrivate(
  48. IN PIRP Irp
  49. );
  50. NTSTATUS
  51. IovpUnloadDriver(
  52. PDRIVER_OBJECT DriverObject
  53. );
  54. BOOLEAN
  55. IovpBuildDriverObjectList(
  56. IN PVOID Object,
  57. IN PUNICODE_STRING ObjectName,
  58. IN ULONG_PTR HandleCount,
  59. IN ULONG_PTR PointerCount,
  60. IN PVOID Parameter
  61. );
  62. NTSTATUS
  63. IovpLocalCompletionRoutine(
  64. IN PDEVICE_OBJECT DeviceObject,
  65. IN PIRP Irp,
  66. IN PVOID Context
  67. );
  68. typedef struct _IOV_COMPLETION_CONTEXT {
  69. PIO_STACK_LOCATION StackPointer;
  70. PVOID IrpContext;
  71. PVOID GlobalContext;
  72. PIO_COMPLETION_ROUTINE CompletionRoutine;
  73. IO_STACK_LOCATION OldStackContents;
  74. } IOV_COMPLETION_CONTEXT, *PIOV_COMPLETION_CONTEXT;
  75. #ifdef ALLOC_PRAGMA
  76. #pragma alloc_text(INIT, IoVerifierInit)
  77. #pragma alloc_text(PAGEVRFY,IovAllocateIrp)
  78. #pragma alloc_text(PAGEVRFY,IovFreeIrp)
  79. #pragma alloc_text(PAGEVRFY,IovCallDriver)
  80. #pragma alloc_text(PAGEVRFY,IovCompleteRequest)
  81. #pragma alloc_text(PAGEVRFY,IovpValidateDeviceObject)
  82. #pragma alloc_text(PAGEVRFY,IovFreeIrpPrivate)
  83. #pragma alloc_text(PAGEVRFY,IovUnloadDrivers)
  84. #pragma alloc_text(PAGEVRFY,IovpUnloadDriver)
  85. #pragma alloc_text(PAGEVRFY,IovBuildDeviceIoControlRequest)
  86. #pragma alloc_text(PAGEVRFY,IovBuildAsynchronousFsdRequest)
  87. #pragma alloc_text(PAGEVRFY,IovpCompleteRequest)
  88. #pragma alloc_text(PAGEVRFY,IovpBuildDriverObjectList)
  89. #pragma alloc_text(PAGEVRFY,IovInitializeIrp)
  90. #pragma alloc_text(PAGEVRFY,IovCancelIrp)
  91. #pragma alloc_text(PAGEVRFY,IovAttachDeviceToDeviceStack)
  92. #pragma alloc_text(PAGEVRFY,IovInitializeTimer)
  93. #pragma alloc_text(PAGEVRFY,IovDetachDevice)
  94. #pragma alloc_text(PAGEVRFY,IovDeleteDevice)
  95. #pragma alloc_text(PAGEVRFY,IovpLocalCompletionRoutine)
  96. #endif
  97. BOOLEAN IopVerifierOn = FALSE;
  98. ULONG IovpVerifierLevel = (ULONG)0;
  99. LONG IovpInitCalled = 0;
  100. ULONG IovpVerifierFlags = 0; // Stashes the verifier flags passed at init.
  101. #ifdef ALLOC_DATA_PRAGMA
  102. #pragma data_seg("INITDATA")
  103. #endif
  104. BOOLEAN IoVerifierOnByDefault = TRUE;
  105. #ifdef ALLOC_DATA_PRAGMA
  106. #pragma data_seg()
  107. #endif
  108. VOID
  109. IoVerifierInit(
  110. IN ULONG VerifierFlags
  111. )
  112. {
  113. IovpVerifierLevel = 2;
  114. if (IoVerifierOnByDefault) {
  115. VerifierFlags |= DRIVER_VERIFIER_IO_CHECKING;
  116. }
  117. VfInitVerifier(VerifierFlags);
  118. if (!VerifierFlags) {
  119. return;
  120. }
  121. pIoAllocateIrp = IovAllocateIrp;
  122. if (!(VerifierFlags & DRIVER_VERIFIER_IO_CHECKING)) {
  123. if (!(VerifierFlags & DRIVER_VERIFIER_DEADLOCK_DETECTION) &&
  124. !(VerifierFlags & DRIVER_VERIFIER_DMA_VERIFIER)) {
  125. return;
  126. } else {
  127. //
  128. // If deadlock or DMA verifier are on we need to let the function
  129. // continue to install the hooks but we will set the
  130. // I/O verifier level to minimal checks.
  131. //
  132. IovpVerifierLevel = 0;
  133. }
  134. }
  135. //
  136. // Enable and hook in the verifier.
  137. //
  138. IopVerifierOn = TRUE;
  139. IovpInitCalled = 1;
  140. IovpVerifierFlags = VerifierFlags;
  141. //
  142. // Initialize the special IRP code as appropriate.
  143. //
  144. InterlockedExchangePointer((PVOID *)&pIofCallDriver, (PVOID) IovCallDriver);
  145. InterlockedExchangePointer((PVOID *)&pIofCompleteRequest, (PVOID) IovCompleteRequest);
  146. InterlockedExchangePointer((PVOID *)&pIoFreeIrp, (PVOID) IovFreeIrpPrivate);
  147. ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  148. }
  149. BOOLEAN
  150. IovpValidateDeviceObject(
  151. IN PDEVICE_OBJECT DeviceObject
  152. )
  153. {
  154. if ((DeviceObject->Type != IO_TYPE_DEVICE) ||
  155. (DeviceObject->DriverObject == NULL) ||
  156. (DeviceObject->ReferenceCount < 0 )) {
  157. return FALSE;
  158. } else {
  159. return TRUE;
  160. }
  161. }
  162. VOID
  163. IovFreeIrp(
  164. IN PIRP Irp
  165. )
  166. {
  167. IovFreeIrpPrivate(Irp);
  168. }
  169. VOID
  170. IovFreeIrpPrivate(
  171. IN PIRP Irp
  172. )
  173. {
  174. BOOLEAN freeHandled ;
  175. if (IopVerifierOn) {
  176. if (Irp->Type != IO_TYPE_IRP) {
  177. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  178. IO_FREE_IRP_TYPE_INVALID,
  179. (ULONG_PTR)Irp,
  180. 0,
  181. 0);
  182. }
  183. if (!IsListEmpty(&(Irp)->ThreadListEntry)) {
  184. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  185. IO_FREE_IRP_NOT_ASSOCIATED_WITH_THREAD,
  186. (ULONG_PTR)Irp,
  187. 0,
  188. 0);
  189. }
  190. }
  191. VerifierIoFreeIrp(Irp, &freeHandled);
  192. if (freeHandled) {
  193. return;
  194. }
  195. IopFreeIrp(Irp);
  196. }
  197. NTSTATUS
  198. FASTCALL
  199. IovCallDriver(
  200. IN PDEVICE_OBJECT DeviceObject,
  201. IN OUT PIRP Irp,
  202. IN PVOID ReturnAddress
  203. )
  204. {
  205. KIRQL saveIrql;
  206. NTSTATUS status;
  207. PIOFCALLDRIVER_STACKDATA iofCallDriverStackData;
  208. BOOLEAN pagingIrp;
  209. PIO_STACK_LOCATION irpSp;
  210. if (!IopVerifierOn) {
  211. return IopfCallDriver(DeviceObject, Irp);
  212. }
  213. if (Irp->Type != IO_TYPE_IRP) {
  214. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  215. IO_CALL_DRIVER_IRP_TYPE_INVALID,
  216. (ULONG_PTR)Irp,
  217. 0,
  218. 0);
  219. }
  220. if (!IovpValidateDeviceObject(DeviceObject)) {
  221. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  222. IO_CALL_DRIVER_INVALID_DEVICE_OBJECT,
  223. (ULONG_PTR)DeviceObject,
  224. 0,
  225. 0);
  226. }
  227. irpSp = IoGetNextIrpStackLocation(Irp);
  228. if (irpSp->MajorFunction == IRP_MJ_CREATE &&
  229. (irpSp->FileObject) &&
  230. ((irpSp->FileObject->Flags &
  231. (FO_CLEANUP_COMPLETE|FO_FILE_OPEN_CANCELLED)) == (FO_CLEANUP_COMPLETE|FO_FILE_OPEN_CANCELLED))) {
  232. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  233. IO_CALL_DRIVER_ISSUING_INVALID_CREATE_REQUEST,
  234. (ULONG_PTR)DeviceObject,
  235. (ULONG_PTR)Irp,
  236. (ULONG_PTR)irpSp->FileObject);
  237. }
  238. saveIrql = KeGetCurrentIrql();
  239. //
  240. // Deadlock verifier functions are called before and after the
  241. // real IoCallDriver() call. If deadlock verifier is not enabled
  242. // this functions will return immediately.
  243. //
  244. pagingIrp = VfDeadlockBeforeCallDriver(DeviceObject, Irp);
  245. //
  246. // VfIrpCallDriverPreprocess is a macro function that may do an alloca as
  247. // part of it's operation. As such callers must be careful not to use
  248. // variable lengthed arrays in a scope that encompasses
  249. // VfIrpCallDriverPreProcess but not VfIrpCallDriverPostProcess.
  250. //
  251. VfIrpCallDriverPreProcess(DeviceObject, &Irp, &iofCallDriverStackData, ReturnAddress);
  252. VfStackSeedStack(0xFFFFFFFF);
  253. status = IopfCallDriver(DeviceObject, Irp);
  254. VfIrpCallDriverPostProcess(DeviceObject, &status, iofCallDriverStackData);
  255. VfDeadlockAfterCallDriver(DeviceObject, Irp, pagingIrp);
  256. if (saveIrql != KeGetCurrentIrql()) {
  257. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  258. IO_CALL_DRIVER_IRQL_NOT_EQUAL,
  259. (ULONG_PTR)DeviceObject,
  260. saveIrql,
  261. KeGetCurrentIrql());
  262. }
  263. return status;
  264. }
  265. //
  266. // Wrapper for IovAllocateIrp. Use special pool to allocate the IRP.
  267. // This is directly called from IoAllocateIrp.
  268. //
  269. PIRP
  270. IovAllocateIrp(
  271. IN CCHAR StackSize,
  272. IN BOOLEAN ChargeQuota
  273. )
  274. {
  275. USHORT allocateSize;
  276. UCHAR fixedSize;
  277. PIRP irp;
  278. USHORT packetSize;
  279. //
  280. // Should we override normal lookaside caching so that we may catch
  281. // more bugs?
  282. //
  283. VerifierIoAllocateIrp1(StackSize, ChargeQuota, &irp);
  284. if (irp) {
  285. return irp;
  286. }
  287. //
  288. // If special pool is not turned on lets just call the standard
  289. // irp allocator.
  290. //
  291. if (!(IovpVerifierFlags & DRIVER_VERIFIER_SPECIAL_POOLING )) {
  292. irp = IopAllocateIrpPrivate(StackSize, ChargeQuota);
  293. return irp;
  294. }
  295. irp = NULL;
  296. fixedSize = 0;
  297. packetSize = IoSizeOfIrp(StackSize);
  298. allocateSize = packetSize;
  299. //
  300. // There are no free packets on the lookaside list, or the packet is
  301. // too large to be allocated from one of the lists, so it must be
  302. // allocated from nonpaged pool. If quota is to be charged, charge it
  303. // against the current process. Otherwise, allocate the pool normally.
  304. //
  305. if (ChargeQuota) {
  306. try {
  307. irp = ExAllocatePoolWithTagPriority(
  308. NonPagedPool,
  309. allocateSize,
  310. ' prI',
  311. HighPoolPrioritySpecialPoolOverrun);
  312. } except(EXCEPTION_EXECUTE_HANDLER) {
  313. NOTHING;
  314. }
  315. } else {
  316. //
  317. // Attempt to allocate the pool from non-paged pool. If this
  318. // fails, and the caller's previous mode was kernel then allocate
  319. // the pool as must succeed.
  320. //
  321. irp = ExAllocatePoolWithTagPriority(
  322. NonPagedPool,
  323. allocateSize,
  324. ' prI',
  325. HighPoolPrioritySpecialPoolOverrun);
  326. }
  327. if (!irp) {
  328. return NULL;
  329. }
  330. //
  331. // Initialize the packet.
  332. //
  333. IopInitializeIrp(irp, packetSize, StackSize);
  334. if (ChargeQuota) {
  335. irp->AllocationFlags |= IRP_QUOTA_CHARGED;
  336. }
  337. VerifierIoAllocateIrp2(irp);
  338. return irp;
  339. }
  340. PIRP
  341. IovBuildAsynchronousFsdRequest(
  342. IN ULONG MajorFunction,
  343. IN PDEVICE_OBJECT DeviceObject,
  344. IN OUT PVOID Buffer OPTIONAL,
  345. IN ULONG Length OPTIONAL,
  346. IN PLARGE_INTEGER StartingOffset OPTIONAL,
  347. IN PIO_STATUS_BLOCK IoStatusBlock OPTIONAL
  348. )
  349. {
  350. PIRP Irp;
  351. try {
  352. Irp = IoBuildAsynchronousFsdRequest(
  353. MajorFunction,
  354. DeviceObject,
  355. Buffer,
  356. Length,
  357. StartingOffset,
  358. IoStatusBlock
  359. );
  360. } except(EXCEPTION_EXECUTE_HANDLER) {
  361. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  362. IO_BUILD_FSD_REQUEST_EXCEPTION,
  363. (ULONG_PTR)DeviceObject,
  364. (ULONG_PTR)MajorFunction,
  365. GetExceptionCode());
  366. }
  367. return (Irp);
  368. }
  369. PIRP
  370. IovBuildDeviceIoControlRequest(
  371. IN ULONG IoControlCode,
  372. IN PDEVICE_OBJECT DeviceObject,
  373. IN PVOID InputBuffer OPTIONAL,
  374. IN ULONG InputBufferLength,
  375. OUT PVOID OutputBuffer OPTIONAL,
  376. IN ULONG OutputBufferLength,
  377. IN BOOLEAN InternalDeviceIoControl,
  378. IN PKEVENT Event,
  379. OUT PIO_STATUS_BLOCK IoStatusBlock
  380. )
  381. {
  382. PIRP Irp;
  383. try {
  384. Irp = IoBuildDeviceIoControlRequest(
  385. IoControlCode,
  386. DeviceObject,
  387. InputBuffer,
  388. InputBufferLength,
  389. OutputBuffer,
  390. OutputBufferLength,
  391. InternalDeviceIoControl,
  392. Event,
  393. IoStatusBlock
  394. );
  395. } except(EXCEPTION_EXECUTE_HANDLER) {
  396. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  397. IO_BUILD_IOCTL_REQUEST_EXCEPTION,
  398. (ULONG_PTR)DeviceObject,
  399. (ULONG_PTR)IoControlCode,
  400. GetExceptionCode());
  401. }
  402. return (Irp);
  403. }
  404. NTSTATUS
  405. IovInitializeTimer(
  406. IN PDEVICE_OBJECT DeviceObject,
  407. IN PIO_TIMER_ROUTINE TimerRoutine,
  408. IN PVOID Context
  409. )
  410. {
  411. if (DeviceObject->Timer) {
  412. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  413. IO_REINITIALIZING_TIMER_OBJECT,
  414. (ULONG_PTR)DeviceObject,
  415. 0,
  416. 0);
  417. }
  418. return (IoInitializeTimer(DeviceObject, TimerRoutine, Context));
  419. }
  420. VOID
  421. IovpCompleteRequest(
  422. IN PKAPC Apc,
  423. IN PVOID *SystemArgument1,
  424. IN PVOID *SystemArgument2
  425. )
  426. {
  427. PIRP irp;
  428. #if defined(_X86_)
  429. PUCHAR addr;
  430. ULONG BestStackOffset;
  431. #endif
  432. irp = CONTAINING_RECORD( Apc, IRP, Tail.Apc );
  433. UNREFERENCED_PARAMETER (SystemArgument1);
  434. UNREFERENCED_PARAMETER (SystemArgument2);
  435. #if defined(_X86_)
  436. addr = (PUCHAR)irp->UserIosb;
  437. if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
  438. (addr <= (PUCHAR)&BestStackOffset)) {
  439. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  440. IO_INVALID_STACK_IOSB,
  441. (ULONG_PTR)addr,
  442. 0,
  443. 0);
  444. }
  445. addr = (PUCHAR)irp->UserEvent;
  446. if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
  447. (addr <= (PUCHAR)&BestStackOffset)) {
  448. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  449. IO_INVALID_STACK_EVENT,
  450. (ULONG_PTR)addr,
  451. 0,
  452. 0);
  453. }
  454. #endif
  455. }
  456. /*-------------------------- SPECIALIRP HOOKS -------------------------------*/
  457. VOID
  458. FASTCALL
  459. IovCompleteRequest(
  460. IN PIRP Irp,
  461. IN CCHAR PriorityBoost
  462. )
  463. {
  464. IOV_COMPLETION_CONTEXT StackContext;
  465. PIOV_COMPLETION_CONTEXT pStackContext;
  466. IOFCOMPLETEREQUEST_STACKDATA completionPacket;
  467. LONG currentLocation;
  468. PIO_STACK_LOCATION stackPointer;
  469. if (!IopVerifierOn) {
  470. IopfCompleteRequest(Irp, PriorityBoost);
  471. return;
  472. }
  473. if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1) ||
  474. Irp->Type != IO_TYPE_IRP) {
  475. KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS,
  476. (ULONG_PTR) Irp,
  477. __LINE__,
  478. 0,
  479. 0);
  480. }
  481. if (Irp->CancelRoutine) {
  482. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  483. IO_COMPLETE_REQUEST_CANCEL_ROUTINE_SET,
  484. (ULONG_PTR)Irp->CancelRoutine,
  485. (ULONG_PTR)Irp,
  486. 0);
  487. }
  488. if (Irp->IoStatus.Status == STATUS_PENDING || Irp->IoStatus.Status == 0xffffffff) {
  489. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  490. IO_COMPLETE_REQUEST_INVALID_STATUS,
  491. Irp->IoStatus.Status,
  492. (ULONG_PTR)Irp,
  493. 0);
  494. }
  495. if (KeGetCurrentIrql() > DISPATCH_LEVEL) {
  496. KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
  497. IO_COMPLETE_REQUEST_INVALID_IRQL,
  498. KeGetCurrentIrql(),
  499. (ULONG_PTR)Irp,
  500. 0);
  501. }
  502. if (IovpVerifierLevel <= 1) {
  503. IopfCompleteRequest(Irp, PriorityBoost);
  504. return;
  505. }
  506. SPECIALIRP_IOF_COMPLETE_1(Irp, PriorityBoost, &completionPacket);
  507. if ((Irp->CurrentLocation) > (CCHAR) (Irp->StackCount)) {
  508. IopfCompleteRequest(Irp, PriorityBoost);
  509. return;
  510. }
  511. currentLocation = Irp->CurrentLocation;
  512. pStackContext = &StackContext;
  513. stackPointer = IoGetCurrentIrpStackLocation(Irp);
  514. //
  515. // Replace the completion routines with verifier completion routines so that
  516. // verifier gets control.
  517. //
  518. IovpKdPrint(("Hook:Irp 0x%x StackCount %d currentlocation %d stackpointer 0%x\n",
  519. Irp,
  520. Irp->StackCount,
  521. currentLocation,
  522. IoGetCurrentIrpStackLocation(Irp)));
  523. pStackContext->CompletionRoutine = NULL;
  524. pStackContext->GlobalContext = &completionPacket;
  525. pStackContext->IrpContext = stackPointer->Context;
  526. pStackContext->StackPointer = stackPointer;
  527. pStackContext->OldStackContents = *(stackPointer); // Save the stack contents
  528. IovpKdPrint(("Seeding completion Rtn 0x%x currentLocation %d stackpointer 0x%x pStackContext 0x%x \n",
  529. stackPointer->CompletionRoutine,
  530. currentLocation,
  531. stackPointer,
  532. pStackContext
  533. ));
  534. if ( (NT_SUCCESS( Irp->IoStatus.Status ) &&
  535. stackPointer->Control & SL_INVOKE_ON_SUCCESS) ||
  536. (!NT_SUCCESS( Irp->IoStatus.Status ) &&
  537. stackPointer->Control & SL_INVOKE_ON_ERROR) ||
  538. (Irp->Cancel &&
  539. stackPointer->Control & SL_INVOKE_ON_CANCEL)
  540. ) {
  541. pStackContext->CompletionRoutine = stackPointer->CompletionRoutine;
  542. pStackContext->IrpContext = stackPointer->Context;
  543. } else {
  544. //
  545. // Force the completion routine to be called.
  546. // Store the old control flag value.
  547. //
  548. stackPointer->Control |= SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
  549. }
  550. stackPointer->CompletionRoutine = IovpLocalCompletionRoutine;
  551. stackPointer->Context = pStackContext;
  552. IopfCompleteRequest(Irp, PriorityBoost);
  553. }
  554. #define ZeroAndDopeIrpStackLocation( IrpSp ) { \
  555. (IrpSp)->MinorFunction = 0; \
  556. (IrpSp)->Flags = 0; \
  557. (IrpSp)->Control = SL_NOTCOPIED; \
  558. (IrpSp)->Parameters.Others.Argument1 = 0; \
  559. (IrpSp)->Parameters.Others.Argument2 = 0; \
  560. (IrpSp)->Parameters.Others.Argument3 = 0; \
  561. (IrpSp)->Parameters.Others.Argument4 = 0; \
  562. (IrpSp)->FileObject = (PFILE_OBJECT) NULL; }
  563. NTSTATUS
  564. IovpLocalCompletionRoutine(
  565. IN PDEVICE_OBJECT DeviceObject,
  566. IN PIRP Irp,
  567. IN PVOID Context
  568. )
  569. {
  570. PIOV_COMPLETION_CONTEXT pStackContext = Context;
  571. NTSTATUS status;
  572. PIO_STACK_LOCATION stackPointer = pStackContext->StackPointer;
  573. BOOLEAN lastStackLocation = FALSE;
  574. //
  575. // Copy back all parameters that were zeroed out.
  576. //
  577. //
  578. stackPointer->MinorFunction = pStackContext->OldStackContents.MinorFunction;
  579. stackPointer->Flags = pStackContext->OldStackContents.Flags;
  580. stackPointer->Control = pStackContext->OldStackContents.Control;
  581. stackPointer->Parameters.Others.Argument1 = pStackContext->OldStackContents.Parameters.Others.Argument1;
  582. stackPointer->Parameters.Others.Argument2 = pStackContext->OldStackContents.Parameters.Others.Argument2;
  583. stackPointer->Parameters.Others.Argument3 = pStackContext->OldStackContents.Parameters.Others.Argument3;
  584. stackPointer->Parameters.Others.Argument4 = pStackContext->OldStackContents.Parameters.Others.Argument4;
  585. stackPointer->FileObject = pStackContext->OldStackContents.FileObject;
  586. //
  587. // Put these back too.
  588. //
  589. stackPointer->CompletionRoutine = pStackContext->CompletionRoutine;
  590. stackPointer->Context = pStackContext->IrpContext;
  591. //
  592. // Get this before the IRP is freed.
  593. //
  594. lastStackLocation = (Irp->CurrentLocation == (CCHAR) (Irp->StackCount + 1));
  595. //
  596. // Simulated completion routine.
  597. //
  598. SPECIALIRP_IOF_COMPLETE_2(Irp, pStackContext->GlobalContext);
  599. ZeroAndDopeIrpStackLocation( stackPointer );
  600. if (!stackPointer->CompletionRoutine) {
  601. IovpKdPrint(("Local completion routine null stackpointer 0x%x \n", stackPointer));
  602. //
  603. // Handle things as if no completion routine existed.
  604. //
  605. if (Irp->PendingReturned && Irp->CurrentLocation <= Irp->StackCount) {
  606. IoMarkIrpPending( Irp );
  607. }
  608. status = STATUS_SUCCESS;
  609. } else {
  610. IovpKdPrint(("Local completion routine 0x%x stackpointer 0x%x \n", routine, stackPointer));
  611. //
  612. // A completion routine exists, call it now.
  613. //
  614. SPECIALIRP_IOF_COMPLETE_3(Irp, (PVOID) (ULONG_PTR) stackPointer->CompletionRoutine, (PIOFCOMPLETEREQUEST_STACKDATA)pStackContext->GlobalContext);
  615. status = stackPointer->CompletionRoutine(DeviceObject, Irp, stackPointer->Context);
  616. SPECIALIRP_IOF_COMPLETE_4(Irp, status, pStackContext->GlobalContext);
  617. }
  618. SPECIALIRP_IOF_COMPLETE_5(Irp, pStackContext->GlobalContext);
  619. if (status != STATUS_MORE_PROCESSING_REQUIRED && !lastStackLocation) {
  620. //
  621. // Seed the next location. We can touch the stack as the IRP is still valid
  622. //
  623. stackPointer++;
  624. pStackContext->StackPointer = stackPointer;
  625. pStackContext->CompletionRoutine = NULL;
  626. pStackContext->IrpContext = stackPointer->Context;
  627. pStackContext->StackPointer = stackPointer;
  628. pStackContext->OldStackContents = *(stackPointer); // Save the stack contents
  629. if ( (NT_SUCCESS( Irp->IoStatus.Status ) &&
  630. stackPointer->Control & SL_INVOKE_ON_SUCCESS) ||
  631. (!NT_SUCCESS( Irp->IoStatus.Status ) &&
  632. stackPointer->Control & SL_INVOKE_ON_ERROR) ||
  633. (Irp->Cancel &&
  634. stackPointer->Control & SL_INVOKE_ON_CANCEL)
  635. ) {
  636. pStackContext->CompletionRoutine = stackPointer->CompletionRoutine;
  637. pStackContext->IrpContext = stackPointer->Context;
  638. } else {
  639. //
  640. // Force the completion routine to be called.
  641. // Store the old control flag value.
  642. //
  643. stackPointer->Control |= SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
  644. }
  645. stackPointer->CompletionRoutine = IovpLocalCompletionRoutine;
  646. stackPointer->Context = pStackContext;
  647. IovpKdPrint(("Seeding completion Rtn 0x%x currentLocation %d stackpointer 0x%x pStackContext 0x%x \n",
  648. stackPointer->CompletionRoutine,
  649. Irp->CurrentLocation,
  650. stackPointer,
  651. pStackContext
  652. ));
  653. }
  654. return status;
  655. }
  656. VOID
  657. IovInitializeIrp(
  658. PIRP Irp,
  659. USHORT PacketSize,
  660. CCHAR StackSize
  661. )
  662. {
  663. BOOLEAN initializeHandled ;
  664. if (IovpVerifierLevel < 2) {
  665. return;
  666. }
  667. VerifierIoInitializeIrp(Irp, PacketSize, StackSize, &initializeHandled);
  668. }
  669. VOID
  670. IovAttachDeviceToDeviceStack(
  671. PDEVICE_OBJECT SourceDevice,
  672. PDEVICE_OBJECT TargetDevice
  673. )
  674. {
  675. if (IovpVerifierLevel < 2) {
  676. return;
  677. }
  678. VerifierIoAttachDeviceToDeviceStack(SourceDevice, TargetDevice);
  679. }
  680. VOID
  681. IovDeleteDevice(
  682. PDEVICE_OBJECT DeleteDevice
  683. )
  684. {
  685. if (IovpVerifierFlags & DRIVER_VERIFIER_DMA_VERIFIER) {
  686. VfHalDeleteDevice(DeleteDevice);
  687. }
  688. if (IovpVerifierLevel < 2) {
  689. return;
  690. }
  691. VerifierIoDeleteDevice(DeleteDevice);
  692. }
  693. VOID
  694. IovDetachDevice(
  695. PDEVICE_OBJECT TargetDevice
  696. )
  697. {
  698. if (IovpVerifierLevel < 2) {
  699. return;
  700. }
  701. VerifierIoDetachDevice(TargetDevice);
  702. }
  703. BOOLEAN
  704. IovCancelIrp(
  705. PIRP Irp,
  706. BOOLEAN *returnValue
  707. )
  708. {
  709. BOOLEAN cancelHandled;
  710. SPECIALIRP_IO_CANCEL_IRP(Irp, &cancelHandled, returnValue) ;
  711. return cancelHandled;
  712. }
  713. typedef struct _IOV_DRIVER_LIST_ENTRY {
  714. SINGLE_LIST_ENTRY listEntry;
  715. PDRIVER_OBJECT DriverObject;
  716. } IOV_DRIVER_LIST_ENTRY, *PIOV_DRIVER_LIST_ENTRY;
  717. SINGLE_LIST_ENTRY IovDriverListHead;
  718. BOOLEAN
  719. IovpBuildDriverObjectList(
  720. IN PVOID Object,
  721. IN PUNICODE_STRING ObjectName,
  722. IN ULONG_PTR HandleCount,
  723. IN ULONG_PTR PointerCount,
  724. IN PVOID Parameter
  725. )
  726. {
  727. PIOV_DRIVER_LIST_ENTRY driverListEntry;
  728. PDRIVER_OBJECT driverObject;
  729. UNREFERENCED_PARAMETER (ObjectName);
  730. UNREFERENCED_PARAMETER (HandleCount);
  731. UNREFERENCED_PARAMETER (PointerCount);
  732. UNREFERENCED_PARAMETER (Parameter);
  733. driverObject = (PDRIVER_OBJECT)Object;
  734. if (IopIsLegacyDriver(driverObject)) {
  735. driverListEntry = ExAllocatePoolWithTag(
  736. NonPagedPool,
  737. sizeof(IOV_DRIVER_LIST_ENTRY),
  738. 'ovI'
  739. );
  740. if (!driverListEntry) {
  741. return FALSE;
  742. }
  743. if (ObReferenceObjectSafe(driverObject)) {
  744. driverListEntry->DriverObject = driverObject;
  745. PushEntryList(&IovDriverListHead, &driverListEntry->listEntry);
  746. } else {
  747. ExFreePool (driverListEntry);
  748. }
  749. } else {
  750. IovpKdPrint (("Rejected non-legacy driver %wZ (%p)\n", &driverObject->DriverName, driverObject));
  751. }
  752. return TRUE;
  753. }
  754. NTSTATUS
  755. IovpUnloadDriver(
  756. PDRIVER_OBJECT DriverObject
  757. )
  758. {
  759. NTSTATUS status;
  760. BOOLEAN unloadDriver;
  761. //
  762. // Check to see whether or not this driver implements unload.
  763. //
  764. if (DriverObject->DriverUnload == (PDRIVER_UNLOAD) NULL) {
  765. IovpKdPrint (("No unload routine for driver %wZ (%p)\n", &DriverObject->DriverName, DriverObject));
  766. return STATUS_INVALID_DEVICE_REQUEST;
  767. }
  768. //
  769. // Check to see whether the driver has already been marked for an unload
  770. // operation by anyone in the past.
  771. //
  772. ObReferenceObject (DriverObject);
  773. status = IopCheckUnloadDriver(DriverObject,&unloadDriver);
  774. if ( NT_SUCCESS(status) ) {
  775. return STATUS_PENDING;
  776. }
  777. ObDereferenceObject (DriverObject);
  778. if (unloadDriver) {
  779. //
  780. // If the current thread is not executing in the context of the system
  781. // process, which is required in order to invoke the driver's unload
  782. // routine. Queue a worker item to one of the worker threads to
  783. // get into the appropriate process context and then invoke the
  784. // routine.
  785. //
  786. if (PsGetCurrentProcess() == PsInitialSystemProcess) {
  787. //
  788. // The current thread is alrady executing in the context of the
  789. // system process, so simply invoke the driver's unload routine.
  790. //
  791. IovpKdPrint (("Calling unload for driver %wZ (%p)\n",
  792. &DriverObject->DriverName, DriverObject));
  793. DriverObject->DriverUnload( DriverObject );
  794. IovpKdPrint (("Unload returned for driver %wZ (%p)\n",
  795. &DriverObject->DriverName, DriverObject));
  796. } else {
  797. LOAD_PACKET loadPacket;
  798. KeInitializeEvent( &loadPacket.Event, NotificationEvent, FALSE );
  799. loadPacket.DriverObject = DriverObject;
  800. ExInitializeWorkItem( &loadPacket.WorkQueueItem,
  801. IopLoadUnloadDriver,
  802. &loadPacket );
  803. ExQueueWorkItem( &loadPacket.WorkQueueItem, DelayedWorkQueue );
  804. (VOID) KeWaitForSingleObject( &loadPacket.Event,
  805. Executive,
  806. KernelMode,
  807. FALSE,
  808. (PLARGE_INTEGER) NULL );
  809. }
  810. ObMakeTemporaryObject( DriverObject );
  811. ObDereferenceObject( DriverObject );
  812. return STATUS_SUCCESS;
  813. } else {
  814. return STATUS_PENDING;
  815. }
  816. }
  817. NTSTATUS
  818. IovUnloadDrivers(
  819. VOID
  820. )
  821. {
  822. NTSTATUS status;
  823. PSINGLE_LIST_ENTRY listEntry;
  824. PIOV_DRIVER_LIST_ENTRY driverListEntry;
  825. SINGLE_LIST_ENTRY NonUnloadedDrivers, NonUnloadedDriversTmp;
  826. BOOLEAN DoneSomething, NeedWait, Break;
  827. if (!PoCleanShutdownEnabled ())
  828. return STATUS_UNSUCCESSFUL;
  829. IovDriverListHead.Next = NULL;
  830. NonUnloadedDrivers.Next = NULL;
  831. //
  832. // Prepare a list of all driver objects.
  833. //
  834. status = ObEnumerateObjectsByType(
  835. IoDriverObjectType,
  836. IovpBuildDriverObjectList,
  837. NULL
  838. );
  839. //
  840. // Walk through the list and unload each driver.
  841. //
  842. while (TRUE) {
  843. listEntry = PopEntryList(&IovDriverListHead);
  844. if (listEntry == NULL) {
  845. break;
  846. }
  847. driverListEntry = CONTAINING_RECORD(listEntry, IOV_DRIVER_LIST_ENTRY, listEntry);
  848. IovpKdPrint (("Trying to unload %wZ (%p)\n",
  849. &driverListEntry->DriverObject->DriverName, driverListEntry->DriverObject));
  850. if (IovpUnloadDriver(driverListEntry->DriverObject) != STATUS_PENDING) {
  851. ObDereferenceObject(driverListEntry->DriverObject);
  852. ExFreePool(driverListEntry);
  853. } else {
  854. IovpKdPrint (("Unload of driver %wZ (%p) pended\n",
  855. &driverListEntry->DriverObject->DriverName, driverListEntry->DriverObject));
  856. PushEntryList(&NonUnloadedDrivers, &driverListEntry->listEntry);
  857. }
  858. }
  859. //
  860. // Walk the drivers that didn't unload straight away and see if any have had their unloads called yet
  861. //
  862. do {
  863. NeedWait = DoneSomething = FALSE;
  864. NonUnloadedDriversTmp.Next = NULL;
  865. while (TRUE) {
  866. listEntry = PopEntryList(&NonUnloadedDrivers);
  867. if (listEntry == NULL) {
  868. break;
  869. }
  870. driverListEntry = CONTAINING_RECORD(listEntry, IOV_DRIVER_LIST_ENTRY, listEntry);
  871. //
  872. // If driver unload is queued to be invoked then
  873. //
  874. if (driverListEntry->DriverObject->Flags & DRVO_UNLOAD_INVOKED) {
  875. IovpKdPrint (("Pending unload of driver %wZ (%p) is being invoked\n",
  876. &driverListEntry->DriverObject->DriverName, driverListEntry->DriverObject));
  877. ObDereferenceObject(driverListEntry->DriverObject);
  878. ExFreePool(driverListEntry);
  879. NeedWait = TRUE;
  880. } else {
  881. PushEntryList(&NonUnloadedDriversTmp, &driverListEntry->listEntry);
  882. }
  883. }
  884. if (NeedWait) {
  885. LARGE_INTEGER tmo = {(ULONG)(-10 * 1000 * 1000 * 10), -1};
  886. ZwDelayExecution (FALSE, &tmo);
  887. DoneSomething = TRUE;
  888. }
  889. NonUnloadedDrivers = NonUnloadedDriversTmp;
  890. } while (DoneSomething == TRUE && NonUnloadedDrivers.Next != NULL);
  891. //
  892. // All the drivers left didn't have unload called becuase they had files open etc
  893. //
  894. Break = FALSE;
  895. while (TRUE) {
  896. listEntry = PopEntryList(&NonUnloadedDrivers);
  897. if (listEntry == NULL) {
  898. break;
  899. }
  900. driverListEntry = CONTAINING_RECORD(listEntry, IOV_DRIVER_LIST_ENTRY, listEntry);
  901. IovpKdPrint (("Unload never got called for driver %wZ (%p)\n",
  902. &driverListEntry->DriverObject->DriverName, driverListEntry->DriverObject));
  903. ObDereferenceObject(driverListEntry->DriverObject);
  904. ExFreePool(driverListEntry);
  905. Break = TRUE;
  906. }
  907. if (Break == TRUE) {
  908. // DbgBreakPoint ();
  909. }
  910. return status;
  911. }