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.

1708 lines
46 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsRootFolder.hxx
  6. //
  7. // Contents: the Root DFS Folder class
  8. //
  9. // Classes: DfsRootFolder
  10. //
  11. // History: Dec. 8 2000, Author: udayh
  12. //
  13. //-----------------------------------------------------------------------------
  14. #ifndef __DFS_ROOT_FOLDER__
  15. #define __DFS_ROOT_FOLDER__
  16. #include "DfsFolder.hxx"
  17. #include "DfsFolderReferralData.hxx"
  18. #include "dfsprefix.h"
  19. #include "dfsnametable.h"
  20. #include "DfsStatistics.hxx"
  21. #define DFS_SHORTNAME_EXPANSION_SIZE 1024
  22. //+----------------------------------------------------------------------------
  23. //
  24. // Class: DfsRootFolder
  25. //
  26. // Synopsis: This class implements The Dfs ROOT folder.
  27. //
  28. //-----------------------------------------------------------------------------
  29. #define NUMBER_OF_SHARED_LINK_LOCKS 0x80
  30. class DfsStore;
  31. //
  32. // The root flags that define the availability of roots for referrals
  33. //
  34. #define ROOT_AVAILABILITY_FLAGS ( ROOT_FOLDER_SHARE_ACQUIRED | \
  35. ROOT_FOLDER_SYNCHRONIZED | \
  36. ROOT_FOLDER_DIRECTORIES_CREATED )
  37. //
  38. // The root flags that define the availability of roots for referrals
  39. //
  40. #define ROOT_REFERRAL_AVAILABILITY_FLAGS ( ROOT_FOLDER_SHARE_ACQUIRED | \
  41. ROOT_FOLDER_SYNCHRONIZED )
  42. //
  43. // The root flags that define the availability of roots for api
  44. //
  45. #define ROOT_API_AVAILABILITY_FLAGS ( ROOT_FOLDER_SYNCHRONIZED )
  46. #define ROOT_SYNCHRONIZE_SKIP_FLAGS ( ROOT_FOLDER_STANDBY | \
  47. ROOT_FOLDER_DELETE_IN_PROGRESS )
  48. #define ROOT_FOLDER_DIRECTORIES_CREATED 0x0010
  49. #define ROOT_FOLDER_SHARE_ACQUIRED 0x0020
  50. #define ROOT_FOLDER_SYNCHRONIZED 0x0100
  51. #define ROOT_FOLDER_STANDBY 0x1000
  52. #define ROOT_FOLDER_DELETE_IN_PROGRESS 0x4000
  53. #define FEWERRORS_ON_ROOT 0
  54. #define TOOMANY_ERRORS_ON_ROOT 1
  55. extern DFSSTATUS
  56. DfsAddReparseVolumeToList (
  57. IN PUNICODE_STRING pDirectoryName);
  58. class DfsRootFolder: public DfsFolder
  59. {
  60. private:
  61. CRITICAL_SECTION *_pRootLock;
  62. CRITICAL_SECTION *_pChildLocks; // All the children locks.
  63. LONG _ChildLockIndex; // Currently allocated lock index.
  64. ULONG _RootFlags;
  65. BOOLEAN _PrefetchNeeded; //load data on startup
  66. BOOLEAN _LogicalShareAddedToTable;
  67. LONG _TooManyEventLogErrors;
  68. UNICODE_STRING _DfsNameContext; // the DfsNameContext for this root.
  69. UNICODE_STRING _DfsNetbiosNameContext; // The netbios DfsNameContext for this root.
  70. UNICODE_STRING _LogicalShareName; // the LogicalShareName of this root.
  71. UNICODE_STRING _PhysicalShareName;
  72. UNICODE_STRING _ShareFilePathName;
  73. UNICODE_STRING _DirectoryCreateRootPathName;
  74. UNICODE_STRING _RootRegKeyName; // the regkey name of the root where we
  75. // store the root information.
  76. // in cae of registry dfs, the metadata is
  77. // also stored under this. IN AD case, this
  78. // will have very little infor such as share info.
  79. BOOLEAN _IgnoreNameContext;
  80. BOOLEAN _CreateDirectories;
  81. DFSSTATUS _DirectoryCreateError;
  82. DFSSTATUS _ShareAcquireStatus;
  83. LONG _ChildCount;
  84. LONG _CurrentErrors;
  85. BOOLEAN _fRootLockInit;
  86. BOOLEAN _fpLockInit;
  87. BOOLEAN _fChildLocksInit[NUMBER_OF_SHARED_LINK_LOCKS];
  88. struct _DFS_PREFIX_TABLE *_pLogicalPrefixTable; // The logical namespace prefix table.
  89. protected:
  90. ULONG _RootFlavor;
  91. BOOLEAN _LocalCreate;
  92. BOOLEAN _RootScalability;
  93. UNICODE_STRING _DfsVisibleContext; // this is the context that should
  94. // be seen during api calls, etc
  95. struct _DFS_NAME_TABLE *_pMetadataNameTable; // the Metadata NameTable.
  96. public:
  97. DfsRootFolder *pPrevRoot, *pNextRoot; // pointers to previos and
  98. // next recognized roots.
  99. DfsStatistics *pStatistics;
  100. private:
  101. virtual
  102. DfsStore *
  103. GetMetadataStore() = 0;
  104. NTSTATUS
  105. SetDfsReparsePoint(
  106. HANDLE DirHandle );
  107. NTSTATUS
  108. CreateLinkDirectories(
  109. PUNICODE_STRING pLinkName,
  110. HANDLE RelativeHandle,
  111. PHANDLE pDirectoryHandle,
  112. PBOOLEAN pIsNewlyCreated,
  113. ULONG ShareMode = 0 );
  114. DFSSTATUS
  115. CreateLinkReparsePoint(
  116. PUNICODE_STRING pLinkName,
  117. HANDLE RelativeHandle );
  118. DFSSTATUS
  119. MorphLinkCollision(
  120. PUNICODE_STRING ParentDirectory,
  121. PUNICODE_STRING DirectoryToRename );
  122. protected:
  123. DFSSTATUS
  124. SetupLinkReparsePoint(
  125. LPWSTR LinkName );
  126. DFSSTATUS
  127. TeardownLinkReparsePoint(
  128. LPWSTR LinkName );
  129. VOID
  130. SetRootFolderShareAcquired()
  131. {
  132. _RootFlags |= ROOT_FOLDER_SHARE_ACQUIRED;
  133. }
  134. VOID
  135. ClearRootFolderShareAcquired()
  136. {
  137. _RootFlags &= ~ROOT_FOLDER_SHARE_ACQUIRED;
  138. }
  139. BOOLEAN
  140. IsRootFolderShareAcquired()
  141. {
  142. return ((_RootFlags & ROOT_FOLDER_SHARE_ACQUIRED) == ROOT_FOLDER_SHARE_ACQUIRED);
  143. }
  144. VOID
  145. SetRootDirectoriesCreated()
  146. {
  147. _RootFlags |= ROOT_FOLDER_DIRECTORIES_CREATED;
  148. }
  149. VOID
  150. ClearRootDirectoriesCreated()
  151. {
  152. _RootFlags &= ~ROOT_FOLDER_DIRECTORIES_CREATED;
  153. }
  154. BOOLEAN
  155. IsRootDirectoriesCreated()
  156. {
  157. return ((_RootFlags & ROOT_FOLDER_DIRECTORIES_CREATED) ==
  158. ROOT_FOLDER_DIRECTORIES_CREATED);
  159. }
  160. VOID
  161. SetRootFolderStandby()
  162. {
  163. ClearRootFolderSynchronized();
  164. _RootFlags |= ROOT_FOLDER_STANDBY;
  165. }
  166. VOID
  167. SetLastCreateDirectoryError( DFSSTATUS Status)
  168. {
  169. _DirectoryCreateError = Status;
  170. }
  171. DFSSTATUS
  172. GetLastCreateDirectoryError()
  173. {
  174. return _DirectoryCreateError;
  175. }
  176. VOID
  177. ClearLastCreateDirectoryError()
  178. {
  179. _DirectoryCreateError = ERROR_SUCCESS;
  180. InterlockedExchange(&_TooManyEventLogErrors, FEWERRORS_ON_ROOT);
  181. _CurrentErrors = 0;
  182. }
  183. VOID
  184. ClearRootFolderStandby()
  185. {
  186. _RootFlags &= ~ROOT_FOLDER_STANDBY;
  187. }
  188. BOOLEAN
  189. IsRootFolderStandby()
  190. {
  191. return ((_RootFlags & ROOT_FOLDER_STANDBY) == ROOT_FOLDER_STANDBY);
  192. }
  193. //
  194. // Function GetChildLock: Increments the ChildLockIndex and picks
  195. // the next lock to allocate. We setup a fixed number of locks, and
  196. // assign a lock to a link in a round-robin basis.
  197. //
  198. CRITICAL_SECTION *
  199. GetChildLock()
  200. {
  201. USHORT LockNum;
  202. LockNum = (USHORT)((ULONG)(InterlockedIncrement(&_ChildLockIndex)) &
  203. (NUMBER_OF_SHARED_LINK_LOCKS - 1));
  204. return &_pChildLocks[LockNum];
  205. }
  206. VOID
  207. SetIgnoreNameContext()
  208. {
  209. _IgnoreNameContext = TRUE;
  210. }
  211. BOOLEAN
  212. IsRootCreateDirectories()
  213. {
  214. return _CreateDirectories;
  215. }
  216. VOID
  217. SetRootShareAcquireStatus( DFSSTATUS Status)
  218. {
  219. _ShareAcquireStatus = Status;
  220. }
  221. DFSSTATUS
  222. GetRootShareAcquireStatus()
  223. {
  224. return _ShareAcquireStatus;
  225. }
  226. DFSSTATUS
  227. InitializeDirectoryCreateInformation()
  228. {
  229. DFSSTATUS Status = ERROR_SUCCESS;
  230. Status = DfsGetSharePath( _DfsNameContext.Buffer,
  231. _PhysicalShareName.Buffer,
  232. &_ShareFilePathName );
  233. if (Status == ERROR_SUCCESS)
  234. {
  235. if (_LocalCreate == TRUE)
  236. {
  237. if (IsEmptyString(_ShareFilePathName.Buffer) )
  238. {
  239. Status = ERROR_INVALID_PARAMETER;
  240. }
  241. else {
  242. Status = DfsCreateUnicodeString( &_DirectoryCreateRootPathName,
  243. &_ShareFilePathName );
  244. }
  245. }
  246. else {
  247. if (IsEmptyString(_DfsNameContext.Buffer))
  248. {
  249. Status = ERROR_INVALID_PARAMETER;
  250. }
  251. else {
  252. Status = DfsCreateUnicodePathString( &_DirectoryCreateRootPathName,
  253. TRUE,
  254. _DfsNameContext.Buffer,
  255. _PhysicalShareName.Buffer );
  256. }
  257. }
  258. }
  259. return Status;
  260. }
  261. //
  262. // Function LoadReplicaReferralData: Loads the replica specific
  263. // data into the DfsFolderReferralData, for the specified child.
  264. //
  265. DFSSTATUS
  266. LoadReplicaReferralData(
  267. DFS_METADATA_HANDLE DfsMetadataHandle,
  268. LPWSTR MetadataName,
  269. DfsFolderReferralData *pReferralData );
  270. //
  271. // Function LoadPolicyReferralData: Loads the policy specific
  272. // data into the DfsFolderReferralData, for the specified child.
  273. // Currently not implemented.
  274. //
  275. DFSSTATUS
  276. LoadPolicyReferralData(
  277. DFS_METADATA_HANDLE DfsMetadataHandle )
  278. {
  279. UNREFERENCED_PARAMETER(DfsMetadataHandle);
  280. return ERROR_SUCCESS;
  281. }
  282. //
  283. // Function UnloadReplicaReferralData: Unloads the replica specific
  284. // data from the DfsFolderReferralData
  285. //
  286. DFSSTATUS
  287. UnloadReplicaReferralData(
  288. DfsFolderReferralData *pReferralData );
  289. //
  290. // Function UnloadPolicyReferralData: Unloads the policy specific
  291. // data from the DfsFolderReferralData.
  292. // Currently not implemented.
  293. //
  294. DFSSTATUS
  295. UnloadPolicyReferralData(
  296. DfsFolderReferralData *pReferralData )
  297. {
  298. UNREFERENCED_PARAMETER(pReferralData);
  299. return ERROR_SUCCESS;
  300. }
  301. VOID IncrementChildCount() {InterlockedIncrement(&_ChildCount); }
  302. VOID DecrementChildCount() {InterlockedDecrement(&_ChildCount); }
  303. public:
  304. VOID
  305. ResetCreateDirectories()
  306. {
  307. _CreateDirectories = FALSE;
  308. }
  309. VOID
  310. SetRootFolderDeleteInProgress()
  311. {
  312. _RootFlags |= ROOT_FOLDER_DELETE_IN_PROGRESS;
  313. }
  314. VOID
  315. ClearRootFolderDeleteInProgress()
  316. {
  317. _RootFlags &= ~ROOT_FOLDER_DELETE_IN_PROGRESS;
  318. }
  319. BOOLEAN
  320. CheckRootFolderSkipSynchronize()
  321. {
  322. return ((_RootFlags & ROOT_SYNCHRONIZE_SKIP_FLAGS) ? TRUE : FALSE);
  323. }
  324. BOOLEAN
  325. IsRootFolderAvailable()
  326. {
  327. return ((_RootFlags & ROOT_AVAILABILITY_FLAGS) == ROOT_AVAILABILITY_FLAGS);
  328. }
  329. BOOLEAN
  330. IsRootSynchronized()
  331. {
  332. return ((_RootFlags & ROOT_FOLDER_SYNCHRONIZED) == ROOT_FOLDER_SYNCHRONIZED);
  333. }
  334. BOOLEAN
  335. IsRootScalabilityMode()
  336. {
  337. return _RootScalability;
  338. }
  339. VOID
  340. SetRootScalabilityMode()
  341. {
  342. _RootScalability = TRUE;
  343. }
  344. VOID
  345. ResetRootScalabilityMode()
  346. {
  347. _RootScalability = FALSE;
  348. }
  349. BOOLEAN
  350. IsRootFolderAvailableForApi()
  351. {
  352. BOOLEAN RetVal = TRUE;
  353. if(_CurrentErrors > DfsServerGlobalData.AllowedErrors)
  354. {
  355. RetVal = FALSE;
  356. }
  357. else
  358. {
  359. RetVal = ((_RootFlags & ROOT_API_AVAILABILITY_FLAGS) == ROOT_API_AVAILABILITY_FLAGS);
  360. }
  361. return RetVal;
  362. }
  363. BOOLEAN
  364. IsRootFolderAvailableForReferral()
  365. {
  366. BOOLEAN RetVal = TRUE;
  367. if(_CurrentErrors > DfsServerGlobalData.AllowedErrors)
  368. {
  369. RetVal = FALSE;
  370. }
  371. else
  372. {
  373. RetVal = ((_RootFlags & ROOT_REFERRAL_AVAILABILITY_FLAGS) == ROOT_REFERRAL_AVAILABILITY_FLAGS);
  374. }
  375. return RetVal;
  376. }
  377. DFSSTATUS
  378. AcquireRootShareDirectory(void);
  379. DFSSTATUS
  380. ReleaseRootShareDirectory(void);
  381. //
  382. // Function DfsRootFolder: Constructor.
  383. //
  384. DfsRootFolder(
  385. LPWSTR NameContext,
  386. LPWSTR RootRegKeyName,
  387. PUNICODE_STRING pLogicalShare,
  388. PUNICODE_STRING pPhysicalShare,
  389. DfsObjectTypeEnumeration ObType,
  390. DFSSTATUS *pStatus );
  391. //
  392. // Function ~DfsRootFolder: destructor.
  393. // Delete all the locks we had allocated for the children links.
  394. // Also delete the lock for this root folder.
  395. //
  396. virtual
  397. ~DfsRootFolder()
  398. {
  399. ULONG i = 0;
  400. if (_pMetadataNameTable)
  401. {
  402. DfsDereferenceNameTable( _pMetadataNameTable);
  403. _pMetadataNameTable = NULL;
  404. }
  405. if (_pLogicalPrefixTable)
  406. {
  407. DfsDereferencePrefixTable( _pLogicalPrefixTable);
  408. _pLogicalPrefixTable = NULL;
  409. }
  410. if(_pRootLock)
  411. {
  412. if(_fRootLockInit)
  413. {
  414. DeleteCriticalSection( _pRootLock );
  415. }
  416. delete _pRootLock;
  417. _pRootLock = NULL;
  418. }
  419. if(_pLock)
  420. {
  421. if(_fpLockInit)
  422. {
  423. DeleteCriticalSection( _pLock );
  424. }
  425. delete _pLock;
  426. _pLock = NULL;
  427. }
  428. if(_pChildLocks)
  429. {
  430. for ( i = 0; i < NUMBER_OF_SHARED_LINK_LOCKS; i++ )
  431. {
  432. if(_fChildLocksInit[i])
  433. {
  434. DeleteCriticalSection( &_pChildLocks[i] );
  435. }
  436. }
  437. delete [] _pChildLocks;
  438. _pChildLocks = NULL;
  439. }
  440. if (pStatistics != NULL)
  441. {
  442. pStatistics->ReleaseReference();
  443. pStatistics = NULL;
  444. }
  445. DfsFreeUnicodeString(&_PhysicalShareName);
  446. DfsFreeUnicodeString(&_RootRegKeyName);
  447. DfsFreeUnicodeString(&_LogicalShareName );
  448. DfsFreeUnicodeString(&_DfsNameContext );
  449. DfsFreeUnicodeString(&_ShareFilePathName );
  450. DfsFreeUnicodeString(&_DirectoryCreateRootPathName);
  451. }
  452. //
  453. // Function GetNetbiosNameContext: Returns the unicode string that
  454. // is the netbios name context for this root
  455. //
  456. PUNICODE_STRING
  457. GetNetbiosNameContext()
  458. {
  459. return &_DfsNetbiosNameContext;
  460. }
  461. //
  462. // Function GetNameContext: Returns the unicode string that
  463. // is the name context for this root
  464. //
  465. PUNICODE_STRING
  466. GetNameContext()
  467. {
  468. return &_DfsNameContext;
  469. }
  470. //
  471. // Function GetNameContextString: Returns the string that
  472. // is the name context for this root
  473. // Note: since we create the unicode string buffer with a null
  474. // terminated wide string, we just return that buffer.
  475. //
  476. LPWSTR
  477. GetNameContextString()
  478. {
  479. return _DfsNameContext.Buffer;
  480. }
  481. //
  482. // Function GetVisibleNameContext: Returns the unicode string that
  483. // is the name context for this root
  484. //
  485. PUNICODE_STRING
  486. GetVisibleContextLocked()
  487. {
  488. return &_DfsVisibleContext;
  489. }
  490. DFSSTATUS
  491. GetVisibleContext( PUNICODE_STRING pString)
  492. {
  493. DFSSTATUS Status;
  494. Status = AcquireRootLock();
  495. if (Status == ERROR_SUCCESS)
  496. {
  497. Status = DfsCreateUnicodeString( pString,
  498. &_DfsVisibleContext);
  499. ReleaseRootLock();
  500. }
  501. return Status;
  502. }
  503. VOID
  504. ReleaseVisibleContext( PUNICODE_STRING pString)
  505. {
  506. DfsFreeUnicodeString( pString );
  507. }
  508. //
  509. // MUST be called with root lock held (or at init)
  510. //
  511. DFSSTATUS
  512. SetVisibleContext( PUNICODE_STRING pString,
  513. BOOLEAN *pChanged)
  514. {
  515. DFSSTATUS Status = ERROR_SUCCESS;
  516. if (pChanged)
  517. {
  518. *pChanged = FALSE;
  519. }
  520. if (RtlCompareUnicodeString(&_DfsVisibleContext, pString, TRUE) != 0)
  521. {
  522. UNICODE_STRING OldString = _DfsVisibleContext;
  523. Status = DfsCreateUnicodeString( &_DfsVisibleContext,
  524. pString );
  525. //
  526. // we use the new name if possible. If we fail due to any reason
  527. // we reuse the old name.
  528. //
  529. if (Status == ERROR_SUCCESS)
  530. {
  531. if (pChanged)
  532. {
  533. *pChanged = TRUE;
  534. }
  535. if (OldString.Length != 0)
  536. {
  537. DfsFreeUnicodeString(&OldString);
  538. }
  539. }
  540. else
  541. {
  542. _DfsVisibleContext = OldString;
  543. }
  544. }
  545. return Status;
  546. }
  547. //
  548. // Function GetLogicalShare: Returns the unicode string that
  549. // is the logical share name for this root
  550. //
  551. PUNICODE_STRING
  552. GetLogicalShare()
  553. {
  554. return &_LogicalShareName;
  555. }
  556. LPWSTR
  557. GetRootRegKeyNameString()
  558. {
  559. return _RootRegKeyName.Buffer;
  560. }
  561. LPWSTR
  562. GetDirectoryCreatePathNameString()
  563. {
  564. return _DirectoryCreateRootPathName.Buffer;
  565. }
  566. PUNICODE_STRING
  567. GetDirectoryCreatePathName()
  568. {
  569. return &_DirectoryCreateRootPathName;
  570. }
  571. PUNICODE_STRING
  572. GetRootPhysicalShareName()
  573. {
  574. return &_PhysicalShareName;
  575. }
  576. BOOLEAN
  577. IsIgnoreNameContext()
  578. {
  579. return _IgnoreNameContext;
  580. }
  581. //
  582. // Function Synchronize: This function should be overridden by
  583. // each of the classes that are derived from this class.
  584. // They implement the store specific synchronize functionality.
  585. //
  586. virtual
  587. DFSSTATUS
  588. Synchronize(BOOLEAN fForceSynch = FALSE, BOOLEAN CalledByApi = FALSE ) = 0;
  589. //
  590. // Function LoadReferralData
  591. //
  592. DFSSTATUS
  593. LoadReferralData(
  594. DfsFolderReferralData *pReferralData );
  595. //
  596. // Function UnloadReferralData
  597. //
  598. DFSSTATUS
  599. UnloadReferralData(
  600. DfsFolderReferralData *pReferralData );
  601. virtual
  602. DFSSTATUS
  603. GetMetadataHandle( PDFS_METADATA_HANDLE pRootHandle) = 0;
  604. virtual
  605. VOID
  606. ReleaseMetadataHandle( DFS_METADATA_HANDLE RootHandle) = 0;
  607. virtual
  608. ULONG
  609. GetBlobSize()
  610. {
  611. return 0;
  612. }
  613. virtual
  614. DFSSTATUS
  615. SetSiteBlob(PVOID pBuffer, ULONG pSize)
  616. {
  617. UNREFERENCED_PARAMETER(pBuffer);
  618. UNREFERENCED_PARAMETER(pSize);
  619. return ERROR_NOT_SUPPORTED;
  620. }
  621. virtual
  622. DFSSTATUS
  623. GetSiteBlob(PVOID *pBuffer, PULONG pSize)
  624. {
  625. UNREFERENCED_PARAMETER(pBuffer);
  626. UNREFERENCED_PARAMETER(pSize);
  627. return ERROR_NOT_SUPPORTED;
  628. }
  629. DFSSTATUS
  630. UpdateLinkInformation(
  631. DFS_METADATA_HANDLE RootHandle,
  632. LPWSTR ChildName,
  633. BOOLEAN CalledByAPI = FALSE);
  634. DFSSTATUS
  635. UpdateFolderInformation(
  636. IN DFS_METADATA_HANDLE DfsHandle,
  637. LPWSTR ChildName,
  638. DfsFolder *pChildFolder);
  639. DFSSTATUS
  640. RemoveAllLinkFolders(
  641. BOOLEAN IsPermanent);
  642. DFSSTATUS
  643. LookupFolder( DfsFolder **ppFolder)
  644. {
  645. NTSTATUS NtStatus;
  646. DFSSTATUS Status;
  647. PVOID pData;
  648. NtStatus = DfsNameTableAcquireReadLock( _pMetadataNameTable );
  649. if (NtStatus == STATUS_SUCCESS)
  650. {
  651. NtStatus = DfsGetEntryNameTableLocked( _pMetadataNameTable,
  652. &pData );
  653. //
  654. // If we were successful, pData is a pointer to the DfsFolder.
  655. // Acquire a reference on the folder while we still have
  656. // the table locked.
  657. //
  658. if ( NtStatus == STATUS_SUCCESS )
  659. {
  660. Status = ERROR_SUCCESS;
  661. *ppFolder = (DfsFolder *)pData;
  662. (*ppFolder)->AcquireReference();
  663. }
  664. DfsNameTableReleaseLock( _pMetadataNameTable );
  665. }
  666. if ( NtStatus != STATUS_SUCCESS )
  667. {
  668. Status = ERROR_NOT_FOUND;
  669. }
  670. return Status;
  671. }
  672. //
  673. // Function LookupFolderByLogicalName: This function searches
  674. // this roots logical namespace table to find a matching folder
  675. // for any part of the passed in logical name.
  676. // The logicalname that is passed in is relative to the Dfs Share
  677. // name of this root.
  678. // If any part of the logical name passed in has a match, the matching
  679. // folder along with the rest of the logical name are returned.
  680. // Otherwise, we return ERROR_NOT_FOUND.
  681. //
  682. DFSSTATUS
  683. LookupFolderByLogicalName(
  684. PUNICODE_STRING pChildLogicalName,
  685. PUNICODE_STRING pRemainingName,
  686. DfsFolder **ppFolder,
  687. PBOOLEAN pSubStringMatch = NULL )
  688. {
  689. NTSTATUS NtStatus;
  690. DFSSTATUS Status;
  691. PVOID pData;
  692. NtStatus = DfsPrefixTableAcquireReadLock( _pLogicalPrefixTable );
  693. if ( NtStatus == STATUS_SUCCESS )
  694. {
  695. NtStatus = DfsFindUnicodePrefixLocked( _pLogicalPrefixTable,
  696. pChildLogicalName,
  697. pRemainingName,
  698. &pData,
  699. pSubStringMatch );
  700. //
  701. // If we were successful, pData is a pointer to a DfsFolder.
  702. // Acquire a reference on the folder while we still have
  703. // the table locked. This is very important: A valid reference
  704. // to the folder exists in table, and this reference cannot
  705. // go away while the table is locked. So we acquire a new
  706. // reference on the folder while the table is locked, and then
  707. // release the table lock.
  708. //
  709. if ( NtStatus == STATUS_SUCCESS )
  710. {
  711. DfsFolder *pFolder = (DfsFolder *)pData;
  712. if (pFolder->IsFolderDeleteInProgress())
  713. {
  714. Status = ERROR_NOT_FOUND;
  715. }
  716. else
  717. {
  718. Status = ERROR_SUCCESS;
  719. *ppFolder = pFolder;
  720. (*ppFolder)->AcquireReference();
  721. }
  722. }
  723. DfsPrefixTableReleaseLock( _pLogicalPrefixTable );
  724. }
  725. if ( NtStatus != STATUS_SUCCESS )
  726. {
  727. Status = ERROR_NOT_FOUND;
  728. }
  729. return Status;
  730. }
  731. //
  732. // Function LookupFolderByMetadataName: This function searches
  733. // this roots Metadata name table to find a matching folder
  734. // for any part of the passed in Metadata Name.
  735. // If a matching folder is found, a reference folder is returned
  736. // to the caller.
  737. // Else ERROR_NOT_FOUND is returned.
  738. //
  739. DFSSTATUS
  740. LookupFolderByMetadataName(
  741. LPWSTR pChildMetadataNameString,
  742. DfsFolder **ppFolder )
  743. {
  744. NTSTATUS NtStatus = STATUS_SUCCESS;
  745. DFSSTATUS Status = ERROR_SUCCESS;
  746. PVOID pData = NULL;
  747. UNICODE_STRING MetadataName;
  748. Status = DfsRtlInitUnicodeStringEx( &MetadataName, pChildMetadataNameString);
  749. if(Status == ERROR_SUCCESS)
  750. {
  751. NtStatus = DfsNameTableAcquireReadLock( _pMetadataNameTable );
  752. if ( NtStatus == STATUS_SUCCESS )
  753. {
  754. NtStatus = DfsLookupNameTableLocked( _pMetadataNameTable,
  755. &MetadataName,
  756. &pData );
  757. //
  758. // If we were successful, pData is a pointer to the DfsFolder.
  759. // Acquire a reference on the folder while we still have
  760. // the table locked.
  761. //
  762. if ( NtStatus == STATUS_SUCCESS )
  763. {
  764. Status = ERROR_SUCCESS;
  765. *ppFolder = (DfsFolder *)pData;
  766. (*ppFolder)->AcquireReference();
  767. }
  768. DfsNameTableReleaseLock( _pMetadataNameTable );
  769. }
  770. Status = RtlNtStatusToDosError(NtStatus);
  771. }
  772. if (Status != ERROR_SUCCESS)
  773. {
  774. Status = ERROR_NOT_FOUND;
  775. }
  776. return Status;
  777. }
  778. //
  779. // Function InsertLinkFolderInMetadataTable: This function attempts
  780. // to insert the passed in folder into the metadata name table of
  781. // the root.
  782. // If the insert is successful, we bump up the reference count on
  783. // the folder to reflect an active reference to it in the metadata
  784. // table.
  785. //
  786. DFSSTATUS
  787. InsertLinkFolderInMetadataTable(
  788. DfsFolder *pLinkFolder )
  789. {
  790. NTSTATUS NtStatus;
  791. DFSSTATUS Status;
  792. NtStatus = DfsNameTableAcquireWriteLock( _pMetadataNameTable );
  793. if ( NtStatus == STATUS_SUCCESS )
  794. {
  795. NtStatus = DfsInsertInNameTableLocked( _pMetadataNameTable,
  796. pLinkFolder->GetFolderMetadataName(),
  797. (PVOID)(pLinkFolder) );
  798. if ( NtStatus == STATUS_SUCCESS )
  799. {
  800. pLinkFolder->AcquireReference();
  801. //
  802. // Set a flag in the folder to indicate that the folder
  803. // is not in the metadata table.
  804. //
  805. pLinkFolder->SetFlag(DFS_FOLDER_IN_METADATA_TABLE);
  806. }
  807. DfsNameTableReleaseLock( _pMetadataNameTable );
  808. }
  809. Status = RtlNtStatusToDosError(NtStatus);
  810. return Status;
  811. }
  812. //
  813. // Function InsertLinkFolderInLogicalTable: This function attempts
  814. // to insert the passed in folder into the logical namespace table of
  815. // the root.
  816. // If the insert is successful, we bump up the reference count on
  817. // the folder to reflect an active reference to it in the logical
  818. // table.
  819. //
  820. DFSSTATUS
  821. InsertLinkFolderInLogicalTable(
  822. DfsFolder *pLinkFolder )
  823. {
  824. NTSTATUS NtStatus = STATUS_SUCCESS;
  825. DFSSTATUS Status = ERROR_SUCCESS;
  826. UNICODE_STRING RemainingName;
  827. PVOID pData;
  828. NtStatus = DfsPrefixTableAcquireWriteLock( _pLogicalPrefixTable );
  829. if ( NtStatus == STATUS_SUCCESS )
  830. {
  831. //
  832. // If another folder by this name is already in teh logical
  833. // table, insert will cause memory to leak. Our InsertInPrefixTable
  834. // should return an error on collision, but it currently doesn't.
  835. // We should fix the insert in Prefix table to return error
  836. // and fix all relevant code to handle this failure gracefully.
  837. //
  838. NtStatus = DfsFindUnicodePrefixLocked( _pLogicalPrefixTable,
  839. pLinkFolder->GetFolderLogicalName(),
  840. &RemainingName,
  841. &pData,
  842. NULL );
  843. if ((NtStatus == STATUS_SUCCESS) &&
  844. (RemainingName.Length == 0))
  845. {
  846. DfsFolder *pFolder = (DfsFolder *)pData;
  847. NtStatus = DfsRemoveFromPrefixTableLocked( _pLogicalPrefixTable,
  848. pLinkFolder->GetFolderLogicalName(),
  849. pData );
  850. if (NtStatus == STATUS_SUCCESS)
  851. {
  852. pFolder->ResetFlag(DFS_FOLDER_IN_LOGICAL_TABLE);
  853. pFolder->ReleaseReference();
  854. }
  855. }
  856. NtStatus = DfsInsertInPrefixTableLocked( _pLogicalPrefixTable,
  857. pLinkFolder->GetFolderLogicalName(),
  858. (PVOID)(pLinkFolder) );
  859. if ( NtStatus == STATUS_SUCCESS )
  860. {
  861. pLinkFolder->AcquireReference();
  862. pLinkFolder->SetFlag(DFS_FOLDER_IN_LOGICAL_TABLE);
  863. }
  864. DfsPrefixTableReleaseLock( _pLogicalPrefixTable );
  865. }
  866. Status = RtlNtStatusToDosError(NtStatus);
  867. return Status;
  868. }
  869. //
  870. // Function RemoveLinkFolderFromMetadataTable: This function attempts
  871. // to remove the passed in folder from the metadata name table of
  872. // the root.
  873. // If the remove is successful, we release our reference on
  874. // the folder.
  875. //
  876. DFSSTATUS
  877. RemoveLinkFolderFromMetadataTable(
  878. DfsFolder *pLinkFolder )
  879. {
  880. NTSTATUS NtStatus;
  881. DFSSTATUS Status;
  882. NtStatus = DfsNameTableAcquireWriteLock( _pMetadataNameTable );
  883. if ( NtStatus == ERROR_SUCCESS )
  884. {
  885. if (pLinkFolder->IsFolderInMetadataTable())
  886. {
  887. NtStatus = DfsRemoveFromNameTableLocked( _pMetadataNameTable,
  888. pLinkFolder->GetFolderMetadataName(),
  889. (PVOID)(pLinkFolder) );
  890. if ( NtStatus == STATUS_SUCCESS )
  891. {
  892. pLinkFolder->ResetFlag(DFS_FOLDER_IN_METADATA_TABLE);
  893. pLinkFolder->ReleaseReference();
  894. }
  895. }
  896. DfsNameTableReleaseLock( _pMetadataNameTable );
  897. }
  898. Status = RtlNtStatusToDosError(NtStatus);
  899. return Status;
  900. }
  901. //
  902. // Function RemoveLinkFolderFromLogicalTable: This function attempts
  903. // to remove the passed in folder from the logical namespace table of
  904. // the root.
  905. // If the remove is successful, we release our reference on
  906. // the folder.
  907. //
  908. DFSSTATUS
  909. RemoveLinkFolderFromLogicalTable(
  910. DfsFolder *pLinkFolder )
  911. {
  912. NTSTATUS NtStatus;
  913. DFSSTATUS Status;
  914. NtStatus = DfsPrefixTableAcquireWriteLock( _pLogicalPrefixTable );
  915. if ( NtStatus == STATUS_SUCCESS )
  916. {
  917. if (pLinkFolder->IsFolderInLogicalTable())
  918. {
  919. NtStatus = DfsRemoveFromPrefixTableLocked( _pLogicalPrefixTable,
  920. pLinkFolder->GetFolderLogicalName(),
  921. (PVOID)(pLinkFolder) );
  922. if ( NtStatus == STATUS_SUCCESS )
  923. {
  924. pLinkFolder->ResetFlag(DFS_FOLDER_IN_LOGICAL_TABLE);
  925. pLinkFolder->ReleaseReference();
  926. }
  927. }
  928. DfsPrefixTableReleaseLock( _pLogicalPrefixTable );
  929. }
  930. Status = RtlNtStatusToDosError(NtStatus);
  931. return Status;
  932. }
  933. //
  934. // Function ReplaceLinkFolderInLogicalTable: This function attempts
  935. // to replace the passed in folder in the logical namespace table of
  936. // the root.
  937. // If the replace is successful, we release our reference on
  938. // replaced folder and acquire a reference on the folder that is
  939. // now inserted into the logical namespace table.
  940. //
  941. DFSSTATUS
  942. ReplaceLinkFolderInLogicalTable(
  943. DfsFolder *pLinkFolder,
  944. DfsFolder *pFolderToReplace )
  945. {
  946. NTSTATUS NtStatus;
  947. DFSSTATUS Status;
  948. NtStatus = DfsPrefixTableAcquireWriteLock( _pLogicalPrefixTable );
  949. if ( NtStatus == STATUS_SUCCESS )
  950. {
  951. NtStatus = DfsReplaceInPrefixTableLocked( _pLogicalPrefixTable,
  952. pLinkFolder->GetFolderLogicalName(),
  953. (PVOID)(pFolderToReplace),
  954. (PVOID)(pLinkFolder) );
  955. if ( NtStatus == STATUS_SUCCESS )
  956. {
  957. pFolderToReplace->ResetFlag(DFS_FOLDER_IN_LOGICAL_TABLE);
  958. pFolderToReplace->ReleaseReference();
  959. pLinkFolder->AcquireReference();
  960. pLinkFolder->SetFlag(DFS_FOLDER_IN_LOGICAL_TABLE);
  961. }
  962. DfsPrefixTableReleaseLock( _pLogicalPrefixTable );
  963. }
  964. Status = RtlNtStatusToDosError(NtStatus);
  965. return Status;
  966. }
  967. //
  968. // Function DfsCreateLinkFolder: Create a new DfsFolder and
  969. // add it to the root's metadata and logical namespace tables.
  970. //
  971. DFSSTATUS
  972. CreateLinkFolder(
  973. IN LPWSTR ChildName,
  974. IN PUNICODE_STRING pLinkName,
  975. OUT DfsFolder **ppChildFolder,
  976. IN BOOLEAN CalledByApi );
  977. //
  978. // Function DfsUpdateLinkFolder: When the DfsFolder needs
  979. // to be updated, this function takes care of the update details.
  980. //
  981. DFSSTATUS
  982. UpdateLinkFolder(
  983. IN LPWSTR ChildName,
  984. IN PUNICODE_STRING pLinkName,
  985. OUT DfsFolder *pChildFolder);
  986. DFSSTATUS
  987. RemoveLinkFolder(
  988. IN DfsFolder *pChildFolder,
  989. BOOLEAN IsPermanent );
  990. DFSSTATUS
  991. RemoveLinkFolder(
  992. IN LPWSTR MetadataName )
  993. {
  994. DfsFolder *pFolder = NULL;
  995. DFSSTATUS Status;
  996. Status =LookupFolderByMetadataName( MetadataName,
  997. &pFolder );
  998. if (Status == ERROR_SUCCESS)
  999. {
  1000. Status = RemoveLinkFolder( pFolder,
  1001. TRUE ); // Permanent removal.
  1002. pFolder->ReleaseReference();
  1003. }
  1004. return Status;
  1005. }
  1006. DFSSTATUS
  1007. ValidateLinkName(
  1008. IN PUNICODE_STRING pLinkName )
  1009. {
  1010. DFSSTATUS Status = ERROR_SUCCESS;
  1011. DfsFolder *pFolder = NULL;
  1012. UNICODE_STRING Remaining;
  1013. BOOLEAN IsSubStringMatch = FALSE;
  1014. UNICODE_STRING CheckName = *pLinkName;
  1015. if (pLinkName->Length == 0)
  1016. {
  1017. return ERROR_SUCCESS; // Root name.
  1018. }
  1019. Status = ValidateAPiShortName(pLinkName);
  1020. if(Status != ERROR_SUCCESS)
  1021. {
  1022. return Status;
  1023. }
  1024. while ((Status == ERROR_SUCCESS) &&
  1025. (CheckName.Length > 0))
  1026. {
  1027. UNICODE_STRING NextComponent;
  1028. UNICODE_STRING CurrentName = CheckName;
  1029. Status = DfsGetNextComponent( &CurrentName,
  1030. &NextComponent,
  1031. &CheckName );
  1032. if (Status == ERROR_SUCCESS)
  1033. {
  1034. if (!IS_VALID_TOKEN(NextComponent.Buffer,
  1035. NextComponent.Length / sizeof(WCHAR)))
  1036. {
  1037. Status = ERROR_INVALID_NAME;
  1038. }
  1039. }
  1040. }
  1041. if (Status == ERROR_SUCCESS)
  1042. {
  1043. Status = LookupFolderByLogicalName( pLinkName,
  1044. &Remaining,
  1045. &pFolder,
  1046. &IsSubStringMatch );
  1047. if (Status == ERROR_SUCCESS)
  1048. {
  1049. pFolder->ReleaseReference();
  1050. if (Remaining.Length > 0) {
  1051. Status = ERROR_FILE_EXISTS;
  1052. }
  1053. }
  1054. else {
  1055. if (IsSubStringMatch)
  1056. {
  1057. Status = ERROR_FILE_EXISTS;
  1058. }
  1059. else {
  1060. Status = ERROR_NOT_FOUND;
  1061. }
  1062. }
  1063. }
  1064. return Status;
  1065. }
  1066. ULONG
  1067. GetChildCount() { return _ChildCount; }
  1068. ULONG
  1069. RootEnumerationCount() { return _ChildCount + 1; }
  1070. //
  1071. // Get the visible name context: This call
  1072. // ensures that the server component of the UNC
  1073. // names are setup correctly.
  1074. // GetVisibleNameContext first attempts to get the
  1075. // name context from the DFS path. If the path is
  1076. // empty, it uses the name context that was setup
  1077. // within the server for this root. If that is also
  1078. // empty (as is the case when the service is running local)
  1079. // it returns the computer name of this machine.
  1080. //
  1081. VOID
  1082. GetVisibleNameContextLocked(
  1083. PUNICODE_STRING pDfsName,
  1084. PUNICODE_STRING pContextName )
  1085. {
  1086. DFSSTATUS Status = ERROR_SUCCESS;
  1087. PUNICODE_STRING pName;
  1088. RtlInitUnicodeString( pContextName, NULL);
  1089. if (pDfsName != NULL)
  1090. {
  1091. Status = DfsGetPathComponents( pDfsName,
  1092. pContextName,
  1093. NULL,
  1094. NULL);
  1095. }
  1096. if (pContextName->Length == 0)
  1097. {
  1098. pName = GetNameContext();
  1099. *pContextName = *pName;
  1100. }
  1101. if (pContextName->Length == 0)
  1102. {
  1103. pName = GetVisibleContextLocked();
  1104. *pContextName = *pName;
  1105. }
  1106. }
  1107. DFSSTATUS
  1108. GetVisibleNameContext(
  1109. PUNICODE_STRING pDfsName,
  1110. PUNICODE_STRING pContextName )
  1111. {
  1112. DFSSTATUS Status = ERROR_SUCCESS;
  1113. UNICODE_STRING Name, *pName;
  1114. RtlInitUnicodeString( pContextName, NULL);
  1115. RtlInitUnicodeString( &Name, NULL);
  1116. if (pDfsName != NULL)
  1117. {
  1118. Status = DfsGetPathComponents( pDfsName,
  1119. &Name,
  1120. NULL,
  1121. NULL);
  1122. }
  1123. if (Name.Length == 0)
  1124. {
  1125. pName = GetNameContext();
  1126. Name = *pName;
  1127. }
  1128. if (Name.Length == 0)
  1129. {
  1130. Status = GetVisibleContext(pContextName);
  1131. }
  1132. else
  1133. {
  1134. Status = DfsCreateUnicodeString(pContextName, &Name);
  1135. }
  1136. return Status;
  1137. }
  1138. DWORD
  1139. GetRootFlavor()
  1140. {
  1141. return _RootFlavor;
  1142. }
  1143. DFSSTATUS
  1144. SetRootStandby();
  1145. DFSSTATUS
  1146. SetRootResynchronize();
  1147. DFSSTATUS
  1148. AddMetadataLink(
  1149. PUNICODE_STRING pLogicalName,
  1150. LPWSTR ReplicaServer,
  1151. LPWSTR ReplicaPath,
  1152. LPWSTR Comment );
  1153. DFSSTATUS
  1154. RemoveMetadataLink(
  1155. PUNICODE_STRING pLinkName );
  1156. DFSSTATUS
  1157. AddMetadataLinkReplica(
  1158. PUNICODE_STRING pLinkName,
  1159. LPWSTR ReplicaServer,
  1160. LPWSTR ReplicaPath );
  1161. DFSSTATUS
  1162. RemoveMetadataLinkReplica(
  1163. PUNICODE_STRING pLinkName,
  1164. LPWSTR ReplicaServer,
  1165. LPWSTR ReplicaPath,
  1166. PBOOLEAN pLastReplica );
  1167. DFSSTATUS
  1168. EnumerateApiLinks(
  1169. LPWSTR DfsPathName,
  1170. DWORD Level,
  1171. LPBYTE pBuffer,
  1172. LONG BufferSize,
  1173. LPDWORD pEntriesRead,
  1174. LPDWORD pResumeHandle,
  1175. PLONG pNextSizeRequired );
  1176. DFSSTATUS
  1177. GetApiInformation(
  1178. PUNICODE_STRING pDfsName,
  1179. PUNICODE_STRING pLinkName,
  1180. DWORD Level,
  1181. LPBYTE pBuffer,
  1182. LONG BufferSize,
  1183. PLONG pNextSizeRequired );
  1184. DFSSTATUS
  1185. ExtendedRootAttributes(
  1186. PULONG pAttr,
  1187. PUNICODE_STRING pRemaining,
  1188. BOOLEAN Set);
  1189. DFSSTATUS
  1190. SetApiInformation(
  1191. PUNICODE_STRING pLinkName,
  1192. LPWSTR Server,
  1193. LPWSTR Share,
  1194. DWORD Level,
  1195. LPBYTE pBuffer );
  1196. VOID
  1197. SetRootFolderSynchronized()
  1198. {
  1199. _RootFlags |= ROOT_FOLDER_SYNCHRONIZED;
  1200. if (IsRootFolderShareAcquired() &&
  1201. GetLastCreateDirectoryError() == ERROR_SUCCESS)
  1202. {
  1203. SetRootDirectoriesCreated();
  1204. }
  1205. else
  1206. {
  1207. ClearRootDirectoriesCreated();
  1208. }
  1209. ClearLastCreateDirectoryError();
  1210. }
  1211. VOID
  1212. ClearRootFolderSynchronized()
  1213. {
  1214. _RootFlags &= ~ROOT_FOLDER_SYNCHRONIZED;
  1215. ClearRootDirectoriesCreated();
  1216. ClearLastCreateDirectoryError();
  1217. }
  1218. virtual
  1219. DFSSTATUS
  1220. GetMetadataLogicalToLinkName( PUNICODE_STRING pIn,
  1221. PUNICODE_STRING pOut ) = 0;
  1222. virtual
  1223. VOID
  1224. ReleaseMetadataLogicalToLinkName( PUNICODE_STRING pIn ) = 0;
  1225. DFSSTATUS
  1226. AcquireRootLock()
  1227. {
  1228. return DfsAcquireWriteLock(_pRootLock);
  1229. }
  1230. VOID
  1231. ReleaseRootLock()
  1232. {
  1233. DfsReleaseLock(_pRootLock);
  1234. return NOTHING;
  1235. }
  1236. DFSSTATUS
  1237. CommonRootApiPrologue( BOOLEAN WriteRequest )
  1238. {
  1239. UNREFERENCED_PARAMETER(WriteRequest);
  1240. DFSSTATUS Status = ERROR_SUCCESS;
  1241. // Check if the root folder is available for api calls. If not,
  1242. // we return an error back to the caller:
  1243. // This appears to be the most appropriate error we return here.
  1244. //
  1245. if (IsRootFolderAvailableForApi() == FALSE)
  1246. {
  1247. Status = ERROR_DEVICE_NOT_AVAILABLE;
  1248. }
  1249. if (Status == ERROR_SUCCESS)
  1250. {
  1251. Status = ReSynchronize();
  1252. }
  1253. return Status;
  1254. }
  1255. virtual
  1256. DFSSTATUS
  1257. RootRequestPrologue( LPWSTR Name ) =0;
  1258. virtual
  1259. VOID
  1260. RootRequestEpilogue () = 0;
  1261. virtual
  1262. DFSSTATUS
  1263. RootApiRequestPrologue( BOOLEAN WriteRequest,
  1264. LPWSTR Name = NULL ) = 0;
  1265. virtual
  1266. VOID
  1267. RootApiRequestEpilogue(
  1268. BOOLEAN WriteRequest,
  1269. DFSSTATUS CompletionStatus ) = 0;
  1270. virtual
  1271. DFSSTATUS
  1272. ReSynchronize(BOOLEAN fForceSynch = FALSE) = 0;
  1273. //
  1274. // Derived classes that cache their metadata in memory
  1275. // (e.g. AdBlob) are expected to override this to flush
  1276. // its entire cache to disk.
  1277. //
  1278. virtual
  1279. DFSSTATUS
  1280. Flush() = 0;
  1281. BOOLEAN
  1282. IsEmptyDirectory(
  1283. HANDLE DirectoryHandle,
  1284. PVOID pDirectoryBuffer,
  1285. ULONG DirectoryBufferSize );
  1286. void
  1287. GenerateEventLog(DWORD EventMsg,
  1288. WORD SubStrings,
  1289. const TCHAR * apszSubStrings[],
  1290. DWORD Errorcode);
  1291. NTSTATUS
  1292. IsDirectoryMountPoint(
  1293. IN HANDLE DirHandle,
  1294. OUT PBOOLEAN pDfsMountPoint );
  1295. NTSTATUS
  1296. IsRootShareMountPoint(PUNICODE_STRING pDirectoryName);
  1297. DFSSTATUS
  1298. PrefetchReplicaData(DfsFolder *pChildFolder);
  1299. DFSSTATUS
  1300. LoadCachedServerSiteData(
  1301. IN DFS_METADATA_HANDLE RootMetadataHandle,
  1302. IN LPWSTR MetadataName);
  1303. DFSSTATUS
  1304. PreloadServerSiteData(void);
  1305. DFSSTATUS
  1306. LoadServerSiteData(DfsFolder *pChildFolder);
  1307. BOOLEAN GetPrefetchDataState(void)
  1308. {
  1309. return _PrefetchNeeded;
  1310. }
  1311. void SetPrefetchData(BOOLEAN Prefetch)
  1312. {
  1313. _PrefetchNeeded = Prefetch;
  1314. }
  1315. DFSSTATUS
  1316. ExpandShortName(PUNICODE_STRING pLinkName,
  1317. PUNICODE_STRING pNewPath,
  1318. PUNICODE_STRING pRemainingName);
  1319. NTSTATUS
  1320. ExpandLinkDirectories(
  1321. PUNICODE_STRING pLinkName,
  1322. PUNICODE_STRING pNewPath,
  1323. HANDLE RelativeHandle,
  1324. BOOLEAN FailOnExpand,
  1325. DWORD * NumComponentsExpanded);
  1326. NTSTATUS
  1327. GetAShortName(HANDLE ParentHandle,
  1328. BOOLEAN *Expanded,
  1329. PUNICODE_STRING pLinkName,
  1330. PUNICODE_STRING pNewPath);
  1331. BOOLEAN
  1332. IsAShortName(PUNICODE_STRING pLinkName);
  1333. NTSTATUS
  1334. CopyShortName(PUNICODE_STRING pNewName,
  1335. PUNICODE_STRING pNewPath);
  1336. NTSTATUS
  1337. FindRemaingName(PUNICODE_STRING pLinkName,
  1338. PUNICODE_STRING pRemainingName,
  1339. DWORD NumComponentsExpanded);
  1340. DFSSTATUS
  1341. ValidateAPiShortName(PUNICODE_STRING pLinkName);
  1342. void FreeShortNameData(PUNICODE_STRING pLinkName);
  1343. DFSSTATUS
  1344. CreateRenameName(PUNICODE_STRING pNewName);
  1345. DFSSTATUS
  1346. RenamePath(PUNICODE_STRING ParentDirectory,
  1347. PUNICODE_STRING DirectoryToRename);
  1348. virtual
  1349. DFSSTATUS
  1350. RenameLinks(
  1351. IN LPWSTR OldDomainName,
  1352. IN LPWSTR NewDomainName) = 0;
  1353. virtual
  1354. DFSSTATUS
  1355. CheckResynchronizeAccess( DFSSTATUS AccessCheckStatus) = 0;
  1356. DFSSTATUS
  1357. ClearRootFolderDeleteInProgressLocked(void)
  1358. {
  1359. DFSSTATUS LockStatus = ERROR_SUCCESS;
  1360. LockStatus = AcquireRootLock();
  1361. if (LockStatus == ERROR_SUCCESS)
  1362. {
  1363. ClearRootFolderDeleteInProgress();
  1364. ReleaseRootLock();
  1365. }
  1366. if (LockStatus != ERROR_SUCCESS)
  1367. {
  1368. ReleaseReference();
  1369. }
  1370. return LockStatus;
  1371. }
  1372. inline DFSSTATUS
  1373. AddReparseVolumeToList( VOID )
  1374. {
  1375. return DfsAddReparseVolumeToList( GetDirectoryCreatePathName() );
  1376. }
  1377. };
  1378. #endif // __DFS_ROOT_FOLDER__