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.

2008 lines
63 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsRegistryStore.cxx
  6. //
  7. // Contents: the Registry DFS Store class, this contains the registry
  8. // specific functionality.
  9. //
  10. // Classes: DfsRegistryStore.
  11. //
  12. // History: Dec. 8 2000, Author: udayh
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include "DfsRegistryStore.hxx"
  16. #include "DfsRegistryRootFolder.hxx"
  17. #include "DfsFilterApi.hxx"
  18. #include "dfsmisc.h"
  19. #include "domainControllerSupport.hxx"
  20. #include "DfsRegStrings.hxx"
  21. #include "shlwapi.h"
  22. #include "align.h"
  23. //
  24. // logging specific includes
  25. //
  26. #include "DfsRegistryStore.tmh"
  27. extern
  28. DFSSTATUS
  29. MigrateDfs(
  30. LPWSTR MachineName);
  31. //+----------------------------------------------------------------------------
  32. //
  33. // Class: DfsRegistryStore
  34. //
  35. // Synopsis: This class inherits the basic DfsStore, and extends it
  36. // to include the registry specific functionality.
  37. //
  38. //-----------------------------------------------------------------------------
  39. LPWSTR DfsRegistryNameString = L"ID";
  40. LPWSTR DfsRegistryRecoveryString = L"Recovery";
  41. LPWSTR DfsRegistryReplicaString = L"Svc";
  42. LPWSTR DfsRegistryDfsDriverLocation = DFS_REG_DFS_DRIVER_LOCATION;
  43. LPWSTR DfsLocalVolumesValue = DFS_REG_LOCAL_VOLUMES_CHILD;
  44. extern LPWSTR DfsVolumesLocation;
  45. //+-------------------------------------------------------------------------
  46. //
  47. // Function: StoreRecognizer - the recognizer for the store.
  48. //
  49. // Arguments: Name - the namespace of interest.
  50. //
  51. // Returns: Status
  52. // ERROR_SUCCESS on success
  53. // ERROR status code otherwise
  54. //
  55. //
  56. // Description: This routine checks if the specified namespace holds
  57. // a registry based DFS. If it does, it reads in the
  58. // root in that namespace and creates and adds it to our
  59. // list of known roots, if it doesn't already exist in our list.
  60. //
  61. //--------------------------------------------------------------------------
  62. DFSSTATUS
  63. DfsRegistryStore::StoreRecognizer(
  64. LPWSTR Name )
  65. {
  66. DFSSTATUS Status = ERROR_SUCCESS;
  67. HKEY OldStandaloneDfsKey = NULL;
  68. HKEY StandaloneDfsKey = NULL;
  69. BOOLEAN MachineContacted = FALSE;
  70. //
  71. // Make sure the namespace is the name of a machine. Registry based
  72. // dfs exist only on machines.
  73. //
  74. if (IsEmptyString(Name) == FALSE)
  75. {
  76. Status = DfsIsThisAMachineName( Name );
  77. if(Status != ERROR_SUCCESS)
  78. {
  79. return Status;
  80. }
  81. }
  82. DFS_TRACE_LOW(REFERRAL_SERVER, "DfsRegistryStore:StoreRecognizer, Name %ws Is Machine Status %x\n", Name, Status);
  83. //
  84. // we now find all the migrated multiple roots standalone DFS's as
  85. // well as the old single root standalone DFS, and add them to our
  86. // in memory metadata.
  87. //
  88. Status = GetNewStandaloneRegistryKey( Name,
  89. FALSE,
  90. &MachineContacted,
  91. &StandaloneDfsKey );
  92. if (Status == ERROR_SUCCESS)
  93. {
  94. Status = StoreRecognizeNewDfs( Name,
  95. StandaloneDfsKey );
  96. RegCloseKey( StandaloneDfsKey );
  97. }
  98. //
  99. // Need to refine the return status further: success should mean
  100. // machine is not std dfs or we have read the std dfs data correctly.
  101. //
  102. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Dfs registry store recognizser, status %x\n", Status);
  103. return Status;
  104. }
  105. //+-------------------------------------------------------------------------
  106. //
  107. // Function: StoreRecognizer - the recognizer for the store.
  108. //
  109. // Arguments: DfsNameContext - the namespace of interest.
  110. // LogicalShare
  111. //
  112. // Returns: Status
  113. // ERROR_SUCCESS on success
  114. // ERROR status code otherwise
  115. //
  116. //
  117. // Description: This routine checks if the specified namespace holds
  118. // a domain based DFS. If it does, it reads in the
  119. // root in that namespace and creates and adds it to our
  120. // list of known roots, if it doesn't already exist in our list.
  121. //
  122. //--------------------------------------------------------------------------
  123. DFSSTATUS
  124. DfsRegistryStore::StoreRecognizer (
  125. LPWSTR DfsNameContext,
  126. PUNICODE_STRING pLogicalShare )
  127. {
  128. DFSSTATUS Status;
  129. Status = DfsIsThisAMachineName( DfsNameContext );
  130. if (Status == ERROR_SUCCESS)
  131. {
  132. Status = StoreRecognizeNewDfs( DfsNameContext,
  133. pLogicalShare );
  134. }
  135. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "DfsRegistryStore:StoreRecognizer (remote), Status %x\n",
  136. Status);
  137. return Status;
  138. }
  139. DFSSTATUS
  140. DfsRegistryStore::LookupDotNetRootByName(
  141. LPWSTR ShareName,
  142. DfsRootFolder **ppRootFolder )
  143. {
  144. DFSSTATUS Status = ERROR_SUCCESS;
  145. HKEY DfsKey = NULL;
  146. HKEY DfsRootKey = NULL;
  147. Status = GetNewStandaloneRegistryKey( NULL,
  148. FALSE,
  149. NULL,
  150. &DfsKey );
  151. if (Status == ERROR_SUCCESS)
  152. {
  153. Status = RegOpenKeyEx( DfsKey,
  154. ShareName,
  155. 0,
  156. KEY_READ,
  157. &DfsRootKey );
  158. RegCloseKey(DfsKey );
  159. if (Status == ERROR_SUCCESS)
  160. {
  161. Status = GetRootFolder( NULL,
  162. ShareName,
  163. DfsRootKey,
  164. ppRootFolder );
  165. RegCloseKey(DfsRootKey);
  166. }
  167. }
  168. return Status;
  169. }
  170. DFSSTATUS
  171. DfsRegistryStore::LookupOldRootByName(
  172. LPWSTR ShareName,
  173. DfsRootFolder **ppRootFolder )
  174. {
  175. DFSSTATUS Status = ERROR_SUCCESS;
  176. HKEY DfsKey = NULL;
  177. HKEY DfsRootKey = NULL;
  178. UNICODE_STRING LogicalShare;
  179. Status = GetOldStandaloneRegistryKey( NULL,
  180. FALSE,
  181. NULL,
  182. &DfsRootKey );
  183. if (Status == ERROR_SUCCESS)
  184. {
  185. Status = GetRootPhysicalShare( DfsRootKey,
  186. &LogicalShare);
  187. if (Status == ERROR_SUCCESS)
  188. {
  189. if (_wcsicmp(ShareName, LogicalShare.Buffer) != 0)
  190. {
  191. Status = ERROR_NOT_FOUND;
  192. ReleaseRootLogicalShare( &LogicalShare );
  193. }
  194. }
  195. if(Status == ERROR_SUCCESS)
  196. {
  197. Status = MigrateDfs( L"" );
  198. if(Status == ERROR_SUCCESS)
  199. {
  200. Status = GetRootFolder( L"",
  201. ShareName,
  202. &LogicalShare,
  203. &LogicalShare,
  204. ppRootFolder );
  205. }
  206. ReleaseRootLogicalShare( &LogicalShare );
  207. }
  208. if(DfsRootKey != NULL)
  209. {
  210. RegCloseKey( DfsRootKey );
  211. }
  212. }
  213. return Status;
  214. }
  215. DFSSTATUS
  216. DfsRegistryStore::LookupNewRootByName(
  217. LPWSTR ShareName,
  218. DfsRootFolder **ppRootFolder )
  219. {
  220. DFSSTATUS Status = ERROR_NOT_FOUND;
  221. if(DfsIsMachineCluster())
  222. {
  223. Status = LookupOldRootByName (ShareName, ppRootFolder);
  224. if(Status != ERROR_SUCCESS)
  225. {
  226. Status = LookupDotNetRootByName (ShareName, ppRootFolder);
  227. }
  228. }
  229. return Status;
  230. }
  231. #if 0
  232. //+-------------------------------------------------------------------------
  233. //
  234. // Function: StoreRecognizeOldStandaloneDfs - recognizer for single root dfs
  235. //
  236. // Arguments: Name - the namespace of interest.
  237. // HKEY OldDfsKey.
  238. //
  239. // Returns: Status
  240. // ERROR_SUCCESS on success
  241. // ERROR status code otherwise
  242. //
  243. //
  244. // Description: This routine reads a single root from the old standalone
  245. // location, and loads it in if the root exists.
  246. //
  247. //--------------------------------------------------------------------------
  248. DFSSTATUS
  249. DfsRegistryStore::StoreRecognizeOldStandaloneDfs(
  250. LPWSTR MachineName,
  251. HKEY OldDfsKey )
  252. {
  253. DfsRootFolder *pRootFolder = NULL;
  254. DFSSTATUS Status = ERROR_SUCCESS;
  255. DFSSTATUS RootStatus = ERROR_SUCCESS;
  256. UNICODE_STRING LogicalRoot;
  257. UNICODE_STRING DfsNameContext;
  258. UNREFERENCED_PARAMETER(MachineName);
  259. RtlZeroMemory(&LogicalRoot, sizeof(LogicalRoot));
  260. //
  261. // Check if we have a root folder read from the old dfs location
  262. // ("domainroot"). If we have not seen the root already, and one
  263. // exists, a new root folder gets created.
  264. // Status = DfsGetRegValueString (OldDfsKey,
  265. // DfsRootShareValueName,
  266. // &LogicalRoot);
  267. Status = GetRootPhysicalShare(OldDfsKey,&LogicalRoot);
  268. if(Status == ERROR_SUCCESS)
  269. {
  270. RtlInitUnicodeStringEx( &DfsNameContext, NULL);
  271. //
  272. // Check if we already know about this root. If we do, this
  273. // routine gives us a referenced root folder which we can return.
  274. // If not, we create a brand new root folder.
  275. //
  276. Status = LookupRoot( &DfsNameContext,
  277. &LogicalRoot,
  278. &pRootFolder );
  279. //
  280. // we did not find a root, so create a new one.
  281. //
  282. if ( Status != ERROR_SUCCESS )
  283. {
  284. Status = MigrateStdDfs( L"",
  285. OldDfsKey,
  286. (LPWSTR) LogicalRoot.Buffer,
  287. (LPWSTR) LogicalRoot.Buffer,
  288. FALSE);
  289. if(Status == ERROR_SUCCESS)
  290. {
  291. //
  292. // Now get either an existing root by this name,
  293. // or create a new one.
  294. //
  295. RootStatus = GetRootFolder( L"",
  296. LogicalRoot.Buffer,
  297. &LogicalRoot,
  298. &LogicalRoot,
  299. &pRootFolder );
  300. if (RootStatus == ERROR_SUCCESS)
  301. {
  302. //
  303. // Call the synchronize method on the root to
  304. // update it with the latest children.
  305. // Again, ignore the error since we need to move
  306. // on to the next root.
  307. // dfsdev: need eventlog to signal this.
  308. //
  309. RootStatus = pRootFolder->Synchronize();
  310. //
  311. // If the Synchronize above had succeeded, then it would
  312. // all the reparse points that the root needs. Now we n
  313. // this volume as one that has DFS reparse points so th
  314. // to perform garbage collection on this volume later o
  315. //
  316. (VOID)pRootFolder->AddReparseVolumeToList();
  317. }
  318. }
  319. }
  320. ReleaseRootPhysicalShare( &LogicalRoot );
  321. }
  322. if(pRootFolder != NULL)
  323. {
  324. pRootFolder->ReleaseReference();
  325. }
  326. return Status;
  327. }
  328. #endif
  329. #if 0
  330. DFSSTATUS
  331. DfsRegistryStore::StoreRecognizeOldStandaloneDfs(
  332. LPWSTR MachineName,
  333. HKEY OldDfsKey )
  334. {
  335. DfsRootFolder *pRootFolder = NULL;
  336. DFSSTATUS Status = ERROR_SUCCESS;
  337. //
  338. // Check if we have a root folder read from the old dfs location
  339. // ("domainroot"). If we have not seen the root already, and one
  340. // exists, a new root folder gets created.
  341. //
  342. Status = GetRootFolder( MachineName,
  343. NULL,
  344. OldDfsKey,
  345. &pRootFolder );
  346. //
  347. // We got a root folder. call synchronize on it to update its contents.
  348. // The synchronize method fills the root with the most upto date
  349. // children data.
  350. //
  351. if (Status == ERROR_SUCCESS)
  352. {
  353. DFSSTATUS RootStatus;
  354. //
  355. // now acquire the root share directory. If this
  356. // fails, we continue our operation: we can continue
  357. // with synchonize and not create directories.
  358. // dfsdev:we need to post a eventlog or something when
  359. // we run into this.
  360. //
  361. RootStatus = pRootFolder->AcquireRootShareDirectory();
  362. //
  363. // Call the synchronize method on the root to
  364. // update it with the latest children.
  365. // Again, ignore the error since we need to move
  366. // on to the next root.
  367. // dfsdev: need eventlog to signal this.
  368. //
  369. RootStatus = pRootFolder->Synchronize();
  370. DFSLOG("Root folder for %ws, Synchronize status %x\n",
  371. RootStatus );
  372. // Release our reference on the root folder.
  373. pRootFolder->ReleaseReference();
  374. }
  375. return Status;
  376. }
  377. #endif
  378. //+-------------------------------------------------------------------------
  379. //
  380. // Function: CreateNewRootFolder - creates a new root folder
  381. //
  382. // Arguments: Name - the namespace of interest.
  383. // pPrefix - the logical share for this DFs.
  384. // ppRoot - the newly created root.
  385. //
  386. //
  387. // Returns: Status
  388. // ERROR_SUCCESS on success
  389. // ERROR status code otherwise
  390. //
  391. //
  392. // Description: This routine creates a new registry root folder, and
  393. // adds it to the list of known roots.
  394. //
  395. //--------------------------------------------------------------------------
  396. DFSSTATUS
  397. DfsRegistryStore::CreateNewRootFolder (
  398. LPWSTR MachineName,
  399. LPWSTR RootRegKeyName,
  400. PUNICODE_STRING pLogicalShare,
  401. PUNICODE_STRING pPhysicalShare,
  402. DfsRootFolder **ppRoot )
  403. {
  404. DFSSTATUS Status = ERROR_SUCCESS;
  405. DfsRootFolder *pNewRoot = NULL;
  406. //
  407. // Create a new instance of the RegistryRootFolder class.
  408. // This gives us a reference RootFolder.
  409. //
  410. pNewRoot = new DfsRegistryRootFolder( MachineName,
  411. RootRegKeyName,
  412. pLogicalShare,
  413. pPhysicalShare,
  414. this,
  415. &Status );
  416. if ( pNewRoot == NULL )
  417. {
  418. Status = ERROR_NOT_ENOUGH_MEMORY;
  419. }
  420. if ( ERROR_SUCCESS == Status )
  421. {
  422. //
  423. // AddRootFolder to the list of known roots. AddRootFolder
  424. // is responsible to acquire any reference on the root folder
  425. // if it is storing a reference to this root.
  426. Status = AddRootFolder( pNewRoot, NewRootList );
  427. if ( ERROR_SUCCESS == Status )
  428. {
  429. //
  430. // We were successful, return the reference root. The reference
  431. // that we are returning is the create reference on the new root.
  432. //
  433. *ppRoot = pNewRoot;
  434. }
  435. else
  436. {
  437. pNewRoot->ReleaseReference();
  438. pNewRoot = NULL;
  439. }
  440. }
  441. else
  442. {
  443. if(pNewRoot != NULL)
  444. {
  445. pNewRoot->ReleaseReference();
  446. pNewRoot = NULL;
  447. }
  448. }
  449. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "RegistryStore::CreateNewRootFolder. New root %p, for root %wZ (%wZ) on machine %ws. Status %x\n",
  450. *ppRoot, pLogicalShare, pPhysicalShare, MachineName, Status);
  451. return Status;
  452. }
  453. //+-------------------------------------------------------------------------
  454. //
  455. // Function: GetMetadata- Gets the DFS metadata information
  456. //
  457. // Arguments: DfsMetadataKey - The key under which the information exists
  458. // RelativeName - the name of the subkey, having info of interest
  459. // RegistryValueNameString - The value name that holds the info.
  460. // ppData - the pointer that holds data buffer being returned
  461. // pDataSize - pointer to size of data being returned.
  462. //
  463. // Returns: Status
  464. // STATUS_SUCCESS if we could read the information,
  465. // error status otherwise.
  466. //
  467. //
  468. // Description: This routine reads the value of interest under the specified
  469. // key/subkey. The information is read in a buffer allocated
  470. // by this routine, and the buffer is returned to the caller.
  471. // It is the caller's responsibility to free this buffer when
  472. // done.
  473. //
  474. //--------------------------------------------------------------------------
  475. DFSSTATUS
  476. DfsRegistryStore::GetMetadata (
  477. IN HKEY DfsMetadataKey,
  478. IN LPWSTR RelativeName,
  479. IN LPWSTR RegistryValueNameString,
  480. OUT PVOID *ppData,
  481. OUT ULONG *pDataSize,
  482. OUT PFILETIME pLastModifiedTime)
  483. {
  484. HKEY NewKey = NULL;
  485. HKEY UseKey = NULL;
  486. PVOID pDataBuffer = NULL;
  487. ULONG DataSize, DataType;
  488. DFSSTATUS Status = ERROR_SUCCESS;
  489. //
  490. // If a relative name was passed in, we need to open a subkey under the
  491. // passed in key. Otherwise, we already have a key open to the information
  492. // of interest.
  493. //
  494. if ( RelativeName != NULL )
  495. {
  496. Status = RegOpenKeyEx( DfsMetadataKey,
  497. RelativeName,
  498. 0,
  499. KEY_READ,
  500. &NewKey );
  501. if ( Status == ERROR_SUCCESS )
  502. {
  503. UseKey = NewKey;
  504. }
  505. else
  506. {
  507. DFS_TRACE_HIGH( REFERRAL_SERVER, "registry store, GetMetadata-RegOpenKeyEx %ws status=%d\n", RelativeName, Status);
  508. }
  509. } else
  510. {
  511. UseKey = DfsMetadataKey;
  512. }
  513. //
  514. // Get the largest size of any value under the key of interest, so we know
  515. // how much we need to allocate in the worst case.
  516. // (If a subkey has 3 values, this returns the maximum memory size required
  517. // to read any one of the values.)
  518. //
  519. if ( Status == ERROR_SUCCESS )
  520. {
  521. Status = RegQueryInfoKey( UseKey, // Key
  522. NULL, // Class string
  523. NULL, // Size of class string
  524. NULL, // Reserved
  525. NULL, // # of subkeys
  526. NULL, // max size of subkey name
  527. NULL, // max size of class name
  528. NULL, // # of values
  529. NULL, // max size of value name
  530. &DataSize, // max size of value data,
  531. NULL, // security descriptor
  532. pLastModifiedTime ); // Last write time
  533. }
  534. //
  535. // We have the required size now: allocate a buffer for that size and
  536. // read the value we are interested in.
  537. //
  538. if ( Status == ERROR_SUCCESS )
  539. {
  540. pDataBuffer = new BYTE [DataSize];
  541. if ( pDataBuffer == NULL )
  542. {
  543. Status = ERROR_NOT_ENOUGH_MEMORY;
  544. } else
  545. {
  546. Status = RegQueryValueEx( UseKey,
  547. RegistryValueNameString,
  548. NULL,
  549. &DataType,
  550. (LPBYTE)pDataBuffer,
  551. &DataSize );
  552. //
  553. // If the format of data is not a certain type (usually binary type for DFS)
  554. // we have bogus data.
  555. //
  556. if ( (Status == ERROR_SUCCESS) && (DataType != DFS_REGISTRY_DATA_TYPE) )
  557. {
  558. Status = ERROR_INVALID_DATA;
  559. }
  560. }
  561. }
  562. //
  563. // If we are successful in reading the value, pass the allcoated buffer and
  564. // size back to caller. Otherwise, free up the allocate buffer and return
  565. // error status to the caller.
  566. //
  567. if ( Status == ERROR_SUCCESS )
  568. {
  569. *ppData = pDataBuffer;
  570. *pDataSize = DataSize;
  571. }
  572. else
  573. {
  574. if ( pDataBuffer != NULL )
  575. {
  576. delete [] pDataBuffer;
  577. }
  578. }
  579. //
  580. // If we did open a new key, it is time to close it now.
  581. //
  582. if ( NewKey != NULL )
  583. RegCloseKey(NewKey);
  584. DFS_TRACE_LOW( REFERRAL_SERVER, "registry store, GetMetadata-leaving %ws status=%d\n", RelativeName, Status);
  585. return Status;
  586. }
  587. //+-------------------------------------------------------------------------
  588. //
  589. // Function: SetMetadata- Sets the DFS metadata information
  590. //
  591. // Arguments: DfsMetadataKey - The key under which the information exists
  592. // RelativeName - the name of the subkey, to store info
  593. // RegistryValueNameString - The value name that holds the info.
  594. // pData - the pointer that holds data buffer
  595. // DataSize - Size of data
  596. //
  597. // Returns: Status
  598. // STATUS_SUCCESS if we could write the information,
  599. // error status otherwise.
  600. //
  601. //
  602. // Description: This routine writes the value of interest under the specified
  603. // key/subkey.
  604. //
  605. //--------------------------------------------------------------------------
  606. DFSSTATUS
  607. DfsRegistryStore::SetMetadata (
  608. IN HKEY DfsMetadataKey,
  609. IN LPWSTR RelativeName,
  610. IN LPWSTR RegistryValueNameString,
  611. IN PVOID pData,
  612. IN ULONG DataSize )
  613. {
  614. HKEY UseKey = NULL;
  615. DFSSTATUS Status = ERROR_SUCCESS;
  616. //
  617. // If a relative name was passed in, we need to open a subkey under the
  618. // passed in key. Otherwise, we already have a key open to the information
  619. // of interest.
  620. //
  621. Status = RegOpenKeyEx( DfsMetadataKey,
  622. RelativeName,
  623. 0,
  624. KEY_READ | KEY_WRITE,
  625. &UseKey );
  626. //
  627. // Store the value against the passed in value string
  628. //
  629. if (Status == ERROR_SUCCESS)
  630. {
  631. Status = RegSetValueEx( UseKey,
  632. RegistryValueNameString,
  633. NULL,
  634. DFS_REGISTRY_DATA_TYPE,
  635. (LPBYTE)pData,
  636. DataSize );
  637. RegCloseKey(UseKey);
  638. }
  639. DFS_TRACE_LOW( REFERRAL_SERVER, "registry store, SetMetadata-RegOpenKeyEx %ws status=%d\n", RelativeName, Status);
  640. return Status;
  641. }
  642. //+-------------------------------------------------------------------------
  643. //
  644. // Function: GetRootKey - get the root key
  645. //
  646. // Arguments: Name - the namespace of interest.
  647. // pMachineContacted - did we contact the machine?
  648. // pDfsRootKey - the returned key.
  649. //
  650. // Returns: Status
  651. // ERROR_SUCCESS on success
  652. // ERROR status code otherwise
  653. //
  654. //
  655. // Description: This routine connects to the appropriate machine, and
  656. // opens the DFS metadata information in the registry.
  657. // If it succeeds, the machine hosts a registry DFs, and
  658. // the opened key is returned.
  659. //
  660. //--------------------------------------------------------------------------
  661. DFSSTATUS
  662. DfsRegistryStore::GetRootKey(
  663. LPWSTR MachineName,
  664. LPWSTR ChildName,
  665. BOOLEAN *pMachineContacted,
  666. OUT PHKEY pDfsRootKey )
  667. {
  668. DFSSTATUS Status;
  669. HKEY DfsStdRegistryKey;
  670. LPWSTR UseChildName = NULL;
  671. if (IsEmptyString(ChildName) == FALSE)
  672. {
  673. UseChildName = ChildName;
  674. }
  675. //
  676. // If there is no childname specified, we are dealing with the
  677. // old style dfs: a single root exists on the machine under "domainroot".
  678. // so open that key, and return it.
  679. // If a childname is specified, we are dealing with a migrated
  680. // dfs. Open the specified child in the new location.
  681. //
  682. if (UseChildName != NULL)
  683. {
  684. Status = GetNewStandaloneRegistryKey( MachineName,
  685. FALSE,
  686. pMachineContacted,
  687. &DfsStdRegistryKey );
  688. if (Status == ERROR_SUCCESS)
  689. {
  690. //
  691. // We then open the required child key, and close
  692. // the parents key.
  693. //
  694. Status = RegOpenKeyEx( DfsStdRegistryKey,
  695. ChildName,
  696. 0,
  697. KEY_READ,
  698. pDfsRootKey );
  699. RegCloseKey( DfsStdRegistryKey );
  700. }
  701. }
  702. else
  703. {
  704. //
  705. // no name was specified. This must be the old standalone
  706. // child. (single root)
  707. //
  708. Status = GetOldStandaloneRegistryKey( MachineName,
  709. FALSE,
  710. pMachineContacted,
  711. pDfsRootKey );
  712. }
  713. DFSLOG("DfsRegistryStore::GetDfsRootKey %ws Machine, Contacted %d Status %x\n",
  714. MachineName, pMachineContacted ? *pMachineContacted : 2, Status );
  715. return Status;
  716. }
  717. //+-------------------------------------------------------------------------
  718. //
  719. // Function: GetDataRecoveryInformation - Gets recovery info
  720. //
  721. // Arguments: DfsMetadataKey - an open key to the registry.
  722. // RelativeName - Name of a subkey under the above key.
  723. // pRecoveryState - The recovery state we read.
  724. //
  725. // Returns: Status
  726. // STATUS_SUCCESS if we could read the information
  727. // error status otherwise.
  728. //
  729. //
  730. // Description: This routine read the RECOVERY value for the Root or link of
  731. // a dfs tree and returns with the value.
  732. // A non-zero state means that some recovery is required.
  733. // Note that there is more information in the RECOVERY value than
  734. // the state. Currently, we ignore that information and just return
  735. // the state.
  736. // In the future, we dont plan to use this value.
  737. //
  738. //--------------------------------------------------------------------------
  739. DFSSTATUS
  740. DfsRegistryStore::GetDataRecoveryState (
  741. IN HKEY DfsMetadataKey,
  742. IN LPWSTR RelativeName,
  743. OUT PULONG pRecoveryState )
  744. {
  745. DFSSTATUS Status = ERROR_SUCCESS;
  746. PVOID DataBuffer = NULL, CurrentBuffer;
  747. ULONG DataSize, CurrentSize;
  748. Status = GetMetadata (DfsMetadataKey,
  749. RelativeName,
  750. DfsRegistryRecoveryString,
  751. &DataBuffer,
  752. &DataSize,
  753. NULL ); // we dont care about last mod time.
  754. //
  755. // We are currently interested in the first word in the data stream.
  756. // This holds the recovery state.
  757. //
  758. if ( Status == STATUS_SUCCESS )
  759. {
  760. CurrentBuffer = DataBuffer;
  761. CurrentSize = DataSize;
  762. Status = PackGetULong( pRecoveryState,
  763. &CurrentBuffer,
  764. &CurrentSize );
  765. }
  766. ReleaseMetadataBlob( DataBuffer );
  767. //
  768. // If we could not read the value, then we return success and
  769. // and indicate state of 0. This is so that we can support roots
  770. // or links that dont have this value.
  771. //
  772. if ( Status != ERROR_SUCCESS )
  773. {
  774. DFSLOG("DfsRegistryStore::DfsGetDataRecoveryState Status %x\n",
  775. Status);
  776. *pRecoveryState = 0;
  777. Status = ERROR_SUCCESS;
  778. }
  779. return Status;
  780. }
  781. INIT_STANDALONE_DFS_ID_PROPERTY_INFO();
  782. //+-------------------------------------------------------------------------
  783. //
  784. // Function: PackGetNameInformation - Unpacks the root/link name info
  785. //
  786. // Arguments: pDfsNameInfo - pointer to the info to fill.
  787. // ppBuffer - pointer to buffer that holds the binary stream.
  788. // pSizeRemaining - pointer to size of above buffer
  789. //
  790. // Returns: Status
  791. // ERROR_SUCCESS if we could unpack the name info
  792. // error status otherwise.
  793. //
  794. //
  795. // Description: This routine expects the binary stream to hold all the
  796. // information that is necessary to return a complete name
  797. // info structure (as defined by MiDfsIdProperty). If the stream
  798. // does not have the sufficient
  799. // info, ERROR_INVALID_DATA is returned back.
  800. //
  801. //--------------------------------------------------------------------------
  802. DFSSTATUS
  803. DfsRegistryStore::PackGetNameInformation(
  804. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  805. IN OUT PVOID *ppBuffer,
  806. IN OUT PULONG pSizeRemaining)
  807. {
  808. DFSSTATUS Status;
  809. //
  810. // Get the name information from the binary stream.
  811. //
  812. Status = PackGetInformation( (ULONG_PTR)pDfsNameInfo,
  813. ppBuffer,
  814. pSizeRemaining,
  815. &MiStdDfsIdProperty );
  816. //
  817. // Immediately following the name value is a timeout value.
  818. // This is not in the MiDfsIdProperty because it appers that some
  819. // of the older DFS may not have the timeout value.
  820. //
  821. if ( Status == ERROR_SUCCESS )
  822. {
  823. pDfsNameInfo->LastModifiedTime = pDfsNameInfo->PrefixTimeStamp;
  824. Status = PackGetULong(&pDfsNameInfo->Timeout,
  825. ppBuffer,
  826. pSizeRemaining);
  827. //
  828. // Use a default value if we cannot get the timeout value in
  829. // the stream.
  830. //
  831. if ( Status != ERROR_SUCCESS )
  832. {
  833. pDfsNameInfo->Timeout = 300; // hard code this value.
  834. Status = ERROR_SUCCESS;
  835. }
  836. }
  837. if (Status == ERROR_SUCCESS)
  838. {
  839. if ((pDfsNameInfo->Type & 0x80) == 0x80)
  840. {
  841. pDfsNameInfo->State |= DFS_VOLUME_FLAVOR_STANDALONE;
  842. }
  843. }
  844. return Status;
  845. }
  846. //+-------------------------------------------------------------------------
  847. //
  848. // Function: PackSetNameInformation - Packs the root/link name info
  849. //
  850. // Arguments: pDfsNameInfo - pointer to the info to pack.
  851. // ppBuffer - pointer to buffer that holds the binary stream.
  852. // pSizeRemaining - pointer to size of above buffer
  853. //
  854. // Returns: Status
  855. // ERROR_SUCCESS if we could pack the name info
  856. // error status otherwise.
  857. //
  858. //
  859. // Description: This routine takes the passedin name information and
  860. // stores it in the binary stream passed in.
  861. //
  862. //--------------------------------------------------------------------------
  863. DFSSTATUS
  864. DfsRegistryStore::PackSetNameInformation(
  865. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  866. IN OUT PVOID *ppBuffer,
  867. IN OUT PULONG pSizeRemaining)
  868. {
  869. DFSSTATUS Status;
  870. pDfsNameInfo->State &= ~DFS_VOLUME_FLAVORS;
  871. pDfsNameInfo->PrefixTimeStamp = pDfsNameInfo->LastModifiedTime;
  872. pDfsNameInfo->StateTimeStamp = pDfsNameInfo->LastModifiedTime;
  873. pDfsNameInfo->CommentTimeStamp = pDfsNameInfo->LastModifiedTime;
  874. //
  875. // Store the DfsNameInfo in the stream first.
  876. //
  877. Status = PackSetInformation( (ULONG_PTR)pDfsNameInfo,
  878. ppBuffer,
  879. pSizeRemaining,
  880. &MiStdDfsIdProperty );
  881. //
  882. // Follow that info with the timeout information.
  883. //
  884. if ( Status == ERROR_SUCCESS )
  885. {
  886. Status = PackSetULong( pDfsNameInfo->Timeout,
  887. ppBuffer,
  888. pSizeRemaining);
  889. }
  890. return Status;
  891. }
  892. //+-------------------------------------------------------------------------
  893. //
  894. // Function: PackSizeNameInformation - Gets the size of the name info.
  895. //
  896. // Arguments: pDfsNameInfo - info to size.
  897. //
  898. // Returns: Status
  899. // ULONG - size needed
  900. //
  901. // Description: This routine gets us the size of the binary stream
  902. // required to pack the passed in name info.
  903. //
  904. //--------------------------------------------------------------------------
  905. ULONG
  906. DfsRegistryStore::PackSizeNameInformation(
  907. IN PDFS_NAME_INFORMATION pDfsNameInfo )
  908. {
  909. ULONG Size;
  910. Size = PackSizeInformation( (ULONG_PTR)pDfsNameInfo,
  911. &MiStdDfsIdProperty );
  912. Size += PackSizeULong();
  913. return Size;
  914. }
  915. //+-------------------------------------------------------------------------
  916. //
  917. // Function: AddChild - Add a child to the metadata.
  918. //
  919. // Arguments:
  920. // DfsMetadataHandle - the Metadata key for the root.
  921. // PUNICODE_STRING pLinkLogicalName - the logical name of the child
  922. // LPWSTR ReplicaServer - the first target server for this link.
  923. // LPWSTR ReplicaPath - the target path for this link
  924. // LPWSTR Comment - the comment to be associated with this link.
  925. // LPWSTR pMetadataName - the metadata name for the child, returned..
  926. //
  927. //
  928. // Returns: Status:
  929. //
  930. // Description: This routine adds a child to the Root metadata. It packs
  931. // the link name into the name information. If the replica
  932. // information exists, it packs that into the replica info.
  933. // It then saves the name and replica streams under the
  934. // Childkey.
  935. // NOTE: this function does not require that the link
  936. // have atleast one replica. Any such requirements
  937. // should be enforced by the caller.
  938. //
  939. //--------------------------------------------------------------------------
  940. DFSSTATUS
  941. DfsRegistryStore::AddChild(
  942. IN DFS_METADATA_HANDLE DfsHandle,
  943. IN PDFS_NAME_INFORMATION pNameInfo,
  944. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  945. IN PUNICODE_STRING pMetadataName )
  946. {
  947. DFSSTATUS Status;
  948. PVOID pNameBlob, pReplicaBlob;
  949. ULONG NameBlobSize, ReplicaBlobSize;
  950. Status = CreateNameInformationBlob( pNameInfo,
  951. &pNameBlob,
  952. &NameBlobSize );
  953. if (Status == ERROR_SUCCESS)
  954. {
  955. Status = CreateReplicaListInformationBlob( pReplicaListInfo,
  956. &pReplicaBlob,
  957. &ReplicaBlobSize );
  958. if (Status == ERROR_SUCCESS)
  959. {
  960. Status = CreateNewChild( DfsHandle,
  961. pNameBlob,
  962. NameBlobSize,
  963. pReplicaBlob,
  964. ReplicaBlobSize,
  965. pMetadataName );
  966. ReleaseMetadataReplicaBlob( pReplicaBlob, ReplicaBlobSize );
  967. }
  968. ReleaseMetadataNameBlob( pNameBlob, NameBlobSize );
  969. }
  970. return Status;
  971. }
  972. DFSSTATUS
  973. DfsRegistryStore::CreateNewChild(
  974. IN DFS_METADATA_HANDLE DfsHandle,
  975. IN PVOID pNameBlob,
  976. IN ULONG NameBlobSize,
  977. IN PVOID pReplicaBlob,
  978. IN ULONG ReplicaBlobSize,
  979. IN PUNICODE_STRING pMetadataName )
  980. {
  981. HKEY DfsMetadataKey;
  982. DFSSTATUS Status;
  983. HKEY ChildKey;
  984. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( DfsHandle );
  985. //
  986. // Now create the child with this name
  987. //
  988. Status = RegCreateKeyEx( DfsMetadataKey,
  989. pMetadataName->Buffer,
  990. 0,
  991. L"",
  992. REG_OPTION_NON_VOLATILE,
  993. KEY_READ | KEY_WRITE,
  994. NULL,
  995. &ChildKey,
  996. NULL );
  997. //
  998. // Now set the name and replica information on this newly created
  999. // key.
  1000. //
  1001. if (Status == ERROR_SUCCESS)
  1002. {
  1003. Status = SetMetadata( ChildKey,
  1004. NULL,
  1005. DfsRegistryNameString,
  1006. pNameBlob,
  1007. NameBlobSize );
  1008. if (Status == ERROR_SUCCESS)
  1009. {
  1010. Status = SetMetadata( ChildKey,
  1011. NULL,
  1012. DfsRegistryReplicaString,
  1013. pReplicaBlob,
  1014. ReplicaBlobSize );
  1015. }
  1016. //
  1017. // we are done with the child key: close it here.
  1018. //
  1019. RegCloseKey (ChildKey);
  1020. //
  1021. // if we were unsuccessful in adding the name and
  1022. // replica details, get rid of the new child registry entry.
  1023. //
  1024. if (Status != ERROR_SUCCESS)
  1025. {
  1026. DFSSTATUS DeleteStatus;
  1027. DeleteStatus = RegDeleteKey( DfsMetadataKey,
  1028. pMetadataName->Buffer );
  1029. DFSLOG("Created Key, but failed to add values %x. Delete Status %x\n",
  1030. Status, DeleteStatus );
  1031. }
  1032. }
  1033. return Status;
  1034. }
  1035. DFSSTATUS
  1036. DfsRegistryStore::RemoveChild(
  1037. IN DFS_METADATA_HANDLE DfsHandle,
  1038. LPWSTR ChildName )
  1039. {
  1040. DFSSTATUS Status;
  1041. HKEY DfsMetadataKey;
  1042. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( DfsHandle );
  1043. Status = RegDeleteKey( DfsMetadataKey,
  1044. ChildName );
  1045. return Status;
  1046. }
  1047. DFSSTATUS
  1048. DfsRegistryStore::CreateStandaloneRoot(
  1049. LPWSTR MachineName,
  1050. LPWSTR LogicalShare,
  1051. LPWSTR Comment )
  1052. {
  1053. DFSSTATUS Status = ERROR_SUCCESS;
  1054. HKEY StdDfsKey = NULL;
  1055. HKEY StdDfsShareKey = NULL;
  1056. DfsRootFolder *pRootFolder = NULL;
  1057. PVOID pBlob = NULL;
  1058. ULONG BlobSize = 0;
  1059. DFS_NAME_INFORMATION NameInfo;
  1060. DFS_REPLICA_LIST_INFORMATION ReplicaListInfo;
  1061. DFS_REPLICA_INFORMATION ReplicaInfo;
  1062. UNICODE_STRING DfsMachine;
  1063. UNICODE_STRING DfsShare;
  1064. DFS_TRACE_LOW( REFERRAL_SERVER, "registry store, create root %ws\n", LogicalShare);
  1065. Status = DfsRtlInitUnicodeStringEx( &DfsMachine, MachineName );
  1066. if(Status != ERROR_SUCCESS)
  1067. {
  1068. Status = ERROR_INVALID_PARAMETER;
  1069. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "CreateStandaloneRoot, DfsRtlInitUnicodeStringEx - create root %ws, status %x\n", LogicalShare, Status);
  1070. return Status;
  1071. }
  1072. Status = DfsRtlInitUnicodeStringEx( &DfsShare, LogicalShare );
  1073. if(Status != ERROR_SUCCESS)
  1074. {
  1075. Status = ERROR_INVALID_PARAMETER;
  1076. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "CreateStandaloneRoot, DfsRtlInitUnicodeStringEx - create root %ws, status %x\n", LogicalShare, Status);
  1077. return Status;
  1078. }
  1079. RtlZeroMemory(&NameInfo, sizeof(DFS_NAME_INFORMATION));
  1080. if (DfsIsSpecialDomainShare(&DfsShare))
  1081. {
  1082. Status = ERROR_INVALID_PARAMETER;
  1083. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "registry store, Special Share - create root %ws, status %x\n", LogicalShare, Status);
  1084. return Status;
  1085. }
  1086. Status = LookupRoot( &DfsMachine,
  1087. &DfsShare,
  1088. &pRootFolder );
  1089. DFS_TRACE_LOW( REFERRAL_SERVER, "registry store, create root, lookup root %p, status %x\n", pRootFolder, Status);
  1090. if (Status == ERROR_SUCCESS)
  1091. {
  1092. pRootFolder->ReleaseReference();
  1093. Status = ERROR_FILE_EXISTS;
  1094. return Status;
  1095. }
  1096. Status = GetNewStandaloneRegistryKey( MachineName,
  1097. TRUE, // write permission required
  1098. NULL,
  1099. &StdDfsKey );
  1100. if (Status == ERROR_SUCCESS)
  1101. {
  1102. UNICODE_STRING LogicalName;
  1103. RtlInitUnicodeString( &LogicalName, LogicalShare );
  1104. StoreInitializeNameInformation( &NameInfo,
  1105. &LogicalName,
  1106. NULL,
  1107. Comment );
  1108. NameInfo.Type |= 0x80;
  1109. StoreInitializeReplicaInformation( &ReplicaListInfo,
  1110. &ReplicaInfo,
  1111. (MachineName == NULL) ? L"." : MachineName,
  1112. LogicalShare );
  1113. }
  1114. if (Status == ERROR_SUCCESS) {
  1115. #if defined (DFS_FUTURES)
  1116. //
  1117. // Check if we need to store the root as a guid instead of
  1118. // the root name itself.
  1119. // It is probably not necessary, but for some reason if we need
  1120. // to, we can scavenge this code.
  1121. //
  1122. //
  1123. // get an unique metadata name for the root.
  1124. //
  1125. Status = DfsGenerateUuidString(&UuidString);
  1126. #endif
  1127. Status = RegCreateKeyEx( StdDfsKey,
  1128. LogicalShare,
  1129. 0,
  1130. L"",
  1131. REG_OPTION_NON_VOLATILE,
  1132. KEY_READ | KEY_WRITE,
  1133. NULL,
  1134. &StdDfsShareKey,
  1135. NULL );
  1136. if (Status == ERROR_SUCCESS)
  1137. {
  1138. size_t LogicalShareCchLength = 0;
  1139. Status = DfsStringCchLength( LogicalShare,
  1140. MAXUSHORT,
  1141. &LogicalShareCchLength );
  1142. if (Status == ERROR_SUCCESS)
  1143. {
  1144. LogicalShareCchLength++; // NULL Terminator
  1145. Status = RegSetValueEx( StdDfsShareKey,
  1146. DfsRootShareValueName,
  1147. 0,
  1148. REG_SZ,
  1149. (PBYTE)LogicalShare,
  1150. LogicalShareCchLength * sizeof(WCHAR) );
  1151. }
  1152. if (Status == ERROR_SUCCESS)
  1153. {
  1154. Status = RegSetValueEx( StdDfsShareKey,
  1155. DfsLogicalShareValueName,
  1156. 0,
  1157. REG_SZ,
  1158. (PBYTE)LogicalShare,
  1159. LogicalShareCchLength * sizeof(WCHAR) );
  1160. }
  1161. if (Status == ERROR_SUCCESS)
  1162. {
  1163. Status = CreateNameInformationBlob( &NameInfo,
  1164. &pBlob,
  1165. &BlobSize);
  1166. if (Status == ERROR_SUCCESS)
  1167. {
  1168. Status = SetMetadata( StdDfsShareKey,
  1169. NULL,
  1170. DfsRegistryNameString,
  1171. pBlob,
  1172. BlobSize );
  1173. ReleaseMetadataNameBlob(pBlob, BlobSize );
  1174. }
  1175. }
  1176. if (Status == ERROR_SUCCESS)
  1177. {
  1178. Status = CreateReplicaListInformationBlob( &ReplicaListInfo,
  1179. &pBlob,
  1180. &BlobSize);
  1181. if (Status == ERROR_SUCCESS)
  1182. {
  1183. Status = SetMetadata( StdDfsShareKey,
  1184. NULL,
  1185. DfsRegistryReplicaString,
  1186. pBlob,
  1187. BlobSize );
  1188. ReleaseMetadataNameBlob( pBlob, BlobSize );
  1189. }
  1190. }
  1191. if (Status == ERROR_SUCCESS)
  1192. {
  1193. Status = GetRootFolder( MachineName,
  1194. LogicalShare,
  1195. &DfsShare,
  1196. &DfsShare,
  1197. &pRootFolder );
  1198. if (Status == ERROR_SUCCESS)
  1199. {
  1200. //
  1201. // Now, acquire the root share directory. If we fail
  1202. // this, we deny the creation of the root.
  1203. // acquire root share directory converts the root share
  1204. // to a physical path, checks if that supports
  1205. // reparse points, and if so tells the dfs driver
  1206. // to attach to the drive.
  1207. // if any of these fail, we cannot proceed.
  1208. //
  1209. Status = pRootFolder->AcquireRootShareDirectory();
  1210. if (Status != ERROR_SUCCESS)
  1211. {
  1212. //
  1213. // make a best effort to remove ourselves
  1214. // dont care about status return, thoug
  1215. // we may want to log it.
  1216. //dfsdev: add logging.
  1217. //
  1218. RemoveRootFolder(pRootFolder,
  1219. TRUE ); // permanent removal
  1220. }
  1221. //
  1222. // now mark the root folder as synchronized:
  1223. // this is true since this root is empty.
  1224. //
  1225. if (Status == ERROR_SUCCESS)
  1226. {
  1227. pRootFolder->SetRootFolderSynchronized();
  1228. }
  1229. pRootFolder->ReleaseReference();
  1230. }
  1231. DFSLOG("Add Standalone Root, adding root folder status %x\n", Status);
  1232. }
  1233. RegCloseKey( StdDfsShareKey );
  1234. if (Status != ERROR_SUCCESS)
  1235. {
  1236. RegDeleteKey( StdDfsKey,
  1237. LogicalShare );
  1238. }
  1239. }
  1240. #if defined (DFS_FUTURES)
  1241. DfsReleaseUuidString(&UuidString);
  1242. #endif
  1243. RegCloseKey( StdDfsKey );
  1244. }
  1245. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "registry store, create root %ws, status %x\n", LogicalShare, Status);
  1246. return Status;
  1247. }
  1248. DFSSTATUS
  1249. DfsRegistryStore::DeleteStandaloneRoot(
  1250. LPWSTR MachineName,
  1251. LPWSTR LogicalShare )
  1252. {
  1253. DFSSTATUS Status = ERROR_SUCCESS;
  1254. HKEY DfsKey = NULL;
  1255. DfsRootFolder *pRootFolder = NULL;
  1256. LPWSTR RootRegistryName = NULL;
  1257. LPWSTR UseChildName = NULL;
  1258. UNICODE_STRING DfsMachine;
  1259. UNICODE_STRING DfsShare;
  1260. DFS_TRACE_LOW( REFERRAL_SERVER, "Delete Standalone root %ws\n", LogicalShare);
  1261. Status = DfsRtlInitUnicodeStringEx( &DfsMachine, MachineName );
  1262. if(Status != ERROR_SUCCESS)
  1263. {
  1264. Status = ERROR_INVALID_PARAMETER;
  1265. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "DeleteStandaloneRoot, DfsRtlInitUnicodeStringEx - create root %ws, status %x\n", LogicalShare, Status);
  1266. return Status;
  1267. }
  1268. Status = DfsRtlInitUnicodeStringEx( &DfsShare, LogicalShare );
  1269. if(Status != ERROR_SUCCESS)
  1270. {
  1271. Status = ERROR_INVALID_PARAMETER;
  1272. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "DeleteStandaloneRoot, DfsRtlInitUnicodeStringEx - create root %ws, status %x\n", LogicalShare, Status);
  1273. return Status;
  1274. }
  1275. Status = LookupRoot( &DfsMachine,
  1276. &DfsShare,
  1277. &pRootFolder );
  1278. DFS_TRACE_LOW( REFERRAL_SERVER, "Delete Standalone root, lookup root %p, status %x\n", pRootFolder, Status);
  1279. if (Status == ERROR_SUCCESS)
  1280. {
  1281. Status = pRootFolder->AcquireRootLock();
  1282. if (Status == ERROR_SUCCESS)
  1283. {
  1284. pRootFolder->SetRootFolderDeleteInProgress();
  1285. pRootFolder->ReleaseRootLock();
  1286. }
  1287. }
  1288. if (Status == ERROR_SUCCESS)
  1289. {
  1290. RootRegistryName = pRootFolder->GetRootRegKeyNameString();
  1291. UseChildName = (IsEmptyString(RootRegistryName) == TRUE) ? NULL : RootRegistryName;
  1292. if (UseChildName == NULL)
  1293. {
  1294. Status = GetOldDfsRegistryKey( MachineName,
  1295. TRUE,
  1296. NULL,
  1297. &DfsKey );
  1298. if (Status == ERROR_SUCCESS)
  1299. {
  1300. Status = SHDeleteKey( DfsKey,
  1301. DfsOldStandaloneChild);
  1302. RegCloseKey( DfsKey );
  1303. }
  1304. }
  1305. else
  1306. {
  1307. Status = GetNewStandaloneRegistryKey( MachineName,
  1308. TRUE,
  1309. NULL,
  1310. &DfsKey );
  1311. if (Status == ERROR_SUCCESS)
  1312. {
  1313. Status = SHDeleteKey( DfsKey,
  1314. UseChildName );
  1315. RegCloseKey( DfsKey );
  1316. }
  1317. }
  1318. }
  1319. //
  1320. // DfsDev: needs fixing.
  1321. //
  1322. if (Status == ERROR_SUCCESS)
  1323. {
  1324. NTSTATUS DeleteStatus;
  1325. //
  1326. // Release the root folder that we had acquired earlier for
  1327. // this root.
  1328. //
  1329. DeleteStatus = RemoveRootFolder( pRootFolder,
  1330. TRUE ); // permanent removal
  1331. DFS_TRACE_ERROR_LOW( DeleteStatus, REFERRAL_SERVER, "remove root folder %p (%ws) status %x\n", pRootFolder, LogicalShare, DeleteStatus);
  1332. DeleteStatus = pRootFolder->ReleaseRootShareDirectory();
  1333. DFS_TRACE_ERROR_LOW( DeleteStatus, REFERRAL_SERVER, "release root share for %ws status %x\n", LogicalShare, DeleteStatus);
  1334. pRootFolder->ReleaseReference();
  1335. }
  1336. DFS_TRACE_ERROR_LOW( Status, REFERRAL_SERVER, "Delete Standalone root for %ws, done, status %x\n", LogicalShare, Status);
  1337. return Status;
  1338. }
  1339. DFSSTATUS
  1340. DfsRegistryStore::EnumerateApiLinks(
  1341. IN DFS_METADATA_HANDLE DfsHandle,
  1342. PUNICODE_STRING pRootName,
  1343. DWORD Level,
  1344. LPBYTE pBuffer,
  1345. LONG BufferSize,
  1346. LPDWORD pEntriesToRead,
  1347. LPDWORD pResumeHandle,
  1348. PLONG pSizeRequired )
  1349. {
  1350. HKEY DfsKey = NULL;
  1351. ULONG ChildNum = 0;
  1352. DFSSTATUS Status = ERROR_SUCCESS;
  1353. BOOLEAN OverFlow = FALSE;
  1354. LONG HeaderSize = 0;
  1355. LONG EntriesRead = 0;
  1356. LONG EntriesToRead = *pEntriesToRead;
  1357. LONG SizeRequired = 0;
  1358. LONG EntryCount = 0;
  1359. LPBYTE pLinkBuffer = NULL;
  1360. LONG LinkBufferSize = 0;
  1361. LPBYTE CurrentBuffer = NULL;
  1362. LPBYTE NewBuffer = NULL;
  1363. LONG SizeRemaining = 0;
  1364. DFSSTATUS PackStatus = ERROR_SUCCESS;
  1365. ULONG_PTR SizeDiff;
  1366. DWORD CchMaxName = 0;
  1367. DWORD CchChildName = 0;
  1368. LPWSTR ChildName = NULL;
  1369. Status = DfsApiSizeLevelHeader( Level, &HeaderSize );
  1370. if (Status != ERROR_SUCCESS)
  1371. {
  1372. return Status;
  1373. }
  1374. DfsKey = (HKEY)ExtractFromMetadataHandle( DfsHandle );
  1375. OverFlow = FALSE;
  1376. SizeRequired = ROUND_UP_COUNT(EntriesToRead * HeaderSize, ALIGN_QUAD);
  1377. if (EntriesToRead * HeaderSize < BufferSize )
  1378. {
  1379. CurrentBuffer = (LPBYTE)((ULONG_PTR)pBuffer + EntriesToRead * HeaderSize);
  1380. SizeRemaining = BufferSize - EntriesToRead * HeaderSize;
  1381. }
  1382. else
  1383. {
  1384. CurrentBuffer = pBuffer;
  1385. SizeRemaining = 0;
  1386. OverFlow = TRUE;
  1387. }
  1388. if(pResumeHandle)
  1389. {
  1390. EntryCount = *pResumeHandle;
  1391. }
  1392. if (EntryCount == 0)
  1393. {
  1394. Status = GetStoreApiInformationBuffer ( DfsHandle,
  1395. pRootName,
  1396. NULL,
  1397. Level,
  1398. &pLinkBuffer,
  1399. &LinkBufferSize );
  1400. if (Status == ERROR_SUCCESS)
  1401. {
  1402. SizeRequired += ROUND_UP_COUNT(LinkBufferSize, ALIGN_QUAD);
  1403. if (OverFlow == FALSE)
  1404. {
  1405. PackStatus = PackageEnumerationInfo( Level,
  1406. EntriesRead,
  1407. pLinkBuffer,
  1408. pBuffer,
  1409. &CurrentBuffer,
  1410. &SizeRemaining );
  1411. if (PackStatus == ERROR_BUFFER_OVERFLOW)
  1412. {
  1413. OverFlow = TRUE;
  1414. }
  1415. NewBuffer = (LPBYTE)ROUND_UP_POINTER( CurrentBuffer, ALIGN_LPVOID);
  1416. SizeDiff = (NewBuffer - CurrentBuffer);
  1417. if ((LONG)SizeDiff > SizeRemaining)
  1418. {
  1419. SizeRemaining = 0;
  1420. }
  1421. else
  1422. {
  1423. SizeRemaining -= (LONG)SizeDiff;
  1424. }
  1425. CurrentBuffer = NewBuffer;
  1426. }
  1427. ReleaseStoreApiInformationBuffer( pLinkBuffer );
  1428. EntryCount++;
  1429. EntriesRead++;
  1430. }
  1431. }
  1432. if (Status != ERROR_SUCCESS )
  1433. {
  1434. return Status;
  1435. }
  1436. ChildNum = EntryCount - 1;
  1437. //
  1438. // First find the length of the longest subkey
  1439. // and allocate a buffer big enough for it.
  1440. //
  1441. Status = RegQueryInfoKey( DfsKey, // Key
  1442. NULL, // Class string
  1443. NULL, // Size of class string
  1444. NULL, // Reserved
  1445. NULL, // # of subkeys
  1446. &CchMaxName, // max size of subkey name in TCHARs
  1447. NULL, // max size of class name
  1448. NULL, // # of values
  1449. NULL, // max size of value name
  1450. NULL, // max size of value data,
  1451. NULL, // security descriptor
  1452. NULL ); // Last write time
  1453. if (Status == ERROR_SUCCESS)
  1454. {
  1455. CchMaxName++; // Space for the NULL terminator.
  1456. ChildName = (LPWSTR) new WCHAR [CchMaxName];
  1457. if (ChildName == NULL)
  1458. {
  1459. Status = ERROR_NOT_ENOUGH_MEMORY;
  1460. }
  1461. }
  1462. if (Status == ERROR_SUCCESS)
  1463. {
  1464. do
  1465. {
  1466. //
  1467. // For each child, get the child name.
  1468. //
  1469. if (EntriesToRead && EntriesRead >= EntriesToRead)
  1470. {
  1471. break;
  1472. }
  1473. CchChildName = CchMaxName;
  1474. //
  1475. // Now enumerate the children, starting from the first child.
  1476. //
  1477. Status = RegEnumKeyEx( DfsKey,
  1478. ChildNum,
  1479. ChildName,
  1480. &CchChildName,
  1481. NULL,
  1482. NULL,
  1483. NULL,
  1484. NULL );
  1485. ChildNum++;
  1486. if (Status == ERROR_SUCCESS)
  1487. {
  1488. Status = GetStoreApiInformationBuffer( DfsHandle,
  1489. pRootName,
  1490. ChildName,
  1491. Level,
  1492. &pLinkBuffer,
  1493. &LinkBufferSize );
  1494. if (Status == ERROR_SUCCESS)
  1495. {
  1496. SizeRequired += ROUND_UP_COUNT(LinkBufferSize, ALIGN_QUAD);
  1497. if (OverFlow == FALSE)
  1498. {
  1499. PackStatus = PackageEnumerationInfo( Level,
  1500. EntriesRead,
  1501. pLinkBuffer,
  1502. pBuffer,
  1503. &CurrentBuffer,
  1504. &SizeRemaining );
  1505. if (PackStatus == ERROR_BUFFER_OVERFLOW)
  1506. {
  1507. OverFlow = TRUE;
  1508. }
  1509. NewBuffer = (LPBYTE)ROUND_UP_POINTER( CurrentBuffer, ALIGN_LPVOID);
  1510. SizeDiff = (NewBuffer - CurrentBuffer);
  1511. if ((LONG)SizeDiff > SizeRemaining)
  1512. {
  1513. SizeRemaining = 0;
  1514. }
  1515. else
  1516. {
  1517. SizeRemaining -= (LONG)SizeDiff;
  1518. }
  1519. CurrentBuffer = NewBuffer;
  1520. }
  1521. ReleaseStoreApiInformationBuffer( pLinkBuffer );
  1522. EntryCount++;
  1523. EntriesRead++;
  1524. }
  1525. }
  1526. } while (Status == ERROR_SUCCESS);
  1527. delete [] ChildName;
  1528. }
  1529. *pSizeRequired = SizeRequired;
  1530. if (Status == ERROR_NO_MORE_ITEMS)
  1531. {
  1532. if (EntriesRead)
  1533. {
  1534. if (OverFlow)
  1535. {
  1536. Status = ERROR_BUFFER_OVERFLOW;
  1537. }
  1538. else
  1539. {
  1540. Status = ERROR_SUCCESS;
  1541. }
  1542. }
  1543. }
  1544. else if (OverFlow)
  1545. {
  1546. Status = ERROR_BUFFER_OVERFLOW;
  1547. }
  1548. if (Status == ERROR_SUCCESS)
  1549. {
  1550. if(pResumeHandle)
  1551. {
  1552. *pResumeHandle = EntryCount;
  1553. }
  1554. *pEntriesToRead = EntriesRead;
  1555. }
  1556. return Status;
  1557. }
  1558. DFSSTATUS
  1559. DfsRegistryStore::GetMetadataNameBlob(
  1560. DFS_METADATA_HANDLE RootHandle,
  1561. LPWSTR MetadataName,
  1562. PVOID *ppData,
  1563. PULONG pDataSize,
  1564. PFILETIME pLastModifiedTime )
  1565. {
  1566. HKEY DfsMetadataKey;
  1567. DFSSTATUS Status;
  1568. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( RootHandle );
  1569. Status = GetMetadata( DfsMetadataKey,
  1570. MetadataName,
  1571. DfsRegistryNameString,
  1572. ppData,
  1573. pDataSize,
  1574. pLastModifiedTime );
  1575. return Status;
  1576. }
  1577. DFSSTATUS
  1578. DfsRegistryStore::GetMetadataReplicaBlob(
  1579. DFS_METADATA_HANDLE RootHandle,
  1580. LPWSTR MetadataName,
  1581. PVOID *ppData,
  1582. PULONG pDataSize,
  1583. PFILETIME pLastModifiedTime )
  1584. {
  1585. HKEY DfsMetadataKey;
  1586. DFSSTATUS Status;
  1587. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( RootHandle );
  1588. Status = GetMetadata( DfsMetadataKey,
  1589. MetadataName,
  1590. DfsRegistryReplicaString,
  1591. ppData,
  1592. pDataSize,
  1593. pLastModifiedTime );
  1594. return Status;
  1595. }
  1596. DFSSTATUS
  1597. DfsRegistryStore::SetMetadataNameBlob(
  1598. DFS_METADATA_HANDLE RootHandle,
  1599. LPWSTR MetadataName,
  1600. PVOID pData,
  1601. ULONG DataSize )
  1602. {
  1603. HKEY DfsMetadataKey;
  1604. DFSSTATUS Status;
  1605. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( RootHandle );
  1606. Status = SetMetadata( DfsMetadataKey,
  1607. MetadataName,
  1608. DfsRegistryNameString,
  1609. pData,
  1610. DataSize );
  1611. return Status;
  1612. }
  1613. DFSSTATUS
  1614. DfsRegistryStore::SetMetadataReplicaBlob(
  1615. DFS_METADATA_HANDLE RootHandle,
  1616. LPWSTR MetadataName,
  1617. PVOID pData,
  1618. ULONG DataSize )
  1619. {
  1620. HKEY DfsMetadataKey;
  1621. DFSSTATUS Status;
  1622. DfsMetadataKey = (HKEY)ExtractFromMetadataHandle( RootHandle );
  1623. Status = SetMetadata( DfsMetadataKey,
  1624. MetadataName,
  1625. DfsRegistryReplicaString,
  1626. pData,
  1627. DataSize );
  1628. return Status;
  1629. }
  1630. //
  1631. // This removes the target share from the
  1632. // Microsoft\Dfs\Roots\Domain registry key.
  1633. //
  1634. DFSSTATUS
  1635. DfsRegistryStore::CleanRegEntry(
  1636. LPWSTR MachineName,
  1637. LPWSTR LogicalShare
  1638. )
  1639. {
  1640. HKEY DfsKey;
  1641. DFSSTATUS Status;
  1642. DFSSTATUS RetStatus = ERROR_NOT_FOUND;
  1643. HKEY DfsDriverKey;
  1644. //
  1645. // If we can open the old registry key,
  1646. // then we assume we are dealing with an
  1647. // old style single root standalone system.
  1648. //
  1649. Status = GetDfsRegistryKey (MachineName,
  1650. DfsRegistryHostLocation, //DfsHost
  1651. TRUE,
  1652. NULL,
  1653. &DfsKey );
  1654. //
  1655. // Delete the \DfsHost\Volumes key and all its values.
  1656. //
  1657. if (Status == ERROR_SUCCESS)
  1658. {
  1659. Status = SHDeleteKey( DfsKey,
  1660. DfsVolumesLocation );
  1661. RegCloseKey( DfsKey );
  1662. if (Status == ERROR_SUCCESS)
  1663. {
  1664. // Something succeeded. We'll return that.
  1665. RetStatus = Status;
  1666. // Delete the DfsDriver\LocalVolumes key as well.
  1667. Status = GetDfsRegistryKey (MachineName,
  1668. DfsRegistryDfsDriverLocation, //System\CCS\Services\DfsDriver
  1669. TRUE,
  1670. NULL,
  1671. &DfsDriverKey );
  1672. //
  1673. // Delete the \LocalVolumes key and all its values.
  1674. //
  1675. if (Status == ERROR_SUCCESS)
  1676. {
  1677. Status = SHDeleteKey( DfsDriverKey,
  1678. DfsLocalVolumesValue );
  1679. RegCloseKey( DfsDriverKey );
  1680. // We don't bother to recreate the DfsHost\Volumes key on error. For all external
  1681. // purposes the root should have disappeared now.
  1682. }
  1683. }
  1684. }
  1685. //
  1686. // BUG 732833: Clean .Net location whether the Win2K location exists or not.
  1687. // We need both locations to co-exist on mix-mode cluster machines.
  1688. //
  1689. Status = GetNewStandaloneRegistryKey( MachineName,
  1690. TRUE,
  1691. NULL,
  1692. &DfsKey );
  1693. if (Status == ERROR_SUCCESS)
  1694. {
  1695. Status = SHDeleteKey( DfsKey,
  1696. LogicalShare );
  1697. if (Status == ERROR_SUCCESS)
  1698. {
  1699. RetStatus = Status;
  1700. }
  1701. RegCloseKey( DfsKey );
  1702. }
  1703. DFS_TRACE_LOW( REFERRAL_SERVER, "registry store, CleanRegistry %ws status=%d\n", MachineName, Status);
  1704. return RetStatus;
  1705. UNREFERENCED_PARAMETER( LogicalShare );
  1706. }