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.

1449 lines
39 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsStore.hxx
  6. //
  7. // Contents: the base DFS Store class, this contains the common
  8. // store functionality.
  9. //
  10. // Classes: DfsStore.
  11. //
  12. // History: Dec. 8 2000, Author: udayh
  13. //
  14. //-----------------------------------------------------------------------------
  15. #ifndef __DFS_STORE__
  16. #define __DFS_STORE__
  17. #include "DfsGeneric.hxx"
  18. #include "DfsRootFolder.hxx"
  19. #include "lmdfs.h"
  20. #include "rpc.h"
  21. #include "rpcdce.h"
  22. #include <DfsServerLibrary.hxx>
  23. //
  24. // The first part of this file contains the marshalling/unmarshalling
  25. // routines that are used by the old stores (registry and AD)
  26. // These routines help us read a binary blob and unravel their contents.
  27. //
  28. // the latter part defines the common store class for all our stores.
  29. //
  30. #define BYTE_0_MASK 0xFF
  31. #define BYTE_0(Value) (UCHAR)( (Value) & BYTE_0_MASK)
  32. #define BYTE_1(Value) (UCHAR)( ((Value) >> 8) & BYTE_0_MASK)
  33. #define BYTE_2(Value) (UCHAR)( ((Value) >> 16) & BYTE_0_MASK)
  34. #define BYTE_3(Value) (UCHAR)( ((Value) >> 24) & BYTE_0_MASK)
  35. #define MTYPE_BASE_TYPE (0x0000ffffL)
  36. #define MTYPE_COMPOUND (0x00000001L)
  37. #define MTYPE_GUID (0x00000002L)
  38. #define MTYPE_ULONG (0x00000003L)
  39. #define MTYPE_USHORT (0x00000004L)
  40. #define MTYPE_PWSTR (0x00000005L)
  41. #define MTYPE_UCHAR (0x00000006L)
  42. #define _MCode_Base(t,s,m,i)\
  43. {t,offsetof(s,m),0L,0L,i}
  44. #define _MCode_struct(s,m,i)\
  45. _MCode_Base(MTYPE_COMPOUND,s,m,i)
  46. #define _MCode_pwstr(s,m)\
  47. _MCode_Base(MTYPE_PWSTR,s,m,NULL)
  48. #define _MCode_ul(s,m)\
  49. _MCode_Base(MTYPE_ULONG,s,m,NULL)
  50. #define _MCode_guid(s,m)\
  51. _MCode_Base(MTYPE_GUID,s,m,NULL)
  52. #define _mkMarshalInfo(s, i)\
  53. {(ULONG)sizeof(s),(ULONG)(sizeof(i)/sizeof(MARSHAL_TYPE_INFO)),i}
  54. typedef struct _MARSHAL_TYPE_INFO
  55. {
  56. ULONG _type; // the type of item to be marshalled
  57. ULONG _off; // offset of item (in the struct)
  58. ULONG _cntsize; // size of counter for counted array
  59. ULONG _cntoff; // else, offset count item (in the struct)
  60. struct _MARSHAL_INFO * _subinfo;// if compound type, need info
  61. } MARSHAL_TYPE_INFO, *PMARSHAL_TYPE_INFO;
  62. typedef struct _MARSHAL_INFO
  63. {
  64. ULONG _size; // size of item
  65. ULONG _typecnt; // number of type infos
  66. PMARSHAL_TYPE_INFO _typeInfo; // type infos
  67. } MARSHAL_INFO, *PMARSHAL_INFO;
  68. typedef struct _DFS_NAME_INFORMATION_
  69. {
  70. PVOID pData;
  71. ULONG DataSize;
  72. UNICODE_STRING Prefix;
  73. UNICODE_STRING ShortPrefix;
  74. GUID VolumeId;
  75. ULONG State;
  76. ULONG Type;
  77. UNICODE_STRING Comment;
  78. FILETIME PrefixTimeStamp;
  79. FILETIME StateTimeStamp;
  80. FILETIME CommentTimeStamp;
  81. ULONG Timeout;
  82. ULONG Version;
  83. FILETIME LastModifiedTime;
  84. } DFS_NAME_INFORMATION, *PDFS_NAME_INFORMATION;
  85. //
  86. // Defines for ReplicaState.
  87. //
  88. #define REPLICA_STORAGE_STATE_OFFLINE 0x1
  89. typedef struct _DFS_REPLICA_INFORMATION__
  90. {
  91. PVOID pData;
  92. ULONG DataSize;
  93. FILETIME ReplicaTimeStamp;
  94. ULONG ReplicaState;
  95. ULONG ReplicaType;
  96. UNICODE_STRING ServerName;
  97. UNICODE_STRING ShareName;
  98. } DFS_REPLICA_INFORMATION, *PDFS_REPLICA_INFORMATION;
  99. typedef struct _DFS_REPLICA_LIST_INFORMATION_
  100. {
  101. PVOID pData;
  102. ULONG DataSize;
  103. ULONG ReplicaCount;
  104. DFS_REPLICA_INFORMATION *pReplicas;
  105. } DFS_REPLICA_LIST_INFORMATION, *PDFS_REPLICA_LIST_INFORMATION;
  106. extern MARSHAL_INFO MiFileTime;
  107. #define INIT_FILE_TIME_INFO() \
  108. static MARSHAL_TYPE_INFO _MCode_FileTime[] = { \
  109. _MCode_ul(FILETIME, dwLowDateTime), \
  110. _MCode_ul(FILETIME, dwHighDateTime), \
  111. }; \
  112. MARSHAL_INFO MiFileTime = _mkMarshalInfo(FILETIME, _MCode_FileTime);
  113. //
  114. // Marshalling info for DFS_REPLICA_INFO structure
  115. //
  116. extern MARSHAL_INFO MiDfsReplicaInfo;
  117. #define INIT_DFS_REPLICA_INFO_MARSHAL_INFO() \
  118. static MARSHAL_TYPE_INFO _MCode_DfsReplicaInfo[] = { \
  119. _MCode_struct(DFS_REPLICA_INFORMATION, ReplicaTimeStamp, &MiFileTime), \
  120. _MCode_ul(DFS_REPLICA_INFORMATION, ReplicaState), \
  121. _MCode_ul(DFS_REPLICA_INFORMATION, ReplicaType), \
  122. _MCode_pwstr(DFS_REPLICA_INFORMATION, ServerName), \
  123. _MCode_pwstr(DFS_REPLICA_INFORMATION, ShareName), \
  124. }; \
  125. MARSHAL_INFO MiDfsReplicaInfo = _mkMarshalInfo(DFS_REPLICA_INFORMATION, _MCode_DfsReplicaInfo);
  126. enum DfsRootListType {
  127. NewRootList,
  128. DeletedRootList,
  129. OldRootList,
  130. };
  131. #define DFS_REGISTRY_CHILD_NAME_SIZE_MAX MAX_PATH
  132. //
  133. // The unmarshalling routines: the existing registry and AD stores
  134. // store the information in binary blobs, and these routines
  135. // help convert the binary data into meaningful data structures.
  136. //
  137. //+----------------------------------------------------------------------------
  138. //
  139. // Class: DfsStore
  140. //
  141. // Synopsis: This abstract class implements a basic DfsStore
  142. // The DfsStore is derived by the actual store modules
  143. // (such as registry, ad, etc) that implement the store
  144. // specific recognize routines.
  145. //
  146. //-----------------------------------------------------------------------------
  147. class DfsStore: public DfsGeneric
  148. {
  149. private:
  150. CRITICAL_SECTION _Lock; // The lock for this store.
  151. UNICODE_STRING _StoreName; // name of the store.
  152. ULONG _GenerationNumber; // ?? TBD
  153. BOOL _fCritInit;
  154. protected:
  155. DfsRootFolder *_DfsRootList; // The roots that this store
  156. // knows about.
  157. DfsRootFolder *_DfsDeletedRootList; // The roots that this store
  158. // knows about.
  159. DfsRootFolder *_DfsOldRootList;
  160. public:
  161. DfsStore *pNextRegisteredStore; // the next registered store.
  162. private:
  163. //
  164. // Function AcquireLock: Acquires the lock on the store.
  165. //
  166. DFSSTATUS
  167. AcquireLock()
  168. {
  169. DFSSTATUS Status = ERROR_SUCCESS;
  170. EnterCriticalSection(&_Lock);
  171. return Status;
  172. }
  173. protected:
  174. DFSSTATUS
  175. PackGetInformation(
  176. ULONG_PTR Info,
  177. IN OUT PVOID *ppBuffer,
  178. PULONG pSizeRemaining,
  179. PMARSHAL_INFO pMarshalInfo );
  180. DFSSTATUS
  181. PackSetInformation(
  182. ULONG_PTR Info,
  183. IN OUT PVOID *ppBuffer,
  184. PULONG pSizeRemaining,
  185. PMARSHAL_INFO pMarshalInfo );
  186. ULONG
  187. PackSizeInformation(
  188. ULONG_PTR Info,
  189. PMARSHAL_INFO pMarshalInfo );
  190. DFSSTATUS
  191. PackGetReplicaInformation(
  192. PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  193. IN OUT PVOID *ppBuffer,
  194. PULONG pSizeRemaining);
  195. DFSSTATUS
  196. PackSetReplicaInformation(
  197. PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  198. IN OUT PVOID *ppBuffer,
  199. PULONG pSizeRemaining);
  200. ULONG
  201. PackSizeReplicaInformation(
  202. PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
  203. DFSSTATUS
  204. GetRootPhysicalShare(
  205. HKEY RootKey,
  206. PUNICODE_STRING pRootPhysicalShare );
  207. VOID
  208. ReleaseRootPhysicalShare(
  209. PUNICODE_STRING pRootPhysicalShare );
  210. DFSSTATUS
  211. GetRootLogicalShare(
  212. HKEY RootKey,
  213. PUNICODE_STRING pRootLogicalShare );
  214. VOID
  215. ReleaseRootLogicalShare(
  216. PUNICODE_STRING pRootLogicalShare );
  217. DFSSTATUS
  218. PackageEnumerationInfo(
  219. DWORD Level,
  220. DWORD EntryCount,
  221. LPBYTE pLinkBuffer,
  222. LPBYTE pBuffer,
  223. LPBYTE *ppCurrentBuffer,
  224. PLONG pSizeRemaining );
  225. //
  226. // Function GetDfsRegistryKey: This function takes a Name as the input,
  227. // and looks up all DFS roots in that namespace.
  228. static
  229. DFSSTATUS
  230. GetDfsRegistryKey( IN LPWSTR MachineName,
  231. IN LPWSTR LocationString,
  232. BOOLEAN WritePermission,
  233. OUT BOOLEAN *pMachineContacted,
  234. OUT PHKEY pDfsRegKey )
  235. {
  236. DFSSTATUS Status;
  237. HKEY RootKey;
  238. BOOLEAN Contacted = FALSE;
  239. LPWSTR UseMachineName = NULL;
  240. REGSAM DesiredAccess = KEY_READ;
  241. if (WritePermission == TRUE)
  242. {
  243. DesiredAccess |= KEY_WRITE;
  244. }
  245. if (IsEmptyString(MachineName) == FALSE) {
  246. UseMachineName = MachineName;
  247. }
  248. Status = RegConnectRegistry( UseMachineName,
  249. HKEY_LOCAL_MACHINE,
  250. &RootKey );
  251. if ( Status == ERROR_SUCCESS )
  252. {
  253. Contacted = TRUE;
  254. Status = RegOpenKeyEx( RootKey,
  255. LocationString,
  256. 0,
  257. DesiredAccess,
  258. pDfsRegKey );
  259. //
  260. // There appears to be a bug in the registry code. When
  261. // we connect to the local machine, the key that is returned
  262. // in the RegConnectRegistry is HKEY_LOCAL_MACHINE. If we
  263. // then attempt to close it here, it affects other threads
  264. // that are using this code: they get STATUS_INVALID_HANDLE
  265. // in some cases. So, dont close the key if it is
  266. // HKEY_LOCAL_MACHINE.
  267. //
  268. if (RootKey != HKEY_LOCAL_MACHINE)
  269. {
  270. RegCloseKey( RootKey );
  271. }
  272. }
  273. if (pMachineContacted != NULL)
  274. {
  275. *pMachineContacted = Contacted;
  276. }
  277. return Status;
  278. }
  279. static
  280. DFSSTATUS
  281. GetNewDfsRegistryKey( IN LPWSTR MachineName,
  282. BOOLEAN WritePermission,
  283. OUT BOOLEAN *pMachineContacted,
  284. OUT PHKEY pDfsRegKey )
  285. {
  286. return GetDfsRegistryKey (MachineName,
  287. DfsNewRegistryLocation,
  288. WritePermission,
  289. pMachineContacted,
  290. pDfsRegKey );
  291. }
  292. //
  293. // Function ReleaseMetadata: frees up space allocated when we
  294. // got the metadata.
  295. //
  296. VOID
  297. ReleaseMetadataBlob(
  298. IN PVOID pBuffer )
  299. {
  300. if ( pBuffer != NULL )
  301. {
  302. delete [] pBuffer;
  303. }
  304. return NOTHING;
  305. }
  306. DFSSTATUS
  307. AllocateMetadataBlob(
  308. IN PVOID *ppBlob,
  309. IN ULONG BlobSize )
  310. {
  311. DFSSTATUS Status = ERROR_SUCCESS;
  312. *ppBlob = (PVOID)new BYTE [ BlobSize ];
  313. if (*ppBlob == NULL)
  314. {
  315. Status = ERROR_NOT_ENOUGH_MEMORY;
  316. }
  317. return Status;
  318. }
  319. VOID
  320. ReleaseMetadataNameBlob(
  321. PVOID pBlob,
  322. ULONG BlobSize )
  323. {
  324. UNREFERENCED_PARAMETER(BlobSize);
  325. ReleaseMetadataBlob( pBlob );
  326. }
  327. VOID
  328. ReleaseMetadataReplicaBlob(
  329. PVOID pBlob,
  330. ULONG BlobSize )
  331. {
  332. UNREFERENCED_PARAMETER(BlobSize);
  333. ReleaseMetadataBlob( pBlob );
  334. }
  335. DFSSTATUS
  336. AllocateMetadataNameBlob(
  337. IN PVOID *ppBlob,
  338. IN ULONG BlobSize )
  339. {
  340. return AllocateMetadataBlob(ppBlob, BlobSize);
  341. }
  342. DFSSTATUS
  343. AllocateMetadataReplicaBlob(
  344. IN PVOID *ppBlob,
  345. IN ULONG BlobSize )
  346. {
  347. return AllocateMetadataBlob(ppBlob, BlobSize);
  348. }
  349. public:
  350. //
  351. // Function DfsStore: the constructor for the store. This initializes
  352. // the critical section, and all the private and public variables
  353. // of the store class.
  354. //
  355. DfsStore(LPWSTR Name, DfsObjectTypeEnumeration ObType, DFSSTATUS *pStatus) :
  356. DfsGeneric(ObType)
  357. {
  358. USHORT NameLen = 0;
  359. DFSSTATUS Status = ERROR_SUCCESS;
  360. UNICODE_STRING Temp;
  361. _fCritInit = FALSE;
  362. _StoreName.Buffer = NULL;
  363. //
  364. // Create a unicode string from the passed in name, and
  365. // initialize our unicode string name to the passed in name.
  366. //
  367. Status = DfsRtlInitUnicodeStringEx(&Temp, Name);
  368. if(Status == ERROR_SUCCESS)
  369. {
  370. NameLen = wcslen(Name) + 1;
  371. _StoreName.MaximumLength = NameLen * sizeof(WCHAR);
  372. _StoreName.Buffer = new WCHAR [NameLen];
  373. if(_StoreName.Buffer == NULL)
  374. {
  375. Status = ERROR_NOT_ENOUGH_MEMORY;
  376. }
  377. }
  378. if(Status == ERROR_SUCCESS)
  379. {
  380. RtlCopyUnicodeString(&_StoreName, &Temp);
  381. _DfsRootList = NULL;
  382. _DfsDeletedRootList = NULL;
  383. _DfsOldRootList = NULL;
  384. pNextRegisteredStore = NULL;
  385. //
  386. // The generation number exists to detect stale dfs folders.
  387. // more on this later.
  388. //
  389. _GenerationNumber = 1;
  390. _fCritInit = InitializeCriticalSectionAndSpinCount( &_Lock, DFS_CRIT_SPIN_COUNT );
  391. if(!_fCritInit)
  392. {
  393. Status = GetLastError();
  394. }
  395. }
  396. *pStatus = Status;
  397. }
  398. //
  399. // Function ~DfsStore: the destructor of dfsstore. Free up
  400. // the allocated resources.
  401. // This is virtual, so that we call the right order of destructors
  402. // for all the instances of classes derived from DfsStore.
  403. //
  404. virtual
  405. ~DfsStore()
  406. {
  407. // We could provide a mechanism to run through the list of
  408. // root metadata, and release all of them, but that is
  409. // unnecessary since we dont get rid of stores today.
  410. // Once registered the stores live forever.
  411. //
  412. // Now free up the buffer we had allocated for the storename.
  413. //
  414. if (_StoreName.Buffer != NULL) {
  415. delete [] _StoreName.Buffer;
  416. }
  417. if(_fCritInit)
  418. {
  419. DeleteCriticalSection( &_Lock );
  420. }
  421. }
  422. static
  423. DFSSTATUS
  424. GetOldDfsRegistryKey( IN LPWSTR MachineName,
  425. BOOLEAN WritePermission,
  426. OUT BOOLEAN *pMachineContacted,
  427. OUT PHKEY pDfsRegKey )
  428. {
  429. return GetDfsRegistryKey (MachineName,
  430. DfsOldRegistryLocation,
  431. WritePermission,
  432. pMachineContacted,
  433. pDfsRegKey );
  434. }
  435. static
  436. DFSSTATUS
  437. GetOldStandaloneRegistryKey( IN LPWSTR MachineName,
  438. BOOLEAN WritePermission,
  439. OUT BOOLEAN *pMachineContacted,
  440. OUT PHKEY pDfsRegKey )
  441. {
  442. DFSSTATUS Status = ERROR_SUCCESS;
  443. HKEY DfsKey = NULL;
  444. *pDfsRegKey = NULL;
  445. Status = GetOldDfsRegistryKey (MachineName,
  446. WritePermission,
  447. pMachineContacted,
  448. &DfsKey );
  449. if (Status == ERROR_SUCCESS)
  450. {
  451. *pDfsRegKey = DfsKey;
  452. }
  453. return Status;
  454. }
  455. static
  456. DFSSTATUS
  457. GetNewStandaloneRegistryKey( IN LPWSTR MachineName,
  458. BOOLEAN WritePermission,
  459. OUT BOOLEAN *pMachineContacted,
  460. OUT PHKEY pDfsRegKey )
  461. {
  462. DFSSTATUS Status;
  463. HKEY DfsKey;
  464. Status = GetNewDfsRegistryKey (MachineName,
  465. WritePermission,
  466. pMachineContacted,
  467. &DfsKey );
  468. if (Status == ERROR_SUCCESS)
  469. {
  470. Status = RegOpenKeyEx( DfsKey,
  471. DfsStandaloneChild,
  472. 0,
  473. KEY_READ | (WritePermission ? KEY_WRITE : 0),
  474. pDfsRegKey );
  475. RegCloseKey( DfsKey);
  476. }
  477. return Status;
  478. }
  479. static
  480. DFSSTATUS
  481. GetNewADBlobRegistryKey( IN LPWSTR MachineName,
  482. BOOLEAN WritePermission,
  483. OUT BOOLEAN *pMachineContacted,
  484. OUT PHKEY pDfsRegKey )
  485. {
  486. DFSSTATUS Status;
  487. HKEY DfsKey;
  488. Status = GetNewDfsRegistryKey (MachineName,
  489. WritePermission,
  490. pMachineContacted,
  491. &DfsKey );
  492. if (Status == ERROR_SUCCESS)
  493. {
  494. Status = RegOpenKeyEx( DfsKey,
  495. DfsADBlobChild,
  496. 0,
  497. KEY_READ | (WritePermission ? KEY_WRITE : 0),
  498. pDfsRegKey );
  499. RegCloseKey( DfsKey);
  500. }
  501. return Status;
  502. }
  503. //
  504. // Function StoreRecognizer: This function takes a Name as the input,
  505. // and looks up all DFS roots in that namespace.
  506. // Since each store has its own mechanisms of identifying a root,
  507. // the base class does not implement the StoreRecognizer. Each of
  508. // the classes that are derived from the DfsStore class are expectged
  509. // to override this function with their own implementation of the
  510. // StoreRecognizer.
  511. //
  512. virtual
  513. DFSSTATUS
  514. StoreRecognizer(LPWSTR Name) = 0;
  515. virtual
  516. DFSSTATUS
  517. StoreRecognizer(
  518. LPWSTR Name,
  519. PUNICODE_STRING Share) = 0;
  520. DFSSTATUS
  521. StoreRecognizeNewDfs(
  522. LPWSTR DfsNameContext,
  523. HKEY DfsKey );
  524. DFSSTATUS
  525. StoreRecognizeNewDfs (
  526. LPWSTR DfsNameContext,
  527. PUNICODE_STRING pLogicalShare );
  528. //
  529. // Function ReleaseLock: release the store lock.
  530. //
  531. VOID
  532. ReleaseLock()
  533. {
  534. LeaveCriticalSection(&_Lock);
  535. return NOTHING;
  536. }
  537. //
  538. // Function AcquireWriteLock: Acquire the store lock exclusively.
  539. // Currently all locks are exclusive, but this could change.
  540. //
  541. DFSSTATUS
  542. AcquireWriteLock()
  543. {
  544. return AcquireLock();
  545. }
  546. //
  547. // Function AcquireReadLock: Acquire the store lock shared.
  548. // Currently all locks are exclusive, but this could change.
  549. //
  550. DFSSTATUS
  551. AcquireReadLock()
  552. {
  553. return AcquireLock();
  554. }
  555. //
  556. // Function AddRootFolder: This function takes a RootFolder and
  557. // adds it to the list of known roots for this store.
  558. // Each store instance keeps a list of all the Roots recognized by
  559. // it.
  560. //
  561. // Make sure that we are adding only one root for a given metadata
  562. // name and context, so that if multiple threads are working, only
  563. // one will succeed.
  564. //
  565. //
  566. DFSSTATUS
  567. AddRootFolder(DfsRootFolder *pNewRoot,
  568. DfsRootListType RootType )
  569. {
  570. DFSSTATUS Status = STATUS_SUCCESS;
  571. DfsRootFolder *pRoot;
  572. DfsRootFolder **ppList;
  573. switch (RootType)
  574. {
  575. case NewRootList:
  576. ppList = &_DfsRootList;
  577. break;
  578. case DeletedRootList:
  579. ppList = &_DfsDeletedRootList;
  580. break;
  581. case OldRootList:
  582. ppList = &_DfsOldRootList;
  583. break;
  584. default:
  585. return STATUS_INVALID_PARAMETER;
  586. break;
  587. }
  588. Status = AcquireWriteLock();
  589. if ( Status != ERROR_SUCCESS )
  590. return Status;
  591. if ( *ppList == NULL )
  592. {
  593. *ppList = pNewRoot;
  594. pNewRoot->pNextRoot = pNewRoot;
  595. pNewRoot->pPrevRoot = pNewRoot;
  596. }
  597. else
  598. {
  599. pRoot = *ppList;
  600. Status = ERROR_SUCCESS;
  601. do
  602. {
  603. if ( (_wcsicmp( pRoot->GetRootRegKeyNameString(),
  604. pNewRoot->GetRootRegKeyNameString()) == 0) &&
  605. (_wcsicmp( pRoot->GetNameContextString(),
  606. pNewRoot->GetNameContextString() ) == 0) )
  607. {
  608. Status = ERROR_FILE_EXISTS;
  609. break;
  610. }
  611. pRoot = pRoot->pNextRoot;
  612. } while ( pRoot != *ppList );
  613. if (Status == ERROR_SUCCESS)
  614. {
  615. pNewRoot->pNextRoot = *ppList;
  616. pNewRoot->pPrevRoot = (*ppList)->pPrevRoot;
  617. (*ppList)->pPrevRoot->pNextRoot = pNewRoot;
  618. (*ppList)->pPrevRoot = pNewRoot;
  619. }
  620. }
  621. if (Status == ERROR_SUCCESS)
  622. {
  623. pNewRoot->AcquireReference();
  624. }
  625. ReleaseLock();
  626. return Status;
  627. }
  628. //
  629. // Function DeleteRootFolder: This function takes a RootFolder and
  630. // removes it from the list of known roots for this store.
  631. // This functions is not supported: any root that has been deleted
  632. // will stay in the root list so that we can get to the statistics
  633. // etc. Future action TBD.
  634. //
  635. DFSSTATUS
  636. DeleteRootFolder(DfsRootFolder *pDfsRoot,
  637. DfsRootListType RootType )
  638. {
  639. DFSSTATUS Status = STATUS_SUCCESS;
  640. DfsRootFolder *pRoot;
  641. DfsRootFolder **ppList;
  642. switch (RootType)
  643. {
  644. case NewRootList:
  645. ppList = &_DfsRootList;
  646. break;
  647. case DeletedRootList:
  648. ppList = &_DfsDeletedRootList;
  649. break;
  650. case OldRootList:
  651. ppList = &_DfsOldRootList;
  652. break;
  653. default:
  654. return STATUS_INVALID_PARAMETER;
  655. break;
  656. }
  657. Status = AcquireWriteLock();
  658. if ( Status != ERROR_SUCCESS )
  659. return Status;
  660. for ( pRoot = *ppList; pRoot != NULL; pRoot = pRoot->pNextRoot )
  661. {
  662. if (pRoot == pDfsRoot)
  663. {
  664. if (pRoot->pNextRoot == pRoot)
  665. {
  666. *ppList = NULL;
  667. }
  668. else
  669. {
  670. pRoot->pNextRoot->pPrevRoot = pRoot->pPrevRoot;
  671. pRoot->pPrevRoot->pNextRoot = pRoot->pNextRoot;
  672. if (pRoot == *ppList)
  673. {
  674. *ppList = pRoot->pNextRoot;
  675. }
  676. }
  677. pRoot->pNextRoot = NULL;
  678. pRoot->pPrevRoot = NULL;
  679. break;
  680. }
  681. }
  682. ReleaseLock();
  683. if (pRoot == NULL)
  684. {
  685. Status = ERROR_NOT_FOUND;
  686. }
  687. else
  688. {
  689. pRoot->ReleaseReference();
  690. }
  691. return Status;
  692. }
  693. DFSSTATUS
  694. RemoveRootFolder( DfsRootFolder *pRootFolder,
  695. BOOLEAN IsPermanent )
  696. {
  697. DFSSTATUS LinkDeleteStatus = ERROR_SUCCESS;
  698. DFSSTATUS Status = ERROR_SUCCESS;
  699. LinkDeleteStatus = pRootFolder->RemoveAllLinkFolders(IsPermanent);
  700. pRootFolder->pStatistics->DumpStatistics(pRootFolder->GetLogicalShare());
  701. Status = DeleteRootFolder( pRootFolder, NewRootList );
  702. #if 0
  703. if (Status == ERROR_SUCCESS) {
  704. Status = AddRootFolder( pRootFolder, DeletedRootList );
  705. }
  706. #endif
  707. return Status;
  708. }
  709. //
  710. // Function LookupRoot: Takes a Dfs name context and logical share,
  711. // and returns a Root that matches the passed in name context and
  712. // logical share, if one exists.
  713. // Note that the same DFS NC and logical share may exist in more than
  714. // one store (though very unlikely). In this case, the first registered
  715. // store wins.
  716. //
  717. DFSSTATUS
  718. LookupRoot( PUNICODE_STRING pMachineName,
  719. PUNICODE_STRING pLogicalShare,
  720. DfsRootFolder **ppRoot );
  721. //
  722. // Function LookupRoot: Takes a Dfs name context and logical share,
  723. // and returns a Root that matches the passed in name context and
  724. // logical share, if one exists.
  725. // Note that the same DFS NC and logical share may exist in more than
  726. // one store (though very unlikely). In this case, the first registered
  727. // store wins.
  728. //
  729. DFSSTATUS
  730. FindFirstRoot( DfsRootFolder **ppRoot )
  731. {
  732. DFSSTATUS Status;
  733. Status = AcquireReadLock();
  734. if ( Status != ERROR_SUCCESS )
  735. {
  736. return Status;
  737. }
  738. *ppRoot = _DfsRootList;
  739. if (*ppRoot == NULL)
  740. {
  741. Status = ERROR_NOT_FOUND;
  742. }
  743. else {
  744. (*ppRoot)->AcquireReference();
  745. }
  746. ReleaseLock();
  747. return Status;
  748. }
  749. DFSSTATUS
  750. GetRootCount(
  751. PULONG pCount)
  752. {
  753. DFSSTATUS Status;
  754. DfsRootFolder *pRoot;
  755. ULONG Count = 0;
  756. *pCount = 0;
  757. Status = AcquireReadLock();
  758. if ( Status != ERROR_SUCCESS )
  759. {
  760. return Status;
  761. }
  762. pRoot = _DfsRootList;
  763. if (pRoot != NULL)
  764. {
  765. do
  766. {
  767. Count++;
  768. pRoot = pRoot->pNextRoot;
  769. } while ( pRoot != _DfsRootList );
  770. }
  771. *pCount = Count;
  772. ReleaseLock();
  773. return Status;
  774. }
  775. ULONG
  776. FindReplicaInReplicaList(
  777. PDFS_REPLICA_LIST_INFORMATION pReplicaList,
  778. LPWSTR Server,
  779. LPWSTR Path )
  780. {
  781. ULONG Index;
  782. PDFS_REPLICA_INFORMATION pReplicaInfo;
  783. UNICODE_STRING Target, TargetPath;
  784. DfsRtlInitUnicodeStringEx(&Target, Server);
  785. DfsRtlInitUnicodeStringEx(&TargetPath, Path);
  786. for (Index = 0; Index < pReplicaList->ReplicaCount; Index++)
  787. {
  788. pReplicaInfo = &pReplicaList->pReplicas[Index];
  789. if ( (RtlCompareUnicodeString( &pReplicaInfo->ServerName,
  790. &Target,
  791. TRUE) == 0) &&
  792. (RtlCompareUnicodeString( &pReplicaInfo->ShareName,
  793. &TargetPath,
  794. TRUE) == 0) )
  795. {
  796. break;
  797. }
  798. }
  799. return Index;
  800. }
  801. DFSSTATUS
  802. DumpStatistics()
  803. {
  804. DFSSTATUS Status = STATUS_SUCCESS;
  805. DfsRootFolder *pRoot;
  806. DfsRootFolder **ppList;
  807. ppList = &_DfsRootList;
  808. Status = AcquireWriteLock();
  809. if ( Status != ERROR_SUCCESS )
  810. return Status;
  811. for ( pRoot = *ppList; pRoot != NULL; pRoot = pRoot->pNextRoot )
  812. {
  813. pRoot->pStatistics->DumpStatistics(pRoot->GetLogicalShare());
  814. if (pRoot->pNextRoot == _DfsRootList)
  815. {
  816. break;
  817. }
  818. }
  819. ReleaseLock();
  820. return Status;
  821. }
  822. virtual
  823. DFSSTATUS
  824. AddChild(
  825. DFS_METADATA_HANDLE DfsHandle,
  826. IN PDFS_NAME_INFORMATION pNameInfo,
  827. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  828. IN PUNICODE_STRING pMetadataName ) = 0;
  829. virtual
  830. DFSSTATUS
  831. RemoveChild(
  832. DFS_METADATA_HANDLE DfsHandle,
  833. LPWSTR ChildName ) = 0;
  834. DFSSTATUS
  835. AddChildReplica (
  836. DFS_METADATA_HANDLE DfsHandle,
  837. LPWSTR LinkMetadataName,
  838. LPWSTR Server,
  839. LPWSTR Share );
  840. DFSSTATUS
  841. RemoveChildReplica (
  842. DFS_METADATA_HANDLE DfsHandle,
  843. LPWSTR LinkMetadataName,
  844. LPWSTR Server,
  845. LPWSTR Share,
  846. PBOOLEAN pLastReplica ,
  847. BOOLEAN Force = FALSE);
  848. virtual
  849. DFSSTATUS
  850. EnumerateApiLinks(
  851. DFS_METADATA_HANDLE DfsHandle,
  852. PUNICODE_STRING pRootName,
  853. DWORD Level,
  854. LPBYTE pBuffer,
  855. LONG BufferSize,
  856. LPDWORD pEntriesToRead,
  857. LPDWORD pResumeHandle,
  858. PLONG pNextSizeRequired ) = 0;
  859. DFSSTATUS
  860. GetStoreApiInformation(
  861. DFS_METADATA_HANDLE DfsHandle,
  862. PUNICODE_STRING pRootName,
  863. LPWSTR LinkMetadataName,
  864. DWORD Level,
  865. LPBYTE pBuffer,
  866. LONG BufferSize,
  867. PLONG pSizeRequired );
  868. DFSSTATUS
  869. SetStoreApiInformation(
  870. DFS_METADATA_HANDLE DfsHandle,
  871. LPWSTR LinkMetadataName,
  872. LPWSTR Server,
  873. LPWSTR Share,
  874. DWORD Level,
  875. LPBYTE pBuffer );
  876. DFSSTATUS
  877. GetExtendedAttributes(
  878. IN DFS_METADATA_HANDLE DfsHandle,
  879. LPWSTR LinkMetadataName,
  880. PULONG pAttr);
  881. DFSSTATUS
  882. SetExtendedAttributes(
  883. IN DFS_METADATA_HANDLE DfsHandle,
  884. LPWSTR LinkMetadataName,
  885. ULONG pAttr);
  886. //
  887. // Function GetRootFolder: Runs through our list of RootFolders
  888. // and sees if there is any root folder with the matching name.
  889. // Returns a reference root folder, if found.
  890. //
  891. DFSSTATUS
  892. GetRootFolder (
  893. LPWSTR DfsNameContext,
  894. LPWSTR RootRegistryName,
  895. HKEY DfsRootKey,
  896. DfsRootFolder **ppRootFolder );
  897. //
  898. // Function GetRootFolder: Runs through our list of RootFolders
  899. // and sees if there is any root folder with the matching name.
  900. // Returns a reference root folder, if found.
  901. //
  902. DFSSTATUS
  903. GetRootFolder (
  904. LPWSTR DfsNameContext,
  905. LPWSTR RootRegistryName,
  906. PUNICODE_STRING pLogicalShare,
  907. PUNICODE_STRING pPhysicalShare,
  908. DfsRootFolder **ppRootFolder );
  909. //
  910. // Similar to the above, except for being aware that
  911. // the root isn't on the local machine.
  912. //
  913. DFSSTATUS
  914. GetRootFolder (
  915. LPWSTR DfsNameContextString,
  916. PUNICODE_STRING pLogicalShare,
  917. DfsRootFolder **ppRootFolder );
  918. //
  919. // Function CreateNewRootFolder: Creates a new root folder
  920. // for the passed in name context, and logical share.
  921. //
  922. virtual
  923. DFSSTATUS
  924. CreateNewRootFolder (
  925. LPWSTR MachineName,
  926. LPWSTR RootRegKeyName,
  927. PUNICODE_STRING pLogicalShare,
  928. PUNICODE_STRING pPhysicalShare,
  929. DfsRootFolder **pRoot ) = 0;
  930. virtual
  931. DFSSTATUS
  932. GenerateLinkMetadataName(
  933. UUID *pUid,
  934. PUNICODE_STRING pLinkMetadataName )
  935. {
  936. DFSSTATUS Status = ERROR_SUCCESS;
  937. LPWSTR String = NULL;
  938. Status = UuidToString( pUid,
  939. &String );
  940. if (Status == ERROR_SUCCESS)
  941. {
  942. Status = DfsRtlInitUnicodeStringEx( pLinkMetadataName, String);
  943. }
  944. return Status;
  945. }
  946. virtual
  947. VOID
  948. ReleaseLinkMetadataName(
  949. PUNICODE_STRING pLinkMetadataName )
  950. {
  951. RpcStringFree(&pLinkMetadataName->Buffer );
  952. return;
  953. }
  954. DFSSTATUS
  955. EnumerateRoots(
  956. BOOLEAN DomainRoots,
  957. PULONG_PTR pBuffer,
  958. PULONG BufferSize,
  959. PULONG pEntriesRead,
  960. DWORD MaxEntriesToRead,
  961. PULONG pCurrentNumRoots,
  962. LPDWORD pResumeHandle,
  963. PULONG pSizeRequired );
  964. DFSSTATUS
  965. AddRootEnumerationInfo(
  966. PUNICODE_STRING pVisibleName,
  967. PUNICODE_STRING pRootName,
  968. DWORD Flavor,
  969. PDFS_INFO_300 *ppDfsInfo300,
  970. PULONG pBufferSize,
  971. PULONG pEntriesRead,
  972. PULONG pTotalSize );
  973. DFSSTATUS
  974. AddRootEnumerationInfo200(
  975. PUNICODE_STRING pRootName,
  976. PDFS_INFO_200 *ppDfsInfo300,
  977. PULONG pBufferSize,
  978. PULONG pEntriesRead,
  979. PULONG pTotalSize );
  980. static
  981. DFSSTATUS
  982. SetupADBlobRootKeyInformation(
  983. HKEY DfsKey,
  984. LPWSTR DfsLogicalShare,
  985. LPWSTR DfsPhysicalShare );
  986. virtual
  987. DFSSTATUS
  988. GetMetadataNameInformation(
  989. IN DFS_METADATA_HANDLE RootHandle,
  990. IN LPWSTR MetadataName,
  991. OUT PDFS_NAME_INFORMATION *ppInfo );
  992. virtual
  993. VOID
  994. ReleaseMetadataNameInformation(
  995. IN DFS_METADATA_HANDLE DfsHandle,
  996. IN PDFS_NAME_INFORMATION pNameInfo );
  997. virtual
  998. DFSSTATUS
  999. SetMetadataNameInformation(
  1000. IN DFS_METADATA_HANDLE RootHandle,
  1001. IN LPWSTR MetadataName,
  1002. IN PDFS_NAME_INFORMATION pNameInfo );
  1003. DFSSTATUS
  1004. GetMetadataReplicaInformation(
  1005. IN DFS_METADATA_HANDLE RootHandle,
  1006. IN LPWSTR MetadataName,
  1007. OUT PDFS_REPLICA_LIST_INFORMATION *ppInfo );
  1008. VOID
  1009. ReleaseMetadataReplicaInformation(
  1010. IN DFS_METADATA_HANDLE DfsHandle,
  1011. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
  1012. DFSSTATUS
  1013. SetMetadataReplicaInformation(
  1014. IN DFS_METADATA_HANDLE RootHandle,
  1015. IN LPWSTR MetadataName,
  1016. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo );
  1017. DFSSTATUS
  1018. CreateNameInformationBlob(
  1019. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  1020. OUT PVOID *ppBlob,
  1021. OUT PULONG pDataSize );
  1022. virtual
  1023. DFSSTATUS
  1024. CreateReplicaListInformationBlob(
  1025. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  1026. OUT PVOID *ppBlob,
  1027. OUT PULONG pDataSize );
  1028. virtual
  1029. DFSSTATUS
  1030. GetMetadataNameBlob(
  1031. DFS_METADATA_HANDLE RootHandle,
  1032. LPWSTR MetadataName,
  1033. PVOID *ppData,
  1034. PULONG pDataSize,
  1035. PFILETIME pLastModifiedTime ) = 0;
  1036. virtual
  1037. DFSSTATUS
  1038. GetMetadataReplicaBlob(
  1039. DFS_METADATA_HANDLE RootHandle,
  1040. LPWSTR MetadataName,
  1041. PVOID *ppData,
  1042. PULONG pDataSize,
  1043. PFILETIME pLastModifiedTime ) = 0;
  1044. virtual
  1045. DFSSTATUS
  1046. SetMetadataNameBlob(
  1047. DFS_METADATA_HANDLE RootHandle,
  1048. LPWSTR MetadataName,
  1049. PVOID pData,
  1050. ULONG DataSize ) = 0;
  1051. virtual
  1052. DFSSTATUS
  1053. SetMetadataReplicaBlob(
  1054. DFS_METADATA_HANDLE RootHandle,
  1055. LPWSTR MetadataName,
  1056. PVOID pData,
  1057. ULONG DataSize ) = 0;
  1058. virtual
  1059. DFSSTATUS
  1060. PackGetNameInformation(
  1061. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  1062. IN OUT PVOID *ppBuffer,
  1063. IN OUT PULONG pSizeRemaining) = 0;
  1064. virtual
  1065. ULONG
  1066. PackSizeNameInformation(
  1067. IN PDFS_NAME_INFORMATION pDfsNameInfo ) = 0;
  1068. virtual
  1069. DFSSTATUS
  1070. PackSetNameInformation(
  1071. IN PDFS_NAME_INFORMATION pDfsNameInfo,
  1072. IN OUT PVOID *ppBuffer,
  1073. IN OUT PULONG pSizeRemaining) = 0;
  1074. virtual
  1075. DFSSTATUS
  1076. GenerateMetadataLogicalName(
  1077. PUNICODE_STRING pRootName,
  1078. PUNICODE_STRING pInput,
  1079. PUNICODE_STRING pOutput ) = 0;
  1080. virtual
  1081. VOID
  1082. ReleaseMetadataLogicalName(
  1083. PUNICODE_STRING pName ) = 0;
  1084. virtual
  1085. DFSSTATUS
  1086. GenerateApiLogicalPath (
  1087. IN PUNICODE_STRING pRootName,
  1088. IN PUNICODE_STRING pMetadataPrefix,
  1089. IN PUNICODE_STRING pApiLogicalName ) = 0;
  1090. virtual
  1091. VOID
  1092. ReleaseApiLogicalPath (
  1093. PUNICODE_STRING pName ) = 0;
  1094. DFSSTATUS
  1095. GetStoreApiInformationBuffer(
  1096. IN DFS_METADATA_HANDLE DfsHandle,
  1097. PUNICODE_STRING pRootName,
  1098. LPWSTR LinkMetadataName,
  1099. DWORD Level,
  1100. LPBYTE *ppBuffer,
  1101. PLONG pBufferSize );
  1102. DFSSTATUS
  1103. ReleaseStoreApiInformationBuffer(
  1104. LPBYTE pBuffer )
  1105. {
  1106. delete [] pBuffer;
  1107. return ERROR_SUCCESS;
  1108. }
  1109. VOID
  1110. StoreInitializeNameInformation(
  1111. IN PDFS_NAME_INFORMATION pNameInfo,
  1112. IN PUNICODE_STRING pLogicalName,
  1113. UUID *pGuid,
  1114. IN LPWSTR Comment )
  1115. {
  1116. //
  1117. // Zero out our information buffers.
  1118. //
  1119. RtlZeroMemory( pNameInfo,
  1120. sizeof(DFS_NAME_INFORMATION) );
  1121. pNameInfo->Prefix = *pLogicalName;
  1122. pNameInfo->ShortPrefix = *pLogicalName;
  1123. pNameInfo->State = DFS_VOLUME_STATE_OK;
  1124. pNameInfo->Type = PKT_ENTRY_TYPE_DFS;
  1125. pNameInfo->Timeout = DEFAULT_LINK_TIMEOUT;
  1126. pNameInfo->Version = 3;
  1127. if (pGuid != NULL)
  1128. {
  1129. pNameInfo->VolumeId = *pGuid;
  1130. }
  1131. DfsRtlInitUnicodeStringEx( &(pNameInfo->Comment), Comment);
  1132. return NOTHING;
  1133. }
  1134. VOID
  1135. StoreInitializeReplicaInformation(
  1136. IN PDFS_REPLICA_LIST_INFORMATION pReplicaListInfo,
  1137. IN PDFS_REPLICA_INFORMATION pReplicaInfo,
  1138. IN LPWSTR ReplicaServer,
  1139. IN LPWSTR ReplicaPath )
  1140. {
  1141. RtlZeroMemory( pReplicaInfo,
  1142. sizeof( DFS_REPLICA_INFORMATION ));
  1143. RtlZeroMemory( pReplicaListInfo,
  1144. sizeof( DFS_REPLICA_LIST_INFORMATION ));
  1145. if ( (ReplicaServer != NULL) &&
  1146. (ReplicaPath != NULL) )
  1147. {
  1148. DfsRtlInitUnicodeStringEx( &(pReplicaInfo->ServerName), ReplicaServer);
  1149. DfsRtlInitUnicodeStringEx( &(pReplicaInfo->ShareName), ReplicaPath );
  1150. pReplicaInfo->ReplicaState = DFS_STORAGE_STATE_ONLINE;
  1151. pReplicaInfo->ReplicaType = 2; // dfsdev: hack for backwards compat.
  1152. pReplicaListInfo->ReplicaCount = 1;
  1153. pReplicaListInfo->pReplicas = pReplicaInfo;
  1154. }
  1155. return NOTHING;
  1156. }
  1157. VOID
  1158. StoreSynchronizer();
  1159. DFSSTATUS
  1160. FindNextRoot(
  1161. ULONG RootNum,
  1162. DfsRootFolder **ppRootFolder );
  1163. DFSSTATUS
  1164. LoadServerSiteDataPerRoot(void);
  1165. //
  1166. // Currently this is a ADBlobStore specific implementation.
  1167. // This provides dfs support for domain rename.
  1168. virtual
  1169. DFSSTATUS
  1170. RenameLinks(
  1171. IN DFS_METADATA_HANDLE RootHandle,
  1172. IN PUNICODE_STRING pLinkMetadataName,
  1173. IN PUNICODE_STRING OldDomainName,
  1174. IN PUNICODE_STRING NewDomainName)
  1175. {
  1176. UNREFERENCED_PARAMETER(RootHandle);
  1177. UNREFERENCED_PARAMETER(pLinkMetadataName);
  1178. UNREFERENCED_PARAMETER(OldDomainName);
  1179. UNREFERENCED_PARAMETER(NewDomainName);
  1180. return ERROR_INVALID_PARAMETER;
  1181. }
  1182. };
  1183. #endif // __DFS_STORE__