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.

1314 lines
27 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. strucsup.c
  5. Abstract:
  6. This module implements the mailslot in-memory data structure
  7. manipulation routines.
  8. Author:
  9. Manny Weiser (mannyw) 9-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_STRUCSUP)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text( INIT, MsInitializeVcb )
  19. #pragma alloc_text( INIT, MsCreateRootDcb )
  20. #pragma alloc_text( PAGE, MsCreateCcb )
  21. #pragma alloc_text( PAGE, MsCreateFcb )
  22. #pragma alloc_text( PAGE, MsCreateRootDcbCcb )
  23. #pragma alloc_text( PAGE, MsDeleteCcb )
  24. #pragma alloc_text( PAGE, MsDeleteFcb )
  25. #pragma alloc_text( PAGE, MsDeleteRootDcb )
  26. #pragma alloc_text( PAGE, MsDeleteVcb )
  27. #pragma alloc_text( PAGE, MsDereferenceCcb )
  28. #pragma alloc_text( PAGE, MsDereferenceFcb )
  29. #pragma alloc_text( PAGE, MsDereferenceNode )
  30. #pragma alloc_text( PAGE, MsDereferenceRootDcb )
  31. #pragma alloc_text( PAGE, MsDereferenceVcb )
  32. #pragma alloc_text( PAGE, MsRemoveFcbName )
  33. #pragma alloc_text( PAGE, MsReferenceVcb )
  34. #pragma alloc_text( PAGE, MsReferenceRootDcb )
  35. #endif
  36. WCHAR FileSystemName[] = MSFS_NAME_STRING;
  37. //
  38. // !!! This module allocates all structures containing a resource from
  39. // non-paged pool. The resources is the only field which must be
  40. // allocated from non-paged pool. Consider allocating the resource
  41. // separately for greater efficiency.
  42. //
  43. VOID
  44. MsInitializeVcb (
  45. IN PVCB Vcb
  46. )
  47. /*++
  48. Routine Description:
  49. This routine initializes new Vcb record. The Vcb record "hangs" off the
  50. end of the Msfs device object and must be allocated by our caller.
  51. Arguments:
  52. Vcb - Supplies the address of the Vcb record being initialized.
  53. Return Value:
  54. None.
  55. --*/
  56. {
  57. PAGED_CODE();
  58. DebugTrace(+1, Dbg, "MsInitializeVcb, Vcb = %08lx\n", (ULONG)Vcb);
  59. //
  60. // We start by first zeroing out all of the VCB, this will guarantee
  61. // that any stale data is wiped clean.
  62. //
  63. RtlZeroMemory( Vcb, sizeof(VCB) );
  64. //
  65. // Set the node type code, node byte size, and reference count.
  66. //
  67. Vcb->Header.NodeTypeCode = MSFS_NTC_VCB;
  68. Vcb->Header.NodeByteSize = sizeof(VCB);
  69. Vcb->Header.ReferenceCount = 1;
  70. Vcb->Header.NodeState = NodeStateActive;
  71. //
  72. // Initialize the Volume name
  73. //
  74. Vcb->FileSystemName.Buffer = FileSystemName;
  75. Vcb->FileSystemName.Length = sizeof( FileSystemName ) - sizeof( WCHAR );
  76. Vcb->FileSystemName.MaximumLength = sizeof( FileSystemName );
  77. //
  78. // Initialize the Prefix table
  79. //
  80. RtlInitializeUnicodePrefix( &Vcb->PrefixTable );
  81. //
  82. // Initialize the resource variable for the VCB.
  83. //
  84. ExInitializeResourceLite( &Vcb->Resource );
  85. //
  86. // Record creation time.
  87. //
  88. KeQuerySystemTime (&Vcb->CreationTime);
  89. //
  90. // Return to the caller.
  91. //
  92. DebugTrace(-1, Dbg, "MsInitializeVcb -> VOID\n", 0);
  93. return;
  94. }
  95. VOID
  96. MsDeleteVcb (
  97. IN PVCB Vcb
  98. )
  99. /*++
  100. Routine Description:
  101. This routine removes the VCB record from our in-memory data
  102. structures. It also will remove all associated underlings
  103. (i.e., FCB records).
  104. Arguments:
  105. Vcb - Supplies the Vcb to be removed
  106. Return Value:
  107. None
  108. --*/
  109. {
  110. PAGED_CODE();
  111. DebugTrace(+1, Dbg, "MsDeleteVcb, Vcb = %08lx\n", (ULONG)Vcb);
  112. ASSERT (Vcb->Header.ReferenceCount == 0);
  113. //
  114. // Remove the Root Dcb
  115. //
  116. if (Vcb->RootDcb != NULL) {
  117. ASSERT (Vcb->RootDcb->Header.ReferenceCount == 1 );
  118. MsDereferenceRootDcb ( Vcb->RootDcb );
  119. }
  120. //
  121. // Uninitialize the resource variable for the VCB.
  122. //
  123. ExDeleteResourceLite( &Vcb->Resource );
  124. //
  125. // And zero out the Vcb, this will help ensure that any stale data is
  126. // wiped clean
  127. //
  128. RtlZeroMemory( Vcb, sizeof(VCB) );
  129. //
  130. // Return to the caller.
  131. //
  132. DebugTrace(-1, Dbg, "MsDeleteVcb -> VOID\n", 0);
  133. return;
  134. }
  135. PROOT_DCB
  136. MsCreateRootDcb (
  137. IN PVCB Vcb
  138. )
  139. /*++
  140. Routine Description:
  141. This routine allocates, initializes, and inserts a new root DCB record
  142. into the in memory data structure.
  143. Arguments:
  144. Vcb - Supplies the Vcb to associate the new DCB under
  145. Return Value:
  146. PROOT_DCB - returns pointer to the newly allocated root DCB.
  147. --*/
  148. {
  149. PROOT_DCB rootDcb;
  150. PWCH Name;
  151. PAGED_CODE();
  152. DebugTrace(+1, Dbg, "MsCreateRootDcb, Vcb = %08lx\n", (ULONG)Vcb);
  153. //
  154. // Make sure we don't already have a root dcb for this vcb
  155. //
  156. rootDcb = Vcb->RootDcb;
  157. if (rootDcb != NULL) {
  158. DebugDump("Error trying to create multiple root dcbs\n", 0, Vcb);
  159. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  160. }
  161. //
  162. // Allocate a new DCB and zero its fields.
  163. //
  164. rootDcb = MsAllocateNonPagedPool ( sizeof(DCB), 'DFsM' );
  165. if (rootDcb == NULL) {
  166. return NULL;
  167. }
  168. RtlZeroMemory( rootDcb, sizeof(DCB));
  169. //
  170. // Set the proper node type code, node byte size, and reference count.
  171. //
  172. rootDcb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB;
  173. rootDcb->Header.NodeByteSize = sizeof(ROOT_DCB);
  174. rootDcb->Header.ReferenceCount = 1;
  175. rootDcb->Header.NodeState = NodeStateActive;
  176. //
  177. // The root Dcb has an empty parent dcb links field
  178. //
  179. InitializeListHead( &rootDcb->ParentDcbLinks );
  180. //
  181. // Initialize the notify queues, and the parent dcb queue.
  182. //
  183. InitializeListHead( &rootDcb->Specific.Dcb.NotifyFullQueue );
  184. InitializeListHead( &rootDcb->Specific.Dcb.NotifyPartialQueue );
  185. InitializeListHead( &rootDcb->Specific.Dcb.ParentDcbQueue );
  186. //
  187. // Initizlize spinlock that protects IRP queues that conatin cancelable IRPs.
  188. //
  189. KeInitializeSpinLock (&rootDcb->Specific.Dcb.SpinLock);
  190. //
  191. // Set the full file name
  192. //
  193. Name = MsAllocatePagedPoolCold(2 * sizeof(WCHAR), 'DFsM' );
  194. if (Name == NULL) {
  195. ExFreePool (rootDcb);
  196. return NULL;
  197. }
  198. Name[0] = L'\\';
  199. Name[1] = L'\0';
  200. rootDcb->FullFileName.Buffer = Name;
  201. rootDcb->FullFileName.Length = sizeof (WCHAR);
  202. rootDcb->FullFileName.MaximumLength = 2*sizeof (WCHAR);
  203. rootDcb->LastFileName = rootDcb->FullFileName;
  204. //
  205. // Set the Vcb and give it a pointer to the new root DCB.
  206. //
  207. rootDcb->Vcb = Vcb;
  208. Vcb->RootDcb = rootDcb;
  209. //
  210. // Initialize the resource variable.
  211. //
  212. ExInitializeResourceLite( &(rootDcb->Resource) );
  213. //
  214. // Insert this DCB into the prefix table. No locks needed in initialization phase.
  215. //
  216. if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable,
  217. &rootDcb->FullFileName,
  218. &rootDcb->PrefixTableEntry )) {
  219. DebugDump("Error trying to insert root dcb into prefix table\n", 0, Vcb);
  220. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  221. }
  222. //
  223. // Return to the caller.
  224. //
  225. DebugTrace(-1, Dbg, "MsCreateRootDcb -> %8lx\n", (ULONG)rootDcb);
  226. return rootDcb;
  227. }
  228. VOID
  229. MsDeleteRootDcb (
  230. IN PROOT_DCB RootDcb
  231. )
  232. /*++
  233. Routine Description:
  234. This routine deallocates and removes the ROOT DCB record
  235. from our in-memory data structures. It also will remove all
  236. associated underlings (i.e., Notify queues and child FCB records).
  237. Arguments:
  238. RootDcb - Supplies the ROOT DCB to be removed
  239. Return Value:
  240. None
  241. --*/
  242. {
  243. PLIST_ENTRY links;
  244. PIRP irp;
  245. PAGED_CODE();
  246. DebugTrace(+1, Dbg, "MsDeleteRootDcb, RootDcb = %08lx\n", (ULONG)RootDcb);
  247. //
  248. // We can only delete this record if the reference count is zero.
  249. //
  250. if (RootDcb->Header.ReferenceCount != 0) {
  251. DebugDump("Error deleting RootDcb, Still Open\n", 0, RootDcb);
  252. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  253. }
  254. ASSERT (IsListEmpty (&RootDcb->Specific.Dcb.NotifyFullQueue));
  255. ASSERT (IsListEmpty (&RootDcb->Specific.Dcb.NotifyPartialQueue));
  256. //
  257. // We can only be removed if the no other FCB have us referenced
  258. // as a their parent DCB.
  259. //
  260. if (!IsListEmpty(&RootDcb->Specific.Dcb.ParentDcbQueue)) {
  261. DebugDump("Error deleting RootDcb\n", 0, RootDcb);
  262. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  263. }
  264. //
  265. // Remove the entry from the prefix table, and then remove the full
  266. // file name. No locks needed when unloading.
  267. //
  268. RtlRemoveUnicodePrefix( &RootDcb->Vcb->PrefixTable, &RootDcb->PrefixTableEntry );
  269. ExFreePool( RootDcb->FullFileName.Buffer );
  270. //
  271. // Free up the resource variable.
  272. //
  273. ExDeleteResourceLite( &(RootDcb->Resource) );
  274. //
  275. // Finally deallocate the DCB record.
  276. //
  277. ExFreePool( RootDcb );
  278. //
  279. // Return to the caller.
  280. //
  281. DebugTrace(-1, Dbg, "MsDeleteRootDcb -> VOID\n", 0);
  282. return;
  283. }
  284. NTSTATUS
  285. MsCreateFcb (
  286. IN PVCB Vcb,
  287. IN PDCB ParentDcb,
  288. IN PUNICODE_STRING FileName,
  289. IN PEPROCESS CreatorProcess,
  290. IN ULONG MailslotQuota,
  291. IN ULONG MaximumMessageSize,
  292. OUT PFCB *ppFcb
  293. )
  294. /*++
  295. Routine Description:
  296. This routine allocates, initializes, and inserts a new Fcb record into
  297. the in memory data structures.
  298. Arguments:
  299. Vcb - Supplies the Vcb to associate the new FCB under.
  300. ParentDcb - Supplies the parent dcb that the new FCB is under.
  301. FileName - Supplies the file name of the file relative to the directory
  302. it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
  303. the preceding backslash).
  304. CreatorProcess - Supplies a pointer to our creator process
  305. MailslotQuota - Supplies the initial quota
  306. MaximumMessageSize - Supplies the size of the largest message that
  307. can be written to the mailslot
  308. ppFcb - Returned allocated FCB
  309. Return Value:
  310. NTSTATUS - status of operation
  311. --*/
  312. {
  313. PFCB fcb;
  314. PWCHAR Name;
  315. USHORT Length;
  316. USHORT MaxLength;
  317. NTSTATUS status;
  318. BOOLEAN AddBackSlash = FALSE;
  319. ULONG i;
  320. PAGED_CODE();
  321. DebugTrace(+1, Dbg, "MsCreateFcb\n", 0);
  322. Length = FileName->Length;
  323. MaxLength = Length + sizeof (UNICODE_NULL);
  324. //
  325. // Reject overflow or underflow cases.
  326. //
  327. if (Length < sizeof (WCHAR) || MaxLength < Length) {
  328. return STATUS_INVALID_PARAMETER;
  329. }
  330. if (FileName->Buffer[0] != '\\') {
  331. AddBackSlash = TRUE;
  332. MaxLength += sizeof (WCHAR);
  333. if (MaxLength < sizeof (WCHAR)) {
  334. return STATUS_INVALID_PARAMETER;
  335. }
  336. }
  337. //
  338. // Allocate a new FCB record, and zero its fields.
  339. //
  340. fcb = MsAllocateNonPagedPoolWithQuota( sizeof(FCB), 'fFsM' );
  341. if (fcb == NULL) {
  342. return STATUS_INSUFFICIENT_RESOURCES;
  343. }
  344. RtlZeroMemory( fcb, sizeof(FCB) );
  345. //
  346. // Set the proper node type code, node byte size, and reference count.
  347. //
  348. fcb->Header.NodeTypeCode = MSFS_NTC_FCB;
  349. fcb->Header.NodeByteSize = sizeof(FCB);
  350. fcb->Header.ReferenceCount = 1;
  351. fcb->Header.NodeState = NodeStateActive;
  352. //
  353. // Set the file name.
  354. //
  355. Name = MsAllocatePagedPoolWithQuotaCold( MaxLength, 'NFsM' );
  356. if (Name == NULL) {
  357. MsFreePool (fcb);
  358. return STATUS_INSUFFICIENT_RESOURCES;
  359. }
  360. i = 0;
  361. if (AddBackSlash == TRUE) {
  362. Name[0] = '\\';
  363. i++;
  364. }
  365. RtlCopyMemory (&Name[i], FileName->Buffer, Length);
  366. *(PWCHAR)( (PCHAR)&Name[i] + Length ) = L'\0';
  367. //
  368. // Don't need to call RtlInitUnicodeString if we know the length already. Its just a waste.
  369. //
  370. fcb->FullFileName.Buffer = Name;
  371. fcb->FullFileName.Length = MaxLength - sizeof (WCHAR);
  372. fcb->FullFileName.MaximumLength = MaxLength;
  373. fcb->LastFileName.Buffer = Name + 1;
  374. fcb->LastFileName.Length = MaxLength - 2 * sizeof (WCHAR);
  375. fcb->LastFileName.MaximumLength = MaxLength - sizeof (WCHAR);
  376. //
  377. // Initialize the data queue. This charges the server process for the quota and can fail
  378. // because of that.
  379. //
  380. status = MsInitializeDataQueue( &fcb->DataQueue,
  381. CreatorProcess,
  382. MailslotQuota,
  383. MaximumMessageSize);
  384. if (!NT_SUCCESS (status)) {
  385. MsFreePool (fcb);
  386. MsFreePool (Name);
  387. return status;
  388. }
  389. //
  390. // Acquire exclusive access to the root DCB.
  391. //
  392. MsAcquireExclusiveFcb( (PFCB)ParentDcb );
  393. //
  394. // Insert this FCB into our parent DCB's queue.
  395. //
  396. InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
  397. &fcb->ParentDcbLinks );
  398. MsReleaseFcb( (PFCB)ParentDcb );
  399. //
  400. // Initialize other FCB fields.
  401. //
  402. fcb->ParentDcb = ParentDcb;
  403. fcb->Vcb = Vcb;
  404. MsReferenceVcb (Vcb);
  405. fcb->CreatorProcess = CreatorProcess;
  406. ExInitializeResourceLite( &(fcb->Resource) );
  407. //
  408. // Initialize the CCB queue.
  409. //
  410. InitializeListHead( &fcb->Specific.Fcb.CcbQueue );
  411. //
  412. // Insert this FCB into the prefix table.
  413. //
  414. ASSERT (MsIsAcquiredExclusiveVcb(Vcb));
  415. if (!RtlInsertUnicodePrefix( &Vcb->PrefixTable,
  416. &fcb->FullFileName,
  417. &fcb->PrefixTableEntry )) {
  418. //
  419. // We should not be able to get here because we already looked up the name and found
  420. // it was not there. A failure here is a fatal error.
  421. //
  422. DebugDump("Error trying to name into prefix table\n", 0, fcb);
  423. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  424. }
  425. //
  426. // Return to the caller.
  427. //
  428. DebugTrace(-1, Dbg, "MsCreateFcb -> %08lx\n", (ULONG)fcb);
  429. *ppFcb = fcb;
  430. return STATUS_SUCCESS;
  431. }
  432. VOID
  433. MsRemoveFcbName (
  434. IN PFCB Fcb
  435. )
  436. /*++
  437. Routine Description:
  438. This routine removes the FCB's name from the prefix table and the root DCB. This is done at
  439. cleanup time and in a backout path of create.
  440. Arguments:
  441. Fcb - Supplies the FCB to have its name removed
  442. Return Value:
  443. None
  444. --*/
  445. {
  446. //
  447. // Remove the Fcb from the prefix table. Make sure we hold the VCB lock exclusive.
  448. //
  449. ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb));
  450. RtlRemoveUnicodePrefix( &Fcb->Vcb->PrefixTable, &Fcb->PrefixTableEntry );
  451. //
  452. // Acquire exclusive access to the root DCB.
  453. //
  454. MsAcquireExclusiveFcb( (PFCB) Fcb->ParentDcb );
  455. //
  456. // Remove the Fcb from our parent DCB's queue.
  457. //
  458. RemoveEntryList( &Fcb->ParentDcbLinks );
  459. MsReleaseFcb( (PFCB) Fcb->ParentDcb );
  460. }
  461. VOID
  462. MsDeleteFcb (
  463. IN PFCB Fcb
  464. )
  465. /*++
  466. Routine Description:
  467. This routine deallocates and removes an FCB from our in-memory data
  468. structures. It also will remove all associated underlings.
  469. Arguments:
  470. Fcb - Supplies the FCB to be removed
  471. Return Value:
  472. None
  473. --*/
  474. {
  475. PAGED_CODE();
  476. DebugTrace(+1, Dbg, "MsDeleteFcb, Fcb = %08lx\n", (ULONG)Fcb);
  477. //
  478. // Release the FCB reference to the VCB.
  479. //
  480. MsDereferenceVcb( Fcb->Vcb );
  481. ExFreePool( Fcb->FullFileName.Buffer );
  482. //
  483. // Free up the data queue.
  484. //
  485. MsUninitializeDataQueue(
  486. &Fcb->DataQueue,
  487. Fcb->CreatorProcess
  488. );
  489. //
  490. // If there is a security descriptor on the mailslot then deassign it
  491. //
  492. if (Fcb->SecurityDescriptor != NULL) {
  493. SeDeassignSecurity( &Fcb->SecurityDescriptor );
  494. }
  495. //
  496. // Free up the resource variable.
  497. //
  498. ExDeleteResourceLite( &(Fcb->Resource) );
  499. //
  500. // Finally deallocate the FCB record.
  501. //
  502. ExFreePool( Fcb );
  503. //
  504. // Return to the caller
  505. //
  506. DebugTrace(-1, Dbg, "MsDeleteFcb -> VOID\n", 0);
  507. return;
  508. }
  509. NTSTATUS
  510. MsCreateCcb (
  511. IN PFCB Fcb,
  512. OUT PCCB *ppCcb
  513. )
  514. /*++
  515. Routine Description:
  516. This routine creates a new CCB record.
  517. Arguments:
  518. Fcb - Supplies a pointer to the FCB to which we are attached.
  519. ppCcb - Output for the allocated CCB
  520. Return Value:
  521. NTSTATUS for the operation
  522. --*/
  523. {
  524. PCCB ccb;
  525. PAGED_CODE();
  526. DebugTrace(+1, Dbg, "MsCreateCcb\n", 0);
  527. ASSERT( Fcb->Header.NodeState == NodeStateActive );
  528. //
  529. // Allocate a new CCB record and zero its fields.
  530. //
  531. ccb = MsAllocateNonPagedPoolWithQuota( sizeof(CCB), 'cFsM' );
  532. if (ccb == NULL) {
  533. return STATUS_INSUFFICIENT_RESOURCES;
  534. }
  535. RtlZeroMemory( ccb, sizeof(CCB) );
  536. //
  537. // Set the proper node type code, node byte size, and reference count.
  538. //
  539. ccb->Header.NodeTypeCode = MSFS_NTC_CCB;
  540. ccb->Header.NodeByteSize = sizeof(CCB);
  541. ccb->Header.ReferenceCount = 1;
  542. ccb->Header.NodeState = NodeStateActive;
  543. //
  544. // Insert ourselves in the list of ccb for the fcb, and reference
  545. // the fcb.
  546. //
  547. MsAcquireExclusiveFcb( Fcb );
  548. InsertTailList( &Fcb->Specific.Fcb.CcbQueue, &ccb->CcbLinks );
  549. MsReleaseFcb( Fcb );
  550. ccb->Fcb = Fcb;
  551. MsAcquireGlobalLock();
  552. MsReferenceNode( &Fcb->Header );
  553. MsReleaseGlobalLock();
  554. //
  555. // Initialize the CCB's resource.
  556. //
  557. ExInitializeResourceLite( &ccb->Resource );
  558. //
  559. // Return to the caller.
  560. //
  561. DebugTrace(-1, Dbg, "MsCreateCcb -> %08lx\n", (ULONG)ccb);
  562. *ppCcb = ccb;
  563. return STATUS_SUCCESS;
  564. }
  565. PROOT_DCB_CCB
  566. MsCreateRootDcbCcb (
  567. IN PROOT_DCB RootDcb,
  568. IN PVCB Vcb
  569. )
  570. /*++
  571. Routine Description:
  572. This routine creates a new root DCB CCB record.
  573. Arguments:
  574. Return Value:
  575. PROOT_DCB_CCB - returns a pointer to the newly allocate ROOT_DCB_CCB
  576. --*/
  577. {
  578. PROOT_DCB_CCB ccb;
  579. PAGED_CODE();
  580. DebugTrace(+1, Dbg, "MsCreateRootDcbCcb\n", 0);
  581. //
  582. // Allocate a new root DCB CCB record, and zero it out.
  583. //
  584. ccb = MsAllocateNonPagedPoolWithQuota( sizeof(ROOT_DCB_CCB), 'CFsM' );
  585. if (ccb == NULL) {
  586. return NULL;
  587. }
  588. RtlZeroMemory( ccb, sizeof(ROOT_DCB_CCB) );
  589. //
  590. // Set the proper node type code, node byte size, and reference count.
  591. //
  592. ccb->Header.NodeTypeCode = MSFS_NTC_ROOT_DCB_CCB;
  593. ccb->Header.NodeByteSize = sizeof(ROOT_DCB_CCB);
  594. ccb->Header.ReferenceCount = 1;
  595. ccb->Header.NodeState = NodeStateActive;
  596. ccb->Vcb = Vcb;
  597. MsReferenceVcb (Vcb);
  598. ccb->Dcb = RootDcb;
  599. MsReferenceRootDcb (RootDcb);
  600. //
  601. // Return to the caller.
  602. //
  603. DebugTrace(-1, Dbg, "MsCreateRootDcbCcb -> %08lx\n", (ULONG)ccb);
  604. return ccb;
  605. }
  606. VOID
  607. MsDeleteCcb (
  608. IN PCCB Ccb
  609. )
  610. /*++
  611. Routine Description:
  612. This routine deallocates and removes the specified CCB record
  613. from the our in memory data structures.
  614. Arguments:
  615. Ccb - Supplies the CCB to remove
  616. Return Value:
  617. None
  618. --*/
  619. {
  620. PAGED_CODE();
  621. DebugTrace(+1, Dbg, "MsDeleteCcb, Ccb = %08lx\n", (ULONG)Ccb);
  622. //
  623. // Case on the type of CCB we are deleting.
  624. //
  625. switch (Ccb->Header.NodeTypeCode) {
  626. case MSFS_NTC_CCB:
  627. MsDereferenceFcb( Ccb->Fcb );
  628. ExDeleteResourceLite( &Ccb->Resource );
  629. break;
  630. case MSFS_NTC_ROOT_DCB_CCB:
  631. MsDereferenceRootDcb ( ((PROOT_DCB_CCB)Ccb)->Dcb );
  632. MsDereferenceVcb ( ((PROOT_DCB_CCB)Ccb)->Vcb );
  633. if (((PROOT_DCB_CCB)Ccb)->QueryTemplate != NULL) {
  634. ExFreePool( ((PROOT_DCB_CCB)Ccb)->QueryTemplate );
  635. }
  636. break;
  637. }
  638. //
  639. // Deallocate the Ccb record.
  640. //
  641. ExFreePool( Ccb );
  642. //
  643. // Return to the caller.
  644. //
  645. DebugTrace(-1, Dbg, "MsDeleteCcb -> VOID\n", 0);
  646. return;
  647. }
  648. VOID
  649. MsReferenceVcb (
  650. IN PVCB Vcb
  651. )
  652. /*++
  653. Routine Description:
  654. This routine references a VCB block. If the reference count reaches 2, the driver paging is restored
  655. to normal so that cancelation and DPC routines won't take pagefaults.
  656. Arguments:
  657. Vcb - Supplies the VCB to reference
  658. Return Value:
  659. None
  660. --*/
  661. {
  662. MsAcquireGlobalLock();
  663. MsReferenceNode( &Vcb->Header );
  664. if (Vcb->Header.ReferenceCount == 2) {
  665. //
  666. // Set the driver paging back to normal
  667. //
  668. MmResetDriverPaging(MsReferenceVcb);
  669. }
  670. MsReleaseGlobalLock();
  671. }
  672. VOID
  673. MsReferenceRootDcb (
  674. IN PROOT_DCB RootDcb
  675. )
  676. /*++
  677. Routine Description:
  678. This routine references a root DCB block. If the reference count reaches 2, a reference is placed on the
  679. VCB so that cancelation and DPC routines won't take pagefaults.
  680. Arguments:
  681. Vcb - Supplies the VCB to reference
  682. Return Value:
  683. None
  684. --*/
  685. {
  686. MsAcquireGlobalLock();
  687. MsReferenceNode( &RootDcb->Header );
  688. MsReleaseGlobalLock();
  689. }
  690. VOID
  691. MsDereferenceVcb (
  692. IN PVCB Vcb
  693. )
  694. /*++
  695. Routine Description:
  696. This routine dereferences a VCB block. If the reference count
  697. reaches zero, the block is freed.
  698. Arguments:
  699. Vcb - Supplies the VCB to dereference
  700. Return Value:
  701. None
  702. --*/
  703. {
  704. PAGED_CODE();
  705. DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceVcb, Vcb = %08lx\n", (ULONG)Vcb);
  706. //
  707. // Acquire the lock that protects the reference count.
  708. //
  709. MsAcquireGlobalLock();
  710. if ( --(Vcb->Header.ReferenceCount) == 0 ) {
  711. //
  712. // This was the last reference to the VCB. Delete it now
  713. //
  714. DebugTrace(0,
  715. DEBUG_TRACE_REFCOUNT,
  716. "Reference count = %lx\n",
  717. Vcb->Header.ReferenceCount );
  718. MsReleaseGlobalLock();
  719. MsDeleteVcb( Vcb );
  720. } else {
  721. DebugTrace(0,
  722. DEBUG_TRACE_REFCOUNT,
  723. "Reference count = %lx\n",
  724. Vcb->Header.ReferenceCount );
  725. if (Vcb->Header.ReferenceCount == 1) {
  726. //
  727. // Set driver to be paged completely out
  728. //
  729. MmPageEntireDriver(MsDereferenceVcb);
  730. }
  731. MsReleaseGlobalLock();
  732. }
  733. DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceVcb -> VOID\n", 0);
  734. return;
  735. }
  736. VOID
  737. MsDereferenceFcb (
  738. IN PFCB Fcb
  739. )
  740. /*++
  741. Routine Description:
  742. This routine dereferences a FCB block.
  743. If the reference count reaches zero, the block is freed.
  744. Arguments:
  745. Fcb - Supplies the FCB to dereference.
  746. Return Value:
  747. None
  748. --*/
  749. {
  750. PAGED_CODE();
  751. DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceFcb, Fcb = %08lx\n", (ULONG)Fcb);
  752. //
  753. // Acquire the lock that protects the reference count.
  754. //
  755. MsAcquireGlobalLock();
  756. if ( --(Fcb->Header.ReferenceCount) == 0 ) {
  757. //
  758. // This was the last reference to the FCB. Delete it now
  759. //
  760. DebugTrace(0,
  761. DEBUG_TRACE_REFCOUNT,
  762. "Reference count = %lx\n",
  763. Fcb->Header.ReferenceCount );
  764. MsReleaseGlobalLock();
  765. MsDeleteFcb( Fcb );
  766. } else {
  767. DebugTrace(0,
  768. DEBUG_TRACE_REFCOUNT,
  769. "Reference count = %lx\n",
  770. Fcb->Header.ReferenceCount );
  771. MsReleaseGlobalLock();
  772. }
  773. DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceFcb -> VOID\n", 0);
  774. return;
  775. }
  776. VOID
  777. MsDereferenceCcb (
  778. IN PCCB Ccb
  779. )
  780. /*++
  781. Routine Description:
  782. This routine dereferences a CCB block. If the reference count
  783. reaches zero, the block is freed.
  784. Arguments:
  785. Ccb - Supplies the Ccb to dereference
  786. Return Value:
  787. None
  788. --*/
  789. {
  790. PAGED_CODE();
  791. DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceCcb, Ccb = %08lx\n", (ULONG)Ccb);
  792. //
  793. // Acquire the lock that protects the reference count.
  794. //
  795. MsAcquireGlobalLock();
  796. if ( --(Ccb->Header.ReferenceCount) == 0 ) {
  797. //
  798. // This was the last reference to the Ccb. Delete it now
  799. //
  800. DebugTrace(0,
  801. DEBUG_TRACE_REFCOUNT,
  802. "Reference count = %lx\n",
  803. Ccb->Header.ReferenceCount );
  804. MsReleaseGlobalLock();
  805. MsDeleteCcb( Ccb );
  806. } else {
  807. DebugTrace(0,
  808. DEBUG_TRACE_REFCOUNT,
  809. "Reference count = %lx\n",
  810. Ccb->Header.ReferenceCount );
  811. MsReleaseGlobalLock();
  812. }
  813. DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceCcb -> VOID\n", 0);
  814. return;
  815. }
  816. VOID
  817. MsDereferenceRootDcb (
  818. IN PROOT_DCB RootDcb
  819. )
  820. /*++
  821. Routine Description:
  822. This routine dereferences a ROOT_DCB block. If the reference count
  823. reaches zero, the block is freed.
  824. Arguments:
  825. RootDcb - Supplies the RootDcb to dereference
  826. Return Value:
  827. None
  828. --*/
  829. {
  830. PAGED_CODE();
  831. DebugTrace(+1, DEBUG_TRACE_REFCOUNT, "MsDereferenceRootDcb, RootDcb = %08lx\n", (ULONG)RootDcb);
  832. //
  833. // Acquire the lock that protects the reference count.
  834. //
  835. MsAcquireGlobalLock();
  836. if ( --(RootDcb->Header.ReferenceCount) == 0 ) {
  837. //
  838. // This was the last reference to the RootDcb. Delete it now
  839. //
  840. DebugTrace(0,
  841. DEBUG_TRACE_REFCOUNT,
  842. "Reference count = %lx\n",
  843. RootDcb->Header.ReferenceCount );
  844. MsReleaseGlobalLock();
  845. MsDeleteRootDcb( RootDcb );
  846. } else {
  847. DebugTrace(0,
  848. DEBUG_TRACE_REFCOUNT,
  849. "Reference count = %lx\n",
  850. RootDcb->Header.ReferenceCount );
  851. MsReleaseGlobalLock();
  852. }
  853. DebugTrace(-1, DEBUG_TRACE_REFCOUNT, "MsDereferenceRootDcb -> VOID\n", 0);
  854. return;
  855. }
  856. VOID
  857. MsDereferenceNode (
  858. IN PNODE_HEADER NodeHeader
  859. )
  860. /*++
  861. Routine Description:
  862. This routine dereferences a generic mailslot block. It figures out
  863. the type of block this is, and calls the appropriate worker function.
  864. Arguments:
  865. NodeHeader - A pointer to a generic mailslot block header.
  866. Return Value:
  867. None
  868. --*/
  869. {
  870. PAGED_CODE();
  871. switch ( NodeHeader->NodeTypeCode ) {
  872. case MSFS_NTC_VCB:
  873. MsDereferenceVcb( (PVCB)NodeHeader );
  874. break;
  875. case MSFS_NTC_ROOT_DCB:
  876. MsDereferenceRootDcb( (PROOT_DCB)NodeHeader );
  877. break;
  878. case MSFS_NTC_FCB:
  879. MsDereferenceFcb( (PFCB)NodeHeader );
  880. break;
  881. case MSFS_NTC_CCB:
  882. case MSFS_NTC_ROOT_DCB_CCB:
  883. MsDereferenceCcb( (PCCB)NodeHeader );
  884. break;
  885. default:
  886. //
  887. // This block is not one of ours.
  888. //
  889. KeBugCheck( MAILSLOT_FILE_SYSTEM );
  890. }
  891. return;
  892. }