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.

967 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. StrucSup.c
  5. Abstract:
  6. This module implements the Named Pipe in-memory data structure manipulation
  7. routines
  8. Author:
  9. Gary Kimura [GaryKi] 22-Jan-1990
  10. Revision History:
  11. --*/
  12. #include "NpProcs.h"
  13. //
  14. // The Bug check file id for this module
  15. //
  16. #define BugCheckFileId (NPFS_BUG_CHECK_STRUCSUP)
  17. //
  18. // The debug trace level
  19. //
  20. #define Dbg (DEBUG_TRACE_STRUCSUP)
  21. WCHAR NpRootDCBName[] = L"\\";
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(INIT, NpInitializeVcb)
  24. #pragma alloc_text(INIT, NpCreateRootDcb)
  25. #pragma alloc_text(PAGE, NpCreateCcb)
  26. #pragma alloc_text(PAGE, NpCreateFcb)
  27. #pragma alloc_text(PAGE, NpCreateRootDcbCcb)
  28. #pragma alloc_text(PAGE, NpDeleteCcb)
  29. #pragma alloc_text(PAGE, NpDeleteFcb)
  30. #pragma alloc_text(PAGE, NpDeleteRootDcb)
  31. #pragma alloc_text(PAGE, NpDeleteVcb)
  32. #endif
  33. VOID
  34. NpInitializeVcb (
  35. VOID
  36. )
  37. /*++
  38. Routine Description:
  39. This routine initializes new Vcb record. The Vcb record "hangs" off the
  40. end of the Npfs device object and must be allocated by our caller.
  41. Arguments:
  42. None.
  43. Return Value:
  44. None.
  45. --*/
  46. {
  47. PAGED_CODE();
  48. DebugTrace(+1, Dbg, "NpInitializeVcb, Vcb = %08lx\n", NpVcb);
  49. //
  50. // We start by first zeroing out all of the VCB, this will guarantee
  51. // that any stale data is wiped clean
  52. //
  53. RtlZeroMemory( NpVcb, sizeof(VCB) );
  54. //
  55. // Set the proper node type code and node byte size
  56. //
  57. NpVcb->NodeTypeCode = NPFS_NTC_VCB;
  58. //
  59. // Initialize the Prefix table
  60. //
  61. RtlInitializeUnicodePrefix( &NpVcb->PrefixTable );
  62. //
  63. // Initialize the resource variable for the Vcb
  64. //
  65. ExInitializeResourceLite( &NpVcb->Resource );
  66. //
  67. // Initialize the event table
  68. //
  69. NpInitializeEventTable( &NpVcb->EventTable );
  70. //
  71. // Initialize the wait queue
  72. //
  73. NpInitializeWaitQueue( &NpVcb->WaitQueue );
  74. //
  75. // return and tell the caller
  76. //
  77. return;
  78. }
  79. VOID
  80. NpDeleteVcb (
  81. IN PLIST_ENTRY DeferredList
  82. )
  83. /*++
  84. Routine Description:
  85. This routine removes the Vcb record from our in-memory data
  86. structures. It also will remove all associated underlings
  87. (i.e., FCB records).
  88. Arguments:
  89. DeferredList - List of deferred IRPs to complete once we release locks
  90. Return Value:
  91. None
  92. --*/
  93. {
  94. PAGED_CODE();
  95. DebugTrace(+1, Dbg, "NpDeleteVcb, Vcb = %08lx\n", NpVcb);
  96. //
  97. // Make sure the open count is zero, and the open underling count
  98. // is also zero.
  99. //
  100. if (NpVcb->OpenCount != 0) {
  101. DebugDump("Error deleting Vcb\n", 0, NpVcb);
  102. NpBugCheck( 0, 0, 0 );
  103. }
  104. //
  105. // Remove the Root Dcb
  106. //
  107. if (NpVcb->RootDcb != NULL) {
  108. NpDeleteRootDcb( NpVcb->RootDcb, DeferredList );
  109. }
  110. //
  111. // Uninitialize the resource variable for the Vcb
  112. //
  113. ExDeleteResourceLite( &NpVcb->Resource );
  114. //
  115. // Uninitialize the event table
  116. //
  117. NpUninitializeEventTable( &NpVcb->EventTable );
  118. //
  119. // Uninitialize the wait queue
  120. //
  121. NpUninitializeWaitQueue( &NpVcb->WaitQueue );
  122. //
  123. // And zero out the Vcb, this will help ensure that any stale data is
  124. // wiped clean
  125. //
  126. RtlZeroMemory( NpVcb, sizeof(VCB) );
  127. //
  128. // return and tell the caller
  129. //
  130. DebugTrace(-1, Dbg, "NpDeleteVcb -> VOID\n", 0);
  131. return;
  132. }
  133. NTSTATUS
  134. NpCreateRootDcb (
  135. VOID
  136. )
  137. /*++
  138. Routine Description:
  139. This routine allocates, initializes, and inserts a new root DCB record
  140. into the in memory data structure.
  141. Arguments:
  142. None.
  143. Return Value:
  144. None.
  145. --*/
  146. {
  147. PAGED_CODE();
  148. DebugTrace(+1, Dbg, "NpCreateRootDcb, Vcb = %08lx\n", NpVcb);
  149. //
  150. // Make sure we don't already have a root dcb for this vcb
  151. //
  152. if (NpVcb->RootDcb != NULL) {
  153. DebugDump("Error trying to create multiple root dcbs\n", 0, NpVcb);
  154. NpBugCheck( 0, 0, 0 );
  155. }
  156. //
  157. // Allocate a new DCB and zero it out
  158. //
  159. NpVcb->RootDcb = NpAllocatePagedPool ( sizeof(DCB), 'DFpN' );
  160. if (NpVcb->RootDcb == NULL) {
  161. return STATUS_INSUFFICIENT_RESOURCES;
  162. }
  163. RtlZeroMemory( NpVcb->RootDcb, sizeof(DCB));
  164. //
  165. // Set the proper node type code and node byte size
  166. //
  167. NpVcb->RootDcb->NodeTypeCode = NPFS_NTC_ROOT_DCB;
  168. //
  169. // The root Dcb has an empty parent dcb links field
  170. //
  171. InitializeListHead( &NpVcb->RootDcb->ParentDcbLinks );
  172. //
  173. // initialize the notify queues, and the parent dcb queue.
  174. //
  175. InitializeListHead( &NpVcb->RootDcb->Specific.Dcb.NotifyFullQueue );
  176. InitializeListHead( &NpVcb->RootDcb->Specific.Dcb.NotifyPartialQueue );
  177. InitializeListHead( &NpVcb->RootDcb->Specific.Dcb.ParentDcbQueue );
  178. NpVcb->RootDcb->FullFileName.Buffer = NpRootDCBName;
  179. NpVcb->RootDcb->FullFileName.Length = sizeof (NpRootDCBName) - sizeof (UNICODE_NULL);
  180. NpVcb->RootDcb->FullFileName.MaximumLength = sizeof (NpRootDCBName);
  181. //
  182. // Last file name is the same as file name.
  183. //
  184. NpVcb->RootDcb->LastFileName = NpVcb->RootDcb->FullFileName;
  185. //
  186. // Insert this dcb into the prefix table
  187. //
  188. if (!RtlInsertUnicodePrefix( &NpVcb->PrefixTable,
  189. &NpVcb->RootDcb->FullFileName,
  190. &NpVcb->RootDcb->PrefixTableEntry )) {
  191. DebugDump("Error trying to insert root dcb into prefix table\n", 0, NpVcb);
  192. NpBugCheck( 0, 0, 0 );
  193. }
  194. DebugTrace(-1, Dbg, "NpCreateRootDcb -> %8lx\n", NpVcb->RootDcb);
  195. return STATUS_SUCCESS;
  196. }
  197. VOID
  198. NpDeleteRootDcb (
  199. IN PROOT_DCB RootDcb,
  200. IN PLIST_ENTRY DeferredList
  201. )
  202. /*++
  203. Routine Description:
  204. This routine deallocates and removes the ROOT DCB record
  205. from our in-memory data structures. It also will remove all
  206. associated underlings (i.e., Notify queues and child FCB records).
  207. Arguments:
  208. RootDcb - Supplies the ROOT DCB to be removed
  209. DeferredList - List of IRPs to complete after we release locks
  210. Return Value:
  211. None
  212. --*/
  213. {
  214. PLIST_ENTRY Links;
  215. PIRP Irp;
  216. PAGED_CODE();
  217. DebugTrace(+1, Dbg, "NpDeleteRootDcb, RootDcb = %08lx\n", RootDcb);
  218. //
  219. // We can only delete this record if the open count is zero.
  220. //
  221. if (RootDcb->OpenCount != 0) {
  222. DebugDump("Error deleting RootDcb, Still Open\n", 0, RootDcb);
  223. NpBugCheck( 0, 0, 0 );
  224. }
  225. //
  226. // Remove every Notify Irp from the two notify queues
  227. //
  228. while (!IsListEmpty(&RootDcb->Specific.Dcb.NotifyFullQueue)) {
  229. Links = RemoveHeadList( &RootDcb->Specific.Dcb.NotifyFullQueue );
  230. Irp = CONTAINING_RECORD( Links, IRP, Tail.Overlay.ListEntry );
  231. NpDeferredCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED, DeferredList );
  232. }
  233. while (!IsListEmpty(&RootDcb->Specific.Dcb.NotifyPartialQueue)) {
  234. Links = RemoveHeadList( &RootDcb->Specific.Dcb.NotifyPartialQueue );
  235. Irp = CONTAINING_RECORD( Links, IRP, Tail.Overlay.ListEntry );
  236. NpDeferredCompleteRequest( Irp, STATUS_FILE_FORCED_CLOSED, DeferredList );
  237. }
  238. //
  239. // We can only be removed if the no other FCB have us referenced
  240. // as a their parent DCB.
  241. //
  242. if (!IsListEmpty(&RootDcb->Specific.Dcb.ParentDcbQueue)) {
  243. DebugDump("Error deleting RootDcb\n", 0, RootDcb);
  244. NpBugCheck( 0, 0, 0 );
  245. }
  246. //
  247. // Remove the entry from the prefix table, and then remove the full
  248. // file name
  249. //
  250. RtlRemoveUnicodePrefix( &NpVcb->PrefixTable, &RootDcb->PrefixTableEntry );
  251. //
  252. // Finally deallocate the Dcb record
  253. //
  254. NpFreePool( RootDcb );
  255. //
  256. // and return to our caller
  257. //
  258. DebugTrace(-1, Dbg, "NpDeleteRootDcb -> VOID\n", 0);
  259. return;
  260. }
  261. NTSTATUS
  262. NpCreateFcb (
  263. IN PDCB ParentDcb,
  264. IN PUNICODE_STRING FileName,
  265. IN ULONG MaximumInstances,
  266. IN LARGE_INTEGER DefaultTimeOut,
  267. IN NAMED_PIPE_CONFIGURATION NamedPipeConfiguration,
  268. IN NAMED_PIPE_TYPE NamedPipeType,
  269. OUT PFCB *ppFcb
  270. )
  271. /*++
  272. Routine Description:
  273. This routine allocates, initializes, and inserts a new Fcb record into
  274. the in memory data structures.
  275. Arguments:
  276. ParentDcb - Supplies the parent dcb that the new FCB is under.
  277. FileName - Supplies the file name of the file relative to the directory
  278. it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
  279. the preceding backslash).
  280. MaximumInstances - Supplies the maximum number of pipe instances
  281. DefaultTimeOut - Supplies the default wait time out value
  282. NamedPipeConfiguration - Supplies our initial pipe configuration
  283. NamedPipeType - Supplies our initial pipe type
  284. Return Value:
  285. PFCB - Returns a pointer to the newly allocated FCB
  286. --*/
  287. {
  288. PFCB Fcb;
  289. PWCH Name;
  290. USHORT Length;
  291. USHORT MaximumLength;
  292. BOOLEAN AddBackSlash = FALSE;
  293. ULONG i;
  294. PAGED_CODE();
  295. DebugTrace(+1, Dbg, "NpCreateFcb\n", 0);
  296. Length = FileName->Length;
  297. MaximumLength = Length + sizeof (WCHAR);
  298. if (Length < sizeof (WCHAR) || MaximumLength < Length) {
  299. return STATUS_INVALID_PARAMETER;
  300. }
  301. if (FileName->Buffer[0] != '\\') {
  302. AddBackSlash = TRUE;
  303. MaximumLength += sizeof (WCHAR);
  304. if (MaximumLength < sizeof (WCHAR)) {
  305. return STATUS_INVALID_PARAMETER;
  306. }
  307. }
  308. //
  309. // Allocate a new FCB record and zero it out
  310. //
  311. Fcb = NpAllocatePagedPoolWithQuota( sizeof(FCB), 'FfpN' );
  312. if (Fcb == NULL) {
  313. return STATUS_INSUFFICIENT_RESOURCES;
  314. }
  315. RtlZeroMemory( Fcb, sizeof(FCB) );
  316. //
  317. // Set the proper node type code and node byte size
  318. //
  319. Fcb->NodeTypeCode = NPFS_NTC_FCB;
  320. //
  321. // Point back to our parent dcb
  322. //
  323. Fcb->ParentDcb = ParentDcb;
  324. //
  325. // Set our maximum instances, default timeout, and initialize our
  326. // ccb queue
  327. //
  328. Fcb->Specific.Fcb.MaximumInstances = MaximumInstances;
  329. Fcb->Specific.Fcb.DefaultTimeOut = DefaultTimeOut;
  330. InitializeListHead( &Fcb->Specific.Fcb.CcbQueue );
  331. //
  332. // set the file name. We need to do this from nonpaged pool because
  333. // cancel waiters works while holding a spinlock and uses the fcb name
  334. //
  335. Name = NpAllocateNonPagedPoolWithQuota( MaximumLength, 'nFpN' );
  336. if (Name == NULL) {
  337. NpFreePool (Fcb);
  338. return STATUS_INSUFFICIENT_RESOURCES;
  339. }
  340. //
  341. // Insert this fcb into our parent dcb's queue
  342. //
  343. InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
  344. &Fcb->ParentDcbLinks );
  345. i = 0;
  346. if (AddBackSlash == TRUE) {
  347. i++;
  348. Name[0] = '\\';
  349. }
  350. RtlCopyMemory( &Name[i], FileName->Buffer, Length );
  351. Name[ i + Length / sizeof(WCHAR) ] = L'\0';
  352. Fcb->FullFileName.Length = MaximumLength - sizeof (WCHAR);
  353. Fcb->FullFileName.MaximumLength = MaximumLength ;
  354. Fcb->FullFileName.Buffer = Name;
  355. Fcb->LastFileName.Length = MaximumLength - 2*sizeof (WCHAR);
  356. Fcb->LastFileName.MaximumLength = MaximumLength - sizeof (WCHAR);
  357. Fcb->LastFileName.Buffer = &Name[1];
  358. //
  359. // Insert this Fcb into the prefix table
  360. //
  361. if (!RtlInsertUnicodePrefix( &NpVcb->PrefixTable,
  362. &Fcb->FullFileName,
  363. &Fcb->PrefixTableEntry )) {
  364. DebugDump("Error trying to name into prefix table\n", 0, Fcb);
  365. NpBugCheck( 0, 0, 0 );
  366. }
  367. //
  368. // Set the configuration and pipe type
  369. //
  370. Fcb->Specific.Fcb.NamedPipeConfiguration = NamedPipeConfiguration;
  371. Fcb->Specific.Fcb.NamedPipeType = NamedPipeType;
  372. DebugTrace(-1, Dbg, "NpCreateFcb -> %08lx\n", Fcb);
  373. //
  374. // return and tell the caller
  375. //
  376. *ppFcb = Fcb;
  377. return STATUS_SUCCESS;
  378. }
  379. VOID
  380. NpDeleteFcb (
  381. IN PFCB Fcb,
  382. IN PLIST_ENTRY DeferredList
  383. )
  384. /*++
  385. Routine Description:
  386. This routine deallocates and removes an FCB
  387. from our in-memory data structures. It also will remove all
  388. associated underlings.
  389. Arguments:
  390. Fcb - Supplies the FCB to be removed
  391. DeferredList - List of IRPs to complete later
  392. Return Value:
  393. None
  394. --*/
  395. {
  396. PDCB ParentDcb;
  397. PAGED_CODE();
  398. DebugTrace(+1, Dbg, "NpDeleteFcb, Fcb = %08lx\n", Fcb);
  399. ParentDcb = Fcb->ParentDcb;
  400. //
  401. // We can only delete this record if the open count is zero.
  402. //
  403. if (Fcb->OpenCount != 0) {
  404. DebugDump("Error deleting Fcb, Still Open\n", 0, Fcb);
  405. NpBugCheck( 0, 0, 0 );
  406. }
  407. //
  408. // Complete any waiters waiting on this server. All instances have now gone.
  409. //
  410. NpCancelWaiter (&NpVcb->WaitQueue,
  411. &Fcb->FullFileName,
  412. STATUS_OBJECT_NAME_NOT_FOUND,
  413. DeferredList);
  414. //
  415. // Remove ourselves from our parents Dcb queue
  416. //
  417. RemoveEntryList( &(Fcb->ParentDcbLinks) );
  418. //
  419. // If there is a security descriptor on the named pipe then deassign it
  420. //
  421. if (Fcb->SecurityDescriptor != NULL) {
  422. ObDereferenceSecurityDescriptor( Fcb->SecurityDescriptor, 1 );
  423. }
  424. //
  425. // Remove the entry from the prefix table, and then remove the full
  426. // file name
  427. //
  428. RtlRemoveUnicodePrefix( &NpVcb->PrefixTable, &Fcb->PrefixTableEntry );
  429. NpFreePool( Fcb->FullFileName.Buffer );
  430. //
  431. // Finally deallocate the Fcb record
  432. //
  433. NpFreePool( Fcb );
  434. //
  435. // Check for any outstanding notify irps
  436. //
  437. NpCheckForNotify( ParentDcb, TRUE, DeferredList );
  438. //
  439. // and return to our caller
  440. //
  441. DebugTrace(-1, Dbg, "NpDeleteFcb -> VOID\n", 0);
  442. return;
  443. }
  444. NTSTATUS
  445. NpCreateCcb (
  446. IN PFCB Fcb,
  447. IN PFILE_OBJECT ServerFileObject,
  448. IN NAMED_PIPE_STATE NamedPipeState,
  449. IN READ_MODE ServerReadMode,
  450. IN COMPLETION_MODE ServerCompletionMode,
  451. IN ULONG InBoundQuota,
  452. IN ULONG OutBoundQuota,
  453. OUT PCCB *ppCcb
  454. )
  455. /*++
  456. Routine Description:
  457. This routine creates a new CCB record
  458. Arguments:
  459. Fcb - Supplies a pointer to the fcb we are attached to
  460. ServerFileObject - Supplies a pointer to the file object for the server
  461. end
  462. NamedPipeState - Supplies the initial pipe state
  463. ServerReadMode - Supplies our initial read mode
  464. ServerCompletionMode - Supplies our initial completion mode
  465. CreatorProcess - Supplies a pointer to our creator process
  466. InBoundQuota - Supplies the initial inbound quota
  467. OutBoundQuota - Supplies the initial outbound quota
  468. Return Value:
  469. PCCB - returns a pointer to the newly allocate CCB
  470. --*/
  471. {
  472. PCCB Ccb;
  473. NTSTATUS status;
  474. PAGED_CODE();
  475. DebugTrace(+1, Dbg, "NpCreateCcb\n", 0);
  476. //
  477. // Allocate a new CCB record (paged and nonpaged), and zero them out
  478. //
  479. Ccb = NpAllocatePagedPoolWithQuotaCold( sizeof(CCB), 'cFpN' );
  480. if (Ccb == NULL) {
  481. return STATUS_INSUFFICIENT_RESOURCES;
  482. }
  483. RtlZeroMemory( Ccb, sizeof(CCB) );
  484. Ccb->NonpagedCcb = NpAllocateNonPagedPoolWithQuota( sizeof(NONPAGED_CCB), 'cFpN');
  485. if (Ccb->NonpagedCcb == NULL) {
  486. NpFreePool (Ccb);
  487. return STATUS_INSUFFICIENT_RESOURCES;
  488. }
  489. RtlZeroMemory( Ccb->NonpagedCcb, sizeof(NONPAGED_CCB) );
  490. //
  491. // Set the proper node type code and node byte size
  492. //
  493. Ccb->NodeTypeCode = NPFS_NTC_CCB;
  494. Ccb->Fcb = Fcb;
  495. //
  496. // Set the server file object
  497. //
  498. Ccb->FileObject[ FILE_PIPE_SERVER_END ] = ServerFileObject;
  499. //
  500. // Initialize the nonpaged ccb
  501. //
  502. // Set the proper node type code and node byte size
  503. //
  504. Ccb->NonpagedCcb->NodeTypeCode = NPFS_NTC_NONPAGED_CCB;
  505. //
  506. // Set the pipe state, read mode, completion mode, and creator process
  507. //
  508. Ccb->NamedPipeState = (UCHAR) NamedPipeState;
  509. Ccb->ReadCompletionMode[ FILE_PIPE_SERVER_END ].ReadMode = (UCHAR) ServerReadMode;
  510. Ccb->ReadCompletionMode[ FILE_PIPE_SERVER_END ].CompletionMode = (UCHAR) ServerCompletionMode;
  511. //
  512. // Initialize the data queues
  513. //
  514. status = NpInitializeDataQueue( &Ccb->DataQueue[ FILE_PIPE_INBOUND ],
  515. InBoundQuota );
  516. if (!NT_SUCCESS (status)) {
  517. NpFreePool (Ccb->NonpagedCcb);
  518. NpFreePool (Ccb);
  519. return status;
  520. }
  521. status = NpInitializeDataQueue( &Ccb->DataQueue[ FILE_PIPE_OUTBOUND ],
  522. OutBoundQuota );
  523. if (!NT_SUCCESS (status)) {
  524. NpUninitializeDataQueue (&Ccb->DataQueue[ FILE_PIPE_INBOUND ]);
  525. NpFreePool (Ccb->NonpagedCcb);
  526. NpFreePool (Ccb);
  527. }
  528. //
  529. // Insert ourselves in the list of ccb for the fcb, and increment
  530. // the reference count in the fcb.
  531. //
  532. InsertTailList( &Fcb->Specific.Fcb.CcbQueue, &Ccb->CcbLinks );
  533. Fcb->OpenCount += 1;
  534. Fcb->ServerOpenCount += 1;
  535. //
  536. // Initialize the listening queue
  537. //
  538. InitializeListHead( &Ccb->ListeningQueue );
  539. ExInitializeResourceLite(&Ccb->NonpagedCcb->Resource);
  540. //
  541. // return and tell the caller
  542. //
  543. *ppCcb = Ccb;
  544. return STATUS_SUCCESS;
  545. }
  546. NTSTATUS
  547. NpCreateRootDcbCcb (
  548. OUT PROOT_DCB_CCB *ppCcb
  549. )
  550. /*++
  551. Routine Description:
  552. This routine creates a new ROOT DCB CCB record
  553. Arguments:
  554. Return Value:
  555. PROOT_DCB_CCB - returns a pointer to the newly allocate ROOT_DCB_CCB
  556. --*/
  557. {
  558. PROOT_DCB_CCB Ccb;
  559. PAGED_CODE();
  560. DebugTrace(+1, Dbg, "NpCreateRootDcbCcb\n", 0);
  561. //
  562. // Allocate a new ROOT DCB CCB record, and zero it out
  563. //
  564. Ccb = NpAllocatePagedPoolWithQuotaCold ( sizeof(ROOT_DCB_CCB), 'CFpN' );
  565. if (Ccb == NULL) {
  566. return STATUS_INSUFFICIENT_RESOURCES;
  567. }
  568. RtlZeroMemory( Ccb, sizeof(ROOT_DCB_CCB) );
  569. //
  570. // Set the proper node type code and node byte size
  571. //
  572. Ccb->NodeTypeCode = NPFS_NTC_ROOT_DCB_CCB;
  573. //
  574. // return and tell the caller
  575. //
  576. *ppCcb = Ccb;
  577. DebugTrace(-1, Dbg, "NpCreateRootDcbCcb -> %08lx\n", Ccb);
  578. return STATUS_SUCCESS;
  579. }
  580. VOID
  581. NpDeleteCcb (
  582. IN PCCB Ccb,
  583. IN PLIST_ENTRY DeferredList
  584. )
  585. /*++
  586. Routine Description:
  587. This routine deallocates and removes the specified CCB record
  588. from the our in memory data structures
  589. Arguments:
  590. Ccb - Supplies the CCB to remove
  591. DeferredList - List of IRPs to complete once we drop locks
  592. Return Value:
  593. None
  594. --*/
  595. {
  596. PAGED_CODE();
  597. DebugTrace(+1, Dbg, "NpDeleteCcb, Ccb = %08lx\n", Ccb);
  598. //
  599. // Case on the type of ccb we are deleting
  600. //
  601. switch (Ccb->NodeTypeCode) {
  602. case NPFS_NTC_CCB:
  603. RemoveEntryList (&Ccb->CcbLinks);
  604. Ccb->Fcb->OpenCount -= 1;
  605. NpDeleteEventTableEntry (&NpVcb->EventTable,
  606. Ccb->NonpagedCcb->EventTableEntry[FILE_PIPE_CLIENT_END]);
  607. NpDeleteEventTableEntry (&NpVcb->EventTable,
  608. Ccb->NonpagedCcb->EventTableEntry[FILE_PIPE_SERVER_END]);
  609. NpUninitializeDataQueue (&Ccb->DataQueue[FILE_PIPE_INBOUND]);
  610. NpUninitializeDataQueue (&Ccb->DataQueue[FILE_PIPE_OUTBOUND]);
  611. //
  612. // Check for any outstanding notify irps
  613. //
  614. NpCheckForNotify (Ccb->Fcb->ParentDcb, FALSE, DeferredList);
  615. //
  616. // Delete the resource
  617. //
  618. ExDeleteResourceLite (&Ccb->NonpagedCcb->Resource);
  619. //
  620. // Free up the security fields in the ccb and then free the nonpaged
  621. // ccb
  622. //
  623. NpUninitializeSecurity (Ccb);
  624. //
  625. // Free up client info if it was allocated.
  626. //
  627. if (Ccb->ClientInfo != NULL) {
  628. NpFreePool (Ccb->ClientInfo);
  629. Ccb->ClientInfo = NULL;
  630. }
  631. NpFreePool (Ccb->NonpagedCcb);
  632. break;
  633. case NPFS_NTC_ROOT_DCB_CCB:
  634. if (((PROOT_DCB_CCB)Ccb)->QueryTemplate != NULL) {
  635. NpFreePool (((PROOT_DCB_CCB)Ccb)->QueryTemplate);
  636. }
  637. break;
  638. }
  639. // Deallocate the Ccb record
  640. //
  641. NpFreePool (Ccb);
  642. //
  643. // return and tell the caller
  644. //
  645. DebugTrace(-1, Dbg, "NpDeleteCcb -> VOID\n", 0);
  646. return;
  647. }
  648.