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.

361 lines
11 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsRegistryRootFolder.cxx
  6. //
  7. // Contents: the Root DFS Folder class for Registry Store
  8. //
  9. // Classes: DfsRegistryRootFolder
  10. //
  11. // History: Dec. 8 2000, Author: udayh
  12. //
  13. //-----------------------------------------------------------------------------
  14. #include "DfsRegistryRootFolder.hxx"
  15. #include "DfsReplica.hxx"
  16. #include "lmdfs.h"
  17. #include "DfsClusterSupport.hxx"
  18. //
  19. // logging specific includes
  20. //
  21. #include "DfsRegistryRootFolder.tmh"
  22. //+----------------------------------------------------------------------------
  23. //
  24. // Class: DfsRegistryRootFolder
  25. //
  26. // Synopsis: This class implements The Dfs Registry root folder.
  27. //
  28. //-----------------------------------------------------------------------------
  29. //+-------------------------------------------------------------------------
  30. //
  31. // Function: DfsRegistryRootFolder - constructor
  32. //
  33. // Arguments: NameContext - the dfs name context
  34. // pLogicalShare - the logical share
  35. // pParentStore - the parent store for this root.
  36. // pStatus - the return status
  37. //
  38. // Returns: NONE
  39. //
  40. // Description: This routine initializes a RegistryRootFolder instance
  41. //
  42. //--------------------------------------------------------------------------
  43. DfsRegistryRootFolder::DfsRegistryRootFolder(
  44. LPWSTR NameContext,
  45. LPWSTR pRootRegKeyNameString,
  46. PUNICODE_STRING pLogicalShare,
  47. PUNICODE_STRING pPhysicalShare,
  48. DfsRegistryStore *pParentStore,
  49. DFSSTATUS *pStatus ) : DfsRootFolder ( NameContext,
  50. pRootRegKeyNameString,
  51. pLogicalShare,
  52. pPhysicalShare,
  53. DFS_OBJECT_TYPE_REGISTRY_ROOT_FOLDER,
  54. pStatus )
  55. {
  56. DFSSTATUS Status = *pStatus;
  57. _pStore = pParentStore;
  58. if (_pStore != NULL)
  59. {
  60. _pStore->AcquireReference();
  61. }
  62. _RootFlavor = DFS_VOLUME_FLAVOR_STANDALONE;
  63. //
  64. // If the namecontext that we are passed is an emptry string,
  65. // then we are dealing with the referral server running on the root
  66. // itself. We are required to ignore the name context for such
  67. // roots during lookups, so that aliasing works. (Aliasing is where
  68. // someone may access the root with an aliased machine name or ip
  69. // address)
  70. //
  71. if (IsEmptyString(NameContext) == TRUE)
  72. {
  73. SetIgnoreNameContext();
  74. _LocalCreate = TRUE;
  75. }
  76. //
  77. // dfsdev: If this is cluster resource, we should set the visible name
  78. // to virtual server name of this resource.
  79. //
  80. // The constructor for DfsRootFolder will be called before we
  81. // get here, and pstatus will be initialized
  82. //
  83. if (Status == ERROR_SUCCESS)
  84. {
  85. if (DfsIsMachineCluster())
  86. {
  87. DFSSTATUS ClusterStatus;
  88. ClusterStatus = GetRootClusterInformation( pLogicalShare,
  89. &_DfsVisibleContext);
  90. if (ClusterStatus != ERROR_SUCCESS)
  91. {
  92. RtlInitUnicodeString(&_DfsVisibleContext, NULL);
  93. }
  94. }
  95. if (IsEmptyString(_DfsVisibleContext.Buffer))
  96. {
  97. Status = DfsGetMachineName( &_DfsVisibleContext );
  98. }
  99. }
  100. *pStatus = Status;
  101. }
  102. //+-------------------------------------------------------------------------
  103. //
  104. // Function: Synchronize
  105. //
  106. // Arguments: None
  107. //
  108. // Returns: Status: Success or Error status code
  109. //
  110. // Description: This routine synchronizes the children folders
  111. // of this root.
  112. //
  113. //--------------------------------------------------------------------------
  114. DFSSTATUS
  115. DfsRegistryRootFolder::Synchronize( BOOLEAN fForceSynch, BOOLEAN CalledByApi )
  116. {
  117. DFSSTATUS Status = ERROR_SUCCESS;
  118. HKEY RootKey = NULL;
  119. ULONG ChildNum = 0;
  120. DWORD CchMaxName = 0;
  121. DWORD CchChildName = 0;
  122. LPWSTR ChildName = NULL;
  123. FILETIME LastModifiedTime;
  124. UNICODE_STRING NewClusterName;
  125. UNREFERENCED_PARAMETER(fForceSynch);
  126. DFS_TRACE_NORM(REFERRAL_SERVER, "Synchronize for %p\n", this);
  127. RtlInitUnicodeString(&NewClusterName, NULL);
  128. if (DfsIsMachineCluster())
  129. {
  130. DFSSTATUS IgnoreStatus;
  131. IgnoreStatus = GetRootClusterInformation( GetLogicalShare(),
  132. &NewClusterName);
  133. ASSERT((IgnoreStatus == ERROR_SUCCESS) ||
  134. (NewClusterName.Buffer == NULL));
  135. }
  136. Status = AcquireRootLock();
  137. if (Status != ERROR_SUCCESS)
  138. {
  139. return Status;
  140. }
  141. if (NewClusterName.Length != 0)
  142. {
  143. DFSSTATUS ClusterNameStatus;
  144. BOOLEAN Changed = FALSE;
  145. ClusterNameStatus = SetVisibleContext( &NewClusterName, &Changed );
  146. //
  147. // if the cluster information has changed, get rid of cached
  148. // referral.
  149. //
  150. if (ClusterNameStatus == ERROR_SUCCESS)
  151. {
  152. if (Changed)
  153. {
  154. RemoveReferralData(NULL, NULL);
  155. }
  156. }
  157. DfsFreeUnicodeString(&NewClusterName);
  158. DFS_TRACE_LOW(REFERRAL_SERVER, "SetVisbleContext, status %x\n",
  159. ClusterNameStatus);
  160. }
  161. if (CheckRootFolderSkipSynchronize() == TRUE)
  162. {
  163. ReleaseRootLock();
  164. return ERROR_SUCCESS;
  165. }
  166. //
  167. // now acquire the root share directory. If this
  168. // fails, we continue our operation: we can continue
  169. // with synchonize and not create directories.
  170. // dfsdev:we need to post a eventlog or something when
  171. // we run into this.
  172. //
  173. do
  174. {
  175. DFSSTATUS RootStatus = AcquireRootShareDirectory();
  176. if(CalledByApi && (RootStatus != ERROR_SUCCESS))
  177. {
  178. DFS_TRACE_ERROR_LOW(RootStatus, REFERRAL_SERVER, "Recognize Dfs: Root folder for %p, validate status %x\n",
  179. this, RootStatus );
  180. Status = RootStatus;
  181. break;
  182. }
  183. //
  184. // if we are in a standby mode, we dont synchronize, till we obtain
  185. // ownership again.
  186. //
  187. Status = GetMetadataKey( &RootKey );
  188. if ( Status == ERROR_SUCCESS )
  189. {
  190. {
  191. DFS_METADATA_HANDLE DfsHandle;
  192. DfsHandle = CreateMetadataHandle(RootKey);
  193. UpdateLinkInformation( DfsHandle, NULL );
  194. DestroyMetadataHandle(DfsHandle );
  195. }
  196. //
  197. // Iterate over all our folders to make sure they actually
  198. // exist in the registry.
  199. //
  200. CheckPreSynchronize( RootKey );
  201. //
  202. // First find the length of the longest subkey
  203. // and allocate a buffer big enough for it.
  204. //
  205. Status = RegQueryInfoKey( RootKey, // Key
  206. NULL, // Class string
  207. NULL, // Size of class string
  208. NULL, // Reserved
  209. NULL, // # of subkeys
  210. &CchMaxName, // max size of subkey name in TCHARs
  211. NULL, // max size of class name
  212. NULL, // # of values
  213. NULL, // max size of value name
  214. NULL, // max size of value data,
  215. NULL, // security descriptor
  216. NULL ); // Last write time
  217. if (Status == ERROR_SUCCESS)
  218. {
  219. // Space for the NULL terminator.
  220. CchMaxName++;
  221. ChildName = (LPWSTR) new WCHAR [CchMaxName];
  222. if (ChildName == NULL)
  223. {
  224. Status = ERROR_NOT_ENOUGH_MEMORY;
  225. }
  226. }
  227. if (Status == ERROR_SUCCESS)
  228. {
  229. do
  230. {
  231. //
  232. // For each child, get the child name.
  233. //
  234. CchChildName = CchMaxName;
  235. Status = RegEnumKeyEx( RootKey,
  236. ChildNum,
  237. ChildName,
  238. &CchChildName,
  239. NULL,
  240. NULL,
  241. NULL,
  242. &LastModifiedTime );
  243. ChildNum++;
  244. //
  245. // Call update on the child. This either adds a new folder
  246. // or if it exists, ensure the child folder is upto date.
  247. //
  248. if ( Status == ERROR_SUCCESS )
  249. {
  250. DFS_METADATA_HANDLE DfsHandle;
  251. DfsHandle = CreateMetadataHandle(RootKey);
  252. Status = UpdateLinkInformation( DfsHandle,
  253. ChildName );
  254. DestroyMetadataHandle(DfsHandle );
  255. }
  256. } while ( Status == ERROR_SUCCESS );
  257. delete [] ChildName;
  258. }
  259. if ( Status == ERROR_NO_MORE_ITEMS )
  260. {
  261. Status = ERROR_SUCCESS;
  262. }
  263. //
  264. // We are done with synchronize.
  265. // update the Root folder, so that this root folder may be made
  266. // either available or unavailable, as the case may be.
  267. //
  268. if (Status == ERROR_SUCCESS)
  269. {
  270. SetRootFolderSynchronized();
  271. }
  272. else
  273. {
  274. ClearRootFolderSynchronized();
  275. }
  276. //
  277. // Now release the Root metadata key.
  278. //
  279. ReleaseMetadataKey( RootKey );
  280. }
  281. if(CalledByApi && (Status != ERROR_SUCCESS))
  282. {
  283. DFS_TRACE_ERROR_LOW(Status, REFERRAL_SERVER, "Recognize Dfs: Registry Synchronize Root folder for %p, validate status %x\n",
  284. this, Status );
  285. (void) ReleaseRootShareDirectory();
  286. }
  287. } while (0);
  288. DFS_TRACE_NORM(REFERRAL_SERVER, "Synchronize for %p, Status %x\n", this, Status);
  289. ReleaseRootLock();
  290. return Status;
  291. }