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.

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