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.

3163 lines
99 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. trackirp.c
  5. Abstract:
  6. This module tracks irps and verified drivers when people do bad things with
  7. them.
  8. Note to people hitting bugs in these code paths due to core changes:
  9. - "This file is NOT vital to operation of the OS, and could easily be
  10. disabled while a redesign to compensate for the core change is
  11. implemented." - the author
  12. Author:
  13. Adrian J. Oney (adriao) 09-May-1998
  14. Environment:
  15. Kernel mode
  16. Revision History:
  17. --*/
  18. #include "iop.h"
  19. #include "pnpi.h"
  20. #include "arbiter.h"
  21. #include "dockintf.h"
  22. #include "pnprlist.h"
  23. #include "pnpiop.h"
  24. #if (( defined(_X86_) ) && ( FPO ))
  25. #pragma optimize( "y", off ) // disable FPO for consistent stack traces
  26. #endif
  27. #define POOL_TAG_DEFERRED_CONTEXT 'dprI'
  28. //
  29. // This entire file is only present if NO_SPECIAL_IRP isn't defined
  30. //
  31. #ifndef NO_SPECIAL_IRP
  32. //
  33. // When enabled, everything is locked down on demand...
  34. //
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGEVRFY, IovpPacketFromIrp)
  37. #pragma alloc_text(PAGEVRFY, IovpCheckIrpForCriticalTracking)
  38. #pragma alloc_text(PAGEVRFY, IovpCallDriver1)
  39. #pragma alloc_text(PAGEVRFY, IovpCallDriver2)
  40. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest1)
  41. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest2)
  42. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest3)
  43. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest4)
  44. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest5)
  45. #pragma alloc_text(PAGEVRFY, IovpCompleteRequest)
  46. #pragma alloc_text(PAGEVRFY, IovpCancelIrp)
  47. #pragma alloc_text(PAGEVRFY, IovpInternalCompletionTrap)
  48. #pragma alloc_text(PAGEVRFY, IovpSwapSurrogateIrp)
  49. #pragma alloc_text(PAGEVRFY, IovpExamineDevObjForwarding)
  50. #pragma alloc_text(PAGEVRFY, IovpExamineIrpStackForwarding)
  51. #pragma alloc_text(PAGEVRFY, IovpInternalDeferredCompletion)
  52. #pragma alloc_text(PAGEVRFY, IovpInternalCompleteAfterWait)
  53. #pragma alloc_text(PAGEVRFY, IovpInternalCompleteAtDPC)
  54. #pragma alloc_text(PAGEVRFY, IovpAdvanceStackDownwards)
  55. #pragma alloc_text(PAGEVRFY, IovpBuildMiniIrpSnapshot)
  56. #endif
  57. //
  58. // This counter is used in picking random IRPs to cancel
  59. //
  60. ULONG IovpCancelCount = 0;
  61. //
  62. // Debug spew level
  63. //
  64. #if DBG
  65. ULONG IovpIrpTrackingSpewLevel = 0;
  66. #endif
  67. /*
  68. * - The IRP verification code works as follows -
  69. *
  70. * To enforce the correct handling of an IRP, we must maintain some data about
  71. * it. But the IRP is a public structure and as drivers are allowed to create
  72. * IRPs without using IoAllocateIrp we cannot add any fields to it. Therefore
  73. * we maintain out own side structures that are looked up via a hash table.
  74. *
  75. * IOV_REQUEST_PACKETs cover the lifetime of the IRP from allocation to
  76. * deallocation, and from there (sans pointer) until all "references" have
  77. * been dropped, which may happen long after the IRP itself was freed and
  78. * recycled.
  79. *
  80. * When an IRP is progress down a stack, a "session" is allocated. An
  81. * IovRequestPacket has a current session until such time as the IRP is
  82. * completed. The session still exists until all references are dropped, but
  83. * before that happens a new session may become the current session (ie the IRP
  84. * was sent back down before the previous call stacks unwound). The tracking
  85. * data is held around until all sessions have decayed.
  86. *
  87. * Each session has an array of stack locations corresponding to those in use
  88. * by the IRP. These IOV_STACK_LOCATIONs are used to track "requests" within
  89. * the IRP, ie the passage of a major/minor/parameter set down the stack.
  90. * Of course multiple requests may exist in the same session/stack at once.
  91. *
  92. * Finally, surrogates. The IoVerifier may "switch" the IRP in use as it goes
  93. * down the stack. In this case the new IRP is usually allocated from the
  94. * special pool and freed as early as possible to catch bugs (people who touch
  95. * after completes). Each surrogate gets it's own IovRequestPacket, which is
  96. * linked to the previous surrogate or real irp in use prior to it.
  97. *
  98. * +--------------------+ +--------------------+
  99. * | IOV_REQUEST_PACKET | | IOV_REQUEST_PACKET |
  100. * | (original irp) |<--------------------| (surrogate) |
  101. * | | | |
  102. * +--------------------+ +--------------------+
  103. * ||
  104. * v
  105. * +-------------------+ +-------------------------+
  106. * | IOV_SESSION_DATA | | IOV_STACK_LOCATION[...] |
  107. * | (current session) |------>| (per IrpSp data) |
  108. * | | | |
  109. * +-------------------+ +-------------------------+
  110. *
  111. */
  112. /*
  113. * The routines listed below -
  114. * IovpCallDriver1
  115. * IovpCallDriver2
  116. * IovpCompleteRequest1
  117. * IovpCompleteRequest2
  118. * IovpCompleteRequest3
  119. * IovpCompleteRequest4
  120. * IovpCompleteRequest5
  121. * IovpCompleteRequest
  122. * IovpCancelIrp
  123. * and their helper routines
  124. * IovpSwapSurrogateIrp
  125. * IovpPacketFromIrp
  126. *
  127. * - all hook into various parts IofCallDriver and IofCompleteRequest to
  128. * track the IRP through it's life and determine whether it has been handled
  129. * correctly. Some of them may even change internal variables in the hooked
  130. * function. Most dramatically, IovpCallDriver1 may build a replacement Irp
  131. * which will take the place of the one passed into IoCallDriver.
  132. *
  133. * All of the below functions use a tracking structure called (reasonably
  134. * enough) IRP_TRACKING_DATA. This lasts the longer of the call stack
  135. * unwinding or the IRP completing.
  136. *
  137. */
  138. VOID
  139. FASTCALL
  140. IovpPacketFromIrp(
  141. IN PIRP Irp,
  142. OUT PIOV_REQUEST_PACKET *IovPacket
  143. )
  144. {
  145. //
  146. // The examined flag is set on any IRP that has come through
  147. // IofCallDriver. We use the flag to detect whether we have seen the IRP
  148. // before.
  149. //
  150. switch(Irp->Flags&IRPFLAG_EXAMINE_MASK) {
  151. case IRPFLAG_EXAMINE_NOT_TRACKED:
  152. //
  153. // This packet is marked do not touch. So we ignore it.
  154. //
  155. *IovPacket = NULL;
  156. return;
  157. case IRPFLAG_EXAMINE_TRACKED:
  158. //
  159. // This packet has been marked. We should find it.
  160. //
  161. *IovPacket = VfPacketFindAndLock(Irp);
  162. ASSERT(*IovPacket != NULL);
  163. return;
  164. case IRPFLAG_EXAMINE_UNMARKED:
  165. *IovPacket = VfPacketFindAndLock(Irp);
  166. if (*IovPacket) {
  167. //
  168. // Was tracked but cache flag got wiped. Replace.
  169. //
  170. Irp->Flags |= IRPFLAG_EXAMINE_TRACKED;
  171. } else if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_TRACK_IRPS)) {
  172. //
  173. // Create the packet
  174. //
  175. *IovPacket = VfPacketCreateAndLock(Irp);
  176. if (*IovPacket) {
  177. //
  178. // Mark it
  179. //
  180. Irp->Flags |= IRPFLAG_EXAMINE_TRACKED;
  181. } else {
  182. //
  183. // No memory, try to keep it out of the IRP assert though.
  184. //
  185. Irp->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED;
  186. }
  187. } else {
  188. //
  189. // Do as told, don't track through IofCallDriver.
  190. //
  191. Irp->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED;
  192. }
  193. return;
  194. default:
  195. ASSERT(0);
  196. *IovPacket = NULL;
  197. return;
  198. }
  199. }
  200. BOOLEAN
  201. FASTCALL
  202. IovpCheckIrpForCriticalTracking(
  203. IN PIRP Irp
  204. )
  205. {
  206. PIOV_REQUEST_PACKET iovPacket;
  207. PIOV_SESSION_DATA iovSessionData;
  208. switch(Irp->Flags&IRPFLAG_EXAMINE_MASK) {
  209. case IRPFLAG_EXAMINE_NOT_TRACKED:
  210. //
  211. // Noncritical, we can avoid tracking this if memory is tight.
  212. //
  213. return FALSE;
  214. case IRPFLAG_EXAMINE_TRACKED:
  215. //
  216. // Might be critical.
  217. //
  218. iovPacket = VfPacketFindAndLock(Irp);
  219. ASSERT(iovPacket);
  220. if (iovPacket == NULL) {
  221. return FALSE;
  222. }
  223. break;
  224. case IRPFLAG_EXAMINE_UNMARKED:
  225. iovPacket = VfPacketFindAndLock(Irp);
  226. if (iovPacket) {
  227. //
  228. // Was tracked but cache flag got wiped. Replace.
  229. //
  230. Irp->Flags |= IRPFLAG_EXAMINE_TRACKED;
  231. break;
  232. }
  233. //
  234. // Noncritical.
  235. //
  236. Irp->Flags |= IRPFLAG_EXAMINE_NOT_TRACKED;
  237. return FALSE;
  238. default:
  239. ASSERT(0);
  240. return FALSE;
  241. }
  242. //
  243. // Look for a session. This IRP is critical if it's already in play.
  244. //
  245. iovSessionData = VfPacketGetCurrentSessionData(iovPacket);
  246. VfPacketReleaseLock(iovPacket);
  247. return (iovSessionData != NULL);
  248. }
  249. VOID
  250. FASTCALL
  251. IovpCallDriver1(
  252. IN PDEVICE_OBJECT DeviceObject,
  253. IN OUT PIRP *IrpPointer,
  254. IN OUT PIOFCALLDRIVER_STACKDATA IofCallDriverStackData OPTIONAL,
  255. IN PVOID CallerAddress OPTIONAL
  256. )
  257. /*++
  258. Description:
  259. This routine is called by IofCallDriver just before adjusting
  260. the IRP stack and calling the driver's dispatch routine.
  261. Arguments:
  262. DeviceObject - Device object passed into IofCallDriver.
  263. IrpPointer - a pointer* to the IRP passed in to
  264. IofCallDriver. This routine may
  265. change the pointer if a surrogate
  266. IRP is allocated.
  267. IofCallDriverStackData - Pointer to a local variable on
  268. IofCallDriver's stack to store data.
  269. The stored information will be picked
  270. up by IovpCallDriver2, and
  271. may be adjusted at other times.
  272. CallerAddress - Address of the caller. May be NULL in cases where
  273. the caller is unknown.
  274. Return Value:
  275. None.
  276. --*/
  277. {
  278. PIOV_REQUEST_PACKET iovPacket;
  279. PIOV_SESSION_DATA iovSessionData;
  280. PIOV_STACK_LOCATION iovCurrentStackLocation;
  281. PIRP irp, replacementIrp;
  282. PIO_STACK_LOCATION irpSp, irpLastSp;
  283. BOOLEAN isNewSession, isNewRequest, previouslyInUse, surrogateSpawned;
  284. ULONG isSameStack;
  285. ULONG locationsAdvanced, completeStyle;
  286. PDEVICE_OBJECT pdo, lowerDeviceObject;
  287. PDRIVER_OBJECT driverObject;
  288. PVOID dispatchRoutine;
  289. LARGE_INTEGER arrivalTime;
  290. KIRQL invocationIrql;
  291. if (IofCallDriverStackData == NULL) {
  292. //
  293. // Nothing to track.
  294. //
  295. return;
  296. }
  297. irp = *IrpPointer;
  298. irpSp = IoGetNextIrpStackLocation( irp );
  299. invocationIrql = KeGetCurrentIrql();
  300. //
  301. // Get a verifier packet for the IRP. Note that we come back at dispatch
  302. // level with a lock held if a packet was available.
  303. //
  304. IovpPacketFromIrp(irp, &iovPacket);
  305. if (iovPacket == NULL) {
  306. //
  307. // Nothing to track, get out.
  308. //
  309. return;
  310. }
  311. //
  312. // Set the arrival and departure Irqls (note that future code will make the
  313. // arrival irql different for PoCallDriver.)
  314. //
  315. iovPacket->ArrivalIrql = invocationIrql;
  316. iovPacket->DepartureIrql = invocationIrql;
  317. //
  318. // Snapshot the arrival time of this IRP.
  319. //
  320. KeQuerySystemTime(&arrivalTime);
  321. //
  322. // If we are going to die shortly, kindly say so.
  323. //
  324. if (DeviceObject == NULL) {
  325. WDM_FAIL_ROUTINE((
  326. DCERROR_NULL_DEVOBJ_FORWARDED,
  327. DCPARAM_IRP + DCPARAM_ROUTINE,
  328. CallerAddress,
  329. irp
  330. ));
  331. }
  332. //
  333. // Find the current session. The session terminates when the final top-level
  334. // completion routine gets called.
  335. //
  336. iovSessionData = VfPacketGetCurrentSessionData(iovPacket);
  337. if (iovSessionData) {
  338. //
  339. // Pre-existing session (ie, the IRP is being forwarded.)
  340. //
  341. ASSERT(iovPacket->Flags&TRACKFLAG_ACTIVE);
  342. isNewSession = FALSE;
  343. IovpSessionDataAdvance(
  344. DeviceObject,
  345. iovSessionData, // This param is optional.
  346. &iovPacket,
  347. &surrogateSpawned
  348. );
  349. } else if (!(iovPacket->Flags&TRACKFLAG_ACTIVE)){
  350. //
  351. // New session. Mark the IRP as "active".
  352. //
  353. iovPacket->Flags |= TRACKFLAG_ACTIVE;
  354. isNewSession = TRUE;
  355. iovSessionData = IovpSessionDataCreate(
  356. DeviceObject,
  357. &iovPacket,
  358. &surrogateSpawned
  359. );
  360. } else {
  361. //
  362. // Might hit this path under low memory, or we are tracking allocations
  363. // but not the IRP sessions themselves.
  364. //
  365. }
  366. //
  367. // Let IovpCallDriver2 know what it's tracking (IovPacket will be
  368. // ignored if IovSessionData is NULL)
  369. //
  370. IofCallDriverStackData->IovSessionData = iovSessionData;
  371. IofCallDriverStackData->IovPacket = iovPacket;
  372. IofCallDriverStackData->DispatchRoutine = DeviceObject->DriverObject->MajorFunction[irpSp->MajorFunction];
  373. if (iovSessionData == NULL) {
  374. VfPacketReleaseLock(iovPacket);
  375. return;
  376. }
  377. VfPacketLogEntry(iovPacket, IOV_EVENT_IO_CALL_DRIVER, CallerAddress, 0);
  378. if (surrogateSpawned) {
  379. //
  380. // iovPacket was changed to cover the surrogate IRP. Update our own
  381. // local variable and IofCallDriver's local variable appropriately.
  382. //
  383. irp = iovPacket->TrackedIrp;
  384. irpSp = IoGetNextIrpStackLocation(irp);
  385. *IrpPointer = irp;
  386. }
  387. if (isNewSession) {
  388. IovUtilGetBottomDeviceObject(DeviceObject, &pdo);
  389. VfIrpLogRecordEvent(iovPacket->VerifierSettings, pdo, irp);
  390. ObDereferenceObject(pdo);
  391. VfPacketReference(iovPacket, IOVREFTYPE_POINTER);
  392. IovpSessionDataReference(iovSessionData);
  393. }
  394. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  395. //
  396. // If someone has given us an IRP with a cancel routine, beat them. Drivers
  397. // set cancel routines when they are going to be pending IRPs *themselves*
  398. // and should remove them before passing the IRP below. This is also true
  399. // as the driver will *not* call your cancel routine if he writes in his
  400. // own (which it may). Nor is the lower driver expected to put yours back
  401. // either...
  402. //
  403. if (irp->CancelRoutine) {
  404. WDM_FAIL_ROUTINE((
  405. DCERROR_CANCELROUTINE_FORWARDED,
  406. DCPARAM_IRP + DCPARAM_ROUTINE,
  407. CallerAddress,
  408. irp
  409. ));
  410. irp->CancelRoutine = NULL;
  411. }
  412. }
  413. //
  414. // Now do any checking that requires tracking data.
  415. //
  416. if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) {
  417. //
  418. // We internally queue irps to catch bugs. When we are doing this, we
  419. // force the stack returned status to STATUS_PENDING, and we queue the
  420. // irp and release it on a timer. We also may make the IRP non-touchable.
  421. // This particular caller is trying to forward an IRP he doesn't own,
  422. // and we didn't actually end up with an untouchable irp.
  423. //
  424. WDM_FAIL_ROUTINE((
  425. DCERROR_QUEUED_IRP_FORWARDED,
  426. DCPARAM_IRP + DCPARAM_ROUTINE,
  427. CallerAddress,
  428. irp
  429. ));
  430. }
  431. //
  432. // Figure out how many stack locations we've moved up since we've last seen
  433. // this IRP, and determine if the stack locations were copied appropriately.
  434. // We also need to see exactly how the IRP was forwarded (down the stack,
  435. // to another stack, straight to the PDO, etc).
  436. //
  437. IovpExamineDevObjForwarding(
  438. DeviceObject,
  439. iovSessionData->DeviceLastCalled,
  440. &iovSessionData->ForwardMethod
  441. );
  442. IovpExamineIrpStackForwarding(
  443. iovPacket,
  444. isNewSession,
  445. iovSessionData->ForwardMethod,
  446. DeviceObject,
  447. irp,
  448. CallerAddress,
  449. &irpSp,
  450. &irpLastSp,
  451. &locationsAdvanced
  452. );
  453. TRACKIRP_DBGPRINT((
  454. " CD1: Current, Last = (%x, %x)\n",
  455. irp->CurrentLocation,
  456. iovPacket->LastLocation
  457. ), 3);
  458. //
  459. // Figure out whether this is a new request or not, and record a
  460. // pointer in this slot to the requests originating slot as appropriate.
  461. //
  462. isNewRequest = VfMajorIsNewRequest(irpLastSp, irpSp);
  463. //
  464. // Record information in our private stack locations and
  465. // write that back into the "stack" data itself...
  466. //
  467. previouslyInUse = IovpAdvanceStackDownwards(
  468. iovSessionData->StackData,
  469. irp->CurrentLocation,
  470. irpSp,
  471. irpLastSp,
  472. locationsAdvanced,
  473. isNewRequest,
  474. TRUE,
  475. &iovCurrentStackLocation
  476. );
  477. ASSERT(iovCurrentStackLocation);
  478. if (previouslyInUse) {
  479. ASSERT(!isNewRequest);
  480. ASSERT(!isNewSession);
  481. iovCurrentStackLocation->PerfDispatchStart = arrivalTime;
  482. } else {
  483. IofCallDriverStackData->Flags |= CALLFLAG_TOPMOST_IN_SLOT;
  484. InitializeListHead(&IofCallDriverStackData->SharedLocationList);
  485. iovCurrentStackLocation->PerfDispatchStart = arrivalTime;
  486. iovCurrentStackLocation->PerfStackLocationStart = arrivalTime;
  487. //
  488. // Record the first thread this IRP slot was dispatched to.
  489. //
  490. iovCurrentStackLocation->ThreadDispatchedTo = PsGetCurrentThread();
  491. if (isNewRequest) {
  492. iovCurrentStackLocation->InitialStatusBlock = irp->IoStatus;
  493. iovCurrentStackLocation->LastStatusBlock = irp->IoStatus;
  494. if (isNewSession) {
  495. iovCurrentStackLocation->Flags |= STACKFLAG_FIRST_REQUEST;
  496. }
  497. }
  498. }
  499. //
  500. // Record whether this is the last device object for this IRP...
  501. // PDO's have devnodes filled out, so look for that field.
  502. // Actually, we can't quite do that trick as during Bus
  503. // enumeration a bus filter might be sending down Irps before
  504. // the OS has ever seen the node. So we assume a devobj is a
  505. // PDO if he has never attached to anyone.
  506. //
  507. IovUtilGetLowerDeviceObject(DeviceObject, &lowerDeviceObject);
  508. if (lowerDeviceObject) {
  509. ObDereferenceObject(lowerDeviceObject);
  510. } else {
  511. iovCurrentStackLocation->Flags |= STACKFLAG_REACHED_PDO;
  512. }
  513. //
  514. // Record who is getting this IRP (we will blame any mistakes on him
  515. // if this request gets completed.) Note that we've already asserted
  516. // DeviceObject is non-NULL...
  517. //
  518. driverObject = DeviceObject->DriverObject;
  519. dispatchRoutine = driverObject->MajorFunction[irpSp->MajorFunction];
  520. iovCurrentStackLocation->LastDispatch = dispatchRoutine;
  521. //
  522. // Uncomplete the request if we are heading back down with it...
  523. //
  524. iovCurrentStackLocation->Flags &= ~STACKFLAG_REQUEST_COMPLETED;
  525. //
  526. // This IofCallDriver2 dude will need to be told what his status should
  527. // be later. Add him to the linked list of addresses to scribble away
  528. // stati when the appropriate level is completed.
  529. //
  530. InsertHeadList(
  531. &iovCurrentStackLocation->CallStackData,
  532. &IofCallDriverStackData->SharedLocationList
  533. );
  534. //
  535. // More IofCallDriver2 stuff, tell him the stack location.
  536. //
  537. IofCallDriverStackData->IovStackLocation = iovCurrentStackLocation;
  538. //
  539. // Snapshot the IRP in case we need to give a summary of it even after the
  540. // IRP has been freed.
  541. //
  542. IovpBuildMiniIrpSnapshot(irp, &IofCallDriverStackData->IrpSnapshot);
  543. //
  544. // If the IRP has arrived pending, we are probably looking at someone
  545. // "wrapping" the IoCallDriver and intending to return STATUS_PENDING
  546. // (PoCallDriver does this). We must remember this, because the unwind
  547. // should be treated as if STATUS_PENDING was returned.
  548. //
  549. if (irpSp->Control & SL_PENDING_RETURNED) {
  550. IofCallDriverStackData->Flags |= CALLFLAG_ARRIVED_PENDING;
  551. }
  552. // If it's a remove IRP, mark everyone appropriately
  553. if ((irpSp->MajorFunction == IRP_MJ_PNP)&&
  554. (irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)) {
  555. IofCallDriverStackData->Flags |= CALLFLAG_IS_REMOVE_IRP;
  556. IovUtilGetBottomDeviceObject(DeviceObject, &pdo);
  557. ASSERT(pdo);
  558. IofCallDriverStackData->RemovePdo = pdo;
  559. ObDereferenceObject(pdo);
  560. if (IovUtilIsInFdoStack(DeviceObject) && (!IovUtilIsRawPdo(DeviceObject))) {
  561. IofCallDriverStackData->Flags |= CALLFLAG_REMOVING_FDO_STACK_DO;
  562. }
  563. }
  564. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  565. VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_MONITOR_MAJORS)) {
  566. //
  567. // Do IRP-major specific assertions as appropriate
  568. //
  569. if (isNewSession) {
  570. VfMajorVerifyNewIrp(
  571. iovPacket,
  572. irp,
  573. irpSp,
  574. iovCurrentStackLocation,
  575. CallerAddress
  576. );
  577. }
  578. if (isNewRequest) {
  579. VfMajorVerifyNewRequest(
  580. iovPacket,
  581. DeviceObject,
  582. irpLastSp,
  583. irpSp,
  584. iovCurrentStackLocation,
  585. CallerAddress
  586. );
  587. }
  588. VfMajorVerifyIrpStackDownward(
  589. iovPacket,
  590. DeviceObject,
  591. irpLastSp,
  592. irpSp,
  593. iovCurrentStackLocation,
  594. CallerAddress
  595. );
  596. }
  597. //
  598. // Update our fields
  599. //
  600. iovSessionData->DeviceLastCalled = DeviceObject;
  601. iovPacket->LastLocation = irp->CurrentLocation;
  602. iovCurrentStackLocation->RequestsFirstStackLocation->LastStatusBlock = irp->IoStatus;
  603. //
  604. // Dope the next stack location so we can detect usage of
  605. // IoCopyCurrentIrpStackLocationToNext or IoSetCompletionRoutine.
  606. //
  607. if (irp->CurrentLocation>1) {
  608. IoSetNextIrpStackLocation( irp );
  609. irpSp = IoGetNextIrpStackLocation( irp );
  610. irpSp->Control |= SL_NOTCOPIED;
  611. IoSkipCurrentIrpStackLocation( irp );
  612. }
  613. //
  614. // Randomly set the cancel flag on a percentage of forwarded IRPs. Many
  615. // drivers queue first and after dequeue assume the cancel routine they
  616. // set must have been cleared if Cancel = TRUE. They don't handle the case
  617. // were the Irp was cancelled in flight.
  618. //
  619. if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_RANDOMLY_CANCEL_IRPS) &&
  620. (!(irp->Flags & IRP_PAGING_IO))) {
  621. if (((++IovpCancelCount) % 4000) == 0) {
  622. irp->Cancel = TRUE;
  623. }
  624. }
  625. //
  626. // Assert LastLocation is consistent with an IRP that may be completed.
  627. //
  628. ASSERT(iovSessionData->StackData[iovPacket->LastLocation-1].InUse);
  629. IovpSessionDataReference(iovSessionData);
  630. VfPacketReference(iovPacket, IOVREFTYPE_PACKET);
  631. VfPacketReleaseLock(iovPacket);
  632. }
  633. VOID
  634. FASTCALL
  635. IovpCallDriver2(
  636. IN PDEVICE_OBJECT DeviceObject,
  637. IN OUT NTSTATUS *FinalStatus,
  638. IN PIOFCALLDRIVER_STACKDATA IofCallDriverStackData OPTIONAL
  639. )
  640. /*++
  641. Description:
  642. This routine is called by IofCallDriver just after the driver's dispatch
  643. routine has been called.
  644. Arguments:
  645. DeviceObject - Device object passed into IofCallDriver.
  646. FinalStatus - A pointer to the status returned by the dispatch
  647. routine. This may be changed if all IRPs are being
  648. forced "pending".
  649. IofCallDriverStackData - Pointer to a local variable on IofCallDriver's
  650. stack to retreive data stored by IovpCallDriver1.
  651. Return Value:
  652. None.
  653. --*/
  654. {
  655. NTSTATUS status, lastStatus;
  656. PIOV_REQUEST_PACKET iovPacket;
  657. PIOV_SESSION_DATA iovSessionData;
  658. ULONG refCount;
  659. PIOV_STACK_LOCATION iovCurrentStackLocation;
  660. PPVREMOVAL_OPTION removalOption;
  661. BOOLEAN pendingReturned;
  662. PDEVICE_OBJECT lowerDevObj;
  663. if (IofCallDriverStackData == NULL) {
  664. return;
  665. }
  666. iovSessionData = IofCallDriverStackData->IovSessionData;
  667. if (iovSessionData == NULL) {
  668. return;
  669. }
  670. iovPacket = IofCallDriverStackData->IovPacket;
  671. ASSERT(iovPacket);
  672. VfPacketAcquireLock(iovPacket);
  673. VfPacketLogEntry(
  674. iovPacket,
  675. IOV_EVENT_IO_CALL_DRIVER_UNWIND,
  676. IofCallDriverStackData->DispatchRoutine,
  677. *FinalStatus
  678. );
  679. //
  680. // The IRP should be considered to have had pending returned if it arrived
  681. // pending or the return status was STATUS_PENDING.
  682. //
  683. pendingReturned =
  684. ((*FinalStatus == STATUS_PENDING) ||
  685. (IofCallDriverStackData->Flags & CALLFLAG_ARRIVED_PENDING));
  686. //
  687. // Also ensure People don't detach/delete on surprise-remove
  688. //
  689. if ((IofCallDriverStackData->Flags&CALLFLAG_IS_REMOVE_IRP) &&
  690. VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings,
  691. VERIFIER_OPTION_MONITOR_REMOVES)) {
  692. //
  693. // Per bad spec, detaching and deleting occurs *after* the IRP is
  694. // completed.
  695. //
  696. if (!pendingReturned) {
  697. IovUtilGetLowerDeviceObject(DeviceObject, &lowerDevObj);
  698. //
  699. // We can look at this because the caller has committed to this being
  700. // completed now, and we are on the original thread.
  701. //
  702. // N.B. This works because all the objects in the stack have been
  703. // referenced during a remove. If we decide to only reference the
  704. // top object, this logic would break...
  705. //
  706. if (IofCallDriverStackData->Flags&CALLFLAG_REMOVING_FDO_STACK_DO) {
  707. //
  708. // FDO, Upper, & Lower filters *must* go. Note that lowerDevObj
  709. // should be null as we should have detached.
  710. //
  711. removalOption = PPVREMOVAL_SHOULD_DELETE;
  712. } else {
  713. removalOption = PpvUtilGetDevnodeRemovalOption(
  714. IofCallDriverStackData->RemovePdo
  715. );
  716. }
  717. if (removalOption == PPVREMOVAL_SHOULD_DELETE) {
  718. //
  719. // IoDetachDevice and IoDeleteDevice should have been called.
  720. // First verify IoDetachDevice...
  721. //
  722. if (lowerDevObj) {
  723. WDM_FAIL_ROUTINE((
  724. DCERROR_SHOULDVE_DETACHED,
  725. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  726. IofCallDriverStackData->DispatchRoutine,
  727. &IofCallDriverStackData->IrpSnapshot,
  728. DeviceObject
  729. ));
  730. }
  731. //
  732. // Now verify IoDeleteDevice
  733. //
  734. if (!IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
  735. WDM_FAIL_ROUTINE((
  736. DCERROR_SHOULDVE_DELETED,
  737. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  738. IofCallDriverStackData->DispatchRoutine,
  739. &IofCallDriverStackData->IrpSnapshot,
  740. DeviceObject
  741. ));
  742. }
  743. } else if (removalOption == PPVREMOVAL_SHOULDNT_DELETE) {
  744. //
  745. // Did we mistakenly leave? Verify we aren't a bus filter that
  746. // has been fooled. In that case, no checking can be done...
  747. //
  748. ASSERT(!(IofCallDriverStackData->Flags&CALLFLAG_REMOVING_FDO_STACK_DO));
  749. if (DeviceObject == IofCallDriverStackData->RemovePdo) {
  750. //
  751. // Check PDO's - did we mistakenly delete ourselves?
  752. //
  753. if (IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
  754. WDM_FAIL_ROUTINE((
  755. DCERROR_DELETED_PRESENT_PDO,
  756. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  757. IofCallDriverStackData->DispatchRoutine,
  758. &IofCallDriverStackData->IrpSnapshot,
  759. DeviceObject
  760. ));
  761. }
  762. } else if (!IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
  763. //
  764. // Check bus filters. Bus filters better not have detached
  765. // or deleted themselves, as the PDO is still present!
  766. //
  767. if (lowerDevObj == NULL) {
  768. //
  769. // Oops, it detached. Baad bus filter...
  770. //
  771. WDM_FAIL_ROUTINE((
  772. DCERROR_BUS_FILTER_ERRONEOUSLY_DETACHED,
  773. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  774. IofCallDriverStackData->DispatchRoutine,
  775. &IofCallDriverStackData->IrpSnapshot,
  776. DeviceObject
  777. ));
  778. }
  779. if (IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
  780. //
  781. // It deleted itself. Also very bad...
  782. //
  783. WDM_FAIL_ROUTINE((
  784. DCERROR_BUS_FILTER_ERRONEOUSLY_DELETED,
  785. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  786. IofCallDriverStackData->DispatchRoutine,
  787. &IofCallDriverStackData->IrpSnapshot,
  788. DeviceObject
  789. ));
  790. }
  791. }
  792. }
  793. if (lowerDevObj) {
  794. ObDereferenceObject(lowerDevObj);
  795. }
  796. }
  797. }
  798. if ((IofCallDriverStackData->Flags&CALLFLAG_COMPLETED) &&
  799. VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_MONITOR_PENDING_IO) &&
  800. (!(iovSessionData->SessionFlags & SESSIONFLAG_MARKED_INCONSISTANT))) {
  801. //
  802. // The rules for the pending bit require that it be set only if
  803. // STATUS_PENDING is returned, and likewise STATUS_PENDING can be returned
  804. // only if the IRP is marked pending.
  805. //
  806. if (IofCallDriverStackData->Flags&CALLFLAG_MARKED_PENDING) {
  807. if (!pendingReturned) {
  808. if (IofCallDriverStackData->IrpSnapshot.IoStackLocation.MajorFunction != IRP_MJ_POWER) {
  809. //
  810. // ADRIAO BUGBUG 2001/06/21 - Some bugs left uncaught
  811. // The verifier only fails IRPs with the DEFER_IO
  812. // flag set right now because we've been failing the
  813. // wrong driver until very very recently. Even worse,
  814. // that driver has been the verifier filters
  815. // themselves, and we don't check the kernel by
  816. // default. Also, PoCallDriver doesn't always mark the
  817. // IRP stack location pending, so we may fail a driver
  818. // due to the PoCallDriver bug (we also caught this
  819. // late cause it's been harmless).
  820. //
  821. // We will address all this stuff next release.
  822. //
  823. WDM_FAIL_ROUTINE((
  824. DCERROR_PENDING_MARKED_NOT_RETURNED,
  825. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_STATUS,
  826. IofCallDriverStackData->DispatchRoutine,
  827. &IofCallDriverStackData->IrpSnapshot,
  828. *FinalStatus
  829. ));
  830. }
  831. iovSessionData->SessionFlags |= SESSIONFLAG_MARKED_INCONSISTANT;
  832. }
  833. } else if (pendingReturned) {
  834. if (IofCallDriverStackData->IrpSnapshot.IoStackLocation.MajorFunction != IRP_MJ_POWER) {
  835. //
  836. // ADRIAO BUGBUG 2001/06/21 - Some bugs left uncaught
  837. // The verifier only fails IRPs with the DEFER_IO
  838. // flag set right now because we've been failing the
  839. // wrong driver until very very recently. Even worse,
  840. // that driver has been the verifier filters
  841. // themselves, and we don't check the kernel by
  842. // default. Also, PoCallDriver doesn't always mark the
  843. // IRP stack location pending, so we may fail a driver
  844. // due to the PoCallDriver bug (we also caught this
  845. // late cause it's been harmless).
  846. //
  847. // We will address all this stuff next release.
  848. //
  849. WDM_FAIL_ROUTINE((
  850. DCERROR_PENDING_RETURNED_NOT_MARKED_2,
  851. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_STATUS,
  852. IofCallDriverStackData->DispatchRoutine,
  853. &IofCallDriverStackData->IrpSnapshot,
  854. *FinalStatus
  855. ));
  856. }
  857. iovSessionData->SessionFlags |= SESSIONFLAG_MARKED_INCONSISTANT;
  858. }
  859. }
  860. if (IofCallDriverStackData->Flags&CALLFLAG_COMPLETED) {
  861. TRACKIRP_DBGPRINT((
  862. " Verifying status in CD2\n"
  863. ),2);
  864. if ((*FinalStatus != IofCallDriverStackData->ExpectedStatus)&&
  865. (*FinalStatus != STATUS_PENDING)) {
  866. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  867. (!(iovSessionData->SessionFlags&SESSIONFLAG_UNWOUND_INCONSISTANT))) {
  868. //
  869. // The completion routine and the return value don't match. Hey!
  870. //
  871. WDM_FAIL_ROUTINE((
  872. DCERROR_INCONSISTANT_STATUS,
  873. DCPARAM_IRPSNAP + DCPARAM_ROUTINE + DCPARAM_STATUS*2,
  874. IofCallDriverStackData->DispatchRoutine,
  875. &IofCallDriverStackData->IrpSnapshot,
  876. IofCallDriverStackData->ExpectedStatus,
  877. *FinalStatus
  878. ));
  879. }
  880. iovSessionData->SessionFlags |= SESSIONFLAG_UNWOUND_INCONSISTANT;
  881. } else if (*FinalStatus == 0xFFFFFFFF) {
  882. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  883. //
  884. // This status value is illegal. If we see it, we probably have
  885. // an uninitialized variable...
  886. //
  887. WDM_FAIL_ROUTINE((
  888. DCERROR_UNINITIALIZED_STATUS,
  889. DCPARAM_IRPSNAP + DCPARAM_ROUTINE,
  890. IofCallDriverStackData->DispatchRoutine,
  891. &IofCallDriverStackData->IrpSnapshot
  892. ));
  893. }
  894. }
  895. //
  896. // We do not need to remove ourselves from the list because
  897. // we will not be completed twice (InUse is NULL makes sure).
  898. //
  899. } else {
  900. //
  901. // OK, we haven't completed yet. Status better
  902. // be pending...
  903. //
  904. TRACKIRP_DBGPRINT((
  905. " Verifying status is STATUS_PENDING in CR2\n"
  906. ), 2);
  907. if (*FinalStatus != STATUS_PENDING) {
  908. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  909. (!(iovPacket->Flags&TRACKFLAG_UNWOUND_BADLY))) {
  910. //
  911. // We got control before this slot was completed. This is
  912. // legal as long as STATUS_PENDING was returned (it was not),
  913. // so it's bug time. Note that the IRP may not be safe to touch.
  914. //
  915. WDM_FAIL_ROUTINE((
  916. DCERROR_IRP_RETURNED_WITHOUT_COMPLETION,
  917. DCPARAM_IRPSNAP + DCPARAM_ROUTINE,
  918. IofCallDriverStackData->DispatchRoutine,
  919. &IofCallDriverStackData->IrpSnapshot
  920. ));
  921. }
  922. iovPacket->Flags |= TRACKFLAG_UNWOUND_BADLY;
  923. }
  924. iovCurrentStackLocation = (PIOV_STACK_LOCATION)(IofCallDriverStackData->IovStackLocation);
  925. ASSERT(iovCurrentStackLocation->InUse);
  926. //
  927. // Here we mark the stack location as having unwound with
  928. // STATUS_PENDING. We do this to verifier the driver has marked the IRP
  929. // pending before completion.
  930. //
  931. iovCurrentStackLocation->Flags |= STACKFLAG_UNWOUND_PENDING;
  932. ASSERT(!IsListEmpty(&iovCurrentStackLocation->CallStackData));
  933. //
  934. // We now extricate ourselves from the list.
  935. //
  936. RemoveEntryList(&IofCallDriverStackData->SharedLocationList);
  937. }
  938. if ((IofCallDriverStackData->Flags&CALLFLAG_OVERRIDE_STATUS)&&
  939. (!pendingReturned)) {
  940. *FinalStatus = IofCallDriverStackData->NewStatus;
  941. }
  942. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING) &&
  943. (!(IofCallDriverStackData->Flags&CALLFLAG_IS_REMOVE_IRP))) {
  944. //
  945. // We also have the option of causing trouble by making every Irp
  946. // look as if were pending.
  947. //
  948. *FinalStatus = STATUS_PENDING;
  949. }
  950. IovpSessionDataDereference(iovSessionData);
  951. VfPacketDereference(iovPacket, IOVREFTYPE_PACKET);
  952. VfPacketReleaseLock(iovPacket);
  953. }
  954. VOID
  955. FASTCALL
  956. IovpCompleteRequest1(
  957. IN PIRP Irp,
  958. IN CCHAR PriorityBoost,
  959. IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
  960. )
  961. /*++
  962. Description
  963. This routine is called the moment IofCompleteRequest is invoked, and
  964. before any completion routines get called and before the IRP stack
  965. is adjusted in any way.
  966. Arguments:
  967. Irp - A pointer to the IRP passed into
  968. IofCompleteRequest.
  969. PriorityBoost - The priority boost passed into
  970. IofCompleteRequest.
  971. CompletionPacket - A pointer to a local variable on the stack of
  972. IofCompleteRequest. The information stored in
  973. this local variable will be picked up by
  974. IovpCompleteRequest2-5.
  975. Return Value:
  976. None.
  977. --*/
  978. {
  979. PIOV_REQUEST_PACKET iovPacket;
  980. PIOV_SESSION_DATA iovSessionData;
  981. BOOLEAN slotIsInUse;
  982. PIOV_STACK_LOCATION iovCurrentStackLocation;
  983. ULONG locationsAdvanced, stackHash;
  984. PIO_STACK_LOCATION irpSp;
  985. PDEVICE_OBJECT lowerDevobj;
  986. PVOID callerAddress;
  987. KIRQL invocationIrql;
  988. invocationIrql = KeGetCurrentIrql();
  989. iovPacket = VfPacketFindAndLock(Irp);
  990. CompletionPacket->RaisedCount = 0;
  991. if (iovPacket == NULL) {
  992. CompletionPacket->IovSessionData = NULL;
  993. return;
  994. }
  995. if (RtlCaptureStackBackTrace(3, 1, &callerAddress, &stackHash) != 1) {
  996. callerAddress = NULL;
  997. }
  998. VfPacketLogEntry(iovPacket, IOV_EVENT_IO_COMPLETE_REQUEST, callerAddress, 0);
  999. //
  1000. // Set the arrival and departure Irqls.
  1001. //
  1002. iovPacket->ArrivalIrql = invocationIrql;
  1003. iovPacket->DepartureIrql = invocationIrql;
  1004. iovSessionData = VfPacketGetCurrentSessionData(iovPacket);
  1005. CompletionPacket->IovSessionData = iovSessionData;
  1006. CompletionPacket->IovRequestPacket = iovPacket;
  1007. if (iovSessionData == NULL) {
  1008. //
  1009. // We just got a look at the allocation, not the session itself.
  1010. // This can happen if a driver calls IofCompleteRequest on an internally
  1011. // generated IRP before calling IofCallDriver. NPFS does this.
  1012. //
  1013. VfPacketReleaseLock(iovPacket);
  1014. return;
  1015. }
  1016. TRACKIRP_DBGPRINT((
  1017. " CR1: Current, Last = (%x, %x)\n",
  1018. Irp->CurrentLocation, iovPacket->LastLocation
  1019. ), 3);
  1020. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1021. if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) {
  1022. //
  1023. // We are probably going to die now. Anyway, it was a good life...
  1024. //
  1025. WDM_FAIL_ROUTINE((
  1026. DCERROR_QUEUED_IRP_COMPLETED,
  1027. DCPARAM_IRP + DCPARAM_ROUTINE,
  1028. callerAddress,
  1029. Irp
  1030. ));
  1031. }
  1032. //
  1033. // This would be *very* bad - someone is completing an IRP that is
  1034. // currently in progress...
  1035. //
  1036. ASSERT(!(Irp->Flags&IRP_DIAG_HAS_SURROGATE));
  1037. //
  1038. // Hmmm, someone is completing an IRP that IoCallDriver never called. These
  1039. // is possible but rather gross, so we warn.
  1040. //
  1041. if (Irp->CurrentLocation == ((CCHAR) Irp->StackCount + 1)) {
  1042. WDM_FAIL_ROUTINE((
  1043. DCERROR_UNFORWARDED_IRP_COMPLETED,
  1044. DCPARAM_IRP + DCPARAM_ROUTINE,
  1045. callerAddress,
  1046. Irp
  1047. ));
  1048. }
  1049. //
  1050. // Check for leaked Cancel routines.
  1051. //
  1052. if (Irp->CancelRoutine) {
  1053. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_VERIFY_CANCEL_LOGIC)) {
  1054. WDM_FAIL_ROUTINE((
  1055. DCERROR_CANCELROUTINE_AFTER_COMPLETION,
  1056. DCPARAM_IRP + DCPARAM_ROUTINE,
  1057. callerAddress,
  1058. Irp
  1059. ));
  1060. }
  1061. }
  1062. //
  1063. // Record priority for our own later recompletion...
  1064. //
  1065. iovPacket->PriorityBoost = PriorityBoost;
  1066. //
  1067. // We have the option of causing trouble by making every Irp look
  1068. // as if were pending. It is best to do it here, as this also takes
  1069. // care of anybody who has synchronized the IRP and thus does not need
  1070. // to mark it pending in his completion routine.
  1071. //
  1072. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING)) {
  1073. IoMarkIrpPending(Irp);
  1074. }
  1075. //
  1076. // Do this so that if the IRP comes down again, it looks like a new one
  1077. // to the "forward them correctly" code.
  1078. //
  1079. iovSessionData->DeviceLastCalled = NULL;
  1080. locationsAdvanced = iovPacket->LastLocation - Irp->CurrentLocation;
  1081. //
  1082. // Remember this so that we can detect the case where someone is completing
  1083. // to themselves.
  1084. //
  1085. CompletionPacket->LocationsAdvanced = locationsAdvanced;
  1086. //
  1087. // If this failed, somebody skipped then completed.
  1088. //
  1089. ASSERT(locationsAdvanced);
  1090. //
  1091. // If somebody called IoSetNextIrpStackLocation, and then completed,
  1092. // update our internal stack locations (slots) as appropriate.
  1093. //
  1094. slotIsInUse = IovpAdvanceStackDownwards(
  1095. iovSessionData->StackData,
  1096. Irp->CurrentLocation,
  1097. irpSp,
  1098. irpSp + locationsAdvanced,
  1099. locationsAdvanced,
  1100. FALSE,
  1101. FALSE,
  1102. &iovCurrentStackLocation
  1103. );
  1104. VfPacketReleaseLock(iovPacket);
  1105. }
  1106. VOID
  1107. FASTCALL
  1108. IovpCompleteRequest2(
  1109. IN PIRP Irp,
  1110. IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
  1111. )
  1112. /*++
  1113. Description:
  1114. This routine is called for each stack location that might have a completion
  1115. routine.
  1116. Arguments:
  1117. Irp - A pointer to the IRP passed into
  1118. IofCompleteRequest.
  1119. CompletionPacket - A pointer to a local variable on the stack of
  1120. IofCompleteRequest. The information stored in
  1121. this local variable will be picked up by
  1122. IovpCompleteRequest4&5.
  1123. Return Value:
  1124. None.
  1125. --*/
  1126. {
  1127. PIOV_REQUEST_PACKET iovPacket;
  1128. PIOV_SESSION_DATA iovSessionData;
  1129. BOOLEAN raiseToDPC, newlyCompleted, requestFinalized;
  1130. KIRQL oldIrql;
  1131. PIOV_STACK_LOCATION iovCurrentStackLocation, requestsFirstStackLocation;
  1132. NTSTATUS status, entranceStatus;
  1133. PIOFCALLDRIVER_STACKDATA IofCallDriverStackData;
  1134. PIO_STACK_LOCATION irpSp;
  1135. ULONG refAction;
  1136. PLIST_ENTRY listEntry;
  1137. iovSessionData = CompletionPacket->IovSessionData;
  1138. if (iovSessionData == NULL) {
  1139. return;
  1140. }
  1141. iovPacket = CompletionPacket->IovRequestPacket;
  1142. ASSERT(iovPacket);
  1143. VfPacketAcquireLock(iovPacket);
  1144. ASSERT(iovSessionData == VfPacketGetCurrentSessionData(iovPacket));
  1145. ASSERT(!Irp->CancelRoutine);
  1146. status = Irp->IoStatus.Status;
  1147. TRACKIRP_DBGPRINT((
  1148. " CR2: Current, Last = (%x, %x)\n",
  1149. Irp->CurrentLocation, iovPacket->LastLocation
  1150. ), 3);
  1151. iovCurrentStackLocation = iovSessionData->StackData + Irp->CurrentLocation -1;
  1152. TRACKIRP_DBGPRINT((
  1153. " Smacking %lx in CR2\n",
  1154. iovCurrentStackLocation-iovSessionData->StackData
  1155. ), 2);
  1156. if (Irp->CurrentLocation <= iovPacket->TopStackLocation) {
  1157. //
  1158. // Might this be false if the completion routine is to an
  1159. // internal stack loc as set up by IoSetNextIrpStackLocation?
  1160. //
  1161. ASSERT(iovCurrentStackLocation->InUse);
  1162. //
  1163. // Determine if a request was newly completed. Note that
  1164. // several requests may exist within an IRP if it is being
  1165. // "reused". For instance, in response to a IRP_MJ_READ, a
  1166. // driver might convert it into a IRP_MJ_PNP request for the
  1167. // rest of the stack. The two are treated as seperate requests.
  1168. //
  1169. requestsFirstStackLocation = iovCurrentStackLocation->RequestsFirstStackLocation;
  1170. TRACKIRP_DBGPRINT((
  1171. " CR2: original request for %lx is %lx\n",
  1172. iovCurrentStackLocation-iovSessionData->StackData,
  1173. requestsFirstStackLocation-iovSessionData->StackData
  1174. ), 3);
  1175. ASSERT(requestsFirstStackLocation);
  1176. if (requestsFirstStackLocation->Flags&STACKFLAG_REQUEST_COMPLETED) {
  1177. newlyCompleted = FALSE;
  1178. } else {
  1179. requestsFirstStackLocation->Flags|=STACKFLAG_REQUEST_COMPLETED;
  1180. newlyCompleted = TRUE;
  1181. TRACKIRP_DBGPRINT((
  1182. " CR2: Request %lx newly completed by %lx\n",
  1183. requestsFirstStackLocation-iovSessionData->StackData,
  1184. iovCurrentStackLocation-iovSessionData->StackData
  1185. ), 3);
  1186. }
  1187. requestFinalized = (iovCurrentStackLocation == requestsFirstStackLocation);
  1188. if (requestFinalized) {
  1189. TRACKIRP_DBGPRINT((
  1190. " CR2: Request %lx finalized\n",
  1191. iovCurrentStackLocation-iovSessionData->StackData
  1192. ), 3);
  1193. }
  1194. //
  1195. // OK -
  1196. // If we haven't unwound yet, then IofCallDriverStackData will
  1197. // start out non-NULL, in which case we will scribble away the final
  1198. // completion routine status to everybody asking (could be multiple
  1199. // if they IoSkip'd).
  1200. // On the other hand, everybody might have unwound, in which
  1201. // case IofCallDriver(...) will start out NULL, and we will already have
  1202. // asserted if STATUS_PENDING wasn't returned much much earlier...
  1203. // Finally, this slot may not have been "prepared" if an
  1204. // internal stack location called IoSetNextIrpStackLocation, thus
  1205. // consuming a stack location. In this case, IofCallDriverStackData
  1206. // will come from a zero'd slot, and we will do nothing, which is
  1207. // also fine.
  1208. //
  1209. irpSp = IoGetNextIrpStackLocation(Irp);
  1210. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  1211. VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_MONITOR_MAJORS)) {
  1212. VfMajorVerifyIrpStackUpward(
  1213. iovPacket,
  1214. irpSp,
  1215. iovCurrentStackLocation,
  1216. newlyCompleted,
  1217. requestFinalized
  1218. );
  1219. }
  1220. entranceStatus = status;
  1221. if ((VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_MONITOR_PENDING_IO)) &&
  1222. (!(iovSessionData->SessionFlags & SESSIONFLAG_MARKED_INCONSISTANT))) {
  1223. if (iovCurrentStackLocation->Flags & STACKFLAG_UNWOUND_PENDING) {
  1224. if (!Irp->PendingReturned) {
  1225. if (Irp->Flags & IRP_DEFER_IO_COMPLETION) {
  1226. //
  1227. // ADRIAO BUGBUG 2001/06/21 - Some bugs left uncaught
  1228. // The verifier only fails IRPs with the DEFER_IO
  1229. // flag set right now because we've been failing the
  1230. // wrong driver until very very recently. Even worse,
  1231. // that driver has been the verifier filters
  1232. // themselves, and we don't check the kernel by
  1233. // default. Also, PoCallDriver doesn't always mark the
  1234. // IRP stack location pending, so we may fail a driver
  1235. // due to the PoCallDriver bug (we also caught this
  1236. // late cause it's been harmless).
  1237. //
  1238. // We will address all this stuff next release.
  1239. //
  1240. WDM_FAIL_ROUTINE((
  1241. DCERROR_PENDING_RETURNED_NOT_MARKED,
  1242. DCPARAM_IRP + DCPARAM_ROUTINE + DCPARAM_STATUS,
  1243. iovCurrentStackLocation->LastDispatch,
  1244. Irp,
  1245. status
  1246. ));
  1247. }
  1248. iovSessionData->SessionFlags |= SESSIONFLAG_MARKED_INCONSISTANT;
  1249. }
  1250. }
  1251. }
  1252. while(!IsListEmpty(&iovCurrentStackLocation->CallStackData)) {
  1253. //
  1254. // Pop off the list head.
  1255. //
  1256. listEntry = RemoveHeadList(&iovCurrentStackLocation->CallStackData);
  1257. IofCallDriverStackData = CONTAINING_RECORD(
  1258. listEntry,
  1259. IOFCALLDRIVER_STACKDATA,
  1260. SharedLocationList);
  1261. ASSERT(!(IofCallDriverStackData->Flags&CALLFLAG_COMPLETED));
  1262. IofCallDriverStackData->Flags |= CALLFLAG_COMPLETED;
  1263. IofCallDriverStackData->ExpectedStatus = status;
  1264. if (Irp->PendingReturned) {
  1265. IofCallDriverStackData->Flags |= CALLFLAG_MARKED_PENDING;
  1266. }
  1267. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_ROTATE_STATUS) &&
  1268. (!(iovPacket->Flags&TRACKFLAG_BOGUS)) &&
  1269. VfMajorAdvanceIrpStatus(irpSp, entranceStatus, &status)) {
  1270. //
  1271. // Purposely munge the returned status for everyone at this
  1272. // layer to flush more bugs. We are specifically trolling for
  1273. // this buggy sequence:
  1274. // Irp->IoStatus.Status = STATUS_SUCCESS;
  1275. // IoSkipCurrentIrpStackLocation(Irp);
  1276. // IoCallDriver(DeviceBelow, Irp);
  1277. // return STATUS_SUCCESS;
  1278. //
  1279. IofCallDriverStackData->Flags |= CALLFLAG_OVERRIDE_STATUS;
  1280. IofCallDriverStackData->NewStatus = status;
  1281. }
  1282. }
  1283. Irp->IoStatus.Status = status;
  1284. //
  1285. // Set InUse = FALSE and CallStackData = NULL
  1286. //
  1287. RtlZeroMemory(iovCurrentStackLocation, sizeof(IOV_STACK_LOCATION));
  1288. InitializeListHead(&iovCurrentStackLocation->CallStackData);
  1289. } else {
  1290. ASSERT(0);
  1291. }
  1292. //
  1293. // Once we return, we may be completed again before IofCompleteRequest3
  1294. // get's called, so we make sure we are at DPC level throughout.
  1295. //
  1296. raiseToDPC = FALSE;
  1297. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_COMPLETE_AT_DISPATCH)) {
  1298. if (!CompletionPacket->RaisedCount) {
  1299. //
  1300. // Copy away the callers IRQL
  1301. //
  1302. CompletionPacket->PreviousIrql = iovPacket->DepartureIrql;
  1303. raiseToDPC = TRUE;
  1304. }
  1305. CompletionPacket->RaisedCount++;
  1306. }
  1307. iovPacket->LastLocation = Irp->CurrentLocation+1;
  1308. if (iovPacket->TopStackLocation == Irp->CurrentLocation) {
  1309. CompletionPacket->IovSessionData = NULL;
  1310. CompletionPacket->IovRequestPacket = NULL;
  1311. if (iovPacket->Flags&TRACKFLAG_SURROGATE) {
  1312. //
  1313. // Scribble away the real completion routine and corrosponding control
  1314. //
  1315. irpSp = IoGetNextIrpStackLocation(Irp);
  1316. iovPacket->RealIrpCompletionRoutine = irpSp->CompletionRoutine;
  1317. iovPacket->RealIrpControl = irpSp->Control;
  1318. iovPacket->RealIrpContext = irpSp->Context;
  1319. //
  1320. // We want to peek at the Irp prior to completion. This is why we
  1321. // have expanded the initial number of stack locations with the
  1322. // driver verifier enabled.
  1323. //
  1324. IoSetCompletionRoutine(
  1325. Irp,
  1326. IovpSwapSurrogateIrp,
  1327. Irp,
  1328. TRUE,
  1329. TRUE,
  1330. TRUE
  1331. );
  1332. } else {
  1333. //
  1334. // Close this session as the IRP has entirely completed. We drop
  1335. // the pointer count we added to the tracking data here for the
  1336. // same reason.
  1337. //
  1338. irpSp = IoGetNextIrpStackLocation(Irp);
  1339. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  1340. VfMajorVerifyFinalIrpStack(iovPacket, irpSp);
  1341. }
  1342. ASSERT(iovPacket->TopStackLocation == Irp->CurrentLocation);
  1343. IovpSessionDataClose(iovSessionData);
  1344. IovpSessionDataDereference(iovSessionData);
  1345. VfPacketDereference(iovPacket, IOVREFTYPE_POINTER);
  1346. }
  1347. } else {
  1348. //
  1349. // We will be seeing this IRP again. Hold a session count and a ref
  1350. // count against it.
  1351. //
  1352. IovpSessionDataReference(iovSessionData);
  1353. VfPacketReference(iovPacket, IOVREFTYPE_PACKET);
  1354. }
  1355. //
  1356. // Assert LastLocation is consistent with an IRP that may be completed.
  1357. //
  1358. if (iovPacket->LastLocation < iovPacket->TopStackLocation) {
  1359. ASSERT(iovSessionData->StackData[iovPacket->LastLocation-1].InUse);
  1360. }
  1361. VfPacketReleaseLock(iovPacket);
  1362. if (raiseToDPC) {
  1363. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  1364. }
  1365. CompletionPacket->LocationsAdvanced--;
  1366. }
  1367. VOID
  1368. FASTCALL
  1369. IovpCompleteRequest3(
  1370. IN PIRP Irp,
  1371. IN PVOID Routine,
  1372. IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
  1373. )
  1374. /*++
  1375. Description:
  1376. This routine is called just before each completion routine is invoked.
  1377. Arguments:
  1378. Irp - A pointer to the IRP passed into
  1379. IofCompleteRequest.
  1380. Routine - The completion routine about to be called.
  1381. CompletionPacket - A pointer to data on the callers stack. This will
  1382. be picked up IovpCompleteRequest4 and
  1383. IovpCompleteRequest5.
  1384. Return Value:
  1385. None.
  1386. --*/
  1387. {
  1388. PIOV_REQUEST_PACKET iovPacket;
  1389. PIOV_SESSION_DATA iovSessionData;
  1390. PIO_STACK_LOCATION irpSpCur, irpSpNext;
  1391. PDEFERRAL_CONTEXT deferralContext;
  1392. iovSessionData = CompletionPacket->IovSessionData;
  1393. if (iovSessionData == NULL) {
  1394. return;
  1395. }
  1396. iovPacket = CompletionPacket->IovRequestPacket;
  1397. ASSERT(iovPacket);
  1398. VfPacketAcquireLock(iovPacket);
  1399. VfPacketLogEntry(iovPacket, IOV_EVENT_IO_COMPLETION_ROUTINE, Routine, 0);
  1400. //
  1401. // Verify all completion routines are in nonpaged code, exempting one
  1402. // special case - when a driver completes the IRP to itself by calling
  1403. // IoSetNextStackLocation before calling IoCompleteRequest.
  1404. //
  1405. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  1406. if ((CompletionPacket->LocationsAdvanced <= 0) &&
  1407. (MmIsSystemAddressLocked(Routine) == FALSE)) {
  1408. //DbgPrint(
  1409. // "Verifier Notes: LocationsAdvanced %d\n",
  1410. // CompletionPacket->LocationsAdvanced
  1411. // );
  1412. WDM_FAIL_ROUTINE((
  1413. DCERROR_COMPLETION_ROUTINE_PAGABLE,
  1414. DCPARAM_IRP + DCPARAM_ROUTINE,
  1415. Routine,
  1416. Irp
  1417. ));
  1418. }
  1419. }
  1420. //
  1421. // Setup fields for those assertion functions that will be called *after*
  1422. // the completion routine has been called.
  1423. //
  1424. irpSpCur = IoGetCurrentIrpStackLocation(Irp);
  1425. CompletionPacket->IsRemoveIrp =
  1426. ((Irp->CurrentLocation <= (CCHAR) Irp->StackCount) &&
  1427. (irpSpCur->MajorFunction == IRP_MJ_PNP) &&
  1428. (irpSpCur->MinorFunction == IRP_MN_REMOVE_DEVICE));
  1429. CompletionPacket->CompletionRoutine = Routine;
  1430. //
  1431. // Is this a completion routine that should be called later? Note that this
  1432. // is only legal if we are pending the IRPs (because to the upper driver,
  1433. // IofCallDriver is returning before it's completion routine has been called)
  1434. //
  1435. if ((!CompletionPacket->IsRemoveIrp)&&
  1436. (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_DEFER_COMPLETION)||
  1437. VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_COMPLETE_AT_PASSIVE))) {
  1438. ASSERT(VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING));
  1439. irpSpNext = IoGetNextIrpStackLocation(Irp);
  1440. deferralContext = ExAllocatePoolWithTag(
  1441. NonPagedPool,
  1442. sizeof(DEFERRAL_CONTEXT),
  1443. POOL_TAG_DEFERRED_CONTEXT
  1444. );
  1445. if (deferralContext) {
  1446. //
  1447. // Swap the original completion and context for our own.
  1448. //
  1449. deferralContext->IovRequestPacket = iovPacket;
  1450. deferralContext->IrpSpNext = irpSpNext;
  1451. deferralContext->OriginalCompletionRoutine = irpSpNext->CompletionRoutine;
  1452. deferralContext->OriginalContext = irpSpNext->Context;
  1453. deferralContext->OriginalIrp = Irp;
  1454. deferralContext->OriginalPriorityBoost = iovPacket->PriorityBoost;
  1455. irpSpNext->CompletionRoutine = IovpInternalDeferredCompletion;
  1456. irpSpNext->Context = deferralContext;
  1457. VfPacketReference(iovPacket, IOVREFTYPE_POINTER);
  1458. }
  1459. }
  1460. VfPacketReleaseLock(iovPacket);
  1461. }
  1462. VOID
  1463. FASTCALL
  1464. IovpCompleteRequest4(
  1465. IN PIRP Irp,
  1466. IN NTSTATUS ReturnedStatus,
  1467. IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
  1468. )
  1469. /*++
  1470. Description:
  1471. This assert routine is called just after each completion routine is
  1472. invoked (but not if STATUS_MORE_PROCESSING is returned)
  1473. Arguments:
  1474. Irp - A pointer to the IRP passed into
  1475. IofCompleteRequest.
  1476. Routine - The completion routine called.
  1477. ReturnedStatus - The status value returned.
  1478. CompletionPacket - A pointer to data on the callers stack. This was
  1479. filled in by IovpCompleteRequest3.
  1480. Return Value:
  1481. None.
  1482. --*/
  1483. {
  1484. PIOV_REQUEST_PACKET iovPacket;
  1485. PIOV_SESSION_DATA iovSessionData;
  1486. PIO_STACK_LOCATION irpSp;
  1487. PVOID routine;
  1488. routine = CompletionPacket->CompletionRoutine;
  1489. iovSessionData = CompletionPacket->IovSessionData;
  1490. if (iovSessionData == NULL) {
  1491. return;
  1492. }
  1493. iovPacket = CompletionPacket->IovRequestPacket;
  1494. ASSERT(iovPacket);
  1495. VfPacketAcquireLock(iovPacket);
  1496. VfPacketLogEntry(
  1497. iovPacket,
  1498. IOV_EVENT_IO_COMPLETION_ROUTINE_UNWIND,
  1499. routine,
  1500. ReturnedStatus
  1501. );
  1502. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING)) {
  1503. if ((ReturnedStatus != STATUS_MORE_PROCESSING_REQUIRED)&&
  1504. (iovPacket->pIovSessionData == iovSessionData)) {
  1505. //
  1506. // At this point, we know the completion routine is required to have
  1507. // set the IRP pending bit, because we've hardwired everyone below
  1508. // him to return pending, and we've marked the pending returned bit.
  1509. // Verify he did his part
  1510. //
  1511. irpSp = IoGetCurrentIrpStackLocation(Irp);
  1512. if (!(irpSp->Control & SL_PENDING_RETURNED )) {
  1513. WDM_FAIL_ROUTINE((
  1514. DCERROR_PENDING_BIT_NOT_MIGRATED,
  1515. DCPARAM_IRP + DCPARAM_ROUTINE,
  1516. routine,
  1517. Irp
  1518. ));
  1519. //
  1520. // This will keep the IRP above from erroneously asserting (and
  1521. // correctly hanging).
  1522. //
  1523. IoMarkIrpPending(Irp);
  1524. }
  1525. }
  1526. }
  1527. VfPacketReleaseLock(iovPacket);
  1528. }
  1529. VOID
  1530. FASTCALL
  1531. IovpCompleteRequest5(
  1532. IN PIRP Irp,
  1533. IN OUT PIOFCOMPLETEREQUEST_STACKDATA CompletionPacket
  1534. )
  1535. /*++
  1536. Description:
  1537. This routine is called for each stack location that could have had a
  1538. completion routine, after any possible completion routine has been
  1539. called.
  1540. Arguments:
  1541. Irp - A pointer to the IRP passed into
  1542. IofCompleteRequest.
  1543. CompletionPacket - A pointer to a local variable on the stack of
  1544. IofCompleteRequest. This information was stored
  1545. by IovpCompleteRequest2 and 3.
  1546. Return Value:
  1547. None.
  1548. --*/
  1549. {
  1550. PIOV_REQUEST_PACKET iovPacket;
  1551. PIOV_SESSION_DATA iovSessionData;
  1552. PIOV_STACK_LOCATION iovCurrentStackLocation;
  1553. NTSTATUS status;
  1554. iovSessionData = CompletionPacket->IovSessionData;
  1555. if (iovSessionData) {
  1556. iovPacket = CompletionPacket->IovRequestPacket;
  1557. ASSERT(iovPacket);
  1558. VfPacketAcquireLock(iovPacket);
  1559. ASSERT((!CompletionPacket->RaisedCount) ||
  1560. (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_COMPLETE_AT_DISPATCH)));
  1561. IovpSessionDataDereference(iovSessionData);
  1562. VfPacketDereference(iovPacket, IOVREFTYPE_PACKET);
  1563. VfPacketReleaseLock(iovPacket);
  1564. }
  1565. //
  1566. // When this count is at zero, we have unnested out of every
  1567. // completion routine, so it is OK to return back to our original IRQL
  1568. //
  1569. if (CompletionPacket->RaisedCount) {
  1570. if (!(--CompletionPacket->RaisedCount)) {
  1571. //
  1572. // Undo IRQL madness (wouldn't want to return to
  1573. // the caller at DPC, would we now?)
  1574. //
  1575. KeLowerIrql(CompletionPacket->PreviousIrql);
  1576. }
  1577. }
  1578. }
  1579. VOID
  1580. FASTCALL
  1581. IovpCompleteRequestApc(
  1582. IN PIRP Irp,
  1583. IN PVOID BestStackOffset
  1584. )
  1585. /*++
  1586. Description:
  1587. This routine is after the APC for completing IRPs and fired.
  1588. Arguments:
  1589. Irp - A pointer to the IRP passed into retrieved from
  1590. the APC in IopCompleteRequest.
  1591. BestStackOffset - A pointer to a last parameter passed on the stack.
  1592. We use this to detect the case where a driver has
  1593. ignored STATUS_PENDING and left the UserIosb on
  1594. it's stack.
  1595. Return Value:
  1596. None.
  1597. --*/
  1598. {
  1599. #if DBG
  1600. #if defined(_X86_)
  1601. PUCHAR addr;
  1602. PIOV_REQUEST_PACKET iovPacket;
  1603. addr = (PUCHAR)Irp->UserIosb;
  1604. if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
  1605. (addr <= (PUCHAR)BestStackOffset)) {
  1606. iovPacket = VfPacketFindAndLock(Irp);
  1607. RtlAssert("UserIosb below stack pointer", __FILE__, (ULONG) iovPacket,
  1608. "Call AdriaO");
  1609. VfPacketReleaseLock(iovPacket);
  1610. }
  1611. addr = (PUCHAR)Irp->UserEvent;
  1612. if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
  1613. (addr <= (PUCHAR)BestStackOffset)) {
  1614. iovPacket = VfPacketFindAndLock(Irp);
  1615. RtlAssert("UserEvent below stack pointer", __FILE__, (ULONG) iovPacket,
  1616. "Call AdriaO");
  1617. VfPacketReleaseLock(iovPacket);
  1618. }
  1619. #endif
  1620. #endif
  1621. }
  1622. BOOLEAN
  1623. IovpAdvanceStackDownwards(
  1624. IN PIOV_STACK_LOCATION StackDataArray,
  1625. IN CCHAR CurrentLocation,
  1626. IN PIO_STACK_LOCATION IrpSp,
  1627. IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
  1628. IN ULONG LocationsAdvanced,
  1629. IN BOOLEAN IsNewRequest,
  1630. IN BOOLEAN MarkAsTaken,
  1631. OUT PIOV_STACK_LOCATION *StackLocationInfo
  1632. )
  1633. {
  1634. PIOV_STACK_LOCATION iovCurrentStackLocation, advancedLocationData, requestOriginalSLD;
  1635. PIO_STACK_LOCATION irpSpTemp;
  1636. PLARGE_INTEGER dispatchTime, stackTime;
  1637. BOOLEAN isNewSession, wasInUse;
  1638. PVOID dispatchRoutine;
  1639. isNewSession = (IrpLastSp == NULL);
  1640. ASSERT((!isNewSession) || (LocationsAdvanced == 1));
  1641. ASSERT(isNewSession || ((ULONG) (IrpLastSp - IrpSp) == LocationsAdvanced));
  1642. //
  1643. // This function is called by IoCallDriver prior to decrementing
  1644. // CurrentLocation field. As the OS bugchecks if it hits zero, the field
  1645. // should as least be two here. We only subtract one as to reserve an extra
  1646. // empty slot at the head of the array.
  1647. //
  1648. iovCurrentStackLocation = StackDataArray + CurrentLocation -1;
  1649. TRACKIRP_DBGPRINT((
  1650. " Smacking %lx (%lx) to valid in SD\n",
  1651. CurrentLocation -1, iovCurrentStackLocation
  1652. ), 2);
  1653. //
  1654. // Is this slot already active? IE, did someone skip and then forward the
  1655. // IRP?
  1656. //
  1657. if (iovCurrentStackLocation->InUse) {
  1658. //
  1659. // IoSkipCurrentIrpStackLocation was used by the forwarder. Don't
  1660. // reinitialize the data.
  1661. //
  1662. ASSERT(!LocationsAdvanced); // && (!isNewSession)
  1663. ASSERT(IrpSp == iovCurrentStackLocation->IrpSp);
  1664. } else if (MarkAsTaken) {
  1665. //
  1666. // ADRIAO N.B. 01/02/1999 -
  1667. // Is the below assertion is not true in the case of an internally
  1668. // forwarded, completed, and then externally forwarded IRP?
  1669. //
  1670. ASSERT(LocationsAdvanced); // || isNewSession
  1671. //
  1672. // Initialize the stack slot appropriately.
  1673. //
  1674. RtlZeroMemory(iovCurrentStackLocation, sizeof(IOV_STACK_LOCATION));
  1675. InitializeListHead(&iovCurrentStackLocation->CallStackData);
  1676. iovCurrentStackLocation->IrpSp = IrpSp;
  1677. }
  1678. //
  1679. // Determine the last original request. A "Request" is block of data in a
  1680. // stack location that is progressively copied downwards as the IRP is
  1681. // forwarded (ie, a forwarded START IRP, a forwarded IOCTL, etc). A clever
  1682. // driver writer could use his own stack location to send down a quick
  1683. // query before forwarding along the original request. We correctly
  1684. // differentiate between those two unique requests within the IRP using
  1685. // code below.
  1686. //
  1687. if (isNewSession) {
  1688. //
  1689. // *We* are the original request. None of these fields below should
  1690. // be used.
  1691. //
  1692. dispatchRoutine = NULL;
  1693. requestOriginalSLD = NULL;
  1694. stackTime = NULL;
  1695. dispatchTime = NULL;
  1696. } else if (LocationsAdvanced) {
  1697. //
  1698. // To get the original request (the pointer to the Irp slot that
  1699. // represents where we *first* saw this request), we go backwards to get
  1700. // the most recent previous irp slot data (set up when the device above
  1701. // forwarded this Irp to us), and we read what it's original request was.
  1702. // We also get the dispatch routine for that slot, which we will use to
  1703. // backfill skipped slots if we advanced more than one Irp stack
  1704. // location this time (ie, someone called IoSetNextIrpStackLocation).
  1705. //
  1706. dispatchTime = &iovCurrentStackLocation[LocationsAdvanced].PerfDispatchStart;
  1707. stackTime = &iovCurrentStackLocation[LocationsAdvanced].PerfStackLocationStart;
  1708. dispatchRoutine = iovCurrentStackLocation[LocationsAdvanced].LastDispatch;
  1709. requestOriginalSLD = iovCurrentStackLocation[LocationsAdvanced].RequestsFirstStackLocation;
  1710. ASSERT(dispatchRoutine);
  1711. ASSERT(iovCurrentStackLocation[LocationsAdvanced].InUse);
  1712. ASSERT(requestOriginalSLD->RequestsFirstStackLocation == requestOriginalSLD);
  1713. iovCurrentStackLocation->RequestsFirstStackLocation = requestOriginalSLD;
  1714. } else {
  1715. //
  1716. // We skipped. The slot should already be filled.
  1717. //
  1718. dispatchRoutine = NULL;
  1719. dispatchTime = NULL;
  1720. stackTime = NULL;
  1721. requestOriginalSLD = iovCurrentStackLocation->RequestsFirstStackLocation;
  1722. ASSERT(requestOriginalSLD);
  1723. ASSERT(requestOriginalSLD->RequestsFirstStackLocation == requestOriginalSLD);
  1724. }
  1725. //
  1726. // The previous request seen is in requestOriginalSLD (NULL if none). If
  1727. // we advanced more than one stack location (ie, someone called
  1728. // IoSetNextIrpStackLocation), we need to update the slots we never saw get
  1729. // consumed. Note that the dispatch routine we set in the slot is for the
  1730. // driver that owned the last slot - we do not use the device object at
  1731. // that IrpSp because it might be stale (or perhaps even NULL).
  1732. //
  1733. advancedLocationData = iovCurrentStackLocation;
  1734. irpSpTemp = IrpSp;
  1735. while(LocationsAdvanced>1) {
  1736. advancedLocationData++;
  1737. LocationsAdvanced--;
  1738. irpSpTemp++;
  1739. TRACKIRP_DBGPRINT((
  1740. " Late smacking %lx to valid in CD1\n",
  1741. advancedLocationData - StackDataArray
  1742. ), 3);
  1743. ASSERT(!advancedLocationData->InUse);
  1744. RtlZeroMemory(advancedLocationData, sizeof(IOV_STACK_LOCATION));
  1745. InitializeListHead(&advancedLocationData->CallStackData);
  1746. advancedLocationData->InUse = TRUE;
  1747. advancedLocationData->IrpSp = irpSpTemp;
  1748. advancedLocationData->RequestsFirstStackLocation = requestOriginalSLD;
  1749. advancedLocationData->PerfDispatchStart = *dispatchTime;
  1750. advancedLocationData->PerfStackLocationStart = *stackTime;
  1751. advancedLocationData->LastDispatch = dispatchRoutine;
  1752. }
  1753. //
  1754. // For the assertion below...
  1755. //
  1756. if (LocationsAdvanced) {
  1757. irpSpTemp++;
  1758. }
  1759. ASSERT((irpSpTemp == IrpLastSp)||(IrpLastSp == NULL));
  1760. //
  1761. // Write out the slot we're using.
  1762. //
  1763. *StackLocationInfo = iovCurrentStackLocation;
  1764. if (!MarkAsTaken) {
  1765. return iovCurrentStackLocation->InUse;
  1766. }
  1767. //
  1768. // Record a pointer in this slot to the requests originating slot as
  1769. // appropriate.
  1770. //
  1771. if (IsNewRequest) {
  1772. TRACKIRP_DBGPRINT((
  1773. " CD1: %lx is a new request\n",
  1774. advancedLocationData-StackDataArray
  1775. ), 3);
  1776. ASSERT(LocationsAdvanced == 1);
  1777. iovCurrentStackLocation->RequestsFirstStackLocation = iovCurrentStackLocation;
  1778. } else if (LocationsAdvanced) {
  1779. ASSERT(!isNewSession);
  1780. TRACKIRP_DBGPRINT((
  1781. " CD1: %lx is a request for %lx\n",
  1782. advancedLocationData-StackDataArray,
  1783. requestOriginalSLD-StackDataArray
  1784. ), 3);
  1785. } else {
  1786. //
  1787. // As we skipped, the request should not have changed. If it did,
  1788. // either guy we called trashed the stack given to him (giving none
  1789. // to the dude under him), or we incorrectly saw a new request when
  1790. // we shouldn't have (see previous comment).
  1791. //
  1792. ASSERT(!isNewSession);
  1793. ASSERT(advancedLocationData->RequestsFirstStackLocation == requestOriginalSLD);
  1794. }
  1795. wasInUse = iovCurrentStackLocation->InUse;
  1796. iovCurrentStackLocation->InUse = TRUE;
  1797. return wasInUse;
  1798. }
  1799. VOID
  1800. IovpExamineIrpStackForwarding(
  1801. IN OUT PIOV_REQUEST_PACKET IovPacket,
  1802. IN BOOLEAN IsNewSession,
  1803. IN ULONG ForwardMethod,
  1804. IN PDEVICE_OBJECT DeviceObject,
  1805. IN PIRP Irp,
  1806. IN PVOID CallerAddress,
  1807. IN OUT PIO_STACK_LOCATION *IoCurrentStackLocation,
  1808. OUT PIO_STACK_LOCATION *IoLastStackLocation,
  1809. OUT ULONG *StackLocationsAdvanced
  1810. )
  1811. {
  1812. PIRP irp;
  1813. PIO_STACK_LOCATION irpSp, irpLastSp;
  1814. BOOLEAN isSameStack, multiplyStacked;
  1815. ULONG locationsAdvanced;
  1816. PDEVICE_OBJECT upperDevice;
  1817. irpSp = *IoCurrentStackLocation;
  1818. if (!IsNewSession) {
  1819. //
  1820. // We are sitting on current next being one back (-1) from
  1821. // CurrentStackLocation.
  1822. //
  1823. locationsAdvanced = IovPacket->LastLocation-Irp->CurrentLocation;
  1824. irpLastSp = Irp->Tail.Overlay.CurrentStackLocation+((ULONG_PTR)locationsAdvanced-1);
  1825. } else {
  1826. //
  1827. // New IRP, so no last SP and we always advance "1"
  1828. //
  1829. locationsAdvanced = 1;
  1830. irpLastSp = NULL;
  1831. }
  1832. if ((!IsNewSession) &&
  1833. VfSettingsIsOptionEnabled(IovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  1834. //
  1835. // As the control field is zeroed by IoCopyCurrentStackLocation, we
  1836. // dope each stack location with the value SL_NOTCOPIED. If it is
  1837. // zeroed or the IRP stack location has stayed the same, the one of
  1838. // the two API's was called. Otherwise the next stack location wasn't
  1839. // set up properly (I have yet to find a case otherwise)...
  1840. //
  1841. if ((irpSp->Control&SL_NOTCOPIED)&&
  1842. IovPacket->LastLocation != Irp->CurrentLocation) {
  1843. #if 0
  1844. WDM_FAIL_ROUTINE((
  1845. DCERROR_NEXTIRPSP_DIRTY,
  1846. DCPARAM_IRP + DCPARAM_ROUTINE,
  1847. CallerAddress,
  1848. Irp
  1849. ));
  1850. #endif
  1851. }
  1852. //
  1853. // Now check for people who copy the stack locations and forget to
  1854. // wipe out previous completion routines.
  1855. //
  1856. if (locationsAdvanced) {
  1857. //
  1858. // IoCopyCurrentStackLocation copies everything but Completion,
  1859. // Context, and Control
  1860. //
  1861. isSameStack = RtlEqualMemory(irpSp, irpLastSp,
  1862. FIELD_OFFSET(IO_STACK_LOCATION, Control));
  1863. isSameStack &= RtlEqualMemory(&irpSp->Parameters, &irpLastSp->Parameters,
  1864. FIELD_OFFSET(IO_STACK_LOCATION, DeviceObject)-
  1865. FIELD_OFFSET(IO_STACK_LOCATION, Parameters));
  1866. isSameStack &= (irpSp->FileObject == irpLastSp->FileObject);
  1867. //
  1868. // We should *never* see this on the stack! If we do, something
  1869. // quite bizarre has happened...
  1870. //
  1871. ASSERT(irpSp->CompletionRoutine != IovpSwapSurrogateIrp);
  1872. if (isSameStack) {
  1873. //
  1874. // We caught them doing something either very bad or quite
  1875. // inefficient. We can tell which based on whether there is
  1876. // a completion routine.
  1877. //
  1878. if ((irpSp->CompletionRoutine == irpLastSp->CompletionRoutine)&&
  1879. (irpSp->Context == irpLastSp->Context) &&
  1880. (irpSp->Control == irpLastSp->Control) &&
  1881. (irpSp->CompletionRoutine != NULL)) {
  1882. //
  1883. // The driver might have copied the entire stack location
  1884. // on purpose if more than one device object for the same
  1885. // driver exists in the stack.
  1886. //
  1887. IovUtilGetUpperDeviceObject(
  1888. irpLastSp->DeviceObject,
  1889. &upperDevice
  1890. );
  1891. multiplyStacked = (upperDevice &&
  1892. (upperDevice->DriverObject == irpLastSp->DeviceObject->DriverObject));
  1893. if (upperDevice) {
  1894. ObDereferenceObject(upperDevice);
  1895. }
  1896. if (!multiplyStacked) {
  1897. //
  1898. // Duplication of both the completion and the context
  1899. // while not properly zeroing the control field is enough
  1900. // to make me believe the caller has made a vexing mistake.
  1901. //
  1902. WDM_FAIL_ROUTINE((
  1903. DCERROR_IRPSP_COPIED,
  1904. DCPARAM_IRP + DCPARAM_ROUTINE,
  1905. CallerAddress,
  1906. Irp
  1907. ));
  1908. //
  1909. // Repair the stack
  1910. //
  1911. irpSp->CompletionRoutine = NULL;
  1912. irpSp->Control = 0;
  1913. }
  1914. } else if (!irpSp->CompletionRoutine) {
  1915. if (!(irpSp->Control&SL_NOTCOPIED) &&
  1916. VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_FLAG_UNNECCESSARY_COPIES)
  1917. ) {
  1918. WDM_FAIL_ROUTINE((
  1919. DCERROR_UNNECCESSARY_COPY,
  1920. DCPARAM_IRP + DCPARAM_ROUTINE,
  1921. CallerAddress,
  1922. Irp
  1923. ));
  1924. }
  1925. IoSetCompletionRoutine(
  1926. Irp,
  1927. IovpInternalCompletionTrap,
  1928. IoGetCurrentIrpStackLocation( Irp ),
  1929. TRUE,
  1930. TRUE,
  1931. TRUE
  1932. );
  1933. }
  1934. }
  1935. } else if (VfSettingsIsOptionEnabled(IovPacket->VerifierSettings, VERIFIER_OPTION_CONSUME_ALWAYS)) {
  1936. if (ForwardMethod == FORWARDED_TO_NEXT_DO) {
  1937. if (Irp->CurrentLocation<=2) {
  1938. WDM_FAIL_ROUTINE((
  1939. DCERROR_INSUFFICIENT_STACK_LOCATIONS,
  1940. DCPARAM_IRP + DCPARAM_ROUTINE,
  1941. CallerAddress,
  1942. Irp
  1943. ));
  1944. } else {
  1945. //
  1946. // Back up the skip, then copy. Add a completion routine with
  1947. // unique and assertable context to catch people who clumsily
  1948. // Rtl-copy stack locations (we can't catch them if the caller
  1949. // above used an empty stack with no completion routine)...
  1950. //
  1951. IoSetNextIrpStackLocation( Irp );
  1952. //
  1953. // Set the trap...
  1954. //
  1955. IoCopyCurrentIrpStackLocationToNext( Irp );
  1956. IoSetCompletionRoutine(
  1957. Irp,
  1958. IovpInternalCompletionTrap,
  1959. IoGetCurrentIrpStackLocation( Irp ),
  1960. TRUE,
  1961. TRUE,
  1962. TRUE
  1963. );
  1964. //
  1965. // This is our new reality...
  1966. //
  1967. locationsAdvanced = 1;
  1968. irpSp = IoGetNextIrpStackLocation( Irp );
  1969. }
  1970. }
  1971. }
  1972. }
  1973. *IoCurrentStackLocation = irpSp;
  1974. *IoLastStackLocation = irpLastSp;
  1975. *StackLocationsAdvanced = locationsAdvanced;
  1976. }
  1977. NTSTATUS
  1978. IovpInternalCompletionTrap(
  1979. IN PDEVICE_OBJECT DeviceObject,
  1980. IN PIRP Irp,
  1981. IN PVOID Context
  1982. )
  1983. /*++
  1984. Description:
  1985. This routine does nothing but act as a trap for people
  1986. incorrectly copying stack locations...
  1987. Arguments:
  1988. DeviceObject - Device object set at this level of the completion
  1989. routine - ignored.
  1990. Irp - A pointer to the IRP.
  1991. Context - Context should equal the Irp's stack location -
  1992. this is asserted.
  1993. Return Value:
  1994. STATUS_SUCCESS
  1995. --*/
  1996. {
  1997. PIO_STACK_LOCATION irpSp;
  1998. if (Irp->PendingReturned) {
  1999. IoMarkIrpPending( Irp );
  2000. }
  2001. irpSp = IoGetCurrentIrpStackLocation( Irp );
  2002. ASSERT((PVOID) irpSp == Context);
  2003. return STATUS_SUCCESS;
  2004. }
  2005. VOID
  2006. IovpInternalCompleteAtDPC(
  2007. IN PKDPC Dpc,
  2008. IN PVOID DeferredContext,
  2009. IN PVOID SystemArgument1,
  2010. IN PVOID SystemArgument2
  2011. )
  2012. {
  2013. IovpInternalCompleteAfterWait(DeferredContext);
  2014. }
  2015. VOID
  2016. IovpInternalCompleteAfterWait(
  2017. IN PVOID Context
  2018. )
  2019. {
  2020. PDEFERRAL_CONTEXT deferralContext = (PDEFERRAL_CONTEXT) Context;
  2021. PIO_STACK_LOCATION irpSpNext;
  2022. NTSTATUS status;
  2023. if (deferralContext->DeferAction == DEFERACTION_QUEUE_PASSIVE_TIMER) {
  2024. //
  2025. // Wait the appropriate amount of time if so ordered...
  2026. //
  2027. ASSERT(KeGetCurrentIrql()==PASSIVE_LEVEL);
  2028. KeWaitForSingleObject(
  2029. &deferralContext->DeferralTimer,
  2030. Executive,
  2031. KernelMode,
  2032. FALSE,
  2033. NULL
  2034. );
  2035. }
  2036. VfPacketAcquireLock(deferralContext->IovRequestPacket);
  2037. VfIrpMakeTouchable(deferralContext->OriginalIrp);
  2038. irpSpNext = IoGetNextIrpStackLocation( deferralContext->OriginalIrp );
  2039. ASSERT(irpSpNext == deferralContext->IrpSpNext);
  2040. ASSERT(irpSpNext->CompletionRoutine == deferralContext->OriginalCompletionRoutine);
  2041. ASSERT(irpSpNext->Context == deferralContext->OriginalContext);
  2042. ASSERT(deferralContext->IovRequestPacket->Flags & TRACKFLAG_QUEUED_INTERNALLY);
  2043. deferralContext->IovRequestPacket->Flags &= ~TRACKFLAG_QUEUED_INTERNALLY;
  2044. VfPacketDereference(deferralContext->IovRequestPacket, IOVREFTYPE_POINTER);
  2045. VfPacketReleaseLock(deferralContext->IovRequestPacket);
  2046. status = irpSpNext->CompletionRoutine(
  2047. deferralContext->DeviceObject,
  2048. deferralContext->OriginalIrp,
  2049. irpSpNext->Context
  2050. );
  2051. if (status!=STATUS_MORE_PROCESSING_REQUIRED) {
  2052. IoCompleteRequest(deferralContext->OriginalIrp, deferralContext->OriginalPriorityBoost);
  2053. }
  2054. ExFreePool(deferralContext);
  2055. }
  2056. NTSTATUS
  2057. IovpInternalDeferredCompletion(
  2058. IN PDEVICE_OBJECT DeviceObject,
  2059. IN PIRP Irp,
  2060. IN PVOID Context
  2061. )
  2062. /*++
  2063. Description:
  2064. This function is slipped in as a completion routine when we are
  2065. "deferring" completion via work item, etc.
  2066. Arguments:
  2067. DeviceObject - Device object set at this level of the completion
  2068. routine - passed on.
  2069. Irp - A pointer to the IRP.
  2070. Context - Context block that includes original completion
  2071. routine.
  2072. Return Value:
  2073. NTSTATUS
  2074. --*/
  2075. {
  2076. PDEFERRAL_CONTEXT deferralContext = (PDEFERRAL_CONTEXT) Context;
  2077. PIO_STACK_LOCATION irpSpNext;
  2078. BOOLEAN passiveCompletionOK;
  2079. DEFER_ACTION deferAction;
  2080. ULONG refAction;
  2081. LARGE_INTEGER deltaTime;
  2082. PVERIFIER_SETTINGS_SNAPSHOT verifierOptions;
  2083. LONG deferralTime;
  2084. //
  2085. // Retrieve time delta.
  2086. //
  2087. VfSettingsGetValue(
  2088. deferralContext->IovRequestPacket->VerifierSettings,
  2089. VERIFIER_VALUE_IRP_DEFERRAL_TIME,
  2090. (PULONG) &deferralTime
  2091. );
  2092. //
  2093. // Do delta time conversion.
  2094. //
  2095. deltaTime.QuadPart = -deferralTime;
  2096. //
  2097. // The *next* stack location holds our completion and context. The current
  2098. // stack location has already been wiped.
  2099. //
  2100. irpSpNext = IoGetNextIrpStackLocation( Irp );
  2101. ASSERT((PVOID) irpSpNext->CompletionRoutine == IovpInternalDeferredCompletion);
  2102. //
  2103. // Put everything back in case someone is looking...
  2104. //
  2105. irpSpNext->CompletionRoutine = deferralContext->OriginalCompletionRoutine;
  2106. irpSpNext->Context = deferralContext->OriginalContext;
  2107. //
  2108. // Some IRP dispatch routines cannot be called at passive. Two examples are
  2109. // paging IRPs (cause we could switch) and Power IRPs. As we don't check yet,
  2110. // if we "were" completed passive, continue to do so, but elsewhere...
  2111. //
  2112. passiveCompletionOK = (KeGetCurrentIrql()==PASSIVE_LEVEL);
  2113. VfPacketAcquireLock(deferralContext->IovRequestPacket);
  2114. //
  2115. // Verify all completion routines are in nonpaged code.
  2116. //
  2117. if (VfSettingsIsOptionEnabled(
  2118. deferralContext->IovRequestPacket->VerifierSettings,
  2119. VERIFIER_OPTION_POLICE_IRPS
  2120. )) {
  2121. if (MmIsSystemAddressLocked(irpSpNext->CompletionRoutine) == FALSE) {
  2122. WDM_FAIL_ROUTINE((
  2123. DCERROR_COMPLETION_ROUTINE_PAGABLE,
  2124. DCPARAM_IRP + DCPARAM_ROUTINE,
  2125. irpSpNext->CompletionRoutine,
  2126. Irp
  2127. ));
  2128. }
  2129. }
  2130. verifierOptions = deferralContext->IovRequestPacket->VerifierSettings;
  2131. ASSERT(VfSettingsIsOptionEnabled(verifierOptions, VERIFIER_OPTION_FORCE_PENDING));
  2132. if (VfSettingsIsOptionEnabled(verifierOptions, VERIFIER_OPTION_DEFER_COMPLETION)) {
  2133. //
  2134. // Now see whether we can safely defer completion...
  2135. //
  2136. if (VfSettingsIsOptionEnabled(verifierOptions, VERIFIER_OPTION_COMPLETE_AT_PASSIVE)) {
  2137. deferAction = passiveCompletionOK ? DEFERACTION_QUEUE_PASSIVE_TIMER :
  2138. DEFERACTION_NORMAL;
  2139. } else if (VfSettingsIsOptionEnabled(verifierOptions, VERIFIER_OPTION_COMPLETE_AT_DISPATCH)) {
  2140. deferAction = DEFERACTION_QUEUE_DISPATCH_TIMER;
  2141. } else {
  2142. deferAction = (KeGetCurrentIrql()==DISPATCH_LEVEL) ?
  2143. DEFERACTION_QUEUE_DISPATCH_TIMER :
  2144. DEFERACTION_QUEUE_PASSIVE_TIMER;
  2145. }
  2146. } else if (VfSettingsIsOptionEnabled(verifierOptions, VERIFIER_OPTION_COMPLETE_AT_PASSIVE)) {
  2147. deferAction = passiveCompletionOK ? DEFERACTION_QUEUE_WORKITEM :
  2148. DEFERACTION_NORMAL;
  2149. } else {
  2150. deferAction = DEFERACTION_NORMAL;
  2151. KDASSERT(0);
  2152. }
  2153. if (deferAction != DEFERACTION_NORMAL) {
  2154. //
  2155. // Set this flag. If anybody uses this IRP while this flag is on, complain
  2156. // immediately!
  2157. //
  2158. ASSERT(!(deferralContext->IovRequestPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY));
  2159. deferralContext->IovRequestPacket->Flags |= TRACKFLAG_QUEUED_INTERNALLY;
  2160. deferralContext->DeviceObject = DeviceObject;
  2161. VfIrpMakeUntouchable(Irp);
  2162. } else {
  2163. VfPacketDereference(deferralContext->IovRequestPacket, IOVREFTYPE_POINTER);
  2164. }
  2165. VfPacketReleaseLock(deferralContext->IovRequestPacket);
  2166. deferralContext->DeferAction = deferAction;
  2167. switch(deferAction) {
  2168. case DEFERACTION_QUEUE_PASSIVE_TIMER:
  2169. KeInitializeTimerEx(&deferralContext->DeferralTimer, SynchronizationTimer);
  2170. KeSetTimerEx(
  2171. &deferralContext->DeferralTimer,
  2172. deltaTime,
  2173. 0,
  2174. NULL
  2175. );
  2176. //
  2177. // Fall through...
  2178. //
  2179. case DEFERACTION_QUEUE_WORKITEM:
  2180. //
  2181. // Queue this up so we can complete this passively.
  2182. //
  2183. ExInitializeWorkItem(
  2184. (PWORK_QUEUE_ITEM)&deferralContext->WorkQueueItem,
  2185. IovpInternalCompleteAfterWait,
  2186. deferralContext
  2187. );
  2188. ExQueueWorkItem(
  2189. (PWORK_QUEUE_ITEM)&deferralContext->WorkQueueItem,
  2190. DelayedWorkQueue
  2191. );
  2192. return STATUS_MORE_PROCESSING_REQUIRED;
  2193. case DEFERACTION_QUEUE_DISPATCH_TIMER:
  2194. KeInitializeDpc(
  2195. &deferralContext->DpcItem,
  2196. IovpInternalCompleteAtDPC,
  2197. deferralContext
  2198. );
  2199. KeInitializeTimerEx(&deferralContext->DeferralTimer, SynchronizationTimer);
  2200. KeSetTimerEx(
  2201. &deferralContext->DeferralTimer,
  2202. deltaTime,
  2203. 0,
  2204. &deferralContext->DpcItem
  2205. );
  2206. return STATUS_MORE_PROCESSING_REQUIRED;
  2207. case DEFERACTION_NORMAL:
  2208. default:
  2209. ExFreePool(deferralContext);
  2210. return irpSpNext->CompletionRoutine(DeviceObject, Irp, irpSpNext->Context);
  2211. }
  2212. }
  2213. NTSTATUS
  2214. IovpSwapSurrogateIrp(
  2215. IN PDEVICE_OBJECT DeviceObject,
  2216. IN PIRP Irp,
  2217. IN PVOID Context
  2218. )
  2219. /*++
  2220. Description:
  2221. This completion routine will copy back the surrogate IRP
  2222. to the original and complete the original IRP.
  2223. Arguments:
  2224. DeviceObject - Device object set at this level
  2225. of the completion routine - ignored.
  2226. Irp - A pointer to the IRP.
  2227. Context - Context should equal the IRP - this is
  2228. asserted.
  2229. Return Value:
  2230. STATUS_MORE_PROCESSING_REQUIRED...
  2231. --*/
  2232. {
  2233. PIOV_REQUEST_PACKET iovPacket, iovPrevPacket;
  2234. PIOV_SESSION_DATA iovSessionData;
  2235. ULONG irpSize;
  2236. PIRP realIrp;
  2237. BOOLEAN freeTrackingData;
  2238. NTSTATUS status, lockedStatus;
  2239. CCHAR priorityBoost;
  2240. PVOID completionRoutine;
  2241. PIO_STACK_LOCATION irpSp;
  2242. BOOLEAN locked;
  2243. //
  2244. // If this one fails, somebody has probably copied the stack
  2245. // inclusive with our completion routine. We should already
  2246. // have caught this...
  2247. //
  2248. ASSERT(Irp == Context);
  2249. iovPacket = VfPacketFindAndLock(Irp);
  2250. ASSERT(iovPacket);
  2251. if (iovPacket == NULL) {
  2252. return STATUS_SUCCESS;
  2253. }
  2254. ASSERT(iovPacket->TopStackLocation == Irp->CurrentLocation);
  2255. iovSessionData = VfPacketGetCurrentSessionData(iovPacket);
  2256. ASSERT(iovSessionData);
  2257. //
  2258. // Put everything back
  2259. //
  2260. ASSERT(iovPacket->ChainHead != (PIOV_DATABASE_HEADER) iovPacket);
  2261. iovPrevPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainPrevious(
  2262. (PIOV_DATABASE_HEADER) iovPacket
  2263. );
  2264. realIrp = iovPrevPacket->TrackedIrp;
  2265. irpSize = IoSizeOfIrp( Irp->StackCount );
  2266. //
  2267. // Back the IRP stack up so that the original completion routine
  2268. // is called if appropriate
  2269. //
  2270. IoSetNextIrpStackLocation(Irp);
  2271. IoSetNextIrpStackLocation(realIrp);
  2272. irpSp = IoGetCurrentIrpStackLocation(Irp);
  2273. irpSp->CompletionRoutine = iovPacket->RealIrpCompletionRoutine;
  2274. irpSp->Control = iovPacket->RealIrpControl;
  2275. irpSp->Context = iovPacket->RealIrpContext;
  2276. //
  2277. // Record final data and make any accesses to the surrogate IRP
  2278. // crash.
  2279. //
  2280. irpSp = IoGetNextIrpStackLocation(Irp);
  2281. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  2282. VfMajorVerifyFinalIrpStack(iovPacket, irpSp);
  2283. }
  2284. priorityBoost = iovPacket->PriorityBoost;
  2285. VfPacketDereference(iovPacket, IOVREFTYPE_POINTER);
  2286. IovpSessionDataFinalizeSurrogate(iovSessionData, iovPacket, Irp);
  2287. IovpSessionDataClose(iovSessionData);
  2288. IovpSessionDataDereference(iovSessionData);
  2289. TRACKIRP_DBGPRINT((
  2290. " Swapping surrogate IRP %lx back to %lx (Tracking data %lx)\n",
  2291. Irp,
  2292. realIrp,
  2293. iovPacket
  2294. ), 1);
  2295. iovPacket->Flags |= TRACKFLAG_SWAPPED_BACK;
  2296. //
  2297. // We have to be a bit more careful since the chain has been split. Release
  2298. // the locks in the proper order.
  2299. //
  2300. VfPacketReleaseLock(iovPrevPacket);
  2301. VfPacketReleaseLock(iovPacket);
  2302. //
  2303. // Send the IRP onwards and upwards.
  2304. //
  2305. IoCompleteRequest(realIrp, priorityBoost);
  2306. return STATUS_MORE_PROCESSING_REQUIRED;
  2307. }
  2308. VOID
  2309. FASTCALL
  2310. IovpCancelIrp(
  2311. IN PIRP Irp,
  2312. OUT PBOOLEAN CancelHandled,
  2313. OUT PBOOLEAN ReturnValue
  2314. )
  2315. /*++
  2316. Description:
  2317. This routine is called by IoCancelIrp and returns TRUE iff
  2318. the cancelation was handled internally here (in which case
  2319. IoCancelIrp should do nothing).
  2320. We need to handle the call internally when we are currently
  2321. dealing with a surrogate. In this case, we make sure the
  2322. surrogate is cancelled instead.
  2323. Arguments:
  2324. Irp - A pointer to the IRP passed into
  2325. IoCancelIrp.
  2326. CancelHandled - Indicates whether the IRP cancellation
  2327. was handled entirely by this routine.
  2328. ReturnValue - Set to the value IoCancelIrp
  2329. should return if the IRP cancelation
  2330. was handled entirely by this routine.
  2331. Return Value:
  2332. None.
  2333. --*/
  2334. {
  2335. PIOV_REQUEST_PACKET iovPacket, iovNextPacket;
  2336. PIRP irpToCancel;
  2337. KIRQL irql;
  2338. *CancelHandled = FALSE;
  2339. iovPacket = VfPacketFindAndLock(Irp);
  2340. if (iovPacket == NULL) {
  2341. return;
  2342. }
  2343. VfPacketLogEntry(
  2344. iovPacket,
  2345. IOV_EVENT_IO_CANCEL_IRP,
  2346. NULL,
  2347. 0
  2348. );
  2349. //
  2350. // If the IRP is queued internally, touching it is not very safe as we may
  2351. // have temporarily removed the page's backing. Restore the backing while
  2352. // under the IRPs track lock.
  2353. //
  2354. if (iovPacket->Flags&TRACKFLAG_QUEUED_INTERNALLY) {
  2355. VfIrpMakeTouchable(Irp);
  2356. }
  2357. if (!(iovPacket->Flags&TRACKFLAG_ACTIVE)) {
  2358. //
  2359. // We've already completed the IRP, and the only reason it's
  2360. // still being tracked is because of it's allocation.
  2361. // So it is not ours to cancel.
  2362. //
  2363. VfPacketReleaseLock(iovPacket);
  2364. return;
  2365. }
  2366. if (!(iovPacket->Flags&TRACKFLAG_HAS_SURROGATE)) {
  2367. //
  2368. // Cancel of an IRP that doesn't have an active surrogate. Let it
  2369. // proceed normally.
  2370. //
  2371. VfPacketReleaseLock(iovPacket);
  2372. return;
  2373. }
  2374. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  2375. if (Irp->CancelRoutine) {
  2376. WDM_FAIL_ROUTINE((
  2377. DCERROR_CANCELROUTINE_ON_FORWARDED_IRP,
  2378. DCPARAM_IRP + DCPARAM_ROUTINE,
  2379. Irp->CancelRoutine,
  2380. Irp
  2381. ));
  2382. //
  2383. // We will ignore this routine. As we should...
  2384. //
  2385. }
  2386. }
  2387. iovNextPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainNext(
  2388. (PIOV_DATABASE_HEADER) iovPacket
  2389. );
  2390. Irp->Cancel = TRUE;
  2391. *CancelHandled = TRUE;
  2392. irpToCancel = iovNextPacket->TrackedIrp;
  2393. VfPacketReleaseLock(iovPacket);
  2394. *ReturnValue = IoCancelIrp(irpToCancel);
  2395. return;
  2396. }
  2397. /*
  2398. * Device Object functions
  2399. * IovpExamineDevObjForwarded
  2400. *
  2401. */
  2402. VOID
  2403. FASTCALL
  2404. IovpExamineDevObjForwarding(
  2405. IN PDEVICE_OBJECT DeviceBeingCalled,
  2406. IN PDEVICE_OBJECT DeviceLastCalled OPTIONAL,
  2407. OUT PULONG ForwardTechnique
  2408. )
  2409. /*++
  2410. Returns:
  2411. STARTED_TOP_OF_STACK
  2412. FORWARDED_TO_NEXT_DO
  2413. SKIPPED_A_DO
  2414. STARTED_INSIDE_STACK
  2415. CHANGED_STACKS_AT_BOTTOM
  2416. CHANGED_STACKS_MID_STACK
  2417. --*/
  2418. {
  2419. PDEVICE_OBJECT upperObject;
  2420. DEVOBJ_RELATION deviceObjectRelation;
  2421. ULONG result;
  2422. if (DeviceLastCalled == NULL) {
  2423. IovUtilGetUpperDeviceObject(DeviceBeingCalled, &upperObject);
  2424. if (upperObject) {
  2425. ObDereferenceObject(upperObject);
  2426. *ForwardTechnique = STARTED_INSIDE_STACK;
  2427. } else {
  2428. *ForwardTechnique = STARTED_TOP_OF_STACK;
  2429. }
  2430. return;
  2431. }
  2432. IovUtilRelateDeviceObjects(
  2433. DeviceBeingCalled,
  2434. DeviceLastCalled,
  2435. &deviceObjectRelation
  2436. );
  2437. switch(deviceObjectRelation) {
  2438. case DEVOBJ_RELATION_IDENTICAL:
  2439. //
  2440. // We map forwarded nowhere to forwarded ahead.
  2441. //
  2442. result = FORWARDED_TO_NEXT_DO;
  2443. break;
  2444. case DEVOBJ_RELATION_FIRST_IMMEDIATELY_BELOW_SECOND:
  2445. result = FORWARDED_TO_NEXT_DO;
  2446. break;
  2447. case DEVOBJ_RELATION_FIRST_BELOW_SECOND:
  2448. //
  2449. // This is very likely a driver forwarding IRPs directly to the PDO.
  2450. //
  2451. result = SKIPPED_A_DO;
  2452. break;
  2453. case DEVOBJ_RELATION_FIRST_IMMEDIATELY_ABOVE_SECOND:
  2454. case DEVOBJ_RELATION_FIRST_ABOVE_SECOND:
  2455. //
  2456. // Weird. Really???? Did the IRP truely go backwards, *up* the
  2457. // stack?
  2458. //
  2459. ASSERT(0);
  2460. result = SKIPPED_A_DO;
  2461. break;
  2462. case DEVOBJ_RELATION_NOT_IN_SAME_STACK:
  2463. IovUtilGetUpperDeviceObject(DeviceBeingCalled, &upperObject);
  2464. if (upperObject) {
  2465. ObDereferenceObject(upperObject);
  2466. result = CHANGED_STACKS_MID_STACK;
  2467. } else {
  2468. result = CHANGED_STACKS_AT_BOTTOM;
  2469. }
  2470. break;
  2471. default:
  2472. ASSERT(0);
  2473. result = FORWARDED_TO_NEXT_DO;
  2474. break;
  2475. }
  2476. *ForwardTechnique = result;
  2477. }
  2478. VOID
  2479. IovpBuildMiniIrpSnapshot(
  2480. IN PIRP Irp,
  2481. OUT IRP_MINI_SNAPSHOT *IrpSnapshot
  2482. )
  2483. /*++
  2484. Routine Description:
  2485. This routine builds a minimal snapshot of an IRP. It covers the Irp pointer
  2486. and the stack location contents.
  2487. Parameters:
  2488. Irp - A pointer to the IRP to snapshot. The *next* stack
  2489. location of the IRP is snapshotted by this
  2490. function.
  2491. IrpSnapshot - Receives snapshot of IRP.
  2492. Return Value:
  2493. None.
  2494. --*/
  2495. {
  2496. IrpSnapshot->Irp = Irp;
  2497. RtlCopyMemory(
  2498. &IrpSnapshot->IoStackLocation,
  2499. IoGetNextIrpStackLocation(Irp),
  2500. sizeof(IO_STACK_LOCATION)
  2501. );
  2502. }
  2503. #endif // NO_SPECIAL_IRP