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.

1477 lines
46 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. BOOLEAN DiscardResult;
  722. DfsDbgTrace(+1, Dbg, "PktEntryAssemble: Entered\n", 0);
  723. ASSERT(ARGUMENT_PRESENT(Entry) &&
  724. ARGUMENT_PRESENT(EntryId));
  725. //
  726. // We do not allow the creation of entries
  727. // without any Uid or Prefix.
  728. //
  729. if (NullGuid(&EntryId->Uid) && EntryId->Prefix.Length == 0) {
  730. DfsDbgTrace(-1, Dbg, "PktEntryAssemble: Exit -> %08lx\n",
  731. ULongToPtr(STATUS_INVALID_PARAMETER) );
  732. return STATUS_INVALID_PARAMETER;
  733. }
  734. //
  735. // Zero out the entry.
  736. //
  737. RtlZeroMemory(Entry, sizeof(DFS_PKT_ENTRY));
  738. //
  739. // Mundane initialization
  740. //
  741. Entry->NodeTypeCode = DSFS_NTC_PKT_ENTRY;
  742. Entry->NodeByteSize = sizeof(DFS_PKT_ENTRY);
  743. //
  744. // Initialize the USN to 1
  745. //
  746. Entry->USN = 1;
  747. //
  748. // Move the Type, Id, and Info into this entry.
  749. //
  750. Entry->Type = EntryType;
  751. PktpEntryIdMove(&Entry->Id, EntryId);
  752. if (ARGUMENT_PRESENT(EntryInfo)) {
  753. PktpEntryInfoMove(&Entry->Info, EntryInfo);
  754. for (i = 0; i < Entry->Info.ServiceCount; i++) {
  755. Entry->Info.ServiceList[i].pMachEntry->UseCount = 1;
  756. }
  757. //
  758. // If we are setting up a PKT_ENTRY_TYPE_REFERRAL_SVC entry then we want
  759. // to mark ALL of its services to be REFERRAL_SERVICES as well.
  760. //
  761. if (EntryType & PKT_ENTRY_TYPE_REFERRAL_SVC) {
  762. pService = Entry->Info.ServiceList;
  763. for (i=0; i<Entry->Info.ServiceCount; i++) {
  764. pService->Type = pService->Type | DFS_SERVICE_TYPE_REFERRAL;
  765. pService++;
  766. }
  767. }
  768. //
  769. // Now we need to make sure that there is only one copy of the
  770. // DS_MACHINE structures for each of the above services that we added.
  771. //
  772. if (!(EntryType & PKT_ENTRY_TYPE_NONDFS)) {
  773. status = DfsFixDSMachineStructs(Entry);
  774. if (!NT_SUCCESS(status)) {
  775. //
  776. // We messed up. This means that something is really messed up.
  777. //
  778. DfsDbgTrace(0, 1,
  779. "DFS: DfsFixDSMachineStructs failed for %wZ\n",
  780. &Entry->Id.Prefix);
  781. PktpEntryIdMove(EntryId, &Entry->Id);
  782. if (ARGUMENT_PRESENT(EntryInfo))
  783. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  784. return(status);
  785. }
  786. }
  787. }
  788. //
  789. // Initialize the head of the subordinate list.
  790. //
  791. InitializeListHead(&Entry->SubordinateList);
  792. //
  793. // Initialize the head of the childList.
  794. //
  795. InitializeListHead(&Entry->ChildList);
  796. //
  797. // Try to get us into the prefix table.
  798. //
  799. if (DfsInsertUnicodePrefix(&Pkt->PrefixTable,
  800. &Entry->Id.Prefix,
  801. &Entry->PrefixTableEntry)) {
  802. //
  803. // We successfully created the prefix entry, so now we link
  804. // this entry into the PKT.
  805. //
  806. PktLinkEntry(Pkt, Entry);
  807. //
  808. // And insert into the short prefix table. We don't do error
  809. // recovery if this fails.
  810. //
  811. DiscardResult = DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  812. &Entry->Id.ShortPrefix,
  813. &Entry->PrefixTableEntry);
  814. } else {
  815. //
  816. // We failed to get the entry into the prefix table. This
  817. // can only happen if a prefix already exists, and a prefix
  818. // can only exist if we've really gotten messed up...
  819. // We disassemble the entry and return an error.
  820. //
  821. DfsDbgTrace(0, 1,
  822. "DFS: PktEntryAssemble failed prefix table insert of %wZ\n",
  823. &Entry->Id.Prefix);
  824. PktpEntryIdMove(EntryId, &Entry->Id);
  825. if (ARGUMENT_PRESENT(EntryInfo))
  826. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  827. MupErrorCase++;
  828. status = DFS_STATUS_ENTRY_EXISTS;
  829. }
  830. if (status == STATUS_SUCCESS)
  831. {
  832. Entry->pDfsTargetInfo = pDfsTargetInfo;
  833. PktAcquireTargetInfo(pDfsTargetInfo);
  834. }
  835. DfsDbgTrace(-1, Dbg, "PktEntryAssemble: Exit -> %08lX\n", ULongToPtr(status) );
  836. // Bug 435639: if insert fails dont return SUCCESS!!
  837. return status;
  838. }
  839. //+-------------------------------------------------------------------------
  840. //
  841. // Function: PktEntryReassemble, private
  842. //
  843. // Synopsis: PktpEntryReassemble blindly reconstructs a partition
  844. // table entry. It provides a mechanism by which an existing
  845. // entry can be modified. The caller must have previously
  846. // determined that no other entry with this UID or Prefix
  847. // existed. The PKT must be acquired exclusively for this
  848. // operation.
  849. //
  850. // Arguments: [Entry] - a pointer to an entry to be reassembled.
  851. // [Pkt] - pointer to a initialized (and acquired
  852. // exclusively) PKT - must be provided if EntryId
  853. // is provided.
  854. // [EntryType] - the type of entry to reassemble.
  855. // [EntryId] - pointer to the entry's new Id.
  856. // [EntryInfo] - pointer to the new guts of the entry.
  857. //
  858. // Returns: [STATUS_SUCCESS] if no error.
  859. // [STATUS_INVALID_PARAMETER] - if the EntryId does not have a
  860. // UID or a Prefix (no such thing as an anonymous entry), or
  861. // and EntryId was provided but a PKT argument was not.
  862. // [DFS_STATUS_ENTRY_EXISTS] - a new prefix table entry could not
  863. // be made.
  864. // [DFS_STATUS_INCONSISTENT] - a new prefix table entry could
  865. // not be made, and we could not back out of the operation.
  866. // This status return indicates that the entry is no longer
  867. // in the prefix table associated with the PKT and that
  868. // it is likely that the PKT is inconsistent as a result.
  869. //
  870. // Notes: The EntryId and EntryInfo structures are MOVED (not
  871. // COPIED) to the entry, the old Id and Info are destroyed.
  872. // The memory used for UNICODE_STRINGS and DFS_SERVICE arrays
  873. // is used by the entry. The associated fields in the EntryId
  874. // and EntryInfo structures passed as arguments are Zero'd to
  875. // indicate that the memory has been "deallocated" from these
  876. // structures and reallocated to the newly created Entry. Note
  877. // that this routine does not deallocate the EntryId structure
  878. // or the EntryInfo structure itself. On successful return from
  879. // this function, the EntryId structure will be modified
  880. // to have a NULL Prefix entry, and the EntryInfo structure
  881. // will be modified to have zero services and a null ServiceList
  882. // entry.
  883. //
  884. //--------------------------------------------------------------------------
  885. NTSTATUS
  886. PktEntryReassemble(
  887. IN OUT PDFS_PKT_ENTRY Entry,
  888. IN PDFS_PKT Pkt,
  889. IN ULONG EntryType,
  890. IN PDFS_PKT_ENTRY_ID EntryId,
  891. IN PDFS_PKT_ENTRY_INFO EntryInfo,
  892. IN PDFS_TARGET_INFO pDfsTargetInfo
  893. )
  894. {
  895. NTSTATUS status = STATUS_SUCCESS;
  896. ULONG i;
  897. PDFS_SERVICE pService;
  898. NTSTATUS DiscardStatus;
  899. BOOLEAN DiscardResult;
  900. DfsDbgTrace(+1, Dbg, "PktEntryReassemble: Entered\n", 0);
  901. ASSERT(ARGUMENT_PRESENT(Entry) &&
  902. ARGUMENT_PRESENT(Pkt));
  903. if (ARGUMENT_PRESENT(EntryId)) {
  904. DFS_PKT_ENTRY_ID oldId;
  905. //
  906. // We do not allow the creation of entries
  907. // without any Prefix.
  908. //
  909. if (EntryId->Prefix.Length == 0) {
  910. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n",
  911. ULongToPtr(STATUS_INVALID_PARAMETER) );
  912. return STATUS_INVALID_PARAMETER;
  913. }
  914. //
  915. // need to get rid of our current prefix info. We save the
  916. // old Id in case we fail to reassemble the new entry.
  917. //
  918. DiscardStatus = DfsRemoveUnicodePrefix(&Pkt->PrefixTable, &(Entry->Id.Prefix));
  919. DiscardStatus = DfsRemoveUnicodePrefix(&Pkt->ShortPrefixTable, &Entry->Id.ShortPrefix);
  920. PktpEntryIdMove(&oldId, &Entry->Id);
  921. //
  922. // Now we assemble the new Id and attempt to make a new entry
  923. // in the Pkt prefix table.
  924. //
  925. PktpEntryIdMove(&Entry->Id, EntryId);
  926. if (DfsInsertUnicodePrefix(&Pkt->PrefixTable,
  927. &Entry->Id.Prefix,
  928. &Entry->PrefixTableEntry)
  929. ) {
  930. //
  931. // Everything looks good so its safe to unload the old Id.
  932. //
  933. DiscardResult = DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  934. &Entry->Id.ShortPrefix,
  935. &Entry->PrefixTableEntry);
  936. PktEntryIdDestroy(&oldId, FALSE);
  937. } else {
  938. //
  939. // We were unable to make the new prefix entry, so we
  940. // attempt to back out and put things back the way
  941. // they were.
  942. //
  943. status = DFS_STATUS_ENTRY_EXISTS;
  944. PktpEntryIdMove(EntryId, &Entry->Id);
  945. PktpEntryIdMove(&Entry->Id, &oldId);
  946. status = DfsInsertInPrefixTable(&Pkt->PrefixTable,
  947. &Entry->Id.Prefix,
  948. &Entry->PrefixTableEntry);
  949. if( !NT_SUCCESS( status ) ) {
  950. //
  951. // We can't get things back to where they were. Return
  952. // the error that DfsInsertInPrefixTable returned to us
  953. // (probably STATUS_INSUFFICIENT_RESOURCES)
  954. //
  955. // Destory the entry since it can't be found.
  956. //
  957. PktEntryDestroy(Entry, Pkt, TRUE);
  958. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n", ULongToPtr(status) );
  959. return status;
  960. } else {
  961. DiscardResult = DfsInsertUnicodePrefix(&Pkt->ShortPrefixTable,
  962. &Entry->Id.ShortPrefix,
  963. &Entry->PrefixTableEntry);
  964. }
  965. }
  966. }
  967. //
  968. // Now we work on the entry info
  969. //
  970. if (NT_SUCCESS(status) && EntryInfo != 0) {
  971. //
  972. // Destroy the existing info structure and move the new
  973. // one into its place. Note that the active service is
  974. // Nulled.
  975. //
  976. PktEntryInfoDestroy(&Entry->Info, FALSE);
  977. PktpEntryInfoMove(&Entry->Info, EntryInfo);
  978. for (i = 0; i < Entry->Info.ServiceCount; i++) {
  979. Entry->Info.ServiceList[i].pMachEntry->UseCount = 1;
  980. }
  981. if (EntryType & PKT_ENTRY_TYPE_REFERRAL_SVC) {
  982. pService = Entry->Info.ServiceList;
  983. for (i=0; i<Entry->Info.ServiceCount; i++) {
  984. pService->Type = pService->Type | DFS_SERVICE_TYPE_REFERRAL;
  985. pService++;
  986. }
  987. }
  988. Entry->ActiveService = NULL;
  989. //
  990. // Now we need to make sure that there is only one copy of the
  991. // DS_MACHINE structures for each of the above services that we added.
  992. //
  993. if (!(EntryType & PKT_ENTRY_TYPE_NONDFS)) {
  994. status = DfsFixDSMachineStructs(Entry);
  995. if (!NT_SUCCESS(status)) {
  996. //
  997. // We messed up. This means that something is really messed up.
  998. //
  999. DfsDbgTrace(0, 1,
  1000. "DFS: DfsFixDSMachineStructs failed for %wZ\n",
  1001. &Entry->Id.Prefix);
  1002. PktpEntryIdMove(EntryId, &Entry->Id);
  1003. if (ARGUMENT_PRESENT(EntryInfo))
  1004. PktpEntryInfoMove(EntryInfo, &Entry->Info);
  1005. return(status);
  1006. }
  1007. }
  1008. }
  1009. if (NT_SUCCESS(status) && EntryInfo != 0) {
  1010. Entry->Type |= EntryType;
  1011. //
  1012. // If the new entry type is "local" we adjust all the
  1013. // subordinates to indicate that they are all now
  1014. // local exit points.
  1015. //
  1016. if (Entry->Type & PKT_ENTRY_TYPE_LOCAL) {
  1017. PDFS_PKT_ENTRY subEntry;
  1018. for (subEntry = PktEntryFirstSubordinate(Entry);
  1019. subEntry != NULL;
  1020. subEntry = PktEntryNextSubordinate(Entry, subEntry)) {
  1021. subEntry->Type |= PKT_ENTRY_TYPE_LOCAL_XPOINT;
  1022. }
  1023. }
  1024. //
  1025. // Finally, we update the USN
  1026. //
  1027. Entry->USN++;
  1028. DfsDbgTrace(0, Dbg, "Updated USN for %wZ", &Entry->Id.Prefix);
  1029. DfsDbgTrace(0, Dbg, " to %d\n", ULongToPtr(Entry->USN) );
  1030. }
  1031. if (status == STATUS_SUCCESS)
  1032. {
  1033. if (Entry->pDfsTargetInfo != NULL)
  1034. {
  1035. PktReleaseTargetInfo( Entry->pDfsTargetInfo );
  1036. Entry->pDfsTargetInfo = pDfsTargetInfo;
  1037. PktAcquireTargetInfo( pDfsTargetInfo );
  1038. }
  1039. }
  1040. DfsDbgTrace(-1, Dbg, "PktEntryReassemble: Exit -> %08lx\n", ULongToPtr(status) );
  1041. return status;
  1042. }
  1043. //+-------------------------------------------------------------------------
  1044. //
  1045. // Function: PktEntryDestroy, public
  1046. //
  1047. // Synopsis: PktEntryDestroy destroys an pkt entry structure, and
  1048. // optionally deallocates the structure itself.
  1049. //
  1050. // Arguments: [Victim] - the entry structure to destroy
  1051. // [Pkt] - pointer to the PKT this entry is in.
  1052. // [DeallocateAll] - if True, indicates that the structure
  1053. // itself is to be deallocated, otherwise, only the
  1054. // service list within the structure is deallocated.
  1055. //
  1056. // Returns: VOID
  1057. //
  1058. // Notes: This should not be called on an entry that has a
  1059. // local service attached, or which is a local exit point.
  1060. //
  1061. //--------------------------------------------------------------------------
  1062. VOID
  1063. PktEntryDestroy(
  1064. IN PDFS_PKT_ENTRY Victim OPTIONAL,
  1065. IN PDFS_PKT Pkt,
  1066. IN BOOLEAN DeallocateAll
  1067. )
  1068. {
  1069. NTSTATUS DiscardStatus;
  1070. DfsDbgTrace(+1, Dbg, "PktEntryDestroy: Entered\n", 0);
  1071. ASSERT(ARGUMENT_PRESENT(Pkt));
  1072. //
  1073. // Make sure we have a victim...
  1074. //
  1075. if (!ARGUMENT_PRESENT(Victim)) {
  1076. DfsDbgTrace(-1, Dbg, "PktEntryDestroy: Exit -> No Victim\n", 0);
  1077. return;
  1078. }
  1079. //
  1080. // We really don't expect to have a LocalService but then even if we
  1081. // do have one due to running DFSINIT again etc. let us try to handle it.
  1082. //
  1083. ASSERT(Victim->LocalService == NULL);
  1084. //
  1085. // Remove the entry from the prefix table and from the PKT.
  1086. //
  1087. DiscardStatus = DfsRemoveUnicodePrefix(&Pkt->PrefixTable, &(Victim->Id.Prefix));
  1088. DiscardStatus = DfsRemoveUnicodePrefix(&Pkt->ShortPrefixTable, &(Victim->Id.ShortPrefix));
  1089. PktUnlinkEntry(Pkt, Victim);
  1090. //
  1091. // We clear away all subordinates and parents.
  1092. //
  1093. PktEntryClearSubordinates(Victim);
  1094. if (Victim->Superior)
  1095. PktEntryUnlinkSubordinate(Victim->Superior, Victim);
  1096. //
  1097. // We clear all the children and parent pointers from here.
  1098. //
  1099. PktEntryClearChildren(Victim);
  1100. if (Victim->ClosestDC) {
  1101. PktEntryUnlinkChild(Victim->ClosestDC, Victim);
  1102. }
  1103. //
  1104. // Now destroy the body of the entry (id, and info).
  1105. //
  1106. Victim->ActiveService = NULL;
  1107. PktEntryIdDestroy(&Victim->Id, FALSE);
  1108. PktEntryInfoDestroy(&Victim->Info, FALSE);
  1109. if (Victim->pDfsTargetInfo != NULL)
  1110. {
  1111. PktReleaseTargetInfo(Victim->pDfsTargetInfo);
  1112. Victim->pDfsTargetInfo = NULL;
  1113. }
  1114. //
  1115. // Deallocate everything if they want us to.
  1116. //
  1117. if (DeallocateAll)
  1118. ExFreePool(Victim);
  1119. DfsDbgTrace(-1, Dbg, "PktEntryDestroy: Exit -> VOID\n", 0);
  1120. }
  1121. //+-------------------------------------------------------------------------
  1122. //
  1123. // Function: PktEntryClearSubordinates, public
  1124. //
  1125. // Synopsis: PktEntryClearSubordinates unlinks all subordinates from
  1126. // this entry.
  1127. //
  1128. // Arguments: [PktEntry] - a pointer to an entry that is to have all its
  1129. // subordinates unlinked.
  1130. //
  1131. // Returns: VOID
  1132. //
  1133. // Notes:
  1134. //
  1135. //--------------------------------------------------------------------------
  1136. VOID
  1137. PktEntryClearSubordinates(
  1138. IN PDFS_PKT_ENTRY PktEntry
  1139. )
  1140. {
  1141. PDFS_PKT_ENTRY subEntry;
  1142. DfsDbgTrace(+1, Dbg, "PktEntryClearSubordinates: Entered\n", 0);
  1143. ASSERT(ARGUMENT_PRESENT(PktEntry));
  1144. subEntry = PktEntryFirstSubordinate(PktEntry);
  1145. while (subEntry) {
  1146. PktEntryUnlinkSubordinate(PktEntry, subEntry);
  1147. subEntry = PktEntryFirstSubordinate(PktEntry);
  1148. }
  1149. DfsDbgTrace(-1, Dbg, "PktEntryClearSubordinates: Exit -> VOID\n", 0)
  1150. }
  1151. //+-------------------------------------------------------------------------
  1152. //
  1153. // Function: PktEntryClearChildren, public
  1154. //
  1155. // Synopsis: PktEntryClearChildren unlinks all children from
  1156. // this entry.
  1157. //
  1158. // Arguments: [PktEntry] - a pointer to an entry that is to have all its
  1159. // children unlinked.
  1160. //
  1161. // Returns: VOID
  1162. //
  1163. // Notes:
  1164. //
  1165. //--------------------------------------------------------------------------
  1166. VOID
  1167. PktEntryClearChildren(
  1168. IN PDFS_PKT_ENTRY PktEntry
  1169. )
  1170. {
  1171. PDFS_PKT_ENTRY subEntry;
  1172. DfsDbgTrace(+1, Dbg, "PktEntryClearChildren: Entered\n", 0);
  1173. ASSERT(ARGUMENT_PRESENT(PktEntry));
  1174. subEntry = PktEntryFirstChild(PktEntry);
  1175. while (subEntry) {
  1176. PktEntryUnlinkAndRelinkChild(PktEntry, subEntry);
  1177. subEntry = PktEntryFirstChild(PktEntry);
  1178. }
  1179. DfsDbgTrace(-1, Dbg, "PktEntryClearChildren: Exit -> VOID\n", 0)
  1180. }
  1181. //+-------------------------------------------------------------------------
  1182. //
  1183. // Function: PktSpecialEntryDestroy, public
  1184. //
  1185. // Synopsis: Returns a DFS_SPECIAL_ENTRY's expansion list to the free pool
  1186. //
  1187. // Arguments: [pSpecialEntry] - Pointer to DFS_SPECIAL_ENTRY
  1188. //
  1189. // Returns: VOID
  1190. //
  1191. // Notes:
  1192. //
  1193. //--------------------------------------------------------------------------
  1194. VOID
  1195. PktSpecialEntryDestroy(
  1196. IN PDFS_SPECIAL_ENTRY pSpecialEntry)
  1197. {
  1198. PDFS_EXPANDED_NAME pExpandedNames = pSpecialEntry->ExpandedNames;
  1199. PUNICODE_STRING pustr;
  1200. ULONG i;
  1201. //
  1202. // Free all the UNICODE_STRING ExpandedName buffers
  1203. //
  1204. if (pExpandedNames) {
  1205. for (i = 0; i < pSpecialEntry->ExpandedCount; i++) {
  1206. pustr = &pExpandedNames[i].ExpandedName;
  1207. if (pustr->Buffer) {
  1208. ExFreePool(pustr->Buffer);
  1209. }
  1210. }
  1211. //
  1212. // Free the array of ExpandedNames
  1213. //
  1214. ExFreePool(pExpandedNames);
  1215. }
  1216. //
  1217. // Free the SpecialName buffer
  1218. //
  1219. if (pSpecialEntry->SpecialName.Buffer != NULL) {
  1220. ExFreePool(pSpecialEntry->SpecialName.Buffer);
  1221. }
  1222. //
  1223. // Free the entry itself
  1224. //
  1225. ExFreePool(pSpecialEntry);
  1226. }