Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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