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.

2354 lines
72 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsADBlobStore.cxx
  6. //
  7. // Contents: the AD Blob DFS Store class, this contains the registry
  8. // specific functionality.
  9. //
  10. // Classes: DfsADBlobStore.
  11. //
  12. // History: Dec. 8 2000, Author: udayh
  13. // April 9 2001 Rohanp - Added ADSI specific code
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include "DfsADBlobStore.hxx"
  17. #include "DfsADBlobRootFolder.hxx"
  18. #include "DfsFilterApi.hxx"
  19. #include "dfsmisc.h"
  20. #include "lmdfs.h"
  21. #include "shlwapi.h"
  22. #include "align.h"
  23. #include "dfserror.hxx"
  24. #include "DomainControllerSupport.hxx"
  25. #include "dfsadsiapi.hxx"
  26. #include "dfsinit.hxx"
  27. #include "DfsAdBlobStore.tmh"
  28. //+----------------------------------------------------------------------------
  29. //
  30. // Class: DfsADBlobStore.
  31. //
  32. // Synopsis: This class inherits the basic DfsStore, and extends it
  33. // to include the blob DS specific functionality.
  34. //
  35. //-----------------------------------------------------------------------------
  36. //+-------------------------------------------------------------------------
  37. //
  38. // Function: StoreRecognizer - the recognizer for the store.
  39. //
  40. // Arguments: Name - the namespace of interest.
  41. //
  42. // Returns: Status
  43. // ERROR_SUCCESS on success
  44. // ERROR status code otherwise
  45. //
  46. //
  47. // Description: This routine checks if the specified namespace holds
  48. // a domain based DFS. If it does, it reads in the
  49. // root in that namespace and creates and adds it to our
  50. // list of known roots, if it doesn't already exist in our list.
  51. //
  52. //--------------------------------------------------------------------------
  53. DFSSTATUS
  54. DfsADBlobStore::StoreRecognizer(
  55. LPWSTR Name )
  56. {
  57. DFSSTATUS Status = ERROR_SUCCESS;
  58. HKEY ADBlobDfsKey;
  59. BOOLEAN MachineContacted = FALSE;
  60. DFSSTATUS NewDfsStatus = ERROR_SUCCESS;
  61. //
  62. // Make sure the namespace is the name of a machine. FT based
  63. // dfs exist only on domains.
  64. //
  65. if (IsEmptyString(Name) == FALSE)
  66. {
  67. Status = DfsIsThisADomainName( Name );
  68. }
  69. DFS_TRACE_LOW(REFERRAL_SERVER, "DfsADBlob:StoreRecognizer, %ws Is domain Status %x\n",
  70. Name, Status);
  71. //
  72. // Now, open the registry key where we store all the DFS root
  73. // information.
  74. //
  75. if ( Status == ERROR_SUCCESS )
  76. {
  77. Status = GetNewADBlobRegistryKey( Name,
  78. FALSE, // write permission not required
  79. &MachineContacted,
  80. &ADBlobDfsKey );
  81. if (Status == ERROR_SUCCESS)
  82. {
  83. Status = StoreRecognizeNewDfs( Name,
  84. ADBlobDfsKey );
  85. RegCloseKey( ADBlobDfsKey );
  86. }
  87. }
  88. //
  89. // Need to refine the return status further: success should mean
  90. // machine is not domain dfs or we have read the domain dfs data
  91. // correctly.
  92. //
  93. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "DfsADBlob:StoreRecognizer, Status %x\n",
  94. Status);
  95. return Status;
  96. }
  97. //+-------------------------------------------------------------------------
  98. //
  99. // Function: StoreRecognizer - the recognizer for the store.
  100. //
  101. // Arguments: DfsNameContext - the namespace of interest.
  102. // LogicalShare
  103. //
  104. // Returns: Status
  105. // ERROR_SUCCESS on success
  106. // ERROR status code otherwise
  107. //
  108. //
  109. // Description: This routine checks if the specified namespace holds
  110. // a domain based DFS. If it does, it reads in the
  111. // root in that namespace and creates and adds it to our
  112. // list of known roots, if it doesn't already exist in our list.
  113. //
  114. //--------------------------------------------------------------------------
  115. DFSSTATUS
  116. DfsADBlobStore::StoreRecognizer (
  117. LPWSTR DfsNameContext,
  118. PUNICODE_STRING pLogicalShare )
  119. {
  120. DFSSTATUS Status;
  121. Status = DfsIsThisADomainName( DfsNameContext );
  122. if (Status == ERROR_SUCCESS)
  123. {
  124. Status = StoreRecognizeNewDfs( DfsNameContext,
  125. pLogicalShare );
  126. }
  127. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "DfsADBlob:StoreRecognizer (remote), Status %x\n",
  128. Status);
  129. return Status;
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Function: CreateNewRootFolder - creates a new root folder
  134. //
  135. // Arguments:
  136. // LPWSTR DfsNameContextString - name context string
  137. // LPWSTR RootRegKeyName - the registry holding the information about this root.
  138. // PUNICODE_STRING pLogicalShare - the logical share name.
  139. // PUNICODE_STRING pPhysicalShare - the physical share name.
  140. // DfsRootFolder **ppRoot - root to return.
  141. //
  142. //
  143. // Returns: Status
  144. // ERROR_SUCCESS on success
  145. // ERROR status code otherwise
  146. //
  147. //
  148. // Description: This routine creates a new root folder, and
  149. // adds it to the list of known roots.
  150. //
  151. //--------------------------------------------------------------------------
  152. DFSSTATUS
  153. DfsADBlobStore::CreateNewRootFolder (
  154. LPWSTR DfsNameContextString,
  155. LPWSTR RootRegKeyName,
  156. PUNICODE_STRING pLogicalShare,
  157. PUNICODE_STRING pPhysicalShare,
  158. DfsRootFolder **ppRoot )
  159. {
  160. DFSSTATUS Status = ERROR_SUCCESS;
  161. DfsRootFolder *pNewRoot = NULL;
  162. //
  163. // Create a new instance of the RegistryRootFolder class.
  164. // This gives us a reference RootFolder.
  165. //
  166. pNewRoot = new DfsADBlobRootFolder( DfsNameContextString,
  167. RootRegKeyName,
  168. pLogicalShare,
  169. pPhysicalShare,
  170. this,
  171. &Status );
  172. if ( NULL == pNewRoot )
  173. {
  174. Status = ERROR_NOT_ENOUGH_MEMORY;
  175. }
  176. if ( ERROR_SUCCESS == Status )
  177. {
  178. //
  179. // AddRootFolder to the list of known roots. AddRootFolder
  180. // is responsible to acquire any reference on the root folder
  181. // if it is storing a reference to this root.
  182. Status = AddRootFolder( pNewRoot, NewRootList );
  183. if ( ERROR_SUCCESS == Status )
  184. {
  185. //
  186. // We were successful, return the reference root. The reference
  187. // that we are returning is the create reference on the new root.
  188. //
  189. *ppRoot = pNewRoot;
  190. }
  191. else
  192. {
  193. pNewRoot->ReleaseReference();
  194. pNewRoot = NULL;
  195. }
  196. }
  197. else
  198. {
  199. //
  200. // Our constructor may have failed. E.g. DC may be down.
  201. // Release our reference to this root and unwind.
  202. //
  203. if (pNewRoot != NULL) {
  204. pNewRoot->ReleaseReference();
  205. pNewRoot = NULL;
  206. }
  207. }
  208. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "ADBlobStore::CreateNewRootFolder. New root %p, for share %wZ (%wZ) on machine %ws. Status %x\n",
  209. pNewRoot, pLogicalShare, pPhysicalShare, DfsNameContextString, Status);
  210. return Status;
  211. }
  212. //+-------------------------------------------------------------------------
  213. //
  214. // Function: GetMetadataReplicaBlob - gets the replica blob
  215. //
  216. // Arguments: DfsMetadataHandle - the handle to the root
  217. // MetadataName - name of the metadata
  218. // ppBlob - the replica blob
  219. // pBlobSize-size of blob
  220. // pLastModifiedTime - time the blob was last modified
  221. //
  222. // Returns: Status
  223. // STATUS_SUCCESS if we could read the information
  224. // error status otherwise.
  225. //
  226. //
  227. // Description: This routine read the replica blob and returns a copy
  228. //
  229. //--------------------------------------------------------------------------
  230. DFSSTATUS
  231. DfsADBlobStore::GetMetadataReplicaBlob(
  232. IN DFS_METADATA_HANDLE DfsMetadataHandle,
  233. IN LPWSTR MetadataName,
  234. OUT PVOID *ppBlob,
  235. OUT PULONG pBlobSize,
  236. OUT PFILETIME pLastModifiedTime )
  237. {
  238. UNREFERENCED_PARAMETER(pLastModifiedTime); // dfsdev: investigate.
  239. DFSSTATUS Status = ERROR_SUCCESS;
  240. PVOID pMetadata;
  241. ULONG MetadataSize;
  242. PVOID pUseBlob;
  243. ULONG UseBlobSize;
  244. PVOID pReplicaBlob = NULL;
  245. ULONG ReplicaBlobSize;
  246. PDFS_NAME_INFORMATION pNameInformation = NULL;
  247. Status = GetMetadata( (PVOID)DfsMetadataHandle,
  248. MetadataName,
  249. NULL,
  250. &pMetadata,
  251. &MetadataSize,
  252. NULL); // pass NULL For time information.
  253. if (Status == ERROR_SUCCESS)
  254. {
  255. pNameInformation = new DFS_NAME_INFORMATION;
  256. if(pNameInformation != NULL)
  257. {
  258. RtlZeroMemory (pNameInformation, sizeof(DFS_NAME_INFORMATION));
  259. pUseBlob = ((PDFSBLOB_DATA)(pMetadata))->pBlob;
  260. UseBlobSize = MetadataSize;
  261. Status = PackGetNameInformation( pNameInformation,
  262. &pUseBlob,
  263. &UseBlobSize );
  264. if (Status == ERROR_SUCCESS)
  265. {
  266. PackGetULong( &ReplicaBlobSize,
  267. &pUseBlob,
  268. &UseBlobSize );
  269. if(ReplicaBlobSize > UseBlobSize)
  270. {
  271. Status = ERROR_INVALID_DATA;
  272. }
  273. else
  274. {
  275. pReplicaBlob = (PVOID) new unsigned char [ReplicaBlobSize];
  276. if(pReplicaBlob != NULL)
  277. {
  278. RtlCopyMemory(pReplicaBlob, pUseBlob, ReplicaBlobSize);
  279. }
  280. else
  281. {
  282. Status = ERROR_NOT_ENOUGH_MEMORY;
  283. }
  284. }
  285. }
  286. delete pNameInformation;
  287. }
  288. else
  289. {
  290. Status = ERROR_NOT_ENOUGH_MEMORY;
  291. }
  292. ReleaseMetadata( (PVOID)DfsMetadataHandle, pMetadata );
  293. }
  294. //
  295. // If we were successful, return the read in information. Otherwise free
  296. // up the allocate resources and return error.
  297. //
  298. if ( Status == STATUS_SUCCESS )
  299. {
  300. *ppBlob = pReplicaBlob;
  301. *pBlobSize = ReplicaBlobSize;
  302. }
  303. return Status;
  304. }
  305. //+-------------------------------------------------------------------------
  306. //
  307. // Function: GetMetadataNameBlob - gets the name blob
  308. //
  309. // Arguments: DfsMetadataHandle - the handle to the root
  310. // MetadataName - name of the metadata
  311. // ppBlob - the name blob
  312. // pBlobSize-size of blob
  313. // pLastModifiedTime - time the blob was last modified
  314. //
  315. // Returns: Status
  316. // STATUS_SUCCESS if we could read the information
  317. // error status otherwise.
  318. //
  319. //
  320. // Description: This routine read the name blob and returns a copy.
  321. //
  322. //--------------------------------------------------------------------------
  323. DFSSTATUS
  324. DfsADBlobStore::GetMetadataNameBlob(
  325. IN DFS_METADATA_HANDLE DfsMetadataHandle,
  326. IN LPWSTR MetadataName,
  327. OUT PVOID *ppBlob,
  328. OUT PULONG pBlobSize,
  329. OUT PFILETIME pLastModifiedTime )
  330. {
  331. DFSSTATUS Status = ERROR_SUCCESS;
  332. PVOID pMetadata;
  333. ULONG MetadataSize;
  334. PVOID pBlob, pUseBlob;
  335. ULONG UseBlobSize, NameBlobSize;
  336. PVOID pNameBlob = NULL;
  337. PDFS_NAME_INFORMATION pNameInformation = NULL;
  338. Status = GetMetadata( (PVOID)DfsMetadataHandle,
  339. MetadataName,
  340. NULL,
  341. &pMetadata,
  342. &MetadataSize,
  343. pLastModifiedTime);
  344. if (Status == ERROR_SUCCESS)
  345. {
  346. pNameInformation = new DFS_NAME_INFORMATION;
  347. if(pNameInformation != NULL)
  348. {
  349. RtlZeroMemory (pNameInformation, sizeof(DFS_NAME_INFORMATION));
  350. pBlob = ((PDFSBLOB_DATA)(pMetadata))->pBlob;
  351. pUseBlob = pBlob;
  352. UseBlobSize = MetadataSize;
  353. Status = PackGetNameInformation( pNameInformation,
  354. &pUseBlob,
  355. &UseBlobSize );
  356. if (Status == ERROR_SUCCESS)
  357. {
  358. NameBlobSize = MetadataSize - UseBlobSize;
  359. pNameBlob = (PVOID) new unsigned char [NameBlobSize ];
  360. if(pNameBlob != NULL)
  361. {
  362. RtlCopyMemory(pNameBlob, pBlob, NameBlobSize );
  363. }
  364. else
  365. {
  366. Status = ERROR_NOT_ENOUGH_MEMORY;
  367. }
  368. }
  369. delete pNameInformation;
  370. }
  371. else
  372. {
  373. Status = ERROR_NOT_ENOUGH_MEMORY;
  374. }
  375. ReleaseMetadata( (PVOID)DfsMetadataHandle, pMetadata );
  376. }
  377. //
  378. // If we were successful, return the read in information. Otherwise free
  379. // up the allocate resources and return error.
  380. //
  381. if ( Status == STATUS_SUCCESS )
  382. {
  383. *ppBlob = pNameBlob;
  384. *pBlobSize = NameBlobSize;
  385. }
  386. return Status;
  387. }
  388. DFSSTATUS
  389. DfsADBlobStore::SetMetadataNameBlob(
  390. DFS_METADATA_HANDLE RootHandle,
  391. LPWSTR MetadataName,
  392. PVOID pNameBlob,
  393. ULONG NameBlobSize )
  394. {
  395. PVOID pReplicaBlob, pNewBlob;
  396. ULONG ReplicaBlobSize, NewBlobSize;
  397. FILETIME LastTime;
  398. DFSSTATUS Status;
  399. Status = GetMetadataReplicaBlob( RootHandle,
  400. MetadataName,
  401. &pReplicaBlob,
  402. &ReplicaBlobSize,
  403. &LastTime );
  404. if (Status == ERROR_SUCCESS)
  405. {
  406. NewBlobSize = NameBlobSize + ReplicaBlobSize;
  407. Status = AllocateMetadataBlob( &pNewBlob,
  408. NewBlobSize );
  409. if (Status == ERROR_SUCCESS)
  410. {
  411. RtlCopyMemory(pNewBlob, pNameBlob, NameBlobSize);
  412. RtlCopyMemory((PVOID)((ULONG_PTR)pNewBlob + NameBlobSize),
  413. pReplicaBlob,
  414. ReplicaBlobSize );
  415. Status = SetMetadata( (PVOID)RootHandle,
  416. MetadataName,
  417. NULL,
  418. pNewBlob,
  419. NewBlobSize );
  420. ReleaseMetadataBlob( pNewBlob );
  421. }
  422. ReleaseMetadataReplicaBlob(pReplicaBlob, ReplicaBlobSize );
  423. }
  424. return Status;
  425. }
  426. DFSSTATUS
  427. DfsADBlobStore::SetMetadataReplicaBlob(
  428. DFS_METADATA_HANDLE RootHandle,
  429. LPWSTR MetadataName,
  430. PVOID pReplicaBlob,
  431. ULONG ReplicaBlobSize )
  432. {
  433. PVOID pNameBlob, pRemainingBlob;
  434. ULONG NameBlobSize, RemainingBlobSize;
  435. PVOID pOldBlob, pNewBlob, pUseBlob;
  436. ULONG OldBlobSize, NewBlobSize, UseBlobSize;
  437. ULONG OldReplicaBlobSize;
  438. PVOID pMetadata;
  439. ULONG MetadataSize;
  440. DFSSTATUS Status;
  441. DFS_NAME_INFORMATION NameInformation;
  442. Status = GetMetadata( (PVOID)RootHandle,
  443. MetadataName,
  444. NULL,
  445. &pMetadata,
  446. &MetadataSize,
  447. NULL);
  448. if (Status == ERROR_SUCCESS)
  449. {
  450. pNameBlob = pOldBlob = ((PDFSBLOB_DATA)(pMetadata))->pBlob;
  451. OldBlobSize = MetadataSize;
  452. Status = PackGetNameInformation( &NameInformation,
  453. &pOldBlob,
  454. &OldBlobSize );
  455. if (Status == ERROR_SUCCESS)
  456. {
  457. Status = PackGetULong( &OldReplicaBlobSize,
  458. &pOldBlob,
  459. &OldBlobSize );
  460. if (Status == ERROR_SUCCESS)
  461. {
  462. pRemainingBlob = (PVOID)((ULONG_PTR)pOldBlob + OldReplicaBlobSize);
  463. RemainingBlobSize = OldBlobSize - OldReplicaBlobSize;
  464. }
  465. }
  466. if (Status == ERROR_SUCCESS)
  467. {
  468. NameBlobSize = PackSizeNameInformation( &NameInformation );
  469. NewBlobSize = NameBlobSize + sizeof(ULONG) + ReplicaBlobSize + RemainingBlobSize;
  470. Status = AllocateMetadataBlob( &pNewBlob, NewBlobSize );
  471. if (Status == ERROR_SUCCESS)
  472. {
  473. SYSTEMTIME CurrentTime;
  474. FILETIME ModifiedTime;
  475. pUseBlob = pNewBlob;
  476. UseBlobSize = NewBlobSize;
  477. GetSystemTime( &CurrentTime);
  478. if (SystemTimeToFileTime( &CurrentTime, &ModifiedTime ))
  479. {
  480. NameInformation.LastModifiedTime = ModifiedTime;
  481. }
  482. Status = PackSetNameInformation( &NameInformation,
  483. &pUseBlob,
  484. &UseBlobSize);
  485. //
  486. // At this point, we better have enough space for
  487. // the rest of the stuff. Otherwise we have an
  488. // internal computing problem.
  489. //
  490. if (Status == ERROR_SUCCESS)
  491. {
  492. if (UseBlobSize < (sizeof(ULONG) + ReplicaBlobSize + RemainingBlobSize))
  493. {
  494. Status = ERROR_INVALID_DATA;
  495. }
  496. }
  497. if (Status == ERROR_SUCCESS)
  498. {
  499. Status = PackSetULong( ReplicaBlobSize,
  500. &pUseBlob,
  501. &UseBlobSize );
  502. }
  503. if (Status == ERROR_SUCCESS)
  504. {
  505. RtlCopyMemory(pUseBlob, pReplicaBlob, ReplicaBlobSize );
  506. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + ReplicaBlobSize);
  507. UseBlobSize -= ReplicaBlobSize;
  508. RtlCopyMemory(pUseBlob, pRemainingBlob, RemainingBlobSize );
  509. Status = SetMetadata( (PVOID)RootHandle,
  510. MetadataName,
  511. NULL,
  512. pNewBlob,
  513. NewBlobSize );
  514. }
  515. ReleaseMetadataBlob( pNewBlob );
  516. }
  517. else
  518. {
  519. Status = ERROR_NOT_ENOUGH_MEMORY;
  520. }
  521. }
  522. ReleaseMetadata((PVOID)RootHandle, pMetadata );
  523. }
  524. return Status;
  525. }
  526. INIT_ADBLOB_DFS_ID_PROPERTY_INFO();
  527. //+-------------------------------------------------------------------------
  528. //
  529. // Function: PackGetNameInformation - Unpacks the root/link name info
  530. //
  531. // Arguments: pDfsNameInfo - pointer to the info to fill.
  532. // ppBuffer - pointer to buffer that holds the binary stream.
  533. // pSizeRemaining - pointer to size of above buffer
  534. //
  535. // Returns: Status
  536. // ERROR_SUCCESS if we could unpack the name info
  537. // error status otherwise.
  538. //
  539. //
  540. // Description: This routine expects the binary stream to hold all the
  541. // information that is necessary to return a complete name
  542. // info structure (as defined by MiADBlobDfsIdProperty). If the stream
  543. // does not have the sufficient
  544. // info, ERROR_INVALID_DATA is returned back.
  545. //
  546. //--------------------------------------------------------------------------
  547. DFSSTATUS
  548. DfsADBlobStore::PackGetNameInformation(
  549. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  550. IN OUT PVOID *ppBuffer,
  551. IN OUT PULONG pSizeRemaining)
  552. {
  553. DFSSTATUS Status = STATUS_SUCCESS;
  554. //
  555. // Get the name information from the binary stream.
  556. //
  557. Status = PackGetInformation( (ULONG_PTR)pDfsNameInfo,
  558. ppBuffer,
  559. pSizeRemaining,
  560. &MiADBlobDfsIdProperty );
  561. if (Status == ERROR_SUCCESS)
  562. {
  563. pDfsNameInfo->LastModifiedTime = pDfsNameInfo->PrefixTimeStamp;
  564. if ((pDfsNameInfo->Type & 0x80) == 0x80)
  565. {
  566. pDfsNameInfo->State |= DFS_VOLUME_FLAVOR_AD_BLOB;
  567. }
  568. }
  569. return Status;
  570. }
  571. //+-------------------------------------------------------------------------
  572. //
  573. // Function: PackSetNameInformation - Packs the root/link name info
  574. //
  575. // Arguments: pDfsNameInfo - pointer to the info to pack.
  576. // ppBuffer - pointer to buffer that holds the binary stream.
  577. // pSizeRemaining - pointer to size of above buffer
  578. //
  579. // Returns: Status
  580. // ERROR_SUCCESS if we could pack the name info
  581. // error status otherwise.
  582. //
  583. //
  584. // Description: This routine takes the passedin name information and
  585. // stores it in the binary stream passed in.
  586. //
  587. //--------------------------------------------------------------------------
  588. DFSSTATUS
  589. DfsADBlobStore::PackSetNameInformation(
  590. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  591. IN OUT PVOID *ppBuffer,
  592. IN OUT PULONG pSizeRemaining)
  593. {
  594. DFSSTATUS Status;
  595. if ((pDfsNameInfo->Type & 0x80) == 0x80)
  596. {
  597. pDfsNameInfo->State &= ~DFS_VOLUME_FLAVORS;
  598. }
  599. pDfsNameInfo->PrefixTimeStamp = pDfsNameInfo->LastModifiedTime;
  600. pDfsNameInfo->StateTimeStamp = pDfsNameInfo->LastModifiedTime;
  601. pDfsNameInfo->CommentTimeStamp = pDfsNameInfo->LastModifiedTime;
  602. //
  603. // Store the DfsNameInfo in the stream first.
  604. //
  605. Status = PackSetInformation( (ULONG_PTR)pDfsNameInfo,
  606. ppBuffer,
  607. pSizeRemaining,
  608. &MiADBlobDfsIdProperty );
  609. return Status;
  610. }
  611. //+-------------------------------------------------------------------------
  612. //
  613. // Function: PackSizeNameInformation - Gets the size of the name info.
  614. //
  615. // Arguments: pDfsNameInfo - info to size.
  616. //
  617. // Returns: Status
  618. // ULONG - size needed
  619. //
  620. // Description: This routine gets us the size of the binary stream
  621. // required to pack the passed in name info.
  622. //
  623. //--------------------------------------------------------------------------
  624. ULONG
  625. DfsADBlobStore::PackSizeNameInformation(
  626. IN PDFS_NAME_INFORMATION pDfsNameInfo )
  627. {
  628. ULONG Size;
  629. Size = PackSizeInformation( (ULONG_PTR)pDfsNameInfo,
  630. &MiADBlobDfsIdProperty );
  631. return Size;
  632. }
  633. DFSSTATUS
  634. DfsADBlobStore::GetMetadata (
  635. IN PVOID DfsMetadataKey,
  636. IN LPWSTR RelativeName,
  637. IN LPWSTR RegistryValueNameString,
  638. OUT PVOID *ppData,
  639. OUT ULONG *pDataSize,
  640. OUT PFILETIME pLastModifiedTime)
  641. {
  642. DFSSTATUS Status = ERROR_SUCCESS;
  643. PVOID pDataBuffer = NULL;
  644. DfsADBlobCache * pBlobCache = NULL;
  645. ULONG DataSize = 0;
  646. ULONG DataType = 0;
  647. PDFSBLOB_DATA BlobData;
  648. UNICODE_STRING BlobName;
  649. UNREFERENCED_PARAMETER (RegistryValueNameString);
  650. UNREFERENCED_PARAMETER (pLastModifiedTime);
  651. Status = DfsRtlInitUnicodeStringEx( &BlobName, RelativeName );
  652. if(Status != ERROR_SUCCESS)
  653. {
  654. return Status;
  655. }
  656. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( DfsMetadataKey );
  657. Status = pBlobCache->GetNamedBlob(&BlobName, &BlobData);
  658. if(Status == STATUS_SUCCESS)
  659. {
  660. *ppData = (PVOID) BlobData;
  661. *pDataSize = BlobData->Size;
  662. }
  663. return Status;
  664. }
  665. DFSSTATUS
  666. DfsADBlobStore::SetMetadata (
  667. IN PVOID DfsMetadataKey,
  668. IN LPWSTR RelativeName,
  669. IN LPWSTR RegistryValueNameString,
  670. IN PVOID pData,
  671. IN ULONG DataSize)
  672. {
  673. DFSSTATUS Status = ERROR_SUCCESS;
  674. DfsADBlobCache * pBlobCache = NULL;
  675. UNICODE_STRING BlobName;
  676. UNREFERENCED_PARAMETER (RegistryValueNameString);
  677. Status = DfsRtlInitUnicodeStringEx( &BlobName, RelativeName );
  678. if(Status != ERROR_SUCCESS)
  679. {
  680. return Status;
  681. }
  682. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( DfsMetadataKey );
  683. Status = pBlobCache->StoreBlobInCache(&BlobName, (PBYTE) pData, DataSize);
  684. if (Status == ERROR_SUCCESS)
  685. {
  686. Status = pBlobCache->WriteBlobToAd();
  687. }
  688. DFS_TRACE_LOW(REFERRAL_SERVER, "Done Setting metadata for %p %ws, Status %x\n", pBlobCache, RelativeName, Status);
  689. return Status;
  690. }
  691. DFSSTATUS
  692. DfsADBlobStore::RemoveMetadata (
  693. IN PVOID DfsMetadataKey,
  694. IN LPWSTR RelativeName)
  695. {
  696. DFSSTATUS Status = ERROR_SUCCESS;
  697. DfsADBlobCache * pBlobCache = NULL;
  698. UNICODE_STRING BlobName;
  699. Status = DfsRtlInitUnicodeStringEx( &BlobName, RelativeName );
  700. if(Status != ERROR_SUCCESS)
  701. {
  702. return Status;
  703. }
  704. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( DfsMetadataKey );
  705. Status = pBlobCache->RemoveNamedBlob( &BlobName );
  706. if (Status == ERROR_SUCCESS)
  707. {
  708. Status = pBlobCache->WriteBlobToAd();
  709. }
  710. return Status;
  711. }
  712. DFSSTATUS
  713. DfsADBlobStore::CreateADBlobRoot(
  714. LPWSTR MachineName,
  715. LPWSTR DCName,
  716. LPWSTR PhysicalShare,
  717. LPWSTR LogicalShare,
  718. LPWSTR Comment,
  719. BOOLEAN NewRoot)
  720. {
  721. DFSSTATUS Status= ERROR_SUCCESS;
  722. HKEY DfsKey = NULL;
  723. DfsRootFolder *pRootFolder = NULL;
  724. DfsRootFolder *pLookupRootFolder = NULL;
  725. BOOLEAN IsLastRootTarget = FALSE;
  726. UNICODE_STRING DfsMachine;
  727. UNICODE_STRING DfsShare;
  728. UNICODE_STRING DfsPhysicalShare;
  729. //
  730. // We had decided to disallow mismatch on Logical and physical
  731. // shares, but we are just going to document this.
  732. //
  733. #if 0
  734. if (_wcsicmp(LogicalShare, PhysicalShare) != 0)
  735. {
  736. return ERROR_INVALID_NAME;
  737. }
  738. #endif
  739. DFS_TRACE_LOW( REFERRAL_SERVER, "Dfs ad blob store, create root %ws\n", LogicalShare);
  740. Status = DfsRtlInitUnicodeStringEx( &DfsShare, LogicalShare );
  741. if(Status != ERROR_SUCCESS)
  742. {
  743. return Status;
  744. }
  745. Status = DfsRtlInitUnicodeStringEx( &DfsPhysicalShare, PhysicalShare );
  746. if(Status != ERROR_SUCCESS)
  747. {
  748. return Status;
  749. }
  750. Status = DfsRtlInitUnicodeStringEx( &DfsMachine, MachineName );
  751. if(Status != ERROR_SUCCESS)
  752. {
  753. return Status;
  754. }
  755. if (DfsIsSpecialDomainShare(&DfsShare) ||
  756. DfsIsSpecialDomainShare(&DfsPhysicalShare))
  757. {
  758. Status = ERROR_INVALID_PARAMETER;
  759. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Dfs ad blob store, special share - create root %ws, status %x\n", LogicalShare, Status);
  760. return Status;
  761. }
  762. Status = LookupRoot( &DfsMachine,
  763. &DfsShare,
  764. &pLookupRootFolder );
  765. DFS_TRACE_LOW( REFERRAL_SERVER, "Dfs ad blob store, looup root %p, status %x\n", pRootFolder, Status);
  766. if (Status == ERROR_SUCCESS)
  767. {
  768. pLookupRootFolder->ReleaseReference();
  769. //
  770. // DO NOT CHANGE this error code. A change here will affect the client
  771. // The client will tear down the root if we return any other
  772. // error code here, so be very careful.
  773. //
  774. // We also need to return here: the rest of the code assumes this.
  775. //
  776. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Dfs ad blob store, Already Exists - create root %ws, status %x\n", LogicalShare, Status);
  777. return ERROR_ALREADY_EXISTS;
  778. }
  779. Status = DfsCheckServerRootHandlingCapability();
  780. if (Status != ERROR_SUCCESS)
  781. {
  782. return Status;
  783. }
  784. Status = GetNewADBlobRegistryKey( MachineName,
  785. TRUE, // write permission required
  786. NULL,
  787. &DfsKey );
  788. if (Status == ERROR_SUCCESS)
  789. {
  790. Status = SetupADBlobRootKeyInformation( DfsKey,
  791. LogicalShare,
  792. PhysicalShare );
  793. //RegCloseKey( DfsKey );
  794. }
  795. if (Status == ERROR_SUCCESS)
  796. {
  797. Status = GetRootFolder( NULL,
  798. LogicalShare,
  799. &DfsShare,
  800. &DfsPhysicalShare,
  801. &pRootFolder );
  802. if (Status == ERROR_SUCCESS)
  803. {
  804. Status = pRootFolder->RootRequestPrologue( DCName );
  805. if (Status == ERROR_SUCCESS)
  806. {
  807. Status = AddRootToBlob( MachineName,
  808. pRootFolder,
  809. NewRoot, //NewRoot,
  810. LogicalShare,
  811. PhysicalShare,
  812. Comment );
  813. if ((Status == ERROR_FILE_EXISTS) ||
  814. (Status == ERROR_ALREADY_EXISTS))
  815. {
  816. Status = ERROR_SUCCESS;
  817. }
  818. if (Status == ERROR_SUCCESS)
  819. {
  820. Status = DfsUpdateRootRemoteServerName( LogicalShare,
  821. DCName,
  822. MachineName,
  823. PhysicalShare,
  824. TRUE );
  825. }
  826. if (Status == ERROR_SUCCESS)
  827. {
  828. Status = pRootFolder->AcquireRootShareDirectory();
  829. //
  830. // now mark the root folder as synchronized:
  831. // this is true since this root is empty.
  832. //
  833. if (Status == ERROR_SUCCESS)
  834. {
  835. pRootFolder->SetRootFolderSynchronized();
  836. }
  837. }
  838. else
  839. {
  840. (void) pRootFolder->ReleaseRootShareDirectory();
  841. }
  842. pRootFolder->RootRequestEpilogue();
  843. }
  844. }
  845. }
  846. if (Status != ERROR_SUCCESS)
  847. {
  848. DFSSTATUS LocalStatus = ERROR_SUCCESS;
  849. LocalStatus = RegDeleteKey( DfsKey,
  850. LogicalShare );
  851. LocalStatus = DfsUpdateRootRemoteServerName( LogicalShare,
  852. DCName,
  853. MachineName,
  854. PhysicalShare,
  855. FALSE );
  856. if(pRootFolder)
  857. {
  858. LocalStatus = pRootFolder->RootRequestPrologue( DCName );
  859. if (LocalStatus == ERROR_SUCCESS)
  860. {
  861. LocalStatus = RemoveRootFromBlob( pRootFolder,
  862. MachineName,
  863. PhysicalShare,
  864. &IsLastRootTarget );
  865. pRootFolder->RootRequestEpilogue();
  866. }
  867. if(IsLastRootTarget)
  868. {
  869. DfsDeleteDfsRootObject( DCName,
  870. LogicalShare);
  871. }
  872. RemoveRootFolder(pRootFolder, TRUE);
  873. }
  874. }
  875. if(pRootFolder)
  876. {
  877. pRootFolder->ReleaseReference();
  878. }
  879. if(DfsKey != NULL)
  880. {
  881. RegCloseKey( DfsKey );
  882. }
  883. //
  884. // At this point we CANNOT return ERROR_ALREADY_EXISTS. The client
  885. // will use this code to mean that the DS object it creates is not
  886. // cleaned up.
  887. //
  888. // Does not mean that ERROR_NOT_SUPPORTED is a better error, but till
  889. // we find one, this should suffice.
  890. //
  891. if (Status == ERROR_ALREADY_EXISTS)
  892. {
  893. Status = ERROR_NOT_SUPPORTED;
  894. }
  895. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Dfs ad blob store, create root %ws, status %x\n", LogicalShare, Status);
  896. return Status;
  897. }
  898. DFSSTATUS
  899. DfsADBlobStore::DeleteADBlobRoot(
  900. LPWSTR MachineName,
  901. LPWSTR DCName,
  902. LPWSTR PhysicalShare,
  903. LPWSTR LogicalShare )
  904. {
  905. DFSSTATUS Status = ERROR_SUCCESS;
  906. UNICODE_STRING DfsMachine;
  907. UNICODE_STRING DfsShare;
  908. DfsRootFolder *pRootFolder = NULL;
  909. BOOLEAN IsLastRootTarget = FALSE;
  910. DFS_TRACE_LOW(REFERRAL_SERVER, "AdBlob: delete ad blob root %ws\n", LogicalShare);
  911. Status = DfsRtlInitUnicodeStringEx( &DfsMachine, MachineName );
  912. if (Status != ERROR_SUCCESS)
  913. {
  914. return Status;
  915. }
  916. Status = DfsRtlInitUnicodeStringEx( &DfsShare, LogicalShare );
  917. if (Status != ERROR_SUCCESS)
  918. {
  919. return Status;
  920. }
  921. Status = LookupRoot( &DfsMachine,
  922. &DfsShare,
  923. &pRootFolder );
  924. DFS_TRACE_LOW(REFERRAL_SERVER, "AdBlob: delete ad blob root %ws, Lookup root %p, Status %x\n", LogicalShare, pRootFolder, Status);
  925. if (Status == ERROR_SUCCESS)
  926. {
  927. PUNICODE_STRING pRootPhysicalShare;
  928. UNICODE_STRING DfsPhysicalShare;
  929. pRootPhysicalShare = pRootFolder->GetRootPhysicalShareName();
  930. Status = DfsRtlInitUnicodeStringEx( &DfsPhysicalShare, PhysicalShare);
  931. if (Status == ERROR_SUCCESS)
  932. {
  933. if (RtlCompareUnicodeString( &DfsPhysicalShare,
  934. pRootPhysicalShare,
  935. TRUE) != 0)
  936. {
  937. Status = ERROR_INVALID_PARAMETER;
  938. }
  939. }
  940. if (Status != ERROR_SUCCESS)
  941. {
  942. pRootFolder->ReleaseReference();
  943. }
  944. }
  945. if (Status == ERROR_SUCCESS)
  946. {
  947. Status = pRootFolder->RootApiRequestPrologue(TRUE,
  948. DCName);
  949. if (Status == ERROR_SUCCESS)
  950. {
  951. Status = DoesUserHaveAccess(pRootFolder, GENERIC_ALL);
  952. if (Status == ERROR_SUCCESS)
  953. {
  954. Status = pRootFolder->AcquireRootLock();
  955. if(Status == ERROR_SUCCESS)
  956. {
  957. pRootFolder->SetRootFolderDeleteInProgress();
  958. pRootFolder->ReleaseRootLock();
  959. }
  960. }
  961. if (Status == ERROR_SUCCESS)
  962. {
  963. Status = CleanRegEntry( MachineName, LogicalShare );
  964. if (Status == ERROR_SUCCESS)
  965. {
  966. Status = DfsUpdateRootRemoteServerName( LogicalShare,
  967. DCName,
  968. MachineName,
  969. PhysicalShare,
  970. FALSE );
  971. }
  972. //
  973. // Update blob and write it back.
  974. //
  975. if (Status == ERROR_SUCCESS)
  976. {
  977. // dfsdev: move this function to rootfolder class.
  978. Status = RemoveRootFromBlob( pRootFolder,
  979. MachineName,
  980. PhysicalShare,
  981. &IsLastRootTarget );
  982. }
  983. NTSTATUS DeleteStatus;
  984. //
  985. // we are done with this folder. Release the root share directory
  986. // we had acquired earlier on: this will tell the driver we are
  987. // no longer interested on the specified drive.
  988. //
  989. DeleteStatus = RemoveRootFolder( pRootFolder, TRUE );
  990. DFS_TRACE_ERROR_HIGH( DeleteStatus, REFERRAL_SERVER, "remove root folder status %x\n", DeleteStatus);
  991. DeleteStatus = pRootFolder->ReleaseRootShareDirectory();
  992. DFS_TRACE_ERROR_LOW( DeleteStatus, REFERRAL_SERVER, "release root dir status %x\n", DeleteStatus);
  993. }
  994. pRootFolder->RootApiRequestEpilogue(TRUE,
  995. Status );
  996. }
  997. pRootFolder->ReleaseReference();
  998. #if 0
  999. if(Status != ERROR_SUCCESS)
  1000. {
  1001. DFS_TRACE_HIGH(REFERRAL_SERVER, "remove root folder failed. Trying to recreate root \n");
  1002. CreateADBlobRoot(MachineName,
  1003. DCName,
  1004. PhysicalShare,
  1005. LogicalShare,
  1006. L"",
  1007. TRUE );
  1008. }
  1009. #endif
  1010. }
  1011. DFS_TRACE_LOW(REFERRAL_SERVER, "AdBlob: delete ad blob root %p (%ws), Status %x\n",
  1012. pRootFolder, LogicalShare, Status);
  1013. return Status;
  1014. }
  1015. DFSSTATUS
  1016. DfsADBlobStore::DeleteADBlobRootForced(
  1017. LPWSTR MachineName,
  1018. LPWSTR DCName,
  1019. LPWSTR PhysicalShare,
  1020. LPWSTR LogicalShare )
  1021. {
  1022. DFSSTATUS Status = ERROR_SUCCESS;
  1023. UNICODE_STRING DfsMachine;
  1024. UNICODE_STRING DfsShare;
  1025. DfsRootFolder *pRootFolder = NULL;
  1026. BOOLEAN IsLastRootTarget = FALSE;
  1027. DFS_TRACE_LOW(REFERRAL_SERVER, "AdBlob: delete ad blob root %ws\n", LogicalShare);
  1028. Status = DfsRtlInitUnicodeStringEx( &DfsMachine, MachineName );
  1029. if (Status != ERROR_SUCCESS)
  1030. {
  1031. return Status;
  1032. }
  1033. Status = DfsRtlInitUnicodeStringEx( &DfsShare, LogicalShare );
  1034. if (Status != ERROR_SUCCESS)
  1035. {
  1036. return Status;
  1037. }
  1038. Status = GetCompatRootFolder( &DfsShare,
  1039. &pRootFolder );
  1040. DFS_TRACE_LOW(REFERRAL_SERVER, "AdBlob: forced delete ad blob root %ws, Lookup root %p, Status %x\n", LogicalShare, pRootFolder, Status);
  1041. if (Status == ERROR_SUCCESS)
  1042. {
  1043. Status = pRootFolder->RootApiRequestPrologue(TRUE,
  1044. DCName);
  1045. if (Status == ERROR_SUCCESS)
  1046. {
  1047. Status = DoesUserHaveAccess(pRootFolder, GENERIC_ALL);
  1048. if (Status == ERROR_SUCCESS)
  1049. {
  1050. Status = pRootFolder->AcquireRootLock();
  1051. if(Status == ERROR_SUCCESS)
  1052. {
  1053. pRootFolder->SetRootFolderDeleteInProgress();
  1054. pRootFolder->ReleaseRootLock();
  1055. }
  1056. }
  1057. if (Status == ERROR_SUCCESS)
  1058. {
  1059. Status = DfsUpdateRootRemoteServerName( LogicalShare,
  1060. DCName,
  1061. MachineName,
  1062. PhysicalShare,
  1063. FALSE );
  1064. if (Status == ERROR_SUCCESS)
  1065. {
  1066. Status = RemoveRootFromBlob( pRootFolder,
  1067. MachineName,
  1068. PhysicalShare,
  1069. &IsLastRootTarget );
  1070. }
  1071. }
  1072. pRootFolder->RootApiRequestEpilogue(TRUE,
  1073. Status );
  1074. }
  1075. pRootFolder->ReleaseReference();
  1076. }
  1077. return Status;
  1078. }
  1079. DFSSTATUS
  1080. DfsADBlobStore::RemoveChild(
  1081. DFS_METADATA_HANDLE DfsHandle,
  1082. LPWSTR ChildName )
  1083. {
  1084. return RemoveMetadata( (PVOID)DfsHandle, ChildName );
  1085. }
  1086. //+-------------------------------------------------------------------------
  1087. //
  1088. // Function: AddChild - Add a child to the metadata.
  1089. //
  1090. // Arguments:
  1091. // DfsMetadataHandle - the Metadata key for the root.
  1092. // PUNICODE_STRING pLinkLogicalName - the logical name of the child
  1093. // LPWSTR ReplicaServer - the first target server for this link.
  1094. // LPWSTR ReplicaPath - the target path for this link
  1095. // LPWSTR Comment - the comment to be associated with this link.
  1096. // LPWSTR pMetadataName - the metadata name for the child, returned..
  1097. //
  1098. //
  1099. // Returns: Status:
  1100. //
  1101. // Description: This routine adds a child to the Root metadata. It packs
  1102. // the link name into the name information. If the replica
  1103. // information exists, it packs that into the replica info.
  1104. // It then saves the name and replica streams under the
  1105. // Childkey.
  1106. // NOTE: this function does not require that the link
  1107. // have atleast one replica. Any such requirements
  1108. // should be enforced by the caller.
  1109. //
  1110. //--------------------------------------------------------------------------
  1111. DFSSTATUS
  1112. DfsADBlobStore::AddChild(
  1113. IN DFS_METADATA_HANDLE DfsHandle,
  1114. IN PDFS_NAME_INFORMATION pNameInfo,
  1115. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  1116. IN PUNICODE_STRING pMetadataName)
  1117. {
  1118. DFSSTATUS Status;
  1119. PVOID pNameBlob, pReplicaBlob, pNewBlob, pUseBlob;
  1120. ULONG NameBlobSize, ReplicaBlobSize, NewBlobSize, UseBlobSize;
  1121. Status = CreateNameInformationBlob( pNameInfo,
  1122. &pNameBlob,
  1123. &NameBlobSize );
  1124. if (Status == ERROR_SUCCESS)
  1125. {
  1126. Status = CreateReplicaListInformationBlob( pReplicaListInfo,
  1127. &pReplicaBlob,
  1128. &ReplicaBlobSize );
  1129. if (Status == ERROR_SUCCESS)
  1130. {
  1131. NewBlobSize = NameBlobSize + sizeof(ULONG) + ReplicaBlobSize +
  1132. 3 * sizeof(ULONG);
  1133. Status = AllocateMetadataBlob( &pNewBlob,
  1134. NewBlobSize );
  1135. if (Status == ERROR_SUCCESS)
  1136. {
  1137. pUseBlob = pNewBlob;
  1138. UseBlobSize = NewBlobSize;
  1139. RtlCopyMemory( pUseBlob, pNameBlob, NameBlobSize );
  1140. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + NameBlobSize);
  1141. UseBlobSize -= NameBlobSize;
  1142. PackSetULong( ReplicaBlobSize,
  1143. &pUseBlob,
  1144. &UseBlobSize );
  1145. RtlCopyMemory(pUseBlob, pReplicaBlob, ReplicaBlobSize );
  1146. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + ReplicaBlobSize);
  1147. UseBlobSize -= ReplicaBlobSize;
  1148. PackSetULong( 4,
  1149. &pUseBlob,
  1150. &UseBlobSize );
  1151. PackSetULong( 0,
  1152. &pUseBlob,
  1153. &UseBlobSize );
  1154. PackSetULong( pNameInfo->Timeout,
  1155. &pUseBlob,
  1156. &UseBlobSize );
  1157. Status = SetMetadata( (PVOID)DfsHandle,
  1158. pMetadataName->Buffer,
  1159. NULL,
  1160. pNewBlob,
  1161. NewBlobSize );
  1162. ReleaseMetadataBlob( pNewBlob );
  1163. }
  1164. ReleaseMetadataReplicaBlob( pReplicaBlob, ReplicaBlobSize );
  1165. }
  1166. ReleaseMetadataNameBlob( pNameBlob, NameBlobSize );
  1167. }
  1168. return Status;
  1169. }
  1170. DFSSTATUS
  1171. DfsADBlobStore::EnumerateApiLinks(
  1172. IN DFS_METADATA_HANDLE DfsHandle,
  1173. PUNICODE_STRING pRootName,
  1174. DWORD Level,
  1175. LPBYTE pBuffer,
  1176. LONG BufferSize,
  1177. LPDWORD pEntriesToRead,
  1178. LPDWORD pResumeHandle,
  1179. PLONG pSizeRequired )
  1180. {
  1181. DFSSTATUS Status = ERROR_SUCCESS;
  1182. BOOLEAN OverFlow = FALSE;
  1183. LONG HeaderSize = 0;
  1184. LONG EntriesRead = 0;
  1185. LONG EntriesToRead = *pEntriesToRead;
  1186. LONG SizeRequired = 0;
  1187. LONG EntryCount = 0;
  1188. ULONG ChildNum = 0;
  1189. LPBYTE pLinkBuffer = NULL;
  1190. LONG LinkBufferSize = 0;
  1191. LPBYTE CurrentBuffer = NULL;
  1192. LPBYTE NewBuffer = NULL;
  1193. LONG SizeRemaining = 0;
  1194. DfsADBlobCache * pBlobCache = NULL;
  1195. PDFSBLOB_DATA pBlobData = NULL;
  1196. LONG CurrentCount = 0;
  1197. ULONG_PTR SizeDiff;
  1198. DFSBOB_ITER Iter;
  1199. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( DfsHandle );
  1200. OverFlow = FALSE;
  1201. Status = DfsApiSizeLevelHeader( Level, &HeaderSize );
  1202. if (Status != ERROR_SUCCESS)
  1203. {
  1204. return Status;
  1205. }
  1206. SizeRequired = ROUND_UP_COUNT(EntriesToRead * HeaderSize, ALIGN_QUAD);
  1207. if (EntriesToRead * HeaderSize < BufferSize )
  1208. {
  1209. CurrentBuffer = (LPBYTE)((ULONG_PTR)pBuffer + EntriesToRead * HeaderSize);
  1210. SizeRemaining = BufferSize - EntriesToRead * HeaderSize;
  1211. }
  1212. else
  1213. {
  1214. CurrentBuffer = pBuffer;
  1215. SizeRemaining = 0;
  1216. OverFlow = TRUE;
  1217. }
  1218. if(pResumeHandle)
  1219. {
  1220. EntryCount = *pResumeHandle;
  1221. }
  1222. CurrentCount = 0;
  1223. pBlobData = pBlobCache->FindFirstBlob(&Iter);
  1224. while ((pBlobData != NULL) &&
  1225. CurrentCount < EntryCount )
  1226. {
  1227. CurrentCount++;
  1228. pBlobData = pBlobCache->FindNextBlob(&Iter);
  1229. }
  1230. while ((pBlobData != NULL) && (pBlobCache->IsStaleBlob(pBlobData)))
  1231. {
  1232. pBlobData = pBlobCache->FindNextBlob(&Iter);
  1233. }
  1234. if (pBlobData == NULL)
  1235. {
  1236. Status = ERROR_NO_MORE_ITEMS;
  1237. }
  1238. while ((pBlobData != NULL) &&
  1239. (Status == ERROR_SUCCESS))
  1240. {
  1241. //
  1242. // For each child, get the child name.
  1243. //
  1244. if (EntriesToRead && EntriesRead >= EntriesToRead)
  1245. {
  1246. break;
  1247. }
  1248. Status = GetStoreApiInformationBuffer( DfsHandle,
  1249. pRootName,
  1250. pBlobData->BlobName.Buffer,
  1251. Level,
  1252. &pLinkBuffer,
  1253. &LinkBufferSize );
  1254. if (Status == ERROR_SUCCESS)
  1255. {
  1256. SizeRequired += ROUND_UP_COUNT(LinkBufferSize, ALIGN_QUAD);
  1257. if (OverFlow == FALSE)
  1258. {
  1259. DFSSTATUS PackStatus;
  1260. PackStatus = PackageEnumerationInfo( Level,
  1261. EntriesRead,
  1262. pLinkBuffer,
  1263. pBuffer,
  1264. &CurrentBuffer,
  1265. &SizeRemaining );
  1266. if (PackStatus == ERROR_BUFFER_OVERFLOW)
  1267. {
  1268. OverFlow = TRUE;
  1269. }
  1270. NewBuffer = (LPBYTE)ROUND_UP_POINTER( CurrentBuffer, ALIGN_LPVOID);
  1271. SizeDiff = (NewBuffer - CurrentBuffer);
  1272. if ((LONG)SizeDiff > SizeRemaining)
  1273. {
  1274. SizeRemaining = 0;
  1275. }
  1276. else
  1277. {
  1278. SizeRemaining -= (LONG)SizeDiff;
  1279. }
  1280. CurrentBuffer = NewBuffer;
  1281. }
  1282. ReleaseStoreApiInformationBuffer( pLinkBuffer );
  1283. EntryCount++;
  1284. EntriesRead++;
  1285. }
  1286. pBlobData = pBlobCache->FindNextBlob(&Iter);
  1287. while ((pBlobData != NULL) && (pBlobCache->IsStaleBlob(pBlobData)))
  1288. {
  1289. pBlobData = pBlobCache->FindNextBlob(&Iter);
  1290. }
  1291. if (pBlobData == NULL)
  1292. {
  1293. Status = ERROR_NO_MORE_ITEMS;
  1294. }
  1295. }
  1296. pBlobCache->FindCloseBlob(&Iter);
  1297. *pSizeRequired = SizeRequired;
  1298. if (Status == ERROR_NO_MORE_ITEMS)
  1299. {
  1300. if (EntriesRead)
  1301. {
  1302. if (OverFlow)
  1303. {
  1304. Status = ERROR_BUFFER_OVERFLOW;
  1305. }
  1306. else
  1307. {
  1308. Status = ERROR_SUCCESS;
  1309. }
  1310. }
  1311. }
  1312. else if (OverFlow)
  1313. {
  1314. Status = ERROR_BUFFER_OVERFLOW;
  1315. }
  1316. if (Status == ERROR_SUCCESS)
  1317. {
  1318. if(pResumeHandle)
  1319. {
  1320. *pResumeHandle = EntryCount;
  1321. }
  1322. *pEntriesToRead = EntriesRead;
  1323. }
  1324. return Status;
  1325. }
  1326. DFSSTATUS
  1327. DfsADBlobStore::AddRootToBlob(
  1328. LPWSTR MachineName,
  1329. DfsRootFolder *pRootFolder,
  1330. BOOLEAN NewRoot,
  1331. LPWSTR LogicalShare,
  1332. LPWSTR ShareName,
  1333. LPWSTR Comment )
  1334. {
  1335. DFS_METADATA_HANDLE RootHandle;
  1336. DFSSTATUS Status;
  1337. UNICODE_STRING DomainName;
  1338. UNICODE_STRING LogicalName, RootMetadataName;
  1339. DFS_NAME_INFORMATION NameInfo;
  1340. DFS_REPLICA_LIST_INFORMATION ReplicaListInfo;
  1341. DFS_REPLICA_INFORMATION ReplicaInfo;
  1342. UUID NewUid;
  1343. LPWSTR RootMetadataNameString = NULL;
  1344. Status = DfsRtlInitUnicodeStringEx( &RootMetadataName, RootMetadataNameString);
  1345. if (Status != ERROR_SUCCESS)
  1346. {
  1347. return Status;
  1348. }
  1349. Status = UuidCreate(&NewUid);
  1350. if (Status != ERROR_SUCCESS)
  1351. {
  1352. return Status;
  1353. }
  1354. Status = pRootFolder->GetMetadataHandle( &RootHandle );
  1355. if (Status == ERROR_SUCCESS)
  1356. {
  1357. if (NewRoot == FALSE)
  1358. {
  1359. Status = pRootFolder->Synchronize(FALSE, TRUE);
  1360. if (Status == ERROR_SUCCESS)
  1361. {
  1362. Status = RootEntryExists((PVOID)RootHandle, &NewRoot);
  1363. }
  1364. }
  1365. if (Status == ERROR_SUCCESS)
  1366. {
  1367. if (NewRoot)
  1368. {
  1369. Status = DfsGetDomainName(&DomainName);
  1370. if (Status == ERROR_SUCCESS)
  1371. {
  1372. Status = DfsCreateUnicodePathString( &LogicalName,
  1373. 1, // 1 leading path seperator.
  1374. DomainName.Buffer,
  1375. LogicalShare);
  1376. if (Status == ERROR_SUCCESS)
  1377. {
  1378. StoreInitializeNameInformation( &NameInfo,
  1379. &LogicalName,
  1380. &NewUid,
  1381. Comment );
  1382. NameInfo.Type |= PKT_ENTRY_TYPE_REFERRAL_SVC;
  1383. StoreInitializeReplicaInformation( &ReplicaListInfo,
  1384. &ReplicaInfo,
  1385. MachineName,
  1386. ShareName );
  1387. Status = AddChild( RootHandle,
  1388. &NameInfo,
  1389. &ReplicaListInfo,
  1390. &RootMetadataName );
  1391. DfsFreeUnicodeString( &LogicalName);
  1392. }
  1393. DfsFreeUnicodeString( &DomainName );
  1394. }
  1395. }
  1396. else
  1397. {
  1398. Status = AddChildReplica( RootHandle,
  1399. RootMetadataNameString,
  1400. MachineName,
  1401. ShareName );
  1402. }
  1403. }
  1404. pRootFolder->ReleaseMetadataHandle( RootHandle );
  1405. }
  1406. return Status;
  1407. }
  1408. DFSSTATUS
  1409. DfsADBlobStore::RemoveRootFromBlob(
  1410. DfsRootFolder *pRootFolder,
  1411. LPWSTR MachineName,
  1412. LPWSTR ShareName,
  1413. PBOOLEAN pLastRoot )
  1414. {
  1415. DFS_METADATA_HANDLE RootHandle;
  1416. DFSSTATUS Status = ERROR_SUCCESS;
  1417. BOOLEAN LastRoot = FALSE;
  1418. DfsADBlobCache *pBlobCache = NULL;
  1419. LPWSTR RootMetadataNameString = NULL;
  1420. Status = pRootFolder->GetMetadataHandle( &RootHandle );
  1421. if (Status == ERROR_SUCCESS)
  1422. {
  1423. Status = RemoveChildReplica( RootHandle,
  1424. RootMetadataNameString,
  1425. MachineName,
  1426. ShareName,
  1427. &LastRoot,
  1428. TRUE);
  1429. if((Status == ERROR_SUCCESS) || (Status == ERROR_LAST_ADMIN))
  1430. {
  1431. if (LastRoot)
  1432. {
  1433. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( RootHandle);
  1434. pBlobCache->InvalidateCache();
  1435. pBlobCache->WriteBlobToAd();
  1436. }
  1437. Status = ERROR_SUCCESS;
  1438. }
  1439. pRootFolder->ReleaseMetadataHandle( RootHandle );
  1440. }
  1441. if (Status == ERROR_SUCCESS)
  1442. {
  1443. *pLastRoot = LastRoot;
  1444. }
  1445. return Status;
  1446. }
  1447. DFSSTATUS
  1448. DfsADBlobStore::GetMetadataNameInformation(
  1449. IN DFS_METADATA_HANDLE RootHandle,
  1450. IN LPWSTR MetadataName,
  1451. OUT PDFS_NAME_INFORMATION *ppInfo )
  1452. {
  1453. PVOID pBlob, pUseBlob;
  1454. ULONG UseBlobSize, ReplicaBlobSize, RecoveryBlobSize;
  1455. FILETIME BlobModifiedTime;
  1456. PVOID pMetadata;
  1457. ULONG MetadataSize;
  1458. PDFS_NAME_INFORMATION pNewInfo = NULL;
  1459. DFSSTATUS Status;
  1460. Status = GetMetadata( (PVOID)RootHandle,
  1461. MetadataName,
  1462. NULL,
  1463. &pMetadata,
  1464. &MetadataSize,
  1465. &BlobModifiedTime);
  1466. if (Status == ERROR_SUCCESS)
  1467. {
  1468. pBlob = ((PDFSBLOB_DATA)(pMetadata))->pBlob;
  1469. pNewInfo = new DFS_NAME_INFORMATION;
  1470. if (pNewInfo != NULL)
  1471. {
  1472. RtlZeroMemory (pNewInfo, sizeof(DFS_NAME_INFORMATION));
  1473. pUseBlob = pBlob;
  1474. UseBlobSize = MetadataSize;
  1475. Status = PackGetNameInformation( pNewInfo,
  1476. &pUseBlob,
  1477. &UseBlobSize );
  1478. if (Status == ERROR_SUCCESS)
  1479. {
  1480. Status = PackGetULong( &ReplicaBlobSize,
  1481. &pUseBlob,
  1482. &UseBlobSize );
  1483. if (Status == ERROR_SUCCESS)
  1484. {
  1485. if(ReplicaBlobSize > UseBlobSize)
  1486. {
  1487. Status = ERROR_INVALID_DATA;
  1488. }
  1489. else
  1490. {
  1491. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + ReplicaBlobSize);
  1492. UseBlobSize -= ReplicaBlobSize;
  1493. }
  1494. }
  1495. }
  1496. if (Status == ERROR_SUCCESS)
  1497. {
  1498. Status = PackGetULong( &RecoveryBlobSize,
  1499. &pUseBlob,
  1500. &UseBlobSize );
  1501. if (Status == ERROR_SUCCESS)
  1502. {
  1503. if(RecoveryBlobSize > UseBlobSize)
  1504. {
  1505. Status = ERROR_INVALID_DATA;
  1506. }
  1507. else
  1508. {
  1509. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + RecoveryBlobSize);
  1510. UseBlobSize -= RecoveryBlobSize;
  1511. }
  1512. }
  1513. }
  1514. if (Status == ERROR_SUCCESS)
  1515. {
  1516. Status = PackGetULong( &pNewInfo->Timeout,
  1517. &pUseBlob,
  1518. &UseBlobSize );
  1519. }
  1520. if (Status != ERROR_SUCCESS)
  1521. {
  1522. ReleaseMetadata( (PVOID)RootHandle, pMetadata );
  1523. delete pNewInfo;
  1524. }
  1525. }
  1526. else
  1527. {
  1528. Status = ERROR_NOT_ENOUGH_MEMORY;
  1529. }
  1530. }
  1531. if (Status == ERROR_SUCCESS)
  1532. {
  1533. pNewInfo->pData = pMetadata;
  1534. pNewInfo->DataSize = MetadataSize;
  1535. *ppInfo = pNewInfo;
  1536. }
  1537. return Status;
  1538. }
  1539. VOID
  1540. DfsADBlobStore::ReleaseMetadataNameInformation(
  1541. IN DFS_METADATA_HANDLE RootHandle,
  1542. IN PDFS_NAME_INFORMATION pNameInfo )
  1543. {
  1544. ReleaseMetadata( (PVOID)RootHandle, pNameInfo->pData );
  1545. delete [] pNameInfo;
  1546. }
  1547. DFSSTATUS
  1548. DfsADBlobStore::SetMetadataNameInformation(
  1549. IN DFS_METADATA_HANDLE RootHandle,
  1550. IN LPWSTR MetadataName,
  1551. IN PDFS_NAME_INFORMATION pNameInfo )
  1552. {
  1553. PVOID pBlob, pUseBlob, pNewBlob;
  1554. ULONG UseBlobSize, NewBlobSize;
  1555. ULONG ReplicaBlobSize, RecoveryBlobSize;
  1556. DFSSTATUS Status;
  1557. PVOID pNameBlob;
  1558. ULONG NameBlobSize;
  1559. FILETIME BlobModifiedTime;
  1560. PVOID pMetadata;
  1561. ULONG MetadataSize;
  1562. SYSTEMTIME CurrentTime;
  1563. FILETIME ModifiedTime;
  1564. GetSystemTime( &CurrentTime);
  1565. if (SystemTimeToFileTime( &CurrentTime, &ModifiedTime ))
  1566. {
  1567. pNameInfo->LastModifiedTime = ModifiedTime;
  1568. }
  1569. Status = CreateNameInformationBlob( pNameInfo,
  1570. &pNameBlob,
  1571. &NameBlobSize );
  1572. if (Status == ERROR_SUCCESS)
  1573. {
  1574. Status = GetMetadata( (PVOID)RootHandle,
  1575. MetadataName,
  1576. NULL,
  1577. &pMetadata,
  1578. &MetadataSize,
  1579. &BlobModifiedTime);
  1580. }
  1581. if (Status == ERROR_SUCCESS)
  1582. {
  1583. DFS_NAME_INFORMATION NameInformation;
  1584. pBlob = ((PDFSBLOB_DATA)(pMetadata))->pBlob;
  1585. pUseBlob = pBlob;
  1586. UseBlobSize = MetadataSize;
  1587. Status = PackGetNameInformation( &NameInformation,
  1588. &pUseBlob,
  1589. &UseBlobSize );
  1590. if (Status == ERROR_SUCCESS)
  1591. {
  1592. NewBlobSize = NameBlobSize + UseBlobSize;
  1593. Status = AllocateMetadataBlob( &pNewBlob,
  1594. NewBlobSize );
  1595. if (Status == ERROR_SUCCESS)
  1596. {
  1597. RtlCopyMemory(pNewBlob, pNameBlob, NameBlobSize);
  1598. RtlCopyMemory((PVOID)((ULONG_PTR)pNewBlob + NameBlobSize),
  1599. pUseBlob,
  1600. UseBlobSize );
  1601. pUseBlob = (PVOID)((ULONG_PTR)pNewBlob + NameBlobSize);
  1602. if (Status == ERROR_SUCCESS)
  1603. {
  1604. Status = PackGetULong( &ReplicaBlobSize,
  1605. &pUseBlob,
  1606. &UseBlobSize );
  1607. if (Status == ERROR_SUCCESS)
  1608. {
  1609. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + ReplicaBlobSize);
  1610. UseBlobSize -= ReplicaBlobSize;
  1611. }
  1612. }
  1613. if (Status == ERROR_SUCCESS)
  1614. {
  1615. Status = PackGetULong( &RecoveryBlobSize,
  1616. &pUseBlob,
  1617. &UseBlobSize );
  1618. if (Status == ERROR_SUCCESS)
  1619. {
  1620. pUseBlob = (PVOID)((ULONG_PTR)pUseBlob + RecoveryBlobSize);
  1621. UseBlobSize -= RecoveryBlobSize;
  1622. }
  1623. }
  1624. if (Status == ERROR_SUCCESS)
  1625. {
  1626. Status = PackSetULong( pNameInfo->Timeout,
  1627. &pUseBlob,
  1628. &UseBlobSize );
  1629. }
  1630. if (Status == ERROR_SUCCESS)
  1631. {
  1632. Status = SetMetadata( (PVOID)RootHandle,
  1633. MetadataName,
  1634. NULL,
  1635. pNewBlob,
  1636. NewBlobSize );
  1637. }
  1638. ReleaseMetadataBlob( pNewBlob );
  1639. }
  1640. }
  1641. ReleaseMetadata( (PVOID)RootHandle, pMetadata );
  1642. }
  1643. return Status;
  1644. }
  1645. //+-------------------------------------------------------------------------
  1646. //
  1647. // Function: RenameLinks
  1648. //
  1649. // Arguments:
  1650. // RootHandle - handle to root's metadata
  1651. // OldDomainName
  1652. // NewDomainName
  1653. //
  1654. // Returns: SUCCESS or error
  1655. //
  1656. // Description: Renames all links referencing the old domain name to the new.
  1657. // To do that, this retrieves NameInformation as well as ReplicaInformation
  1658. // from the blob cache. Once done, the metadata are written back to the
  1659. // cache. Flushing the metadata to the AD or aborting the changes is
  1660. // the caller's responsibility.
  1661. //--------------------------------------------------------------------------
  1662. DFSSTATUS
  1663. DfsADBlobStore::RenameLinks(
  1664. DFS_METADATA_HANDLE RootHandle,
  1665. IN PUNICODE_STRING pLinkMetadataName,
  1666. IN PUNICODE_STRING pOldDomainName,
  1667. IN PUNICODE_STRING pNewDomainName)
  1668. {
  1669. DFSSTATUS Status;
  1670. //
  1671. // Change the NameInfo structure first.
  1672. //
  1673. Status = RenameNameInfo( RootHandle,
  1674. pLinkMetadataName,
  1675. pNewDomainName,
  1676. pOldDomainName );
  1677. //
  1678. // We've successfully renamed the prefix in the NameInfo. Now see if there are
  1679. // any links to change in the Replica List.
  1680. //
  1681. if (Status == ERROR_SUCCESS)
  1682. {
  1683. Status = RenameReplicaInfo( RootHandle,
  1684. pLinkMetadataName,
  1685. pNewDomainName,
  1686. pOldDomainName);
  1687. }
  1688. return Status;
  1689. }
  1690. //
  1691. // RenameNameInfoPrefix - replace both the Prefix and the ShortPrefix.
  1692. // SUCCESS indicates a successful rename.
  1693. //
  1694. //
  1695. DFSSTATUS
  1696. DfsADBlobStore::RenameNameInfo(
  1697. IN DFS_METADATA_HANDLE RootHandle,
  1698. IN PUNICODE_STRING pLinkMetadataName,
  1699. IN PUNICODE_STRING pNewDomainName,
  1700. IN PUNICODE_STRING pOldDomainName)
  1701. {
  1702. DFSSTATUS Status;
  1703. PDFS_NAME_INFORMATION pNameInfo;
  1704. UNICODE_STRING FirstComponent;
  1705. Status = GetMetadataNameInformation( RootHandle,
  1706. pLinkMetadataName->Buffer,
  1707. &pNameInfo);
  1708. if (Status != ERROR_SUCCESS)
  1709. {
  1710. return Status;
  1711. }
  1712. //
  1713. // Sanity check the Prefix string of the NameInfo.
  1714. // Although the LinkMetadataName is NULL for
  1715. // the root the NameInfo->Prefix has the real name.
  1716. //
  1717. Status = DfsGetFirstComponent( &pNameInfo->Prefix, &FirstComponent, NULL );
  1718. if ((Status != ERROR_SUCCESS) ||
  1719. (RtlEqualDomainName(pOldDomainName, &FirstComponent) == FALSE))
  1720. {
  1721. ReleaseMetadataNameInformation( RootHandle, pNameInfo );
  1722. return Status;
  1723. }
  1724. //
  1725. // We have a match. Just replace that first component with the
  1726. // new domain name. The substitution happens in place, so we ideally should save
  1727. // the old pointer to patch back the nameinfo snapshot afterwards.
  1728. //
  1729. Status = GenerateMetadataLogicalName(pNewDomainName,
  1730. &pNameInfo->Prefix,
  1731. &pNameInfo->Prefix);
  1732. if (Status == ERROR_SUCCESS)
  1733. {
  1734. //
  1735. // Similarly, change the ShortPrefix as well. We don't just assume
  1736. // that they are identical, although in practice they are currently.
  1737. //
  1738. Status = GenerateMetadataLogicalName(pNewDomainName,
  1739. &pNameInfo->ShortPrefix,
  1740. &pNameInfo->ShortPrefix);
  1741. // We don't bother to modify the timestamps.
  1742. //
  1743. // We don't bother to undo our previous changes if we get errors.
  1744. // The understanding is that the whole metadata blob will be
  1745. // thrown away without getting written back to the AD. Just free the old
  1746. // NameInfo strings on our way out.
  1747. //
  1748. if (Status == ERROR_SUCCESS)
  1749. {
  1750. Status = SetMetadataNameInformation( RootHandle,
  1751. pLinkMetadataName->Buffer,
  1752. pNameInfo );
  1753. ReleaseMetadataLogicalName( &pNameInfo->ShortPrefix );
  1754. }
  1755. ReleaseMetadataLogicalName( &pNameInfo->Prefix );
  1756. }
  1757. //
  1758. // Release our snapshot of the blob. This doesn't write the changes back to the cache;
  1759. // the SetMetadata above does that.
  1760. //
  1761. ReleaseMetadataNameInformation( RootHandle, pNameInfo );
  1762. return Status;
  1763. }
  1764. //
  1765. // RenameReplicaInfo - Walk through the replica list and replace stale domain names.
  1766. //
  1767. DFSSTATUS
  1768. DfsADBlobStore::RenameReplicaInfo(
  1769. IN DFS_METADATA_HANDLE RootHandle,
  1770. IN PUNICODE_STRING pLinkMetadataName,
  1771. IN PUNICODE_STRING pNewDomainName,
  1772. IN PUNICODE_STRING pOldDomainName)
  1773. {
  1774. DFSSTATUS Status;
  1775. PUNICODE_STRING pReplicaName;
  1776. PDFS_REPLICA_LIST_INFORMATION pReplicaList;
  1777. BOOLEAN RenamedLink = FALSE;
  1778. ULONG i;
  1779. //
  1780. // Get a snapshot of the replica set.
  1781. //
  1782. Status = GetMetadataReplicaInformation( RootHandle,
  1783. pLinkMetadataName->Buffer,
  1784. &pReplicaList );
  1785. if (Status != ERROR_SUCCESS)
  1786. {
  1787. return Status;
  1788. }
  1789. //
  1790. // Go through all its links looking for a match of the stale domain name.
  1791. //
  1792. for (i = 0; i < pReplicaList->ReplicaCount; i++)
  1793. {
  1794. pReplicaName = &pReplicaList->pReplicas[i].ServerName;
  1795. //
  1796. // The names must match to change the replica.
  1797. //
  1798. if (!RtlEqualDomainName( pOldDomainName, pReplicaName ))
  1799. {
  1800. continue;
  1801. }
  1802. // XXX: Ideally we should keep a pointer to the old ServerName
  1803. // and put it back after we SetMetadata and before we release
  1804. // this NameInfo snapshot. The current logic basically assumes that losing
  1805. // the old pointer doesn't end in a memory leak (TRUE currently).
  1806. //
  1807. Status = DfsRtlInitUnicodeStringEx( pReplicaName, pNewDomainName->Buffer );
  1808. if (Status != ERROR_SUCCESS)
  1809. {
  1810. // The rootfolder will resynchronize to revert the changes.
  1811. break;
  1812. }
  1813. RenamedLink = TRUE;
  1814. }
  1815. if ((Status == ERROR_SUCCESS) &&
  1816. (RenamedLink))
  1817. {
  1818. //
  1819. // Put the blob back in the cache if we've changed any of it.
  1820. // We don't need to make this operation atomic with respect to
  1821. // NameInfo changes because if any of these fails, the caller's supposed to
  1822. // purge the cache with a ReSynchronize().
  1823. //
  1824. Status = SetMetadataReplicaInformation( RootHandle,
  1825. pLinkMetadataName->Buffer,
  1826. pReplicaList );
  1827. }
  1828. ReleaseMetadataReplicaInformation( RootHandle, pReplicaList );
  1829. return Status;
  1830. }
  1831. //
  1832. // This removes the target share from the
  1833. // Microsoft\Dfs\Roots\Domain registry key.
  1834. //
  1835. DFSSTATUS
  1836. DfsADBlobStore::CleanRegEntry(
  1837. LPWSTR MachineName,
  1838. LPWSTR LogicalShare
  1839. )
  1840. {
  1841. HKEY FtDfsKey;
  1842. DFSSTATUS Status;
  1843. DFSSTATUS RetStatus = ERROR_NOT_FOUND;
  1844. Status = GetNewADBlobRegistryKey( MachineName,
  1845. TRUE, // write permission required
  1846. NULL,
  1847. &FtDfsKey );
  1848. if (Status == ERROR_SUCCESS)
  1849. {
  1850. Status = RegDeleteKey( FtDfsKey,
  1851. LogicalShare );
  1852. // Return success only if something got successfully deleted.
  1853. if (Status == ERROR_SUCCESS)
  1854. {
  1855. RetStatus = Status;
  1856. }
  1857. RegCloseKey( FtDfsKey );
  1858. }
  1859. return RetStatus;
  1860. }
  1861. DFSSTATUS
  1862. DfsADBlobStore::GenerateApiLogicalPath (
  1863. IN PUNICODE_STRING pRootName,
  1864. IN PUNICODE_STRING pMetadataPrefix,
  1865. IN PUNICODE_STRING pApiLogicalName )
  1866. {
  1867. DFSSTATUS Status;
  1868. UNICODE_STRING FirstComponent;
  1869. UNICODE_STRING Remaining;
  1870. //
  1871. // For the ad blob store, the metadata prefix holds the
  1872. // name context, the share name and the link name.
  1873. // However, we will want to replace the first component
  1874. // with the rootname, so that when domains are renamed,
  1875. // we keep passing back correct information even though
  1876. // the blob has not been updated.
  1877. //
  1878. if (DfsCheckSubstitutePaths())
  1879. {
  1880. Status = DfsGetFirstComponent( pMetadataPrefix,
  1881. &FirstComponent,
  1882. &Remaining );
  1883. if (Status == ERROR_SUCCESS)
  1884. {
  1885. Status = DfsCreateUnicodePathStringFromUnicode( pApiLogicalName,
  1886. 2, // 2 leading path sep
  1887. pRootName,
  1888. &Remaining );
  1889. }
  1890. } else
  1891. {
  1892. //
  1893. // The caller has disabled path name substitution because she wants to see
  1894. // things as is. So just make a copy.
  1895. //
  1896. Status = DfsCreateUnicodePathStringFromUnicode(pApiLogicalName,
  1897. 2, // 2 leading path separators
  1898. pMetadataPrefix,
  1899. NULL);
  1900. }
  1901. return Status;
  1902. }
  1903. DFSSTATUS
  1904. DfsADBlobStore::GetCompatRootFolder(
  1905. PUNICODE_STRING pName,
  1906. DfsRootFolder **ppNewRoot )
  1907. {
  1908. DfsADBlobRootFolder *pNewRoot = NULL;
  1909. UNICODE_STRING DomainName;
  1910. DFSSTATUS Status = ERROR_SUCCESS;
  1911. *ppNewRoot = NULL;
  1912. Status = DfsGetDomainName( &DomainName );
  1913. if (Status != ERROR_SUCCESS)
  1914. {
  1915. return Status;
  1916. }
  1917. pNewRoot = new DfsADBlobRootFolder( DomainName.Buffer,
  1918. L"Unknown",
  1919. pName,
  1920. pName,
  1921. this,
  1922. &Status );
  1923. //
  1924. // The root folder made a copy of this, so we are safe to delete.
  1925. //
  1926. DfsReleaseDomainName( &DomainName );
  1927. // The new operator may fail.
  1928. if (pNewRoot == NULL)
  1929. {
  1930. Status = ERROR_NOT_ENOUGH_MEMORY;
  1931. return Status;
  1932. }
  1933. if (Status == ERROR_SUCCESS)
  1934. {
  1935. pNewRoot->ResetCreateDirectories();
  1936. //set this so we read from this DC, instead of the PDC.
  1937. pNewRoot->SetRootScalabilityMode();
  1938. Status = pNewRoot->Synchronize( TRUE );
  1939. if (Status == ERROR_SUCCESS)
  1940. {
  1941. *ppNewRoot = pNewRoot;
  1942. }
  1943. }
  1944. if (Status != ERROR_SUCCESS)
  1945. {
  1946. ASSERT(pNewRoot);
  1947. pNewRoot->ReleaseReference();
  1948. }
  1949. return Status;
  1950. }
  1951. DFSSTATUS
  1952. DfsADBlobStore::DoesUserHaveAccess(DfsRootFolder *pRootFolder,
  1953. DWORD DesiredAccess)
  1954. {
  1955. DFS_METADATA_HANDLE RootHandle = NULL;
  1956. DFSSTATUS Status = ERROR_SUCCESS;
  1957. DfsADBlobCache *pBlobCache = NULL;
  1958. Status = pRootFolder->GetMetadataHandle( &RootHandle );
  1959. if (Status == ERROR_SUCCESS)
  1960. {
  1961. pBlobCache = (DfsADBlobCache *)ExtractFromMetadataHandle( RootHandle);
  1962. Status = pBlobCache->DfsDoesUserHaveAccess(DesiredAccess);
  1963. pRootFolder->ReleaseMetadataHandle( RootHandle );
  1964. }
  1965. return Status;
  1966. }