Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

908 lines
24 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. sessnirp.c
  5. Abstract:
  6. I/O Verifier irp support routines.
  7. Author:
  8. Adrian Oney (adriao)
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "iop.h"
  14. #include "srb.h"
  15. //
  16. // This entire file is only present if NO_SPECIAL_IRP isn't defined
  17. //
  18. #ifndef NO_SPECIAL_IRP
  19. //
  20. // When enabled, everything is locked down on demand...
  21. //
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGEVRFY, IovpSessionDataCreate)
  24. #pragma alloc_text(PAGEVRFY, IovpSessionDataAdvance)
  25. #pragma alloc_text(PAGEVRFY, IovpSessionDataReference)
  26. #pragma alloc_text(PAGEVRFY, IovpSessionDataDereference)
  27. #pragma alloc_text(PAGEVRFY, IovpSessionDataClose)
  28. #pragma alloc_text(PAGEVRFY, IovpSessionDataDeterminePolicy)
  29. #pragma alloc_text(PAGEVRFY, IovpSessionDataAttachSurrogate)
  30. #pragma alloc_text(PAGEVRFY, IovpSessionDataFinalizeSurrogate)
  31. #pragma alloc_text(PAGEVRFY, IovpSessionDataBufferIO)
  32. #pragma alloc_text(PAGEVRFY, IovpSessionDataUnbufferIO)
  33. #endif
  34. #define POOL_TAG_SESSION_DATA 'sprI'
  35. #define POOL_TAG_DIRECT_BUFFER 'BprI'
  36. PIOV_SESSION_DATA
  37. FASTCALL
  38. IovpSessionDataCreate(
  39. IN PDEVICE_OBJECT DeviceObject,
  40. IN OUT PIOV_REQUEST_PACKET *IovPacketPointer,
  41. OUT PBOOLEAN SurrogateSpawned
  42. )
  43. /*++
  44. Description:
  45. This routine creates tracking data for a new IRP. It must be called on the
  46. thread the IRP was originally sent down...
  47. Arguments:
  48. Irp - Irp to track.
  49. Return Value:
  50. iovPacket block, NULL if no memory.
  51. --*/
  52. {
  53. PIRP irp, surrogateIrp;
  54. PIOV_SESSION_DATA iovSessionData;
  55. PIOV_REQUEST_PACKET headPacket;
  56. ULONG sessionDataSize;
  57. BOOLEAN trackable, useSurrogateIrp;
  58. *SurrogateSpawned = FALSE;
  59. headPacket = (PIOV_REQUEST_PACKET) (*IovPacketPointer)->ChainHead;
  60. ASSERT(headPacket == (*IovPacketPointer));
  61. irp = headPacket->TrackedIrp;
  62. //
  63. // Check the IRP appropriately
  64. //
  65. IovpSessionDataDeterminePolicy(
  66. headPacket,
  67. DeviceObject,
  68. &trackable,
  69. &useSurrogateIrp
  70. );
  71. if (!trackable) {
  72. return NULL;
  73. }
  74. //
  75. // One extra stack location is allocated as the "zero'th" is used to
  76. // simplify some logic...
  77. //
  78. sessionDataSize =
  79. sizeof(IOV_SESSION_DATA)+
  80. irp->StackCount*sizeof(IOV_STACK_LOCATION) +
  81. VfSettingsGetSnapshotSize();
  82. iovSessionData = ExAllocatePoolWithTag(
  83. NonPagedPool,
  84. sessionDataSize,
  85. POOL_TAG_SESSION_DATA
  86. );
  87. if (iovSessionData == NULL) {
  88. return NULL;
  89. }
  90. RtlZeroMemory(iovSessionData, sessionDataSize);
  91. iovSessionData->VerifierSettings = (PVERIFIER_SETTINGS_SNAPSHOT)
  92. (((PUCHAR) iovSessionData) + (sessionDataSize-VfSettingsGetSnapshotSize()));
  93. RtlCopyMemory(
  94. iovSessionData->VerifierSettings,
  95. headPacket->VerifierSettings,
  96. VfSettingsGetSnapshotSize()
  97. );
  98. iovSessionData->IovRequestPacket = headPacket;
  99. InsertHeadList(&headPacket->SessionHead, &iovSessionData->SessionLink);
  100. if (VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_DEFER_COMPLETION)||
  101. VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_COMPLETE_AT_PASSIVE)) {
  102. VfSettingsSetOption(iovSessionData->VerifierSettings, VERIFIER_OPTION_FORCE_PENDING, TRUE);
  103. }
  104. //
  105. // If DeferIoCompletion is set we definitely want to monitor pending I/O, as
  106. // screwing it up is gaurenteed to be fatal!
  107. //
  108. if ((irp->Flags & IRP_DEFER_IO_COMPLETION) &&
  109. VfSettingsIsOptionEnabled(iovSessionData->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  110. VfSettingsSetOption(iovSessionData->VerifierSettings, VERIFIER_OPTION_MONITOR_PENDING_IO, TRUE);
  111. }
  112. headPacket->pIovSessionData = iovSessionData;
  113. headPacket->TopStackLocation = irp->CurrentLocation;
  114. headPacket->Flags |= TRACKFLAG_ACTIVE;
  115. headPacket->Flags &= ~
  116. (
  117. TRACKFLAG_QUEUED_INTERNALLY|
  118. TRACKFLAG_RELEASED|
  119. TRACKFLAG_SRB_MUNGED|
  120. TRACKFLAG_SWAPPED_BACK
  121. );
  122. iovSessionData->BestVisibleIrp = irp;
  123. if (useSurrogateIrp) {
  124. //
  125. // We will track the IRP using a surrogate.
  126. //
  127. *SurrogateSpawned = IovpSessionDataAttachSurrogate(
  128. IovPacketPointer,
  129. iovSessionData
  130. );
  131. }
  132. TRACKIRP_DBGPRINT((
  133. " SSN CREATE(%x)->%x\n",
  134. headPacket,
  135. iovSessionData
  136. ), 3);
  137. return iovSessionData;
  138. }
  139. VOID
  140. FASTCALL
  141. IovpSessionDataAdvance(
  142. IN PDEVICE_OBJECT DeviceObject,
  143. IN PIOV_SESSION_DATA IovSessionData,
  144. IN OUT PIOV_REQUEST_PACKET *IovPacketPointer,
  145. OUT PBOOLEAN SurrogateSpawned
  146. )
  147. {
  148. *SurrogateSpawned = FALSE;
  149. }
  150. VOID
  151. FASTCALL
  152. IovpSessionDataDereference(
  153. IN PIOV_SESSION_DATA IovSessionData
  154. )
  155. {
  156. PIOV_REQUEST_PACKET iovPacket;
  157. iovPacket = IovSessionData->IovRequestPacket;
  158. ASSERT((PIOV_REQUEST_PACKET) iovPacket->ChainHead == iovPacket);
  159. ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
  160. ASSERT(IovSessionData->SessionRefCount > 0);
  161. ASSERT(iovPacket->ReferenceCount >= 0);
  162. TRACKIRP_DBGPRINT((
  163. " SSN DEREF(%x) %x--\n",
  164. IovSessionData,
  165. IovSessionData->SessionRefCount
  166. ), 3);
  167. IovSessionData->SessionRefCount--;
  168. if (!IovSessionData->SessionRefCount) {
  169. ASSERT(iovPacket->pIovSessionData != IovSessionData);
  170. ASSERT(iovPacket->ReferenceCount > iovPacket->PointerCount);
  171. //ASSERT(IsListEmpty(&IovSessionData->SessionLink));
  172. RemoveEntryList(&IovSessionData->SessionLink);
  173. InitializeListHead(&IovSessionData->SessionLink);
  174. VfPacketDereference(iovPacket, IOVREFTYPE_PACKET);
  175. ExFreePool(IovSessionData);
  176. }
  177. }
  178. VOID
  179. FASTCALL
  180. IovpSessionDataReference(
  181. IN PIOV_SESSION_DATA IovSessionData
  182. )
  183. {
  184. PIOV_REQUEST_PACKET iovPacket;
  185. iovPacket = IovSessionData->IovRequestPacket;
  186. ASSERT((PIOV_REQUEST_PACKET) iovPacket->ChainHead == iovPacket);
  187. ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
  188. ASSERT(IovSessionData->SessionRefCount >= 0);
  189. ASSERT(iovPacket->ReferenceCount >= 0);
  190. TRACKIRP_DBGPRINT((
  191. " SSN REF(%x) %x++\n",
  192. IovSessionData,
  193. IovSessionData->SessionRefCount
  194. ), 3);
  195. if (!IovSessionData->SessionRefCount) {
  196. VfPacketReference(iovPacket, IOVREFTYPE_PACKET);
  197. }
  198. IovSessionData->SessionRefCount++;
  199. }
  200. VOID
  201. FASTCALL
  202. IovpSessionDataClose(
  203. IN PIOV_SESSION_DATA IovSessionData
  204. )
  205. {
  206. PIOV_REQUEST_PACKET iovPacket = IovSessionData->IovRequestPacket;
  207. ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
  208. ASSERT(iovPacket == (PIOV_REQUEST_PACKET) iovPacket->ChainHead);
  209. ASSERT(iovPacket->pIovSessionData == IovSessionData);
  210. TRACKIRP_DBGPRINT((
  211. " SSN CLOSE(%x)\n",
  212. IovSessionData
  213. ), 3);
  214. iovPacket->Flags &= ~TRACKFLAG_ACTIVE;
  215. iovPacket->pIovSessionData = NULL;
  216. }
  217. VOID
  218. IovpSessionDataDeterminePolicy(
  219. IN PIOV_REQUEST_PACKET IovRequestPacket,
  220. IN PDEVICE_OBJECT DeviceObject,
  221. OUT PBOOLEAN Trackable,
  222. OUT PBOOLEAN UseSurrogateIrp
  223. )
  224. /*++
  225. Description:
  226. This routine is called by IovpCallDriver1 to determine which IRPs should
  227. be tracked and how that tracking should be done.
  228. Arguments:
  229. IovRequestPacket - Verifier data representing the incoming IRP
  230. DeviceObject - Device object the IRP is being forwarded to
  231. Trackable - Set if the IRP should be marked trackable
  232. UseSurrogateIrp - Set a surrogate should be created for this IRP
  233. Return Value:
  234. None.
  235. --*/
  236. {
  237. PIO_STACK_LOCATION irpSp;
  238. PIRP irp;
  239. irp = IovRequestPacket->TrackedIrp;
  240. //
  241. // Determine whether we are to monitor this IRP. If we are going to test
  242. // any one driver in a stack, then we must unfortunately monitor the IRP's
  243. // progress through the *entire* stack. Thus our granularity here is stack
  244. // based, not device based! We will compensate for this somewhat in the
  245. // driver check code, which will attempt to ignore asserts from those
  246. // "non-targetted" drivers who happen to have messed up in our stack...
  247. //
  248. *Trackable = IovUtilIsVerifiedDeviceStack(DeviceObject);
  249. irpSp = IoGetNextIrpStackLocation(irp);
  250. if (VfSettingsIsOptionEnabled(IovRequestPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  251. *UseSurrogateIrp = VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SURROGATE_IRPS);
  252. *UseSurrogateIrp &= (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_SMASH_SRBS) ||
  253. (irpSp->MajorFunction != IRP_MJ_SCSI));
  254. } else {
  255. *UseSurrogateIrp = FALSE;
  256. }
  257. }
  258. BOOLEAN
  259. FASTCALL
  260. IovpSessionDataAttachSurrogate(
  261. IN OUT PIOV_REQUEST_PACKET *IovPacketPointer,
  262. IN PIOV_SESSION_DATA IovSessionData
  263. )
  264. /*++
  265. Description:
  266. This routine creates tracking data for a new IRP. It must be called on the
  267. thread the IRP was originally sent down...
  268. Arguments:
  269. IovPacketPointer - Pointer to IRP packet to attach surrogate to. If
  270. a surrogate can be attached the packet will be
  271. updated to track the surrogate.
  272. SurrogateIrp - Prepared surrogate IRP to attach.
  273. Return Value:
  274. iovPacket block, NULL if no memory.
  275. --*/
  276. {
  277. PIOV_REQUEST_PACKET iovSurrogatePacket, iovPacket, headPacket;
  278. PIRP surrogateIrp, irp;
  279. PIO_STACK_LOCATION irpSp;
  280. PSCSI_REQUEST_BLOCK srb;
  281. CCHAR activeSize;
  282. iovPacket = *IovPacketPointer;
  283. ASSERT_SPINLOCK_HELD(&iovPacket->HeaderLock);
  284. ASSERT(VfIrpDatabaseEntryGetChainNext((PIOV_DATABASE_HEADER) iovPacket) == NULL);
  285. ASSERT(iovPacket->Flags & TRACKFLAG_ACTIVE);
  286. irp = iovPacket->TrackedIrp;
  287. activeSize = (irp->CurrentLocation-1);
  288. ASSERT(activeSize);
  289. //
  290. // We now try to make a copy of this new IRP which we will track. We
  291. // do this so that we may free *every* tracked IRP immediately upon
  292. // completion.
  293. // Technically speaking, we only need to allocate what's left of the
  294. // stack, not the entire thing. But using the entire stack makes our
  295. // work much much easier. Specifically the session stack array may depend
  296. // on this.
  297. //
  298. // ADRIAO N.B. 03/04/1999 - Make this work only copying a portion of the
  299. // IRP.
  300. //
  301. surrogateIrp = VfIrpAllocate(irp->StackCount); // activeSize
  302. if (surrogateIrp == NULL) {
  303. return FALSE;
  304. }
  305. //
  306. // Now set up the new IRP - we do this here so VfPacketCreateAndLock
  307. // can peek at it's fields. Start with the IRP header.
  308. //
  309. RtlCopyMemory(surrogateIrp, irp, sizeof(IRP));
  310. //
  311. // Adjust StackCount and CurrentLocation
  312. //
  313. surrogateIrp->StackCount = irp->StackCount; // activeSize
  314. surrogateIrp->Tail.Overlay.CurrentStackLocation =
  315. ((PIO_STACK_LOCATION) (surrogateIrp+1))+activeSize;
  316. //
  317. // Our new IRP "floats", and is not attached to any thread.
  318. // Note that all cancels due to thread death will come through the
  319. // original IRP.
  320. //
  321. InitializeListHead(&surrogateIrp->ThreadListEntry);
  322. //
  323. // Our new IRP also is not connected to user mode.
  324. //
  325. surrogateIrp->UserEvent = NULL;
  326. surrogateIrp->UserIosb = NULL;
  327. //
  328. // Now copy over only the active portions of IRP. Be very careful to not
  329. // assume that the last stack location is right after the end of the IRP,
  330. // as we may change this someday!
  331. //
  332. irpSp = (IoGetCurrentIrpStackLocation(irp)-activeSize);
  333. RtlCopyMemory(surrogateIrp+1, irpSp, sizeof(IO_STACK_LOCATION)*activeSize);
  334. //
  335. // Zero the portion of the new IRP we won't be using (this should
  336. // eventually go away).
  337. //
  338. RtlZeroMemory(
  339. ((PIO_STACK_LOCATION) (surrogateIrp+1))+activeSize,
  340. sizeof(IO_STACK_LOCATION)*(surrogateIrp->StackCount - activeSize)
  341. );
  342. //
  343. // Now create a surrogate packet to track the new IRP.
  344. //
  345. iovSurrogatePacket = VfPacketCreateAndLock(surrogateIrp);
  346. if (iovSurrogatePacket == NULL) {
  347. VfIrpFree(surrogateIrp);
  348. return FALSE;
  349. }
  350. headPacket = (PIOV_REQUEST_PACKET) iovPacket->ChainHead;
  351. ASSERT(iovSurrogatePacket->LockIrql == DISPATCH_LEVEL);
  352. irpSp = IoGetNextIrpStackLocation(irp);
  353. //
  354. // We will flag this bug later.
  355. //
  356. irp->CancelRoutine = NULL;
  357. //
  358. // Let's take advantage of the original IRP not being the thing partied on
  359. // now; store a pointer to our tracking data in the information field. We
  360. // don't use this, but it's nice when debugging...
  361. //
  362. irp->IoStatus.Information = (ULONG_PTR) iovPacket;
  363. //
  364. // ADRIAO N.B. #28 06/10/98 - This is absolutely *gross*, and not
  365. // deterministic enough for my tastes.
  366. //
  367. // For IRP_MJ_SCSI (ie, IRP_MJ_INTERNAL_DEVICE_CONTROL), look and see
  368. // if we have an SRB coming through. If so, fake out the OriginalRequest
  369. // IRP pointer as appropriate.
  370. //
  371. if (irpSp->MajorFunction == IRP_MJ_SCSI) {
  372. srb = irpSp->Parameters.Others.Argument1;
  373. if (VfUtilIsMemoryRangeReadable(srb, SCSI_REQUEST_BLOCK_SIZE, VFMP_INSTANT_NONPAGED)) {
  374. if ((srb->Length == SCSI_REQUEST_BLOCK_SIZE)&&(srb->OriginalRequest == irp)) {
  375. srb->OriginalRequest = surrogateIrp;
  376. headPacket->Flags |= TRACKFLAG_SRB_MUNGED;
  377. }
  378. }
  379. }
  380. //
  381. // Since the replacement will never make it back to user mode (the real
  382. // IRP shall of course), we will steal a field or two for debugging info.
  383. //
  384. surrogateIrp->UserIosb = (PIO_STATUS_BLOCK) iovPacket;
  385. //
  386. // Now that everything is built correctly, attach the surrogate. The
  387. // surrogate holds down the packet we are attaching to. When the surrogate
  388. // dies we will remove this reference.
  389. //
  390. VfPacketReference(iovPacket, IOVREFTYPE_POINTER);
  391. //
  392. // Stamp IRPs appropriately.
  393. //
  394. surrogateIrp->Flags |= IRP_DIAG_IS_SURROGATE;
  395. irp->Flags |= IRP_DIAG_HAS_SURROGATE;
  396. //
  397. // Mark packet as surrogate and inherit appropriate fields from iovPacket.
  398. //
  399. iovSurrogatePacket->Flags |= TRACKFLAG_SURROGATE | TRACKFLAG_ACTIVE;
  400. iovSurrogatePacket->pIovSessionData = iovPacket->pIovSessionData;
  401. RtlCopyMemory(
  402. iovSurrogatePacket->VerifierSettings,
  403. iovPacket->VerifierSettings,
  404. VfSettingsGetSnapshotSize()
  405. );
  406. iovSurrogatePacket->LastLocation = iovPacket->LastLocation;
  407. iovSurrogatePacket->TopStackLocation = irp->CurrentLocation;
  408. iovSurrogatePacket->ArrivalIrql = iovPacket->ArrivalIrql;
  409. iovSurrogatePacket->DepartureIrql = iovPacket->DepartureIrql;
  410. iovPacket->Flags |= TRACKFLAG_HAS_SURROGATE;
  411. //
  412. // Link in the new surrogate
  413. //
  414. VfIrpDatabaseEntryAppendToChain(
  415. (PIOV_DATABASE_HEADER) iovPacket,
  416. (PIOV_DATABASE_HEADER) iovSurrogatePacket
  417. );
  418. *IovPacketPointer = iovSurrogatePacket;
  419. IovpSessionDataBufferIO(
  420. iovSurrogatePacket,
  421. surrogateIrp
  422. );
  423. return TRUE;
  424. }
  425. VOID
  426. FASTCALL
  427. IovpSessionDataFinalizeSurrogate(
  428. IN PIOV_SESSION_DATA IovSessionData,
  429. IN OUT PIOV_REQUEST_PACKET IovPacket,
  430. IN PIRP SurrogateIrp
  431. )
  432. /*++
  433. Description:
  434. This routine removes the flags from both the real and
  435. surrogate IRP and records the final IRP settings. Finally,
  436. the surrogate IRP is made "untouchable" (decommitted).
  437. Arguments:
  438. iovPacket - Pointer to the IRP tracking data.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. PIOV_REQUEST_PACKET iovPrevPacket;
  444. NTSTATUS status, lockedStatus;
  445. ULONG nonInterestingFlags;
  446. PIO_STACK_LOCATION irpSp;
  447. PIRP irp;
  448. ASSERT(IovPacket->Flags&TRACKFLAG_SURROGATE);
  449. ASSERT(VfPacketGetCurrentSessionData(IovPacket) == IovSessionData);
  450. IovPacket->pIovSessionData = NULL;
  451. //
  452. // It's a surrogate, do as appropriate.
  453. //
  454. ASSERT(IovPacket->TopStackLocation == SurrogateIrp->CurrentLocation+1);
  455. IovpSessionDataUnbufferIO(IovPacket, SurrogateIrp);
  456. iovPrevPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainPrevious(
  457. (PIOV_DATABASE_HEADER) IovPacket
  458. );
  459. irp = iovPrevPacket->TrackedIrp;
  460. //
  461. // Carry the pending bit over.
  462. //
  463. if (SurrogateIrp->PendingReturned) {
  464. IoMarkIrpPending(irp);
  465. }
  466. nonInterestingFlags = (
  467. IRPFLAG_EXAMINE_MASK |
  468. IRP_DIAG_IS_SURROGATE|
  469. IRP_DIAG_HAS_SURROGATE
  470. );
  471. //
  472. // Wipe the flags nice and clean
  473. //
  474. SurrogateIrp->Flags &= ~IRP_DIAG_IS_SURROGATE;
  475. irp->Flags &= ~IRP_DIAG_HAS_SURROGATE;
  476. //
  477. // ASSERT portions of the IRP header have not changed.
  478. //
  479. ASSERT(irp->StackCount == SurrogateIrp->StackCount); // Later to be removed
  480. ASSERT(irp->Type == SurrogateIrp->Type);
  481. ASSERT(irp->RequestorMode == SurrogateIrp->RequestorMode);
  482. ASSERT(irp->ApcEnvironment == SurrogateIrp->ApcEnvironment);
  483. ASSERT(irp->AllocationFlags == SurrogateIrp->AllocationFlags);
  484. ASSERT(irp->Tail.Overlay.Thread == SurrogateIrp->Tail.Overlay.Thread);
  485. ASSERT(
  486. irp->Overlay.AsynchronousParameters.UserApcRoutine ==
  487. SurrogateIrp->Overlay.AsynchronousParameters.UserApcRoutine
  488. );
  489. ASSERT(
  490. irp->Overlay.AsynchronousParameters.UserApcContext ==
  491. SurrogateIrp->Overlay.AsynchronousParameters.UserApcContext
  492. );
  493. ASSERT(
  494. irp->Tail.Overlay.OriginalFileObject ==
  495. SurrogateIrp->Tail.Overlay.OriginalFileObject
  496. );
  497. ASSERT(
  498. irp->Tail.Overlay.AuxiliaryBuffer ==
  499. SurrogateIrp->Tail.Overlay.AuxiliaryBuffer
  500. );
  501. /*
  502. ASSERT(
  503. irp->AssociatedIrp.SystemBuffer ==
  504. SurrogateIrp->AssociatedIrp.SystemBuffer
  505. );
  506. ASSERT(
  507. (irp->Flags & ~nonInterestingFlags) ==
  508. (SurrogateIrp->Flags & ~nonInterestingFlags)
  509. );
  510. ASSERT(irp->MdlAddress == SurrogateIrp->MdlAddress);
  511. */
  512. //
  513. // ADRIAO N.B. 02/28/1999 -
  514. // How do these change as an IRP progresses?
  515. //
  516. irp->Flags |= SurrogateIrp->Flags;
  517. irp->MdlAddress = SurrogateIrp->MdlAddress;
  518. irp->AssociatedIrp.SystemBuffer = SurrogateIrp->AssociatedIrp.SystemBuffer;
  519. //
  520. // ADRIAO N.B. 10/18/1999 - UserBuffer is edited by netbios on Type3 device
  521. // ioctls. Yuck!
  522. //
  523. irp->UserBuffer = SurrogateIrp->UserBuffer;
  524. if ((irp->Flags&IRP_DEALLOCATE_BUFFER)&&
  525. (irp->AssociatedIrp.SystemBuffer == NULL)) {
  526. irp->Flags &= ~IRP_DEALLOCATE_BUFFER;
  527. }
  528. //
  529. // Copy the salient fields back. We only need to touch certain areas of the
  530. // header.
  531. //
  532. irp->IoStatus = SurrogateIrp->IoStatus;
  533. irp->PendingReturned = SurrogateIrp->PendingReturned;
  534. irp->Cancel = SurrogateIrp->Cancel;
  535. iovPrevPacket->Flags &= ~TRACKFLAG_HAS_SURROGATE;
  536. //
  537. // Record data from it and make the system fault if the IRP is touched
  538. // after this completion routine.
  539. //
  540. IovSessionData->BestVisibleIrp = irp;
  541. IovSessionData->IovRequestPacket = iovPrevPacket;
  542. VfIrpDatabaseEntryRemoveFromChain((PIOV_DATABASE_HEADER) IovPacket);
  543. VfPacketDereference(iovPrevPacket, IOVREFTYPE_POINTER);
  544. ASSERT(IovPacket->PointerCount == 0);
  545. VfIrpFree(SurrogateIrp);
  546. }
  547. VOID
  548. FASTCALL
  549. IovpSessionDataBufferIO(
  550. IN OUT PIOV_REQUEST_PACKET IovSurrogatePacket,
  551. IN PIRP SurrogateIrp
  552. )
  553. {
  554. PMDL mdl;
  555. ULONG bufferLength;
  556. PUCHAR bufferVA, systemDestVA;
  557. PVOID systemBuffer;
  558. PIO_STACK_LOCATION irpSp;
  559. if (!VfSettingsIsOptionEnabled(IovSurrogatePacket->VerifierSettings, VERIFIER_OPTION_BUFFER_DIRECT_IO)) {
  560. return;
  561. }
  562. if (SurrogateIrp->Flags & IRP_PAGING_IO) {
  563. return;
  564. }
  565. if (SurrogateIrp->MdlAddress == NULL) {
  566. return;
  567. }
  568. if (SurrogateIrp->MdlAddress->Next) {
  569. return;
  570. }
  571. if (SurrogateIrp->Flags & IRP_BUFFERED_IO) {
  572. return;
  573. }
  574. irpSp = IoGetNextIrpStackLocation(SurrogateIrp);
  575. if (irpSp->MajorFunction != IRP_MJ_READ) {
  576. return;
  577. }
  578. //
  579. // Extract length and VA from the MDL.
  580. //
  581. bufferLength = SurrogateIrp->MdlAddress->ByteCount;
  582. bufferVA = (PUCHAR) SurrogateIrp->MdlAddress->StartVa +
  583. SurrogateIrp->MdlAddress->ByteOffset;
  584. //
  585. // Allocate memory and make it the target of the MDL
  586. //
  587. systemBuffer = ExAllocatePoolWithTagPriority(
  588. NonPagedPool,
  589. bufferLength,
  590. POOL_TAG_DIRECT_BUFFER,
  591. HighPoolPrioritySpecialPoolOverrun
  592. );
  593. if (systemBuffer == NULL) {
  594. return;
  595. }
  596. //
  597. // Save off a pointer to the Mdl's buffer. This should never fail, but
  598. // one never knows...
  599. //
  600. systemDestVA =
  601. MmGetSystemAddressForMdlSafe(SurrogateIrp->MdlAddress, HighPagePriority);
  602. if (systemDestVA == NULL) {
  603. ASSERT(0);
  604. ExFreePool(systemBuffer);
  605. return;
  606. }
  607. //
  608. // Allocate a MDL, update the IRP.
  609. //
  610. mdl = IoAllocateMdl(
  611. systemBuffer,
  612. bufferLength,
  613. FALSE,
  614. TRUE,
  615. SurrogateIrp
  616. );
  617. if (mdl == NULL) {
  618. ExFreePool(systemBuffer);
  619. return;
  620. }
  621. MmProbeAndLockPages( mdl, KernelMode, IoWriteAccess );
  622. IovSurrogatePacket->SystemDestVA = systemDestVA;
  623. IovSurrogatePacket->Flags |= TRACKFLAG_DIRECT_BUFFERED;
  624. }
  625. VOID
  626. FASTCALL
  627. IovpSessionDataUnbufferIO(
  628. IN OUT PIOV_REQUEST_PACKET IovSurrogatePacket,
  629. IN PIRP SurrogateIrp
  630. )
  631. {
  632. PMDL mdl;
  633. ULONG surrogateLength, originalLength;
  634. ULONG_PTR bufferLength;
  635. PUCHAR surrogateVA, originalVA, systemDestVA;
  636. PVOID systemBuffer;
  637. PIOV_REQUEST_PACKET iovPrevPacket;
  638. PIRP irp;
  639. if (!(IovSurrogatePacket->Flags & TRACKFLAG_DIRECT_BUFFERED)) {
  640. return;
  641. }
  642. iovPrevPacket = (PIOV_REQUEST_PACKET) VfIrpDatabaseEntryGetChainPrevious(
  643. (PIOV_DATABASE_HEADER) IovSurrogatePacket
  644. );
  645. irp = iovPrevPacket->TrackedIrp;
  646. ASSERT(SurrogateIrp->MdlAddress);
  647. ASSERT(SurrogateIrp->MdlAddress->Next == NULL);
  648. ASSERT(irp->MdlAddress);
  649. ASSERT(irp->MdlAddress->Next == NULL);
  650. ASSERT(!(SurrogateIrp->Flags & IRP_BUFFERED_IO));
  651. ASSERT(!(irp->Flags & IRP_BUFFERED_IO));
  652. //
  653. // Extract length and VA from the MDLs.
  654. //
  655. surrogateLength = SurrogateIrp->MdlAddress->ByteCount;
  656. surrogateVA = (PUCHAR) SurrogateIrp->MdlAddress->StartVa +
  657. SurrogateIrp->MdlAddress->ByteOffset;
  658. //
  659. // We use these only for the purpose of assertions.
  660. //
  661. originalLength = irp->MdlAddress->ByteCount;
  662. originalVA = (PUCHAR) irp->MdlAddress->StartVa +
  663. irp->MdlAddress->ByteOffset;
  664. ASSERT(surrogateLength == originalLength);
  665. ASSERT(SurrogateIrp->IoStatus.Information <= originalLength);
  666. //
  667. // Get the target buffer address and the length to write.
  668. //
  669. bufferLength = SurrogateIrp->IoStatus.Information;
  670. systemDestVA = IovSurrogatePacket->SystemDestVA;
  671. //
  672. // Copy things over.
  673. //
  674. RtlCopyMemory(systemDestVA, surrogateVA, bufferLength);
  675. //
  676. // Unlock the MDL. We have to do this ourselves as this IRP is not going to
  677. // progress through all of IoCompleteRequest.
  678. //
  679. MmUnlockPages(SurrogateIrp->MdlAddress);
  680. //
  681. // Cleanup.
  682. //
  683. IoFreeMdl(SurrogateIrp->MdlAddress);
  684. //
  685. // Free our allocated VA
  686. //
  687. ExFreePool(surrogateVA);
  688. //
  689. // Hack the MDL back as IovpSessionDataFinalizeSurrogate requires it.
  690. //
  691. SurrogateIrp->MdlAddress = irp->MdlAddress;
  692. IovSurrogatePacket->Flags &= ~TRACKFLAG_DIRECT_BUFFERED;
  693. }
  694. #endif // NO_SPECIAL_IRP