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.

1166 lines
22 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. block.c
  5. Abstract:
  6. This module implements block management functions.
  7. Author:
  8. Manny Weiser (mannyw) 12-29-91
  9. Revision History:
  10. --*/
  11. #include "mup.h"
  12. //
  13. // The debug trace level
  14. //
  15. #define Dbg (DEBUG_TRACE_BLOCK)
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text( PAGE, MupAllocateMasterIoContext )
  18. #pragma alloc_text( PAGE, MupAllocateMasterQueryContext )
  19. #pragma alloc_text( PAGE, MupAllocatePrefixEntry )
  20. #pragma alloc_text( PAGE, MupAllocateUncProvider )
  21. #pragma alloc_text( PAGE, MupCalculateTimeout )
  22. #pragma alloc_text( PAGE, MupCloseUncProvider )
  23. #pragma alloc_text( PAGE, MupCreateCcb )
  24. #pragma alloc_text( PAGE, MupCreateFcb )
  25. #pragma alloc_text( PAGE, MupDereferenceVcb )
  26. #pragma alloc_text( INIT, MupInitializeVcb )
  27. #endif
  28. VOID
  29. MupInitializeVcb(
  30. IN PVCB Vcb
  31. )
  32. /*++
  33. Routine Description:
  34. The routine initializes the VCB for the MUP.
  35. Arguments:
  36. VCB - A pointer to the MUP VCB.
  37. Return Value:
  38. None.
  39. --*/
  40. {
  41. PAGED_CODE();
  42. DebugTrace(+1, Dbg, "MupInitializeVcb\n", 0);
  43. RtlZeroMemory( Vcb, sizeof( VCB ) );
  44. Vcb->BlockHeader.BlockType = BlockTypeVcb;
  45. Vcb->BlockHeader.BlockState = BlockStateActive;
  46. Vcb->BlockHeader.ReferenceCount = 1;
  47. Vcb->BlockHeader.BlockSize = sizeof( VCB );
  48. DebugTrace(-1, Dbg, "MupInitializeVcb -> VOID\n", 0);
  49. }
  50. VOID
  51. MupDereferenceVcb(
  52. PVCB Vcb
  53. )
  54. {
  55. LONG result;
  56. PAGED_CODE();
  57. DebugTrace( +1, Dbg, "MupDereferenceVcb\n", 0 );
  58. result = InterlockedDecrement(
  59. &Vcb->BlockHeader.ReferenceCount
  60. );
  61. DebugTrace( 0, Dbg, "ReferenceCount = %d\n", Vcb->BlockHeader.ReferenceCount );
  62. if ( result == 0 ) {
  63. KeBugCheckEx( FILE_SYSTEM, 3, 0, 0, 0 );
  64. }
  65. DebugTrace( -1, Dbg, "MupDereferenceVcb -> VOID\n", 0 );
  66. }
  67. PFCB
  68. MupCreateFcb(
  69. VOID
  70. )
  71. /*++
  72. Routine Description:
  73. This routine allocates an FCB block
  74. Arguments:
  75. None.
  76. Return Value:
  77. A pointer to the allocated FCB.
  78. --*/
  79. {
  80. PFCB fcb;
  81. PAGED_CODE();
  82. DebugTrace( +1, Dbg, "MupCreateFcb\n", 0 );
  83. //
  84. // Attempt to allocate memory.
  85. //
  86. fcb = ExAllocatePoolWithTag(
  87. PagedPool,
  88. sizeof(FCB),
  89. ' puM');
  90. if (fcb == NULL) {
  91. return NULL;
  92. }
  93. //
  94. // Initialize the UNC provider block header
  95. //
  96. fcb->BlockHeader.BlockType = BlockTypeFcb;
  97. fcb->BlockHeader.BlockState = BlockStateActive;
  98. fcb->BlockHeader.ReferenceCount = 1;
  99. fcb->BlockHeader.BlockSize = sizeof( FCB );
  100. InitializeListHead( &fcb->CcbList );
  101. DebugTrace( -1, Dbg, "MupCreateFcb -> 0x%8lx\n", fcb );
  102. return fcb;
  103. }
  104. VOID
  105. MupDereferenceFcb(
  106. PFCB Fcb
  107. )
  108. {
  109. LONG result;
  110. ASSERT( Fcb->BlockHeader.BlockType == BlockTypeFcb );
  111. DebugTrace( +1, Dbg, "MupDereferenceFcb\n", 0 );
  112. result = InterlockedDecrement(
  113. &Fcb->BlockHeader.ReferenceCount
  114. );
  115. DebugTrace( 0, Dbg, "ReferenceCount = %d\n", Fcb->BlockHeader.ReferenceCount);
  116. if ( result == 0 ) {
  117. ASSERT( IsListEmpty( &Fcb->CcbList ) );
  118. MupFreeFcb( Fcb );
  119. }
  120. DebugTrace( -1, Dbg, "MupDereferenceFcb -> VOID\n", 0 );
  121. }
  122. VOID
  123. MupFreeFcb(
  124. PFCB Fcb
  125. )
  126. /*++
  127. Routine Description:
  128. This routine frees an FCB block
  129. Arguments:
  130. A pointer to the FCB block to free.
  131. Return Value:
  132. None.
  133. --*/
  134. {
  135. DebugTrace( +1, Dbg, "MupFreeFcb\n", 0 );
  136. ASSERT( Fcb->BlockHeader.BlockType == BlockTypeFcb );
  137. ExFreePool( Fcb );
  138. DebugTrace( -1, Dbg, "MupFreeFcb -> VOID\n", 0 );
  139. }
  140. PCCB
  141. MupCreateCcb(
  142. VOID
  143. )
  144. /*++
  145. Routine Description:
  146. This routine allocates an CCB block
  147. Arguments:
  148. None.
  149. Return Value:
  150. A pointer to the allocated CCB.
  151. --*/
  152. {
  153. PCCB ccb;
  154. PAGED_CODE();
  155. DebugTrace( +1, Dbg, "MupCreateCcb\n", 0 );
  156. //
  157. // Attempt to allocate memory.
  158. //
  159. ccb = ExAllocatePoolWithTag(
  160. PagedPool,
  161. sizeof(CCB),
  162. ' puM');
  163. if (ccb == NULL) {
  164. return NULL;
  165. }
  166. //
  167. // Initialize the UNC provider block header
  168. //
  169. ccb->BlockHeader.BlockType = BlockTypeCcb;
  170. ccb->BlockHeader.BlockState = BlockStateActive;
  171. ccb->BlockHeader.ReferenceCount = 1;
  172. ccb->BlockHeader.BlockSize = sizeof( CCB );
  173. DebugTrace( -1, Dbg, "MupCreateCcb -> 0x%8lx\n", ccb );
  174. return ccb;
  175. }
  176. VOID
  177. MupDereferenceCcb(
  178. PCCB Ccb
  179. )
  180. {
  181. LONG result;
  182. DebugTrace( +1, Dbg, "MupDereferenceCcb\n", 0 );
  183. ASSERT( Ccb->BlockHeader.BlockType == BlockTypeCcb );
  184. result = InterlockedDecrement(
  185. &Ccb->BlockHeader.ReferenceCount
  186. );
  187. DebugTrace( 0, Dbg, "ReferenceCount = %d\n", Ccb->BlockHeader.ReferenceCount );
  188. if ( result == 0 ) {
  189. ACQUIRE_LOCK( &MupCcbListLock );
  190. RemoveEntryList( &Ccb->ListEntry );
  191. RELEASE_LOCK( &MupCcbListLock );
  192. //
  193. // Release our references then free the CCB.
  194. //
  195. ObDereferenceObject( Ccb->FileObject );
  196. MupDereferenceFcb( Ccb->Fcb );
  197. MupFreeCcb( Ccb );
  198. }
  199. DebugTrace( -1, Dbg, "MupDereferenceCcb -> VOID\n", 0 );
  200. }
  201. VOID
  202. MupFreeCcb(
  203. PCCB Ccb
  204. )
  205. /*++
  206. Routine Description:
  207. This routine frees a CCB block
  208. Arguments:
  209. A pointer to the CCB block to free.
  210. Return Value:
  211. None.
  212. --*/
  213. {
  214. DebugTrace( +1, Dbg, "MupFreeCcb\n", 0 );
  215. ASSERT( Ccb->BlockHeader.BlockType == BlockTypeCcb );
  216. ExFreePool( Ccb );
  217. DebugTrace( -1, Dbg, "MupFreeCcb -> VOID\n", 0 );
  218. }
  219. PUNC_PROVIDER
  220. MupAllocateUncProvider(
  221. ULONG DataLength
  222. )
  223. /*++
  224. Routine Description:
  225. The routine allocates and initializes the VCB for the MUP.
  226. Arguments:
  227. DataLength - The size (in bytes) of the UNC provider.
  228. Return Value:
  229. None.
  230. --*/
  231. {
  232. PUNC_PROVIDER uncProvider;
  233. ULONG size;
  234. PAGED_CODE();
  235. DebugTrace(+1, Dbg, "MupAllocateUncProvider\n", 0);
  236. size = DataLength + sizeof( UNC_PROVIDER );
  237. uncProvider = ExAllocatePoolWithTag(
  238. PagedPool,
  239. size,
  240. ' puM');
  241. if (uncProvider != NULL) {
  242. //
  243. // Initialize the UNC provider block header
  244. //
  245. uncProvider->BlockHeader.BlockType = BlockTypeUncProvider;
  246. uncProvider->BlockHeader.BlockState = BlockStateActive;
  247. uncProvider->BlockHeader.ReferenceCount = 0;
  248. uncProvider->BlockHeader.BlockSize = size;
  249. //
  250. // By default we will make the provider unregistered
  251. //
  252. uncProvider->Registered = FALSE;
  253. }
  254. DebugTrace(-1, Dbg, "MupAllocateUncProvider -> 0x%8lx\n", uncProvider);
  255. return uncProvider;
  256. }
  257. VOID
  258. MupDereferenceUncProvider(
  259. PUNC_PROVIDER UncProvider
  260. )
  261. /*++
  262. Routine Description:
  263. The routine dereference a UNC provider block.
  264. Arguments:
  265. UncProvider - A pointer to the UNC provider block.
  266. Return Value:
  267. None.
  268. --*/
  269. {
  270. LONG result;
  271. DebugTrace(+1, Dbg, "MupDereferenceProvider\n", 0);
  272. ASSERT( UncProvider->BlockHeader.BlockType == BlockTypeUncProvider );
  273. result = InterlockedDecrement(
  274. &UncProvider->BlockHeader.ReferenceCount
  275. );
  276. DebugTrace(0, Dbg, "ReferenceCount = %d\n", UncProvider->BlockHeader.ReferenceCount);
  277. ASSERT( result >= 0 );
  278. //
  279. // Do not free this block, even if the result is zero. This
  280. // saves us from having to reread information for this provider
  281. // from the registry when the provider re-registers.
  282. //
  283. DebugTrace(-1, Dbg, "MupDereferenceUncProvider -> VOID\n", 0);
  284. }
  285. VOID
  286. MupCloseUncProvider(
  287. PUNC_PROVIDER UncProvider
  288. )
  289. /*++
  290. Routine Description:
  291. The routine closes a UNC provider block.
  292. Arguments:
  293. UncProvider - A pointer to the UNC provider block.
  294. Return Value:
  295. None.
  296. --*/
  297. {
  298. PAGED_CODE();
  299. DebugTrace(+1, Dbg, "MupDereferenceProvider\n", 0);
  300. ASSERT( UncProvider->BlockHeader.BlockType == BlockTypeUncProvider );
  301. MupAcquireGlobalLock();
  302. if ( UncProvider->BlockHeader.BlockState == BlockStateActive ) {
  303. DebugTrace(0, Dbg, "Closing UNC provider %08lx\n", UncProvider );
  304. UncProvider->BlockHeader.BlockState = BlockStateClosing;
  305. //
  306. // Mark the provider as unregistered
  307. //
  308. UncProvider->Registered = FALSE;
  309. MupReleaseGlobalLock();
  310. //
  311. // Close our handle to the provider, and release our reference
  312. // to the file object.
  313. //
  314. if (UncProvider->FileObject != NULL) {
  315. ZwClose( UncProvider->Handle );
  316. ObDereferenceObject( UncProvider->FileObject );
  317. }
  318. } else {
  319. MupReleaseGlobalLock();
  320. }
  321. DebugTrace(-1, Dbg, "MupDereferenceUncProvider -> VOID\n", 0);
  322. }
  323. PKNOWN_PREFIX
  324. MupAllocatePrefixEntry(
  325. ULONG DataLength
  326. )
  327. /*++
  328. Routine Description:
  329. The routine allocates known prefix block.
  330. Arguments:
  331. DataLength - The size (in bytes) of the extra data to allocate in the
  332. buffer for the prefix buffer.
  333. Return Value:
  334. A pointer to the newly allocated block or NULL if it could not be
  335. allocated.
  336. --*/
  337. {
  338. PKNOWN_PREFIX knownPrefix;
  339. ULONG size;
  340. PAGED_CODE();
  341. DebugTrace(+1, Dbg, "MupAllocatePrefixEntry\n", 0);
  342. size = DataLength + sizeof( KNOWN_PREFIX );
  343. knownPrefix = ExAllocatePoolWithTag(
  344. PagedPool,
  345. size,
  346. ' puM');
  347. if (knownPrefix == NULL) {
  348. return NULL;
  349. }
  350. RtlZeroMemory( knownPrefix, size );
  351. //
  352. // Initialize the UNC provider block header
  353. //
  354. knownPrefix->BlockHeader.BlockType = BlockTypeKnownPrefix;
  355. knownPrefix->BlockHeader.BlockState = BlockStateActive;
  356. knownPrefix->BlockHeader.ReferenceCount = 1;
  357. knownPrefix->BlockHeader.BlockSize = size;
  358. if ( DataLength > 0 ) {
  359. knownPrefix->Prefix.Buffer = (PWCH)(knownPrefix + 1);
  360. knownPrefix->Prefix.MaximumLength = (USHORT)DataLength;
  361. } else {
  362. //
  363. // It is up to the caller to really allocate the memory!
  364. //
  365. knownPrefix->PrefixStringAllocated = TRUE;
  366. }
  367. knownPrefix->Active = FALSE;
  368. MupCalculateTimeout( &knownPrefix->LastUsedTime );
  369. DebugTrace(-1, Dbg, "MupAllocatePrefixEntry -> 0x%8lx\n", knownPrefix);
  370. return knownPrefix;
  371. }
  372. VOID
  373. MupDereferenceKnownPrefix(
  374. PKNOWN_PREFIX KnownPrefix
  375. )
  376. /*++
  377. Routine Description:
  378. The routine dereferences a Known prefix block.
  379. *** MupPrefixTableLock assumed held when this routine is called.
  380. Remains held on exit. ***
  381. Arguments:
  382. KnownPrefix - A pointer to the Known prefix block.
  383. Return Value:
  384. None.
  385. --*/
  386. {
  387. LONG result;
  388. DebugTrace(+1, Dbg, "MupDereferenceKnownPrefix\n", 0);
  389. ASSERT( KnownPrefix->BlockHeader.BlockType == BlockTypeKnownPrefix );
  390. result = InterlockedDecrement(
  391. &KnownPrefix->BlockHeader.ReferenceCount
  392. );
  393. DebugTrace(0, Dbg, "ReferenceCount = %d\n", KnownPrefix->BlockHeader.ReferenceCount);
  394. ASSERT( result >= 0 );
  395. if ( result == 0 ) {
  396. //
  397. // Remove the table entry
  398. //
  399. if ( KnownPrefix->InTable ) {
  400. RtlRemoveUnicodePrefix( &MupPrefixTable, &KnownPrefix->TableEntry );
  401. RemoveEntryList(&KnownPrefix->ListEntry);
  402. }
  403. //
  404. // Free the Prefix string.
  405. //
  406. if ( KnownPrefix->PrefixStringAllocated &&
  407. KnownPrefix->Prefix.Buffer != NULL ) {
  408. ExFreePool( KnownPrefix->Prefix.Buffer );
  409. }
  410. //
  411. // Dereference the associated UNC provider
  412. //
  413. if ( KnownPrefix->UncProvider != NULL ) {
  414. MupDereferenceUncProvider( KnownPrefix->UncProvider );
  415. }
  416. //
  417. // Time to free the block
  418. //
  419. MupFreeKnownPrefix( KnownPrefix );
  420. }
  421. DebugTrace( 0, Dbg, "MupDereferenceKnownPrefix -> VOID\n", 0 );
  422. }
  423. VOID
  424. MupFreeKnownPrefix(
  425. PKNOWN_PREFIX KnownPrefix
  426. )
  427. /*++
  428. Routine Description:
  429. This routine frees a known prefix block
  430. Arguments:
  431. A pointer to the known prefix block to free.
  432. Return Value:
  433. None.
  434. --*/
  435. {
  436. DebugTrace( +1, Dbg, "MupFreeKnownPrefix\n", 0 );
  437. ASSERT( KnownPrefix->BlockHeader.BlockType == BlockTypeKnownPrefix );
  438. ExFreePool( KnownPrefix );
  439. DebugTrace( -1, Dbg, "MupFreeKnownPrefix -> VOID\n", 0 );
  440. }
  441. PMASTER_FORWARDED_IO_CONTEXT
  442. MupAllocateMasterIoContext(
  443. VOID
  444. )
  445. /*++
  446. Routine Description:
  447. This routine allocates a master fowarded io context block.
  448. Arguments:
  449. None.
  450. Return Value:
  451. A pointer to the master forwarded context block, or NULL if the
  452. allocation fails
  453. --*/
  454. {
  455. PMASTER_FORWARDED_IO_CONTEXT masterContext;
  456. PAGED_CODE();
  457. DebugTrace( +1, Dbg, "MupAllocateMasterIoContext\n", 0 );
  458. masterContext = ExAllocatePoolWithTag(
  459. NonPagedPool,
  460. sizeof( MASTER_FORWARDED_IO_CONTEXT ),
  461. ' puM');
  462. if (masterContext != NULL) {
  463. //
  464. // Initialize the block header
  465. //
  466. masterContext->BlockHeader.BlockType = BlockTypeMasterIoContext;
  467. masterContext->BlockHeader.BlockState = BlockStateActive;
  468. masterContext->BlockHeader.ReferenceCount = 1;
  469. masterContext->BlockHeader.BlockSize = sizeof( MASTER_FORWARDED_IO_CONTEXT );
  470. }
  471. DebugTrace( -1, Dbg, "MupAllocateWorkContext -> 0x%8lx\n", masterContext );
  472. return masterContext;
  473. }
  474. NTSTATUS
  475. MupDereferenceMasterIoContext(
  476. PMASTER_FORWARDED_IO_CONTEXT MasterContext,
  477. PNTSTATUS Status
  478. )
  479. /*++
  480. Routine Description:
  481. The routine dereferences a Master forwarded io context block.
  482. If the count reaches zero the original IRP is completed.
  483. Arguments:
  484. A pointer to the a master forwarded io context block.
  485. Status for this mini context.
  486. Return Value:
  487. NTSTATUS - OPTIONAL - The status of the original IRP.
  488. --*/
  489. {
  490. int result;
  491. PIRP originalIrp;
  492. NTSTATUS status;
  493. PIO_STACK_LOCATION irpSp;
  494. KIRQL oldIrql;
  495. DebugTrace(+1, Dbg, "MupDereferenceMasterIoContext\n", 0);
  496. DebugTrace( 0, Dbg, "MasterContext = 0x%08lx\n", MasterContext );
  497. ASSERT( MasterContext->BlockHeader.BlockType == BlockTypeMasterIoContext );
  498. //
  499. // If any requests pass then set Irp status to success and leave
  500. // it as success. If they all fail then use the last errorcode.
  501. // To make this work we create the context with an error status.
  502. //
  503. if (Status != NULL) {
  504. //
  505. // We can modify MasterContext because we have it referenced and
  506. // we write 32 bits which is atomic.
  507. //
  508. if (NT_SUCCESS(*Status)) {
  509. MasterContext->SuccessStatus = STATUS_SUCCESS;
  510. } else {
  511. MasterContext->ErrorStatus = *Status;
  512. }
  513. }
  514. DebugTrace(0, Dbg, "ReferenceCount = %d\n", MasterContext->BlockHeader.ReferenceCount);
  515. DebugTrace(0, Dbg, "MasterContext->Status = %8lx\n", MasterContext->ErrorStatus);
  516. result = InterlockedDecrement(
  517. &MasterContext->BlockHeader.ReferenceCount
  518. );
  519. ASSERT( result >= 0 );
  520. if ( result == 0 ) {
  521. //
  522. // Complete the original IRP
  523. //
  524. originalIrp = MasterContext->OriginalIrp;
  525. irpSp = IoGetCurrentIrpStackLocation( originalIrp );
  526. if ( irpSp->MajorFunction == IRP_MJ_WRITE ) {
  527. originalIrp->IoStatus.Information = irpSp->Parameters.Write.Length;
  528. } else {
  529. originalIrp->IoStatus.Information = 0;
  530. }
  531. //
  532. // If any requests pass then set Irp status to success and return
  533. // success. If they all fail then use the last errorcode.
  534. //
  535. if (NT_SUCCESS(MasterContext->SuccessStatus)) {
  536. status = STATUS_SUCCESS;
  537. } else {
  538. status = MasterContext->ErrorStatus;
  539. }
  540. DebugTrace(0, Dbg, "MupCompleteRequest = %8lx\n", status);
  541. MupCompleteRequest( originalIrp, status );
  542. //
  543. // Dereference the FCB
  544. //
  545. MupDereferenceFcb( MasterContext->Fcb );
  546. //
  547. // Free the Master context block
  548. //
  549. MupFreeMasterIoContext( MasterContext );
  550. // return status
  551. } else {
  552. status = STATUS_PENDING;
  553. }
  554. DebugTrace( 0, Dbg, "MupDereferenceMasterIoContext -> %X\n", status );
  555. return status;
  556. }
  557. VOID
  558. MupFreeMasterIoContext(
  559. PMASTER_FORWARDED_IO_CONTEXT MasterContext
  560. )
  561. /*++
  562. Routine Description:
  563. This routine frees a master forwarded io context block.
  564. Arguments:
  565. A pointer to the a master forwarded io context block.
  566. Return Value:
  567. None.
  568. --*/
  569. {
  570. DebugTrace( +1, Dbg, "MupFreeMasterIoContext\n", 0 );
  571. ASSERT( MasterContext->BlockHeader.BlockType == BlockTypeMasterIoContext );
  572. ExFreePool( MasterContext );
  573. DebugTrace( -1, Dbg, "MupFreeMasterIoContext -> VOID\n", 0 );
  574. }
  575. PMASTER_QUERY_PATH_CONTEXT
  576. MupAllocateMasterQueryContext(
  577. VOID
  578. )
  579. /*++
  580. Routine Description:
  581. This routine allocates a master query path context block.
  582. Arguments:
  583. None.
  584. Return Value:
  585. A pointer to the master query path block. If the allocation
  586. fails, NULL is returned.
  587. --*/
  588. {
  589. PMASTER_QUERY_PATH_CONTEXT masterContext;
  590. PAGED_CODE();
  591. DebugTrace( +1, Dbg, "MupAllocateMasterQueryContext\n", 0 );
  592. masterContext = ExAllocatePoolWithTag(
  593. NonPagedPool,
  594. sizeof( MASTER_QUERY_PATH_CONTEXT ),
  595. ' puM');
  596. if (masterContext == NULL) {
  597. return NULL;
  598. }
  599. //
  600. // Initialize the block header
  601. //
  602. masterContext->BlockHeader.BlockType = BlockTypeMasterQueryContext;
  603. masterContext->BlockHeader.BlockState = BlockStateActive;
  604. masterContext->BlockHeader.ReferenceCount = 1;
  605. masterContext->BlockHeader.BlockSize = sizeof( MASTER_QUERY_PATH_CONTEXT );
  606. InitializeListHead(&masterContext->MasterQueryList);
  607. InitializeListHead(&masterContext->QueryList);
  608. INITIALIZE_LOCK(
  609. &masterContext->Lock,
  610. QUERY_CONTEXT_LOCK_LEVEL,
  611. "Master query context lock"
  612. );
  613. DebugTrace( -1, Dbg, "MupAllocateMasterQueryContext -> 0x%8lx\n", masterContext );
  614. return masterContext;
  615. }
  616. NTSTATUS
  617. MupDereferenceMasterQueryContext(
  618. PMASTER_QUERY_PATH_CONTEXT MasterContext
  619. )
  620. /*++
  621. Routine Description:
  622. The routine dereferences a Master query path context block.
  623. If the count reaches zero the original IRP is completed.
  624. Arguments:
  625. A pointer to the a master query path context block.
  626. Return Value:
  627. NTSTATUS - The final create IRP status.
  628. --*/
  629. {
  630. LONG result;
  631. NTSTATUS status;
  632. DebugTrace(+1, Dbg, "MupDereferenceMasterQueryContext\n", 0);
  633. DebugTrace( 0, Dbg, "MasterContext = 0x%08lx\n", MasterContext );
  634. ASSERT( MasterContext->BlockHeader.BlockType == BlockTypeMasterQueryContext );
  635. MupAcquireGlobalLock();
  636. result = --MasterContext->BlockHeader.ReferenceCount;
  637. MupReleaseGlobalLock();
  638. DebugTrace(0, Dbg, "ReferenceCount = %d\n", MasterContext->BlockHeader.ReferenceCount);
  639. ASSERT( result >= 0 );
  640. if ( result == 0 ) {
  641. BOOLEAN fActive;
  642. if (MasterContext->OriginalIrp == NULL) {
  643. DbgPrint("OriginalIrp == NULL, MasterContext=0x%x\n", MasterContext);
  644. KeBugCheck( FILE_SYSTEM );
  645. }
  646. // we are done with this master query so remove it from the global list
  647. MupAcquireGlobalLock();
  648. RemoveEntryList(&MasterContext->MasterQueryList);
  649. MupReleaseGlobalLock();
  650. ACQUIRE_LOCK( &MupPrefixTableLock );
  651. fActive = MasterContext->KnownPrefix->Active;
  652. MupDereferenceKnownPrefix( MasterContext->KnownPrefix );
  653. //
  654. // Reroute the request and complete the original IRP
  655. //
  656. if (( MasterContext->Provider != NULL) &&
  657. ( MasterContext->ErrorStatus == STATUS_SUCCESS )) {
  658. //
  659. // Remove final ref if nothing ended up in the table
  660. //
  661. if (fActive == FALSE) {
  662. MupDereferenceKnownPrefix( MasterContext->KnownPrefix );
  663. }
  664. RELEASE_LOCK( &MupPrefixTableLock );
  665. MUP_TRACE_NORM(TRACE_IRP, MupDereferenceMasterQueryContext_RerouteOpen,
  666. LOGUSTR(MasterContext->Provider->DeviceName)
  667. LOGUSTR(MasterContext->FileObject->FileName)
  668. LOGPTR(MasterContext->OriginalIrp)
  669. LOGPTR(MasterContext->FileObject));
  670. status = MupRerouteOpen(
  671. MasterContext->FileObject,
  672. MasterContext->Provider
  673. );
  674. } else {
  675. if (MasterContext->Provider != NULL) {
  676. MupDereferenceUncProvider(MasterContext->Provider);
  677. }
  678. //
  679. // No provider claimed this open. Dereference the known prefix
  680. // entry and fail the create request.
  681. //
  682. MupDereferenceKnownPrefix( MasterContext->KnownPrefix );
  683. RELEASE_LOCK( &MupPrefixTableLock );
  684. status = MasterContext->ErrorStatus;
  685. }
  686. MUP_TRACE_NORM(TRACE_IRP, MupDereferenceMasterQueryContext_CompleteRequest,
  687. LOGPTR(MasterContext->OriginalIrp)
  688. LOGSTATUS(status));
  689. FsRtlCompleteRequest( MasterContext->OriginalIrp, status );
  690. MasterContext->OriginalIrp = NULL;
  691. MupFreeMasterQueryContext( MasterContext );
  692. } else {
  693. status = STATUS_PENDING;
  694. }
  695. DebugTrace( 0, Dbg, "MupDereferenceMasterQueryContext -> 0x%08lx\n", status );
  696. return status;
  697. }
  698. VOID
  699. MupFreeMasterQueryContext(
  700. PMASTER_QUERY_PATH_CONTEXT MasterContext
  701. )
  702. /*++
  703. Routine Description:
  704. This routine frees a master query path context block.
  705. Arguments:
  706. A pointer to the a master query path context block.
  707. Return Value:
  708. None.
  709. --*/
  710. {
  711. DebugTrace( +1, Dbg, "MupFreeMasterQueryPathContext\n", 0 );
  712. ASSERT( BlockType( MasterContext ) == BlockTypeMasterQueryContext );
  713. DELETE_LOCK( &MasterContext->Lock );
  714. ExFreePool( MasterContext );
  715. DebugTrace( -1, Dbg, "MupFreeMasterQueryPathContext -> VOID\n", 0 );
  716. }
  717. VOID
  718. MupCalculateTimeout(
  719. PLARGE_INTEGER Time
  720. )
  721. /*++
  722. Routine Description:
  723. This routine calculates the an absolute timeout time. This value
  724. equals the current system time plus the MUP timeout time.
  725. Arguments:
  726. A pointer to the time structure.
  727. Return Value:
  728. None.
  729. --*/
  730. {
  731. LARGE_INTEGER now;
  732. PAGED_CODE();
  733. KeQuerySystemTime( &now );
  734. Time->QuadPart = now.QuadPart + MupKnownPrefixTimeout.QuadPart;
  735. return;
  736. }