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.

1073 lines
24 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfirp.c
  5. Abstract:
  6. This module contains functions used to manage IRPs used in the verification
  7. process.
  8. Author:
  9. Adrian J. Oney (adriao) 20-Apr-1998
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. AdriaO 05/02/2000 - Seperated out from ntos\io\hashirp.c
  14. --*/
  15. #include "vfdef.h"
  16. #include "viirp.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(INIT, VfIrpInit)
  19. #pragma alloc_text(PAGEVRFY, VfIrpReserveCallStackData)
  20. #pragma alloc_text(PAGEVRFY, VfIrpPrepareAllocaCallStackData)
  21. #pragma alloc_text(PAGEVRFY, VfIrpReleaseCallStackData)
  22. #pragma alloc_text(PAGEVRFY, VfIrpAllocate)
  23. #pragma alloc_text(PAGEVRFY, ViIrpAllocateLockedPacket)
  24. #pragma alloc_text(PAGEVRFY, VfIrpMakeTouchable)
  25. #pragma alloc_text(PAGEVRFY, VfIrpMakeUntouchable)
  26. #pragma alloc_text(PAGEVRFY, VfIrpFree)
  27. #pragma alloc_text(PAGEVRFY, VerifierIoAllocateIrp1)
  28. #pragma alloc_text(PAGEVRFY, VerifierIoAllocateIrp2)
  29. #pragma alloc_text(PAGEVRFY, VerifierIoFreeIrp)
  30. #pragma alloc_text(PAGEVRFY, VerifierIoInitializeIrp)
  31. #pragma alloc_text(PAGEVRFY, VfIrpSendSynchronousIrp)
  32. #pragma alloc_text(PAGEVRFY, ViIrpSynchronousCompletionRoutine)
  33. #pragma alloc_text(PAGEVRFY, VfIrpWatermark)
  34. #endif
  35. #define POOL_TAG_PROTECTED_IRP '+prI'
  36. #define POOL_TAG_CALL_STACK_DATA 'CprI'
  37. NPAGED_LOOKASIDE_LIST ViIrpCallStackDataList;
  38. VOID
  39. FASTCALL
  40. VfIrpInit(
  41. VOID
  42. )
  43. /*++
  44. Description:
  45. This routine initializes IRP tracking support for the verifier.
  46. Arguments:
  47. None.
  48. Return Value:
  49. None.
  50. --*/
  51. {
  52. ExInitializeNPagedLookasideList(
  53. &ViIrpCallStackDataList,
  54. NULL,
  55. NULL,
  56. 0,
  57. sizeof(IOFCALLDRIVER_STACKDATA),
  58. POOL_TAG_CALL_STACK_DATA,
  59. 0
  60. );
  61. }
  62. BOOLEAN
  63. FASTCALL
  64. VfIrpReserveCallStackData(
  65. IN PIRP Irp,
  66. OUT PIOFCALLDRIVER_STACKDATA *IofCallDriverStackData
  67. )
  68. /*++
  69. Description:
  70. This routine reserves call stack data for IovCallDriver.
  71. Arguments:
  72. Irp - Contains IRP the call stack data is being reserved for.
  73. IofCallDriverStackData - Receives allocated call stack data, NULL if
  74. insufficient memory.
  75. Return Value:
  76. TRUE if either the allocation was successful, or it failed but is
  77. noncritical. If FALSE, memory should be allocated on the stack to
  78. support the request.
  79. --*/
  80. {
  81. PIOFCALLDRIVER_STACKDATA newCallStackData;
  82. newCallStackData = ExAllocateFromNPagedLookasideList(&ViIrpCallStackDataList);
  83. *IofCallDriverStackData = newCallStackData;
  84. if (newCallStackData == NULL) {
  85. //
  86. // We're low on memory, test the IRP to see if it's critical. If not,
  87. // the IRP will be tainted so we ignore it forever after.
  88. //
  89. return (!IovpCheckIrpForCriticalTracking(Irp));
  90. };
  91. //
  92. // Use the alloca initialization function here and then adjust the flags
  93. // accordingly.
  94. //
  95. VfIrpPrepareAllocaCallStackData(newCallStackData);
  96. newCallStackData->Flags |= CALLFLAG_STACK_DATA_ALLOCATED;
  97. return TRUE;
  98. }
  99. VOID
  100. FASTCALL
  101. VfIrpPrepareAllocaCallStackData(
  102. OUT PIOFCALLDRIVER_STACKDATA IofCallDriverStackData
  103. )
  104. /*++
  105. Description:
  106. This routine initializes call stack data allocated on the stack.
  107. Arguments:
  108. IofCallDriverStackData - Call stack data to initialize (from stack).
  109. Return Value:
  110. None.
  111. Note: This initializer is also called by VfIrpReserveCallStackData in case
  112. of a successful pool allocation. In this case flags are later adjusted.
  113. --*/
  114. {
  115. //
  116. // Preinitialize the CallStackData.
  117. //
  118. RtlZeroMemory(IofCallDriverStackData, sizeof(IOFCALLDRIVER_STACKDATA));
  119. }
  120. VOID
  121. FASTCALL
  122. VfIrpReleaseCallStackData(
  123. IN PIOFCALLDRIVER_STACKDATA IofCallDriverStackData OPTIONAL
  124. )
  125. /*++
  126. Description:
  127. This routine releases call stack data if it was allocated from pool. If the
  128. memory was allocated from the stack, this function does nothing.
  129. Arguments:
  130. IofCallDriverStackData - Call stack data to free.
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. if (IofCallDriverStackData &&
  136. (IofCallDriverStackData->Flags & CALLFLAG_STACK_DATA_ALLOCATED)) {
  137. ExFreeToNPagedLookasideList(
  138. &ViIrpCallStackDataList,
  139. IofCallDriverStackData
  140. );
  141. }
  142. }
  143. /*
  144. * The 4 routines listed below -
  145. * VfIrpAllocate
  146. * VfIrpMakeTouchable
  147. * VfIrpMakeUntouchable
  148. * VfIrpFree
  149. *
  150. * - handle management of the replacement IRP. Specifically, we want to be
  151. * able to allocate a set of non-paged bytes we can remove the backing
  152. * physical memory from, and release the virtual addresses for later (we
  153. * are essentially breaking free into it's two components). We do this with
  154. * help from the special pool.
  155. *
  156. */
  157. PIRP
  158. FASTCALL
  159. VfIrpAllocate(
  160. IN CCHAR StackSize
  161. )
  162. /*++
  163. Description:
  164. This routine allocates an IRP from the special pool using the
  165. "replacement IRP" tag.
  166. Arguments:
  167. StackSize - Number of stack locations to give the new IRP
  168. Return Value:
  169. Pointer to the memory allocated.
  170. --*/
  171. {
  172. PIRP pIrp;
  173. ULONG_PTR irpPtr;
  174. SIZE_T sizeOfAllocation;
  175. //
  176. // We are allocating an IRP from the special pool. Since IRPs may come from
  177. // lookaside lists they may be ULONG aligned. The memory manager on the
  178. // other hand gaurentees quad-aligned allocations. So to catch all special
  179. // pool overrun bugs we "skew" the IRP right up to the edge.
  180. //
  181. sizeOfAllocation = IoSizeOfIrp(StackSize);
  182. ASSERT((sizeOfAllocation % (sizeof(ULONG))) == 0);
  183. irpPtr = (ULONG_PTR) ExAllocatePoolWithTagPriority(
  184. NonPagedPool,
  185. sizeOfAllocation,
  186. POOL_TAG_PROTECTED_IRP,
  187. HighPoolPrioritySpecialPoolOverrun
  188. );
  189. pIrp = (PIRP) (irpPtr);
  190. return pIrp;
  191. }
  192. VOID
  193. FASTCALL
  194. ViIrpAllocateLockedPacket(
  195. IN CCHAR StackSize,
  196. IN BOOLEAN ChargeQuota,
  197. OUT PIOV_REQUEST_PACKET *IovPacket
  198. )
  199. /*++
  200. Description:
  201. This routine allocates an IRP tracked by the verifier. The IRP is allocated
  202. from the special pool and is initialized appropriately. Caller must call
  203. VfPacketReleaseLock to release the lock.
  204. Arguments:
  205. StackSize - Count of stack locations to allocate for this IRP.
  206. ChargeQuote - TRUE if quote should be charged against the current
  207. thread.
  208. IovPacket - Receives verifier request packet (the IRP is
  209. then IovPacket->TrackedIrp), or NULL on error.
  210. Return Value:
  211. None.
  212. --*/
  213. {
  214. PIOV_REQUEST_PACKET iovNewPacket;
  215. PIRP irp;
  216. NTSTATUS status;
  217. ULONG quotaCharge;
  218. PEPROCESS quotaProcess;
  219. *IovPacket = NULL;
  220. irp = VfIrpAllocate(StackSize);
  221. if (irp == NULL) {
  222. return;
  223. }
  224. //
  225. // Make compiler happy and void warning for variable used without being
  226. // initialized even if it is not true.
  227. //
  228. quotaCharge = 0;
  229. quotaProcess = NULL;
  230. if (ChargeQuota) {
  231. quotaCharge = PAGE_SIZE;
  232. quotaProcess = PsGetCurrentProcess();
  233. status = PsChargeProcessNonPagedPoolQuota(
  234. quotaProcess,
  235. quotaCharge
  236. );
  237. if (!NT_SUCCESS(status)) {
  238. VfIrpFree(irp);
  239. return;
  240. }
  241. }
  242. //
  243. // Call this before the IRP has a packet associated with it!
  244. //
  245. IoInitializeIrp(irp, IoSizeOfIrp(StackSize), StackSize);
  246. iovNewPacket = VfPacketCreateAndLock(irp);
  247. if (iovNewPacket == NULL) {
  248. VfIrpFree(irp);
  249. if (ChargeQuota) {
  250. PsReturnProcessNonPagedPoolQuota(
  251. quotaProcess,
  252. quotaCharge
  253. );
  254. }
  255. return;
  256. }
  257. iovNewPacket->Flags |= TRACKFLAG_PROTECTEDIRP | TRACKFLAG_IO_ALLOCATED;
  258. VfPacketReference(iovNewPacket, IOVREFTYPE_POINTER);
  259. irp->Flags |= IRPFLAG_EXAMINE_TRACKED;
  260. irp->AllocationFlags |= IRP_ALLOCATION_MONITORED;
  261. if (ChargeQuota) {
  262. irp->AllocationFlags |= IRP_QUOTA_CHARGED;
  263. iovNewPacket->QuotaCharge = quotaCharge;
  264. iovNewPacket->QuotaProcess = quotaProcess;
  265. ObReferenceObject(quotaProcess);
  266. }
  267. *IovPacket = iovNewPacket;
  268. }
  269. VOID
  270. FASTCALL
  271. VfIrpMakeUntouchable(
  272. IN PIRP Irp OPTIONAL
  273. )
  274. /*++
  275. Description:
  276. This routine makes the surrogate IRP untouchable.
  277. Arguments:
  278. Irp - Pointer to the Irp to make untouchable
  279. Return Value:
  280. None.
  281. --*/
  282. {
  283. if (!Irp) {
  284. return;
  285. }
  286. MmProtectSpecialPool(Irp, PAGE_NOACCESS);
  287. }
  288. VOID
  289. FASTCALL
  290. VfIrpMakeTouchable(
  291. IN PIRP Irp
  292. )
  293. /*++
  294. Description:
  295. This routine makes the an IRP touchable if previously untouchable.
  296. Arguments:
  297. Irp - Pointer to the Irp to make untouchable
  298. Return Value:
  299. None.
  300. --*/
  301. {
  302. MmProtectSpecialPool(Irp, PAGE_READWRITE);
  303. }
  304. VOID
  305. FASTCALL
  306. VfIrpFree(
  307. IN PIRP Irp OPTIONAL
  308. )
  309. /*++
  310. Description:
  311. This routine is called when the call stack has entirely unwound
  312. and the IRP has completed. At this point it is no longer really
  313. useful to hold the surrogate IRP around.
  314. Arguments:
  315. Irp - Pointer to the Irp to free
  316. Return Value:
  317. None.
  318. --*/
  319. {
  320. if (!Irp) {
  321. return;
  322. }
  323. ExFreePool(Irp);
  324. }
  325. VOID
  326. FASTCALL
  327. VerifierIoAllocateIrp1(
  328. IN CCHAR StackSize,
  329. IN BOOLEAN ChargeQuota,
  330. IN OUT PIRP *IrpPointer
  331. )
  332. /*++
  333. Description:
  334. This routine is called by IoAllocateIrp and returns an IRP iff
  335. we are handled the allocations ourselves.
  336. We may need to do this internally so we can turn off IRP lookaside lists
  337. and use the special pool to catch people reusing free'd IRPs.
  338. Arguments:
  339. StackSize - Count of stack locations to allocate for this IRP.
  340. ChargeQuote - TRUE if quote should be charged against the current
  341. thread.
  342. IrpPointer - Pointer to IRP if one was allocated. This will
  343. point to NULL after the call iff IoAllocateIrp
  344. should use it's normal lookaside list code.
  345. Return Value:
  346. None.
  347. --*/
  348. {
  349. PIOV_REQUEST_PACKET iovPacket;
  350. ULONG stackHash;
  351. *IrpPointer = NULL;
  352. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_MONITOR_IRP_ALLOCS)) {
  353. return;
  354. }
  355. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_POLICE_IRPS)) {
  356. return;
  357. }
  358. //
  359. // Allocate a new IRP and the associated verification data.
  360. //
  361. ViIrpAllocateLockedPacket(StackSize, ChargeQuota, &iovPacket);
  362. if (iovPacket == NULL) {
  363. return;
  364. }
  365. //
  366. // Update the pointer.
  367. //
  368. *IrpPointer = iovPacket->TrackedIrp;
  369. //
  370. // Record he who allocated this IRP (if we can get it)
  371. //
  372. RtlCaptureStackBackTrace(1, IRP_ALLOC_COUNT, iovPacket->AllocatorStack, &stackHash);
  373. VfPacketLogEntry(
  374. iovPacket,
  375. IOV_EVENT_IO_ALLOCATE_IRP,
  376. iovPacket->AllocatorStack[0],
  377. (ULONG_PTR) iovPacket->AllocatorStack[2]
  378. );
  379. VfPacketReleaseLock(iovPacket);
  380. }
  381. VOID
  382. FASTCALL
  383. VerifierIoAllocateIrp2(
  384. IN PIRP Irp
  385. )
  386. /*++
  387. Description:
  388. This routine is called by IoAllocateIrp and captures information if
  389. the IRP was allocated by the OS.
  390. Arguments:
  391. Irp - Pointer to IRP
  392. Return Value:
  393. None.
  394. --*/
  395. {
  396. PIOV_REQUEST_PACKET iovPacket;
  397. ULONG stackHash;
  398. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_MONITOR_IRP_ALLOCS)) {
  399. return;
  400. }
  401. iovPacket = VfPacketCreateAndLock(Irp);
  402. if (iovPacket == NULL) {
  403. return;
  404. }
  405. VfPacketReference(iovPacket, IOVREFTYPE_POINTER);
  406. iovPacket->Flags |= TRACKFLAG_IO_ALLOCATED;
  407. Irp->AllocationFlags |= IRP_ALLOCATION_MONITORED;
  408. Irp->Flags |= IRPFLAG_EXAMINE_TRACKED;
  409. //
  410. // Record he who allocated this IRP (if we can get it)
  411. //
  412. RtlCaptureStackBackTrace(1, IRP_ALLOC_COUNT, iovPacket->AllocatorStack, &stackHash);
  413. VfPacketLogEntry(
  414. iovPacket,
  415. IOV_EVENT_IO_ALLOCATE_IRP,
  416. iovPacket->AllocatorStack[0],
  417. (ULONG_PTR) iovPacket->AllocatorStack[2]
  418. );
  419. VfPacketReleaseLock(iovPacket);
  420. }
  421. VOID
  422. FASTCALL
  423. VerifierIoFreeIrp(
  424. IN PIRP Irp,
  425. IN OUT PBOOLEAN FreeHandled
  426. )
  427. /*++
  428. Description:
  429. This routine is called by IoFreeIrp and returns TRUE iff
  430. the free was handled internally here (in which case IoFreeIrp
  431. should do nothing).
  432. We need to handle the call internally because we may turn off lookaside
  433. list cacheing to catch people reusing IRPs after they are freed.
  434. Arguments:
  435. Irp - A pointer to the IRP passed into
  436. IoCancelIrp.
  437. FreeHandled - Indicates whether the free operation was
  438. handled entirely by this routine.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. PIOV_REQUEST_PACKET iovPacket;
  444. PVOID callerAddress;
  445. ULONG stackHash;
  446. iovPacket = VfPacketFindAndLock(Irp);
  447. if (iovPacket == NULL) {
  448. //
  449. // The below assertion might fire if an IRP allocated then freed twice.
  450. // Normally we won't even survive the assert as the IRP would have been
  451. // allocated from special pool.
  452. //
  453. ASSERT(!(Irp->AllocationFlags&IRP_ALLOCATION_MONITORED));
  454. *FreeHandled = FALSE;
  455. return;
  456. }
  457. VfPacketLogEntry(
  458. iovPacket,
  459. IOV_EVENT_IO_FREE_IRP,
  460. NULL,
  461. 0
  462. );
  463. if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
  464. callerAddress = NULL;
  465. }
  466. if (!IsListEmpty(&Irp->ThreadListEntry)) {
  467. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS)) {
  468. WDM_FAIL_ROUTINE((
  469. DCERROR_FREE_OF_THREADED_IRP,
  470. DCPARAM_IRP + DCPARAM_ROUTINE,
  471. callerAddress,
  472. Irp
  473. ));
  474. }
  475. //
  476. // <Grumble> keep us alive by not actually freeing the IRP if someone did
  477. // this to us. We leak for life...
  478. //
  479. *FreeHandled = TRUE;
  480. return;
  481. }
  482. if (VfPacketGetCurrentSessionData(iovPacket)) {
  483. //
  484. // If there's a current session, that means someone is freeing an IRP
  485. // that they don't own. Of course, if the stack unwound badly because
  486. // someone forgot to return PENDING or complete the IRP, then we don't
  487. // assert here (we'd probably end up blaiming kernel).
  488. //
  489. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  490. (!(iovPacket->Flags&TRACKFLAG_UNWOUND_BADLY))) {
  491. WDM_FAIL_ROUTINE((
  492. DCERROR_FREE_OF_INUSE_IRP,
  493. DCPARAM_IRP + DCPARAM_ROUTINE,
  494. callerAddress,
  495. Irp
  496. ));
  497. }
  498. //
  499. // <Grumble> keep us alive by not actually freeing the IRP if someone did
  500. // this to us. We leak for life...
  501. //
  502. VfPacketReleaseLock(iovPacket);
  503. *FreeHandled = TRUE;
  504. return;
  505. }
  506. if (!(iovPacket->Flags&TRACKFLAG_IO_ALLOCATED)) {
  507. //
  508. // We weren't tracking this at allocation time. We shouldn't got our
  509. // packet unless the IRP had a pointer count still, meaning it's has
  510. // a session. And that should've been caught above.
  511. //
  512. ASSERT(0);
  513. VfPacketReleaseLock(iovPacket);
  514. *FreeHandled = FALSE;
  515. return;
  516. }
  517. //
  518. // The IRP may have been reinitialized, possibly losing it's allocation
  519. // flags. We catch this bug in the IoInitializeIrp hook.
  520. //
  521. //ASSERT(Irp->AllocationFlags&IRP_ALLOCATION_MONITORED);
  522. //
  523. if (!(iovPacket->Flags&TRACKFLAG_PROTECTEDIRP)) {
  524. //
  525. // We're just tagging along this IRP. Drop our pointer count but bail.
  526. //
  527. VfPacketDereference(iovPacket, IOVREFTYPE_POINTER);
  528. VfPacketReleaseLock(iovPacket);
  529. *FreeHandled = FALSE;
  530. return;
  531. }
  532. //
  533. // Set up a nice bugcheck for those who free their IRPs twice. This is done
  534. // because the special pool may have been exhausted, in which case the IRP
  535. // can be touched after it has been freed.
  536. //
  537. Irp->Type = 0;
  538. ASSERT(iovPacket);
  539. ASSERT(VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS));
  540. //
  541. // Release any quota we charged.
  542. //
  543. if (Irp->AllocationFlags & IRP_QUOTA_CHARGED) {
  544. PsReturnProcessNonPagedPoolQuota(
  545. iovPacket->QuotaProcess,
  546. iovPacket->QuotaCharge
  547. );
  548. ObDereferenceObject(iovPacket->QuotaProcess);
  549. }
  550. VfPacketDereference(iovPacket, IOVREFTYPE_POINTER);
  551. ASSERT(iovPacket->PointerCount == 0);
  552. VfPacketReleaseLock(iovPacket);
  553. VfIrpFree(Irp);
  554. //
  555. // We handled allocation and initialization. There is nothing much more to
  556. // do.
  557. //
  558. *FreeHandled = TRUE;
  559. }
  560. VOID
  561. FASTCALL
  562. VerifierIoInitializeIrp(
  563. IN OUT PIRP Irp,
  564. IN USHORT PacketSize,
  565. IN CCHAR StackSize,
  566. IN OUT PBOOLEAN InitializeHandled
  567. )
  568. /*++
  569. Description:
  570. This routine is called by IoInitializeIrp and sets InitializeHandled to
  571. TRUE if the entire initialization was handled internally.
  572. While here we verify the caller is not Initializing an IRP allocated
  573. through IoAllocateIrp, as doing so means we may leak quota/etc.
  574. Arguments:
  575. Irp - Irp to initialize
  576. PacketSize - Size of the IRP in bytes.
  577. StackSize - Count of stack locations for this IRP.
  578. InitializeHandled - Pointer to a BOOLEAN that will be set to true iff
  579. the initialization of the IRP was handled entirely
  580. within this routine. If FALSE, IoInitializeIrp
  581. should initialize the IRP as normal.
  582. ADRIAO N.B. 06/16/2000 - As currently coded in iomgr\ioverifier.c, this
  583. function is expected to set InitializeHandled to
  584. FALSE!
  585. Return Value:
  586. None.
  587. --*/
  588. {
  589. PIOV_REQUEST_PACKET iovPacket;
  590. PVOID callerAddress;
  591. ULONG stackHash;
  592. UNREFERENCED_PARAMETER (PacketSize);
  593. UNREFERENCED_PARAMETER (StackSize);
  594. iovPacket = VfPacketFindAndLock(Irp);
  595. if (iovPacket == NULL) {
  596. *InitializeHandled = FALSE;
  597. return;
  598. }
  599. if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
  600. callerAddress = NULL;
  601. }
  602. if (VfSettingsIsOptionEnabled(iovPacket->VerifierSettings, VERIFIER_OPTION_POLICE_IRPS) &&
  603. (iovPacket->Flags&TRACKFLAG_IO_ALLOCATED)) {
  604. if (Irp->AllocationFlags&IRP_QUOTA_CHARGED) {
  605. //
  606. // Don't let us leak quota now!
  607. //
  608. WDM_FAIL_ROUTINE((
  609. DCERROR_REINIT_OF_ALLOCATED_IRP_WITH_QUOTA,
  610. DCPARAM_IRP + DCPARAM_ROUTINE,
  611. callerAddress,
  612. Irp
  613. ));
  614. } else {
  615. //
  616. // In this case we are draining our lookaside lists erroneously.
  617. //
  618. // WDM_CHASTISE_CALLER2(
  619. // (DCERROR_REINIT_OF_ALLOCATED_IRP_WITHOUT_QUOTA, DCPARAM_IRP, Irp)
  620. // );
  621. }
  622. }
  623. *InitializeHandled = FALSE;
  624. VfPacketReleaseLock(iovPacket);
  625. }
  626. BOOLEAN
  627. VfIrpSendSynchronousIrp(
  628. IN PDEVICE_OBJECT DeviceObject,
  629. IN PIO_STACK_LOCATION TopStackLocation,
  630. IN BOOLEAN Untouchable,
  631. IN NTSTATUS InitialStatus,
  632. IN ULONG_PTR InitialInformation OPTIONAL,
  633. OUT ULONG_PTR *FinalInformation OPTIONAL,
  634. OUT NTSTATUS *FinalStatus OPTIONAL
  635. )
  636. /*++
  637. Routine Description:
  638. This function sends a synchronous irp to the top level device
  639. object which roots on DeviceObject.
  640. Parameters:
  641. DeviceObject - Supplies the device object of the device being removed.
  642. TopStackLocation - Supplies a pointer to the parameter block for the irp.
  643. Untouchable - TRUE iff IRP should be marked untouchable (ie status and
  644. information should be left alone by target.)
  645. InitialStatus - Initial value for the IRPs status field.
  646. InitialInformation - Initial value for the IRPs information field.
  647. FinalInformation - Receives final result of information field, or NULL if
  648. IRP could not be allocated.
  649. FinalStatus - Receives final status for sent IRP, or STATUS_SUCCESS if IRP
  650. could not be allocated.
  651. Return Value:
  652. TRUE iff IRP was sent, FALSE if IRP could not be sent due to low resources.
  653. --*/
  654. {
  655. PIRP irp;
  656. PIO_STACK_LOCATION irpSp;
  657. KEVENT event;
  658. NTSTATUS status;
  659. PDEVICE_OBJECT topDeviceObject;
  660. PAGED_CODE();
  661. //
  662. // Preinit for failure
  663. //
  664. if (ARGUMENT_PRESENT(FinalInformation)) {
  665. *FinalInformation = 0;
  666. }
  667. if (ARGUMENT_PRESENT(FinalStatus)) {
  668. *FinalStatus = STATUS_SUCCESS;
  669. }
  670. //
  671. // Get a pointer to the topmost device object in the stack of devices,
  672. // beginning with the deviceObject.
  673. //
  674. topDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
  675. //
  676. // Begin by allocating the IRP for this request. Do not charge quota to
  677. // the current process for this IRP.
  678. //
  679. irp = IoAllocateIrp(topDeviceObject->StackSize, FALSE);
  680. if (irp == NULL){
  681. ObDereferenceObject(topDeviceObject);
  682. return FALSE;
  683. }
  684. if (Untouchable) {
  685. SPECIALIRP_WATERMARK_IRP(irp, IRP_BOGUS);
  686. }
  687. //
  688. // Initialize the IRP
  689. //
  690. irp->IoStatus.Status = InitialStatus;
  691. irp->IoStatus.Information = InitialInformation;
  692. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  693. //
  694. // Get a pointer to the stack location of the first driver which will be
  695. // invoked. This is where the function codes and parameters are set.
  696. //
  697. irpSp = IoGetNextIrpStackLocation(irp);
  698. //
  699. // Copy in the caller-supplied stack location contents
  700. //
  701. *irpSp = *TopStackLocation;
  702. //
  703. // Set a top level completion routine.
  704. //
  705. IoSetCompletionRoutine(
  706. irp,
  707. ViIrpSynchronousCompletionRoutine,
  708. (PVOID) &event,
  709. TRUE,
  710. TRUE,
  711. TRUE
  712. );
  713. //
  714. // Call the driver
  715. //
  716. status = IoCallDriver(topDeviceObject, irp);
  717. ObDereferenceObject(topDeviceObject);
  718. //
  719. // If a driver returns STATUS_PENDING, we will wait for it to complete
  720. //
  721. if (status == STATUS_PENDING) {
  722. KeWaitForSingleObject(
  723. &event,
  724. Executive,
  725. KernelMode,
  726. FALSE,
  727. (PLARGE_INTEGER) NULL
  728. );
  729. status = irp->IoStatus.Status;
  730. }
  731. if (ARGUMENT_PRESENT(FinalStatus)) {
  732. *FinalStatus = status;
  733. }
  734. if (ARGUMENT_PRESENT(FinalInformation)) {
  735. *FinalInformation = irp->IoStatus.Information;
  736. }
  737. IoFreeIrp(irp);
  738. return TRUE;
  739. }
  740. NTSTATUS
  741. ViIrpSynchronousCompletionRoutine(
  742. IN PDEVICE_OBJECT DeviceObject,
  743. IN PIRP Irp,
  744. IN PVOID Context
  745. )
  746. {
  747. UNREFERENCED_PARAMETER(DeviceObject);
  748. UNREFERENCED_PARAMETER(Irp);
  749. KeSetEvent((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
  750. return STATUS_MORE_PROCESSING_REQUIRED;
  751. }
  752. VOID
  753. FASTCALL
  754. VfIrpWatermark(
  755. IN PIRP Irp,
  756. IN ULONG Flags
  757. )
  758. {
  759. PIOV_REQUEST_PACKET iovPacket;
  760. iovPacket = VfPacketFindAndLock(Irp);
  761. if (iovPacket == NULL) {
  762. return;
  763. }
  764. if (Flags & IRP_SYSTEM_RESTRICTED) {
  765. //
  766. // Note that calling this function is not in itself enough to get the
  767. // system to prevent drivers from sending restricted IRPs. Those IRPs to
  768. // be protected must also be added to the system restricted callbacks
  769. // registered by VfMajorRegisterHandlers.
  770. //
  771. iovPacket->Flags |= TRACKFLAG_WATERMARKED;
  772. }
  773. if (Flags & IRP_BOGUS) {
  774. iovPacket->Flags |= TRACKFLAG_BOGUS;
  775. }
  776. VfPacketReleaseLock(iovPacket);
  777. }