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.

1473 lines
45 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: PktSup.C
  6. //
  7. // Contents: This module implements routines specific to the partition
  8. // knowledge table entry.
  9. //
  10. // Functions: PktDSTransportDestroy -
  11. // PktDSMachineDestroy -
  12. // PktServiceConstruct -
  13. // PktServiceDestroy -
  14. // PktEntryIdConstruct -
  15. // PktEntryIdDestroy -
  16. // PktEntryInfoConstruct -
  17. // PktEntryInfoDestroy -
  18. // PktEntryAssemble -
  19. // PktEntryReassemble -
  20. // PktEntryDestroy -
  21. // PktEntryClearSubordinates -
  22. // PktEntryClearChildren -
  23. // PktpServiceToReferral -
  24. // DfsFixDSMachineStructs -
  25. // DfspFixService -
  26. // DfsDecrementMachEntryCount -
  27. // PktSpecialEntryDestroy -
  28. //
  29. // History: 27 May 1992 PeterCo Created.
  30. //
  31. //-----------------------------------------------------------------------------
  32. #include "dfsprocs.h"
  33. #include "dnr.h"
  34. #include "creds.h"
  35. #include "fsctrl.h"
  36. #include "know.h"
  37. #include "log.h"
  38. #define Dbg (DEBUG_TRACE_PKT)
  39. ULONG MupErrorCase = 0;
  40. NTSTATUS
  41. DfsFixDSMachineStructs(
  42. PDFS_PKT_ENTRY pEntry
  43. );
  44. NTSTATUS
  45. DfspFixService(
  46. PDFS_SERVICE pService
  47. );
  48. VOID
  49. PktDSTransportDestroy(
  50. IN PDS_TRANSPORT Victim OPTIONAL,
  51. IN BOOLEAN DeallocateAll
  52. );
  53. VOID
  54. PktDSMachineDestroy(
  55. IN PDS_MACHINE Victim OPTIONAL,
  56. IN BOOLEAN DeallocateAll
  57. );
  58. #ifdef ALLOC_PRAGMA
  59. #pragma alloc_text( PAGE, PktServiceConstruct )
  60. #pragma alloc_text( PAGE, PktServiceDestroy )
  61. #pragma alloc_text( PAGE, PktEntryIdConstruct )
  62. #pragma alloc_text( PAGE, PktEntryIdDestroy )
  63. #pragma alloc_text( PAGE, PktEntryInfoDestroy )
  64. #pragma alloc_text( PAGE, PktEntryAssemble )
  65. #pragma alloc_text( PAGE, PktEntryReassemble )
  66. #pragma alloc_text( PAGE, PktEntryDestroy)
  67. #pragma alloc_text( PAGE, PktEntryClearSubordinates )
  68. #pragma alloc_text( PAGE, PktEntryClearChildren )
  69. #pragma alloc_text( PAGE, DfsFixDSMachineStructs )
  70. #pragma alloc_text( PAGE, DfspFixService )
  71. #pragma alloc_text( PAGE, DfsDecrementMachEntryCount )
  72. #pragma alloc_text( PAGE, PktDSTransportDestroy )
  73. #pragma alloc_text( PAGE, PktDSMachineDestroy )
  74. #pragma alloc_text( PAGE, PktSpecialEntryDestroy )
  75. #endif // ALLOC_PRAGMA
  76. //
  77. // NOTE - we designed for only one system-wide PKT; there is no provision
  78. // for multiple PKTs.
  79. //
  80. #define _GetPkt() (&DfsData.Pkt)
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Function: PktServiceConstruct, public
  84. //
  85. // Synopsis: PktServiceConstruct creates a new service structure.
  86. //
  87. // Arguments: [Service] - a pointer to a service structure to fill.
  88. // [ServiceType] - the type of the new service.
  89. // [ServiceCapability] - the capabilities of the new service.
  90. // [ServiceStatus] - the initial status of the new service.
  91. // [ServiceProviderId] - the provider Id of the new service.
  92. // [ServiceName] - the name of the principal for the service
  93. // [ServiceAddress] - a string which gives the address
  94. // of the service.
  95. //
  96. // Returns: [STATUS_SUCCESS] - all is well.
  97. // [STATUS_INSUFFICIENT_RESOURCES] - memory could not be
  98. // allocated for this new service.
  99. //
  100. // Notes: All data is copied (Not MOVED).
  101. //
  102. //--------------------------------------------------------------------------
  103. NTSTATUS
  104. PktServiceConstruct(
  105. OUT PDFS_SERVICE Service,
  106. IN ULONG ServiceType,
  107. IN ULONG ServiceCapability,
  108. IN ULONG ServiceStatus,
  109. IN ULONG ServiceProviderId,
  110. IN PUNICODE_STRING ServiceName OPTIONAL,
  111. IN PUNICODE_STRING ServiceAddress OPTIONAL
  112. ) {
  113. DfsDbgTrace(+1, Dbg, "PktServiceConstruct: Entered\n", 0);
  114. ASSERT(ARGUMENT_PRESENT(Service));
  115. RtlZeroMemory(Service, sizeof(DFS_SERVICE));
  116. if (ARGUMENT_PRESENT(ServiceName) && ServiceName->Length != 0) {
  117. Service->Name.Buffer = DfsAllocate(ServiceName->Length);
  118. if (Service->Name.Buffer == NULL) {
  119. DfsDbgTrace(-1, Dbg, "PktServiceConstruct: Exit -> %08lx\n",
  120. ULongToPtr(STATUS_INSUFFICIENT_RESOURCES) );
  121. return STATUS_INSUFFICIENT_RESOURCES;
  122. }
  123. Service->Name.Length = ServiceName->Length;
  124. Service->Name.MaximumLength = ServiceName->Length;
  125. RtlCopyUnicodeString(&Service->Name, ServiceName);
  126. } else {
  127. Service->Name.Buffer = NULL;
  128. Service->Name.Length = Service->Name.MaximumLength = 0;
  129. }
  130. if (ARGUMENT_PRESENT(ServiceAddress) && ServiceAddress->Length != 0) {
  131. Service->Address.Buffer = DfsAllocate(ServiceAddress->Length);
  132. if (Service->Address.Buffer == NULL) {
  133. if (Service->Name.Buffer != NULL)
  134. DfsFree(Service->Name.Buffer);
  135. DfsDbgTrace(-1, Dbg, "PktServiceConstruct: Exit -> %08lx\n",
  136. ULongToPtr(STATUS_INSUFFICIENT_RESOURCES) );
  137. return STATUS_INSUFFICIENT_RESOURCES;
  138. }
  139. RtlMoveMemory(Service->Address.Buffer, ServiceAddress->Buffer,
  140. ServiceAddress->Length);
  141. Service->Address.Length =
  142. Service->Address.MaximumLength = ServiceAddress->Length;
  143. } else {
  144. Service->Address.Buffer = NULL;
  145. Service->Address.Length = Service->Address.MaximumLength = 0;
  146. }
  147. Service->Type = ServiceType;
  148. Service->Capability = ServiceCapability;
  149. Service->ProviderId = ServiceProviderId;
  150. Service->pProvider = NULL;
  151. DfsDbgTrace(-1, Dbg, "PktServiceConstruct: Exit -> %08lx\n",
  152. STATUS_SUCCESS );
  153. return STATUS_SUCCESS;
  154. }
  155. //+-------------------------------------------------------------------------
  156. //
  157. // Function: PktDSTransportDestroy, public
  158. //
  159. // Synopsis: PktDSTransportDestroy destroys a DS_TRANSPORT structure, and
  160. // optionally deallocates the structure itself.
  161. //
  162. // Arguments: [Victim] - the DS_TRANSPORT structure to destroy
  163. // [DeallocateAll] - if True, indicates that the structure
  164. // it self is to be deallocated, otherwise, only the
  165. // strings within the structure are deallocated.
  166. //
  167. // Returns: VOID
  168. //
  169. // Notes:
  170. //
  171. //--------------------------------------------------------------------------
  172. VOID
  173. PktDSTransportDestroy(
  174. IN PDS_TRANSPORT Victim OPTIONAL,
  175. IN BOOLEAN DeallocateAll
  176. )
  177. {
  178. DfsDbgTrace(+1, Dbg, "PktDSTransportDestroy: Entered\n", 0);
  179. if (ARGUMENT_PRESENT(Victim)) {
  180. //
  181. // Nothing to free in this structure??
  182. //
  183. if (DeallocateAll)
  184. ExFreePool(Victim);
  185. } else
  186. DfsDbgTrace(0, Dbg, "PktDSTransportDestroy: No Victim\n", 0 );
  187. DfsDbgTrace(-1, Dbg, "PktDSTransportDestroy: Exit -> VOID\n", 0 );
  188. }
  189. //+-------------------------------------------------------------------------
  190. //
  191. // Function: PktDSMachineDestroy, public
  192. //
  193. // Synopsis: PktDSMachineDestroy destroys a DS_MACHINE structure, and
  194. // optionally deallocates the structure itself.
  195. //
  196. // Arguments: [Victim] - the DS_MACHINE structure to destroy
  197. // [DeallocateAll] - if True, indicates that the structure
  198. // it self is to be deallocated, otherwise, only the
  199. // strings within the structure are deallocated.
  200. //
  201. // Returns: VOID
  202. //
  203. // Notes:
  204. //
  205. //--------------------------------------------------------------------------
  206. VOID
  207. PktDSMachineDestroy(
  208. IN PDS_MACHINE Victim OPTIONAL,
  209. IN BOOLEAN DeallocateAll
  210. )
  211. {
  212. ULONG i;
  213. DfsDbgTrace(+1, Dbg, "PktDSMachineDestroy: Entered\n", 0);
  214. if (ARGUMENT_PRESENT(Victim)) {
  215. if (Victim->pwszShareName != NULL) {
  216. DfsFree(Victim->pwszShareName);
  217. Victim->pwszShareName = NULL;
  218. }
  219. if (Victim->prgpwszPrincipals != NULL && Victim->cPrincipals > 0) {
  220. for (i = 0; i < Victim->cPrincipals; i++) {
  221. if (Victim->prgpwszPrincipals[i] != NULL) {
  222. DfsFree(Victim->prgpwszPrincipals[i]);
  223. Victim->prgpwszPrincipals[i] = NULL;
  224. }
  225. }
  226. }
  227. if (Victim->prgpwszPrincipals) {
  228. ExFreePool(Victim->prgpwszPrincipals);
  229. Victim->prgpwszPrincipals = NULL;
  230. }
  231. for (i = 0; i < Victim->cTransports; i++) {
  232. PktDSTransportDestroy(Victim->rpTrans[i], TRUE);
  233. }
  234. if (DeallocateAll)
  235. ExFreePool(Victim);
  236. } else
  237. DfsDbgTrace(0, Dbg, "PktDSMachineDestroy: No Victim\n", 0 );
  238. DfsDbgTrace(-1, Dbg, "PktDSMachineDestroy: Exit -> VOID\n", 0 );
  239. }
  240. //+-------------------------------------------------------------------------
  241. //
  242. // Function: DfsDecrementMachEntryCount
  243. //
  244. // Synopsis: This function decrements the count for the pMachine passed
  245. // in and if necessary will also free up the DS_MACHINE struct
  246. //
  247. //--------------------------------------------------------------------------
  248. VOID
  249. DfsDecrementMachEntryCount(
  250. PDFS_MACHINE_ENTRY pMachEntry,
  251. BOOLEAN DeallocateMachine
  252. )
  253. {
  254. NTSTATUS status = STATUS_SUCCESS;
  255. UNICODE_STRING ustrMachineName;
  256. PUNICODE_PREFIX_TABLE_ENTRY pfxEntry;
  257. PDS_MACHINE pMachine;
  258. PDFS_PKT Pkt;
  259. LONG Count;
  260. ASSERT(pMachEntry != NULL);
  261. if (pMachEntry == NULL)
  262. return;
  263. pMachine = pMachEntry->pMachine;
  264. ASSERT(pMachine != NULL);
  265. if (pMachine == NULL)
  266. return;
  267. //
  268. // We already have appropriate locks
  269. //
  270. Pkt = _GetPkt();
  271. //
  272. // For now we only expect one principal, by design?
  273. //
  274. ASSERT(pMachine->cPrincipals == 1);
  275. Count = InterlockedDecrement( &pMachEntry->UseCount );
  276. if (Count == 0) {
  277. if (pMachEntry->AuthConn != NULL) {
  278. DfsDeleteTreeConnection( pMachEntry->AuthConn, USE_LOTS_OF_FORCE );
  279. pMachEntry->Credentials->RefCount--;
  280. }
  281. //
  282. // This means we can now actually delete this DS_MACHINE structure
  283. //
  284. RtlRemoveUnicodePrefix(&Pkt->DSMachineTable,
  285. &pMachEntry->PrefixTableEntry);
  286. if (DeallocateMachine)
  287. PktDSMachineDestroy(pMachine, TRUE);
  288. //
  289. // Free the entry itself. Note that the UNICODE_STRING in the
  290. // entry gets freed up as part of above pMachine deletion.
  291. //
  292. DfsFree(pMachEntry);
  293. }
  294. }
  295. //+-------------------------------------------------------------------------
  296. //
  297. // Function: PktServiceDestroy, public
  298. //
  299. // Synopsis: PktServiceDestroy destroys a service structure, and
  300. // optionally deallocates the structure itself.
  301. //
  302. // Arguments: [Victim] - the service structure to destroy
  303. // [DeallocateAll] - if True, indicates that the structure
  304. // it self is to be deallocated, otherwise, only the
  305. // strings within the structure are deallocated.
  306. //
  307. // Returns: VOID
  308. //
  309. // Notes:
  310. //
  311. //--------------------------------------------------------------------------
  312. VOID
  313. PktServiceDestroy(
  314. IN PDFS_SERVICE Victim OPTIONAL,
  315. IN BOOLEAN DeallocateAll
  316. )
  317. {
  318. DfsDbgTrace(+1, Dbg, "PktServiceDestroy: Entered\n", 0);
  319. if (ARGUMENT_PRESENT(Victim)) {
  320. if (Victim->ConnFile != NULL) {
  321. DfsCloseConnection(Victim);
  322. Victim->ConnFile = NULL;
  323. }
  324. if (Victim->Name.Buffer != NULL) {
  325. DfsFree(Victim->Name.Buffer);
  326. Victim->Name.Buffer = NULL;
  327. }
  328. if (Victim->Address.Buffer != NULL) {
  329. DfsFree(Victim->Address.Buffer);
  330. Victim->Address.Buffer = NULL;
  331. }
  332. //
  333. // Decrement the usage count. If it is to be deleted it will happen
  334. // automatically.
  335. //
  336. if (Victim->pMachEntry != NULL) {
  337. DfsDecrementMachEntryCount(Victim->pMachEntry, TRUE);
  338. }
  339. if (DeallocateAll)
  340. ExFreePool(Victim);
  341. } else
  342. DfsDbgTrace(0, Dbg, "PktServiceDestroy: No Victim\n", 0 );
  343. DfsDbgTrace(-1, Dbg, "PktServiceDestroy: Exit -> VOID\n", 0 );
  344. }
  345. //+-------------------------------------------------------------------------
  346. //
  347. // Function: PktEntryIdConstruct, public
  348. //
  349. // Synopsis: PktEntryIdConstruct creates a PKT Entry Id
  350. //
  351. // Arguments: [NewPktEntryId] - Where the new entry is placed
  352. // [NewUid] - The UID of the new Pkt Entry
  353. // [NewPrefix] - The new prefix of the new Pkt Entry
  354. //
  355. // Returns: [STATUS_SUCCESS] - all is well.
  356. // [STATUS_INSUFFICIENT_RESOURCES] - could not allocate
  357. // memory for the Prefix part of the Id.
  358. //
  359. // Notes: The UNICODE_STRING used in the Prefix of the Id is COPIED,
  360. // not MOVED!
  361. //
  362. //--------------------------------------------------------------------------
  363. NTSTATUS
  364. PktEntryIdConstruct(
  365. OUT PDFS_PKT_ENTRY_ID PktEntryId,
  366. IN GUID *Uid OPTIONAL,
  367. IN UNICODE_STRING *Prefix OPTIONAL
  368. )
  369. {
  370. DfsDbgTrace(+1, Dbg, "PktEntryIdConstruct: Entered\n", 0);
  371. ASSERT(ARGUMENT_PRESENT(PktEntryId));
  372. ASSERT(ARGUMENT_PRESENT(Prefix));
  373. //
  374. // Zero the memory
  375. //
  376. RtlZeroMemory(PktEntryId, sizeof(DFS_PKT_ENTRY_ID));
  377. //
  378. // deal with the prefix.
  379. //
  380. if (ARGUMENT_PRESENT(Prefix)) {
  381. PUNICODE_STRING pus = &PktEntryId->Prefix;
  382. if (Prefix->Length != 0) {
  383. pus->Length = pus->MaximumLength = Prefix->Length;
  384. pus->Buffer = DfsAllocate(pus->Length);
  385. if (pus->Buffer != NULL) {
  386. RtlCopyUnicodeString(pus, Prefix);
  387. } else {
  388. DfsDbgTrace(-1,Dbg,"PktEntryIdConstruct: Exit -> %08lx\n",
  389. ULongToPtr(STATUS_INSUFFICIENT_RESOURCES) );
  390. return STATUS_INSUFFICIENT_RESOURCES;
  391. }
  392. }
  393. }
  394. //
  395. // deal with the GUID.
  396. //
  397. if (ARGUMENT_PRESENT(Uid)) {
  398. PktEntryId->Uid = (*Uid);
  399. }
  400. DfsDbgTrace(-1,Dbg,"PktEntryIdConstruct: Exit -> %08lx\n",STATUS_SUCCESS);
  401. return STATUS_SUCCESS;
  402. }
  403. //+-------------------------------------------------------------------------
  404. //
  405. // Function: PktEntryIdDestroy, public
  406. //
  407. // Synopsis: PktEntryIdDestroy destroys a PKT Entry Id
  408. //
  409. // Arguments: [Victim] - Id to destroy
  410. // [DeallocateAll] - if true, indicates that the memory
  411. // for the Id itself is to be release, otherwise,
  412. // this memory is not released (only the memory for
  413. // the UNICODE_STRING in the Prefix is released).
  414. //
  415. // Returns: VOID
  416. //
  417. // Notes: Memory for the UNICODE_STRING in the Prefix is released.
  418. //
  419. //--------------------------------------------------------------------------
  420. VOID
  421. PktEntryIdDestroy(
  422. IN PDFS_PKT_ENTRY_ID Victim OPTIONAL,
  423. IN BOOLEAN DeallocateAll
  424. )
  425. {
  426. DfsDbgTrace(+1, Dbg, "PktEntryIdDestroy: Entered\n", 0);
  427. if (ARGUMENT_PRESENT(Victim)) {
  428. if (Victim->Prefix.Buffer != NULL) {
  429. DfsFree(Victim->Prefix.Buffer);
  430. Victim->Prefix.Buffer = NULL;
  431. }
  432. if (Victim->ShortPrefix.Buffer != NULL) {
  433. DfsFree(Victim->ShortPrefix.Buffer);
  434. Victim->ShortPrefix.Buffer = NULL;
  435. }
  436. if (DeallocateAll)
  437. ExFreePool(Victim);
  438. } else
  439. DfsDbgTrace(0, Dbg, "PktEntryIdDestroy: No Victim\n", 0 );
  440. DfsDbgTrace(-1, Dbg, "PktEntryIdDestroy: Exit -> VOID\n", 0 );
  441. }
  442. //+-------------------------------------------------------------------------
  443. //
  444. // Function: PktEntryInfoDestroy, public
  445. //
  446. // Synopsis: PktEntryInfoDestroy destroys an info structure, and
  447. // optionally deallocates the structure itself.
  448. //
  449. // Arguments: [Victim] - the info structure to destroy
  450. // [DeallocateAll] - if True, indicates that the structure
  451. // itself is to be deallocated, otherwise, only the
  452. // service list within the structure is deallocated.
  453. //
  454. // Returns: VOID
  455. //
  456. // Notes:
  457. //
  458. //--------------------------------------------------------------------------
  459. VOID
  460. PktEntryInfoDestroy(
  461. IN PDFS_PKT_ENTRY_INFO Victim OPTIONAL,
  462. IN BOOLEAN DeallocateAll
  463. )
  464. {
  465. DfsDbgTrace(+1, Dbg, "PktEntryInfoDestroy: Entered\n", 0);
  466. if (ARGUMENT_PRESENT(Victim)) {
  467. ULONG i;
  468. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  469. if (Victim->ServiceList != NULL) {
  470. for (i = 0; i < Victim->ServiceCount; i++)
  471. PktServiceDestroy(&Victim->ServiceList[i], FALSE);
  472. }
  473. Victim->ServiceCount = 0;
  474. if (Victim->ServiceList != NULL) {
  475. ExFreePool(Victim->ServiceList);
  476. Victim->ServiceList = NULL;
  477. }
  478. if (DeallocateAll)
  479. ExFreePool(Victim);
  480. ExReleaseResourceLite( &DfsData.Resource );
  481. } else
  482. DfsDbgTrace(0, Dbg, "PktEntryInfoDestroy: No Victim\n", 0 );
  483. DfsDbgTrace(-1, Dbg, "PktEntryInfoDestroy: Exit -> VOID\n", 0 );
  484. }
  485. //+-------------------------------------------------------------------------
  486. //
  487. // Function: DfspFixService
  488. //
  489. // Synopsis: This function should be called when a new service's DS_MACHINE
  490. // struct has to be adjusted to make sure there is a unique one
  491. // for each machine in the PKT.
  492. //
  493. // Arguments: [pService] -- The Service struct to fix up.
  494. //
  495. // History: 23 August 1994 SudK Created.
  496. //
  497. //--------------------------------------------------------------------------
  498. NTSTATUS
  499. DfspFixService(
  500. PDFS_SERVICE pService
  501. )
  502. {
  503. NTSTATUS status = STATUS_SUCCESS;
  504. UNICODE_STRING ustrMachineName;
  505. PDS_MACHINE pMachine;
  506. PUNICODE_PREFIX_TABLE_ENTRY pfxEntry;
  507. PDFS_MACHINE_ENTRY machEntry;
  508. PDFS_PKT Pkt;
  509. ASSERT(pService != NULL);
  510. ASSERT(pService->pMachEntry != NULL);
  511. pMachine = pService->pMachEntry->pMachine;
  512. if (pMachine->cPrincipals == 0) {
  513. ASSERT(pService->Type && DFS_SERVICE_TYPE_DOWN_LEVEL);
  514. pService->pMachEntry->UseCount = 1;
  515. return(status);
  516. }
  517. //
  518. // We are called during PktCreateEntry. We already have appropriate locks
  519. //
  520. Pkt = _GetPkt();
  521. //
  522. // For now we only expect one principal. by design
  523. //
  524. ASSERT(pMachine->cPrincipals == 1);
  525. RtlInitUnicodeString(&ustrMachineName,
  526. pMachine->prgpwszPrincipals[0]);
  527. ASSERT(ustrMachineName.Buffer != NULL);
  528. pfxEntry = RtlFindUnicodePrefix(&Pkt->DSMachineTable,&ustrMachineName,TRUE);
  529. if (pfxEntry != NULL) {
  530. //
  531. // In this case the DS_Machine structure already exists. Just use the
  532. // existing DS_Machine struct and bump the UseCount
  533. //
  534. machEntry = CONTAINING_RECORD(pfxEntry,
  535. DFS_MACHINE_ENTRY,
  536. PrefixTableEntry);
  537. InterlockedIncrement( &machEntry->UseCount );
  538. //
  539. // Even though we are "reusing" the Machine Entry, we might have a
  540. // better DS_MACHINE (ie, one with more transports) in the incoming
  541. // one. If so, lets use the new one.
  542. //
  543. if (pMachine->cTransports > machEntry->pMachine->cTransports) {
  544. PDS_MACHINE pTempMachine;
  545. DfsDbgTrace(0, 0, "DfspFixService: Using new DS_MACHINE for [%wZ]\n", &ustrMachineName);
  546. pTempMachine = machEntry->pMachine;
  547. machEntry->pMachine = pMachine;
  548. pService->pMachEntry->pMachine = pTempMachine;
  549. RtlRemoveUnicodePrefix(
  550. &Pkt->DSMachineTable,
  551. &machEntry->PrefixTableEntry);
  552. machEntry->MachineName = ustrMachineName;
  553. RtlInsertUnicodePrefix(
  554. &Pkt->DSMachineTable,
  555. &machEntry->MachineName,
  556. &machEntry->PrefixTableEntry);
  557. }
  558. pService->pMachEntry = machEntry;
  559. } else {
  560. //
  561. // In this case the DS_Machine is not there in the table. Need to add
  562. // current one to the table.
  563. //
  564. machEntry = pService->pMachEntry;
  565. machEntry->UseCount = 1;
  566. machEntry->MachineName = ustrMachineName; // Use same mem in DS_MACHINE.
  567. //
  568. // Now insert the machEntry and then we are done. This better not fail.
  569. //
  570. if (!RtlInsertUnicodePrefix(&Pkt->DSMachineTable,
  571. &machEntry->MachineName,
  572. &machEntry->PrefixTableEntry)) {
  573. BugCheck("DFS Pkt inconsistent DfspFixService");
  574. }
  575. }
  576. return(status);
  577. }
  578. //+-------------------------------------------------------------------------
  579. //
  580. // Function: DfsFixDSMachineStructs
  581. //
  582. // Synopsis: For the entry given this function makes sure that there is
  583. // only one DS_MACHINE structure in the PKT. If there isn't one
  584. // then one is registered. If there is one then the same one is
  585. // used and the current one in the DFS_SERVICE struct is freed up.
  586. //
  587. // Arguments: [pEntry] -- The PKT entry that has to be fixed.
  588. //
  589. // Notes: If this function fails then it will reset the pEntry to the
  590. // same format it was when it was called.
  591. //
  592. // History: 22 Aug 1994 SudK Created.
  593. //
  594. //--------------------------------------------------------------------------
  595. NTSTATUS
  596. DfsFixDSMachineStructs(
  597. PDFS_PKT_ENTRY pEntry
  598. )
  599. {
  600. NTSTATUS status = STATUS_SUCCESS;
  601. ULONG i;
  602. PDFS_MACHINE_ENTRY *apMachineEntry;
  603. PDFS_SERVICE pService;
  604. if (pEntry->Info.ServiceCount == 0)
  605. return(status);
  606. //
  607. // In case of downlevel we do nothing
  608. //
  609. if (pEntry->Type & PKT_ENTRY_TYPE_NONDFS)
  610. return(status);
  611. apMachineEntry =
  612. ExAllocatePoolWithTag(PagedPool,
  613. sizeof(PDFS_MACHINE_ENTRY) * pEntry->Info.ServiceCount,
  614. ' puM');
  615. if (apMachineEntry == NULL) {
  616. return(STATUS_INSUFFICIENT_RESOURCES);
  617. }
  618. for (i=0; i < pEntry->Info.ServiceCount; i++) {
  619. //
  620. // First Save the current DS_Machine and then fix up
  621. //
  622. apMachineEntry[i] = pEntry->Info.ServiceList[i].pMachEntry;
  623. status = DfspFixService(&pEntry->Info.ServiceList[i]);
  624. if (!NT_SUCCESS(status)) {
  625. //
  626. // In this case we break and let the cleanup part below take care
  627. // of cleaning up everything.
  628. //
  629. break;
  630. }
  631. }
  632. if (!NT_SUCCESS(status)) {
  633. //
  634. // We need to cleanup in this case. I.E. reset all the PDS_MACHINEs
  635. // back to old values and decrement any usage counts on DS_MACHINE
  636. // structures.
  637. //
  638. ULONG j;
  639. for (j=0; j < i; j++) {
  640. pService = &pEntry->Info.ServiceList[j];
  641. //
  642. // These have already been fixed up so decrement the count on the
  643. // pMachine structs. Dont want to deallocate the pMachine structs
  644. // if we were the last one to use it.
  645. //
  646. DfsDecrementMachEntryCount(pService->pMachEntry, FALSE);
  647. if (apMachineEntry[j] != pService->pMachEntry)
  648. pService->pMachEntry = apMachineEntry[j];
  649. }
  650. }
  651. else {
  652. //
  653. // In this case everything went fine. So we need to free up the
  654. // DS_MACHINE structures that were superfluously allocated for now.
  655. //
  656. for (i=0; i<pEntry->Info.ServiceCount; i++) {
  657. if (apMachineEntry[i] != pEntry->Info.ServiceList[i].pMachEntry) {
  658. //
  659. // This means that the pMachine in the service list got replaced
  660. // by a different one so let us free this one now.
  661. //
  662. PktDSMachineDestroy(apMachineEntry[i]->pMachine, TRUE);
  663. ExFreePool( apMachineEntry[i] );
  664. }
  665. }
  666. }
  667. ExFreePool(apMachineEntry);
  668. return(status);
  669. }
  670. //+-------------------------------------------------------------------------
  671. //
  672. // Function: PktEntryAssemble, private
  673. //
  674. // Synopsis: PktpEntryAssemble blindly constructs a new partition
  675. // table entry and places it in the PKT. The caller must
  676. // have previously determined that no other entry with this
  677. // UID or Prefix existed. The PKT must be acquired exclusively
  678. // for this operation.
  679. //
  680. // Arguments: [Entry] - a pointer to an entry to be filled.
  681. // [Pkt] - pointer to a initialized (and acquired
  682. // exclusively) PKT
  683. // [EntryType] - the type of entry to assemble.
  684. // [EntryId] - pointer to the new entry's Id.
  685. // [EntryInfo] - pointer to the guts of the entry.
  686. //
  687. // Returns: [STATUS_SUCCESS] if no error.
  688. // [STATUS_INVALID_PARAMETER] - if the EntryId does not have a
  689. // UID or a Prefix (no such thing as an anonymous entry).
  690. // [PKT_ENTRY_EXISTS] - a new prefix table entry could not
  691. // be made.
  692. //
  693. // Notes: The EntryId and EntryInfo structures are MOVED (not
  694. // COPIED) to the new entry. The memory used for UNICODE_STRINGS
  695. // and DFS_SERVICE arrays is used by the new entry. The
  696. // associated fields in the EntryId and EntryInfo
  697. // structures passed as arguments are Zero'd to indicate that
  698. // the memory has been "deallocated" from these strutures and
  699. // reallocated to the newly create Entry. Note that this
  700. // routine does not deallocate the EntryId structure or
  701. // the EntryInfo structure itself. On successful return from
  702. // this function, the EntryId structure will be modified
  703. // to have a NULL Prefix entry, and the EntryInfo structure
  704. // will be modified to have zero services and a null ServiceList
  705. // entry.
  706. //
  707. //--------------------------------------------------------------------------
  708. NTSTATUS
  709. PktEntryAssemble(
  710. IN OUT PDFS_PKT_ENTRY Entry,
  711. IN PDFS_PKT Pkt,
  712. IN ULONG EntryType,
  713. IN PDFS_PKT_ENTRY_ID EntryId,
  714. IN PDFS_PKT_ENTRY_INFO EntryInfo,
  715. IN PDFS_TARGET_INFO pDfsTargetInfo
  716. )
  717. {
  718. NTSTATUS status = STATUS_SUCCESS;
  719. ULONG i;
  720. PDFS_SERVICE pService;
  721. DfsDbgTrace(+1, Dbg, "PktEntryAssemble: Entered\n", 0);
  722. ASSERT(ARGUMENT_PRESENT(Entry) &&
  723. ARGUMENT_PRESENT(EntryId));
  724. //
  725. // We do not allow the creation of entries
  726. // without any Uid or Prefix.
  727. //
  728. if (NullGuid(&EntryId->Uid) && EntryId->Prefix.Length == 0) {
  729. DfsDbgTrace(-1, Dbg, "PktEntryAssemble: Exit -> %08lx\n",
  730. ULongToPtr(STATUS_INVALID_PARAMETER) );
  731. return STATUS_INVALID_PARAMETER;
  732. }
  733. //
  734. // Zero out the entry.
  735. //
  736. RtlZeroMemory(Entry, sizeof(DFS_PKT_ENTRY));
  737. //
  738. // Mundane initialization
  739. //
  740. Entry->NodeTypeCode = DSFS_NTC_PKT_ENTRY;
  741. Entry->NodeByteSize = sizeof(DFS_PKT_ENTRY);
  742. //
  743. // Initialize the USN to 1
  744. //
  745. Entry->USN = 1;
  746. //
  747. // Move the Type, Id, and Info into this entry.
  748. //
  749. Entry->Type = EntryType;
  750. PktpEntryIdMove(&Entry->Id, EntryId);
  751. if (ARGUMENT_PRESENT(EntryInfo)) {
  752. PktpEntryInfoMove(&Entry->Info, EntryInfo);
  753. for (i = 0; i < Entry->Info.ServiceCount; i++) {
  754. Entry->Info.ServiceList[i].pMachEntry->UseCount = 1;
  755. }
  756. //
  757. // If we are setting up a PKT_ENTRY_TYPE_REFERRAL_SVC entry then we want
  758. // to mark ALL of its services to be REFERRAL_SERVICES as well.
  759. //
  760. if (EntryType & PKT_ENTRY_TYPE_REFERRAL_SVC) {
  761. pService = Entry->Info.ServiceList;
  762. for (i=0; i<Entry->Info.ServiceCount; i++) {
  763. pService->Type = pService->Type | DFS_SERVICE_TYPE_REFERRAL;
  764. pService++;
  765. }
  766. }
  767. //
  768. // Now we need to make sure that there is only one copy of the
  769. // DS_MACHINE structures for each of the above services that we added.
  770. //
  771. if (!(EntryType & PKT_ENTRY_TYPE_NONDFS)) {
  772. status = DfsFixDSMachineStructs(Entry);
  773. if (!NT_SUCCESS(status)) {
  774. //
  775. // We messed up. This means that something is really messed up.
  776. //
  777. DfsDbgTrace(0, 1,
  778. "DFS: DfsFixDSMachineStructs failed for %wZ\n",
  779. &Entry->Id.Prefix);
  780. PktpEntryIdMove(EntryId, &Entry->Id);
  781. if (ARGUMENT_PRESENT(EntryInfo))
  782. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  783. return(status);
  784. }
  785. }
  786. }
  787. //
  788. // Initialize the head of the subordinate list.
  789. //
  790. InitializeListHead(&Entry->SubordinateList);
  791. //
  792. // Initialize the head of the childList.
  793. //
  794. InitializeListHead(&Entry->ChildList);
  795. //
  796. // Try to get us into the prefix table.
  797. //
  798. if (DfsInsertUnicodePrefix(&Pkt->PrefixTable,
  799. &Entry->Id.Prefix,
  800. &Entry->PrefixTableEntry)) {
  801. //
  802. // We successfully created the prefix entry, so now we link
  803. // this entry into the PKT.
  804. //
  805. PktLinkEntry(Pkt, Entry);
  806. //
  807. // And insert into the short prefix table. We don't do error
  808. // recovery if this fails.
  809. //
  810. DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  811. &Entry->Id.ShortPrefix,
  812. &Entry->PrefixTableEntry);
  813. } else {
  814. //
  815. // We failed to get the entry into the prefix table. This
  816. // can only happen if a prefix already exists, and a prefix
  817. // can only exist if we've really gotten messed up...
  818. // We disassemble the entry and return an error.
  819. //
  820. DfsDbgTrace(0, 1,
  821. "DFS: PktEntryAssemble failed prefix table insert of %wZ\n",
  822. &Entry->Id.Prefix);
  823. PktpEntryIdMove(EntryId, &Entry->Id);
  824. if (ARGUMENT_PRESENT(EntryInfo))
  825. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  826. MupErrorCase++;
  827. status = DFS_STATUS_ENTRY_EXISTS;
  828. }
  829. if (status == STATUS_SUCCESS)
  830. {
  831. Entry->pDfsTargetInfo = pDfsTargetInfo;
  832. PktAcquireTargetInfo(pDfsTargetInfo);
  833. }
  834. DfsDbgTrace(-1, Dbg, "PktEntryAssemble: Exit -> %08lX\n", ULongToPtr(status) );
  835. // Bug 435639: if insert fails dont return SUCCESS!!
  836. return status;
  837. }
  838. //+-------------------------------------------------------------------------
  839. //
  840. // Function: PktEntryReassemble, private
  841. //
  842. // Synopsis: PktpEntryReassemble blindly reconstructs a partition
  843. // table entry. It provides a mechanism by which an existing
  844. // entry can be modified. The caller must have previously
  845. // determined that no other entry with this UID or Prefix
  846. // existed. The PKT must be acquired exclusively for this
  847. // operation.
  848. //
  849. // Arguments: [Entry] - a pointer to an entry to be reassembled.
  850. // [Pkt] - pointer to a initialized (and acquired
  851. // exclusively) PKT - must be provided if EntryId
  852. // is provided.
  853. // [EntryType] - the type of entry to reassemble.
  854. // [EntryId] - pointer to the entry's new Id.
  855. // [EntryInfo] - pointer to the new guts of the entry.
  856. //
  857. // Returns: [STATUS_SUCCESS] if no error.
  858. // [STATUS_INVALID_PARAMETER] - if the EntryId does not have a
  859. // UID or a Prefix (no such thing as an anonymous entry), or
  860. // and EntryId was provided but a PKT argument was not.
  861. // [DFS_STATUS_ENTRY_EXISTS] - a new prefix table entry could not
  862. // be made.
  863. // [DFS_STATUS_INCONSISTENT] - a new prefix table entry could
  864. // not be made, and we could not back out of the operation.
  865. // This status return indicates that the entry is no longer
  866. // in the prefix table associated with the PKT and that
  867. // it is likely that the PKT is inconsistent as a result.
  868. //
  869. // Notes: The EntryId and EntryInfo structures are MOVED (not
  870. // COPIED) to the entry, the old Id and Info are destroyed.
  871. // The memory used for UNICODE_STRINGS and DFS_SERVICE arrays
  872. // is used by the entry. The associated fields in the EntryId
  873. // and EntryInfo structures passed as arguments are Zero'd to
  874. // indicate that the memory has been "deallocated" from these
  875. // structures and reallocated to the newly created Entry. Note
  876. // that this routine does not deallocate the EntryId structure
  877. // or the EntryInfo structure itself. On successful return from
  878. // this function, the EntryId structure will be modified
  879. // to have a NULL Prefix entry, and the EntryInfo structure
  880. // will be modified to have zero services and a null ServiceList
  881. // entry.
  882. //
  883. //--------------------------------------------------------------------------
  884. NTSTATUS
  885. PktEntryReassemble(
  886. IN OUT PDFS_PKT_ENTRY Entry,
  887. IN PDFS_PKT Pkt,
  888. IN ULONG EntryType,
  889. IN PDFS_PKT_ENTRY_ID EntryId,
  890. IN PDFS_PKT_ENTRY_INFO EntryInfo,
  891. IN PDFS_TARGET_INFO pDfsTargetInfo
  892. )
  893. {
  894. NTSTATUS status = STATUS_SUCCESS;
  895. ULONG i;
  896. PDFS_SERVICE pService;
  897. DfsDbgTrace(+1, Dbg, "PktEntryReassemble: Entered\n", 0);
  898. ASSERT(ARGUMENT_PRESENT(Entry) &&
  899. ARGUMENT_PRESENT(Pkt));
  900. if (ARGUMENT_PRESENT(EntryId)) {
  901. DFS_PKT_ENTRY_ID oldId;
  902. //
  903. // We do not allow the creation of entries
  904. // without any Prefix.
  905. //
  906. if (EntryId->Prefix.Length == 0) {
  907. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n",
  908. ULongToPtr(STATUS_INVALID_PARAMETER) );
  909. return STATUS_INVALID_PARAMETER;
  910. }
  911. //
  912. // need to get rid of our current prefix info. We save the
  913. // old Id in case we fail to reassemble the new entry.
  914. //
  915. DfsRemoveUnicodePrefix(&Pkt->PrefixTable, &(Entry->Id.Prefix));
  916. DfsRemoveUnicodePrefix(&Pkt->ShortPrefixTable, &Entry->Id.ShortPrefix);
  917. PktpEntryIdMove(&oldId, &Entry->Id);
  918. //
  919. // Now we assemble the new Id and attempt to make a new entry
  920. // in the Pkt prefix table.
  921. //
  922. PktpEntryIdMove(&Entry->Id, EntryId);
  923. if (DfsInsertUnicodePrefix(&Pkt->PrefixTable,
  924. &Entry->Id.Prefix,
  925. &Entry->PrefixTableEntry)
  926. ) {
  927. //
  928. // Everything looks good so its safe to unload the old Id.
  929. //
  930. DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  931. &Entry->Id.ShortPrefix,
  932. &Entry->PrefixTableEntry);
  933. PktEntryIdDestroy(&oldId, FALSE);
  934. } else {
  935. //
  936. // We were unable to make the new prefix entry, so we
  937. // attempt to back out and put things back the way
  938. // they were.
  939. //
  940. status = DFS_STATUS_ENTRY_EXISTS;
  941. PktpEntryIdMove(EntryId, &Entry->Id);
  942. PktpEntryIdMove(&Entry->Id, &oldId);
  943. status = DfsInsertInPrefixTable(&Pkt->PrefixTable,
  944. &Entry->Id.Prefix,
  945. &Entry->PrefixTableEntry);
  946. if( !NT_SUCCESS( status ) ) {
  947. //
  948. // We can't get things back to where they were. Return
  949. // the error that DfsInsertInPrefixTable returned to us
  950. // (probably STATUS_INSUFFICIENT_RESOURCES)
  951. //
  952. // Destory the entry since it can't be found.
  953. //
  954. PktEntryDestroy(Entry, Pkt, TRUE);
  955. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n", ULongToPtr(status) );
  956. return status;
  957. } else {
  958. DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  959. &Entry->Id.ShortPrefix,
  960. &Entry->PrefixTableEntry);
  961. }
  962. }
  963. }
  964. //
  965. // Now we work on the entry info
  966. //
  967. if (NT_SUCCESS(status) && EntryInfo != 0) {
  968. //
  969. // Destroy the existing info structure and move the new
  970. // one into its place. Note that the active service is
  971. // Nulled.
  972. //
  973. PktEntryInfoDestroy(&Entry->Info, FALSE);
  974. PktpEntryInfoMove(&Entry->Info, EntryInfo);
  975. for (i = 0; i < Entry->Info.ServiceCount; i++) {
  976. Entry->Info.ServiceList[i].pMachEntry->UseCount = 1;
  977. }
  978. if (EntryType & PKT_ENTRY_TYPE_REFERRAL_SVC) {
  979. pService = Entry->Info.ServiceList;
  980. for (i=0; i<Entry->Info.ServiceCount; i++) {
  981. pService->Type = pService->Type | DFS_SERVICE_TYPE_REFERRAL;
  982. pService++;
  983. }
  984. }
  985. Entry->ActiveService = NULL;
  986. //
  987. // Now we need to make sure that there is only one copy of the
  988. // DS_MACHINE structures for each of the above services that we added.
  989. //
  990. if (!(EntryType & PKT_ENTRY_TYPE_NONDFS)) {
  991. status = DfsFixDSMachineStructs(Entry);
  992. if (!NT_SUCCESS(status)) {
  993. //
  994. // We messed up. This means that something is really messed up.
  995. //
  996. DfsDbgTrace(0, 1,
  997. "DFS: DfsFixDSMachineStructs failed for %wZ\n",
  998. &Entry->Id.Prefix);
  999. PktpEntryIdMove(EntryId, &Entry->Id);
  1000. if (ARGUMENT_PRESENT(EntryInfo))
  1001. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  1002. return(status);
  1003. }
  1004. }
  1005. }
  1006. if (NT_SUCCESS(status) && EntryInfo != 0) {
  1007. Entry->Type |= EntryType;
  1008. //
  1009. // If the new entry type is "local" we adjust all the
  1010. // subordinates to indicate that they are all now
  1011. // local exit points.
  1012. //
  1013. if (Entry->Type & PKT_ENTRY_TYPE_LOCAL) {
  1014. PDFS_PKT_ENTRY subEntry;
  1015. for (subEntry = PktEntryFirstSubordinate(Entry);
  1016. subEntry != NULL;
  1017. subEntry = PktEntryNextSubordinate(Entry, subEntry)) {
  1018. subEntry->Type |= PKT_ENTRY_TYPE_LOCAL_XPOINT;
  1019. }
  1020. }
  1021. //
  1022. // Finally, we update the USN
  1023. //
  1024. Entry->USN++;
  1025. DfsDbgTrace(0, Dbg, "Updated USN for %wZ", &Entry->Id.Prefix);
  1026. DfsDbgTrace(0, Dbg, " to %d\n", ULongToPtr(Entry->USN) );
  1027. }
  1028. if (status == STATUS_SUCCESS)
  1029. {
  1030. if (Entry->pDfsTargetInfo != NULL)
  1031. {
  1032. PktReleaseTargetInfo( Entry->pDfsTargetInfo );
  1033. Entry->pDfsTargetInfo = pDfsTargetInfo;
  1034. PktAcquireTargetInfo( pDfsTargetInfo );
  1035. }
  1036. }
  1037. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n", ULongToPtr(status) );
  1038. return status;
  1039. }
  1040. //+-------------------------------------------------------------------------
  1041. //
  1042. // Function: PktEntryDestroy, public
  1043. //
  1044. // Synopsis: PktEntryDestroy destroys an pkt entry structure, and
  1045. // optionally deallocates the structure itself.
  1046. //
  1047. // Arguments: [Victim] - the entry structure to destroy
  1048. // [Pkt] - pointer to the PKT this entry is in.
  1049. // [DeallocateAll] - if True, indicates that the structure
  1050. // itself is to be deallocated, otherwise, only the
  1051. // service list within the structure is deallocated.
  1052. //
  1053. // Returns: VOID
  1054. //
  1055. // Notes: This should not be called on an entry that has a
  1056. // local service attached, or which is a local exit point.
  1057. //
  1058. //--------------------------------------------------------------------------
  1059. VOID
  1060. PktEntryDestroy(
  1061. IN PDFS_PKT_ENTRY Victim OPTIONAL,
  1062. IN PDFS_PKT Pkt,
  1063. IN BOOLEAN DeallocateAll
  1064. )
  1065. {
  1066. DfsDbgTrace(+1, Dbg, "PktEntryDestroy: Entered\n", 0);
  1067. ASSERT(ARGUMENT_PRESENT(Pkt));
  1068. //
  1069. // Make sure we have a victim...
  1070. //
  1071. if (!ARGUMENT_PRESENT(Victim)) {
  1072. DfsDbgTrace(-1, Dbg, "PktEntryDestroy: Exit -> No Victim\n", 0);
  1073. return;
  1074. }
  1075. //
  1076. // We really don't expect to have a LocalService but then even if we
  1077. // do have one due to running DFSINIT again etc. let us try to handle it.
  1078. //
  1079. ASSERT(Victim->LocalService == NULL);
  1080. //
  1081. // Remove the entry from the prefix table and from the PKT.
  1082. //
  1083. DfsRemoveUnicodePrefix(&Pkt->PrefixTable, &(Victim->Id.Prefix));
  1084. DfsRemoveUnicodePrefix(&Pkt->ShortPrefixTable, &(Victim->Id.ShortPrefix));
  1085. PktUnlinkEntry(Pkt, Victim);
  1086. //
  1087. // We clear away all subordinates and parents.
  1088. //
  1089. PktEntryClearSubordinates(Victim);
  1090. if (Victim->Superior)
  1091. PktEntryUnlinkSubordinate(Victim->Superior, Victim);
  1092. //
  1093. // We clear all the children and parent pointers from here.
  1094. //
  1095. PktEntryClearChildren(Victim);
  1096. if (Victim->ClosestDC) {
  1097. PktEntryUnlinkChild(Victim->ClosestDC, Victim);
  1098. }
  1099. //
  1100. // Now destroy the body of the entry (id, and info).
  1101. //
  1102. Victim->ActiveService = NULL;
  1103. PktEntryIdDestroy(&Victim->Id, FALSE);
  1104. PktEntryInfoDestroy(&Victim->Info, FALSE);
  1105. if (Victim->pDfsTargetInfo != NULL)
  1106. {
  1107. PktReleaseTargetInfo(Victim->pDfsTargetInfo);
  1108. Victim->pDfsTargetInfo = NULL;
  1109. }
  1110. //
  1111. // Deallocate everything if they want us to.
  1112. //
  1113. if (DeallocateAll)
  1114. ExFreePool(Victim);
  1115. DfsDbgTrace(-1, Dbg, "PktEntryDestroy: Exit -> VOID\n", 0);
  1116. }
  1117. //+-------------------------------------------------------------------------
  1118. //
  1119. // Function: PktEntryClearSubordinates, public
  1120. //
  1121. // Synopsis: PktEntryClearSubordinates unlinks all subordinates from
  1122. // this entry.
  1123. //
  1124. // Arguments: [PktEntry] - a pointer to an entry that is to have all its
  1125. // subordinates unlinked.
  1126. //
  1127. // Returns: VOID
  1128. //
  1129. // Notes:
  1130. //
  1131. //--------------------------------------------------------------------------
  1132. VOID
  1133. PktEntryClearSubordinates(
  1134. IN PDFS_PKT_ENTRY PktEntry
  1135. )
  1136. {
  1137. PDFS_PKT_ENTRY subEntry;
  1138. DfsDbgTrace(+1, Dbg, "PktEntryClearSubordinates: Entered\n", 0);
  1139. ASSERT(ARGUMENT_PRESENT(PktEntry));
  1140. subEntry = PktEntryFirstSubordinate(PktEntry);
  1141. while (subEntry) {
  1142. PktEntryUnlinkSubordinate(PktEntry, subEntry);
  1143. subEntry = PktEntryFirstSubordinate(PktEntry);
  1144. }
  1145. DfsDbgTrace(-1, Dbg, "PktEntryClearSubordinates: Exit -> VOID\n", 0)
  1146. }
  1147. //+-------------------------------------------------------------------------
  1148. //
  1149. // Function: PktEntryClearChildren, public
  1150. //
  1151. // Synopsis: PktEntryClearChildren unlinks all children from
  1152. // this entry.
  1153. //
  1154. // Arguments: [PktEntry] - a pointer to an entry that is to have all its
  1155. // children unlinked.
  1156. //
  1157. // Returns: VOID
  1158. //
  1159. // Notes:
  1160. //
  1161. //--------------------------------------------------------------------------
  1162. VOID
  1163. PktEntryClearChildren(
  1164. IN PDFS_PKT_ENTRY PktEntry
  1165. )
  1166. {
  1167. PDFS_PKT_ENTRY subEntry;
  1168. DfsDbgTrace(+1, Dbg, "PktEntryClearChildren: Entered\n", 0);
  1169. ASSERT(ARGUMENT_PRESENT(PktEntry));
  1170. subEntry = PktEntryFirstChild(PktEntry);
  1171. while (subEntry) {
  1172. PktEntryUnlinkAndRelinkChild(PktEntry, subEntry);
  1173. subEntry = PktEntryFirstChild(PktEntry);
  1174. }
  1175. DfsDbgTrace(-1, Dbg, "PktEntryClearChildren: Exit -> VOID\n", 0)
  1176. }
  1177. //+-------------------------------------------------------------------------
  1178. //
  1179. // Function: PktSpecialEntryDestroy, public
  1180. //
  1181. // Synopsis: Returns a DFS_SPECIAL_ENTRY's expansion list to the free pool
  1182. //
  1183. // Arguments: [pSpecialEntry] - Pointer to DFS_SPECIAL_ENTRY
  1184. //
  1185. // Returns: VOID
  1186. //
  1187. // Notes:
  1188. //
  1189. //--------------------------------------------------------------------------
  1190. VOID
  1191. PktSpecialEntryDestroy(
  1192. IN PDFS_SPECIAL_ENTRY pSpecialEntry)
  1193. {
  1194. PDFS_EXPANDED_NAME pExpandedNames = pSpecialEntry->ExpandedNames;
  1195. PUNICODE_STRING pustr;
  1196. ULONG i;
  1197. //
  1198. // Free all the UNICODE_STRING ExpandedName buffers
  1199. //
  1200. if (pExpandedNames) {
  1201. for (i = 0; i < pSpecialEntry->ExpandedCount; i++) {
  1202. pustr = &pExpandedNames[i].ExpandedName;
  1203. if (pustr->Buffer) {
  1204. ExFreePool(pustr->Buffer);
  1205. }
  1206. }
  1207. //
  1208. // Free the array of ExpandedNames
  1209. //
  1210. ExFreePool(pExpandedNames);
  1211. }
  1212. //
  1213. // Free the SpecialName buffer
  1214. //
  1215. if (pSpecialEntry->SpecialName.Buffer != NULL) {
  1216. ExFreePool(pSpecialEntry->SpecialName.Buffer);
  1217. }
  1218. //
  1219. // Free the entry itself
  1220. //
  1221. ExFreePool(pSpecialEntry);
  1222. }