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.

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