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.

444 lines
15 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2000, Microsoft Corporation
  4. //
  5. // File: DfsMigrate.cxx
  6. //
  7. // Contents: Contains the routines to migrate existing DFS root
  8. // information in the registry to a different location,
  9. // to allow multiple roots per server.
  10. //
  11. // Classes: none.
  12. //
  13. // History: Feb. 8 2000, Author: udayh
  14. //
  15. //-----------------------------------------------------------------------------
  16. //
  17. // dfsdev: need to add code to delete, on failure, any intermediate stuff
  18. // we create during migration
  19. //
  20. #include "DfsGeneric.hxx"
  21. #include "DfsInit.hxx"
  22. #include "shlwapi.h"
  23. #include "DfsStore.hxx"
  24. DFSSTATUS
  25. MigrateFTDfs(
  26. LPWSTR MachineName,
  27. HKEY DfsKey,
  28. LPWSTR DfsLogicalShare,
  29. LPWSTR DfsRootShare );
  30. DFSSTATUS
  31. MigrateStdDfs(
  32. LPWSTR MachineName,
  33. HKEY DfsKey,
  34. LPWSTR DfsLogicalShare,
  35. LPWSTR DfsRootShare,
  36. BOOLEAN fDoCleanup);
  37. //+----------------------------------------------------------------------------
  38. //
  39. // Function: MigrateDfs
  40. //
  41. // Arguments: MachineName - Name of the machine to target.
  42. // Can be NULL for local machine.
  43. // Returns: ERROR_SUCCESS
  44. // Error code other wise.
  45. //
  46. // Description: This routine contacts the specified machine, and checks
  47. // if the registry information indicates the machine is
  48. // hosting a standalone or domain DFS. It moves this
  49. // information appropriately under the new StandaloneRoot
  50. // or DomainRoots key, so that we can have multiple roots
  51. // on the machine.
  52. //
  53. //-----------------------------------------------------------------------------
  54. DFSSTATUS
  55. MigrateDfs(
  56. LPWSTR MachineName )
  57. {
  58. LPWSTR DfsRootShare = NULL;
  59. LPWSTR FtDfsValue = NULL;
  60. ULONG DataSize = 0;
  61. ULONG DataType = 0;
  62. ULONG RootShareLength = 0;
  63. ULONG FtDfsValueSize;
  64. DWORD Status;
  65. HKEY OldKey;
  66. PRINTF("Migrate DFS Called. This will migrate the DFS on %wS\n",
  67. (MachineName != NULL) ? MachineName : L"this machine");
  68. Status = DfsStore::GetOldDfsRegistryKey( MachineName,
  69. TRUE,
  70. NULL,
  71. &OldKey );
  72. //
  73. // If we opened the DFS hierarchy key properly, get the maximum
  74. // size of any of the values under this key. This is so that we
  75. // know how much memory to allocate, so that we can read any of
  76. // the values we desire.
  77. //
  78. //
  79. if ( Status == ERROR_SUCCESS ) {
  80. Status = RegQueryInfoKey( OldKey, // Key
  81. NULL, // Class string
  82. NULL, // Size of class string
  83. NULL, // Reserved
  84. NULL, // # of subkeys
  85. NULL, // max size of subkey name
  86. NULL, // max size of class name
  87. NULL, // # of values
  88. NULL, // max size of value name
  89. &DataSize, // max size of value data,
  90. NULL, // security descriptor
  91. NULL ); // Last write time
  92. //
  93. // We want to read the value of the DfsRootShare. If the value
  94. // is still a string, this is indeed an old style DFS and needs
  95. // to be migrated. If the value is something else, this is
  96. // already a migrated machine, so do nothing.
  97. //
  98. if (Status == ERROR_SUCCESS) {
  99. //
  100. // Space for null terminator
  101. //
  102. DataSize += sizeof(WCHAR);
  103. RootShareLength = DataSize;
  104. DfsRootShare = (LPWSTR) new BYTE[DataSize];
  105. if (DfsRootShare == NULL) {
  106. Status = ERROR_NOT_ENOUGH_MEMORY;
  107. }
  108. else {
  109. Status = RegQueryValueEx( OldKey,
  110. DfsRootShareValueName,
  111. NULL,
  112. &DataType,
  113. (LPBYTE)DfsRootShare,
  114. &RootShareLength);
  115. }
  116. }
  117. //
  118. // check if the value is a string.
  119. //
  120. if ((Status == ERROR_SUCCESS) &&
  121. (DataType == REG_SZ)) {
  122. DWORD Migrated;
  123. ULONG MigrateSize;
  124. MigrateSize = sizeof(Migrated);
  125. Status = RegQueryValueEx( OldKey,
  126. DfsMigratedValueName,
  127. NULL,
  128. &DataType,
  129. (PBYTE)&Migrated,
  130. &MigrateSize);
  131. if (Status == ERROR_FILE_NOT_FOUND)
  132. {
  133. FtDfsValueSize = DataSize;
  134. FtDfsValue = (LPWSTR) new BYTE[DataSize];
  135. if (FtDfsValue == NULL) {
  136. Status = ERROR_NOT_ENOUGH_MEMORY;
  137. }
  138. else {
  139. //
  140. // Now check if this is a Domain Based root.
  141. //
  142. Status = RegQueryValueEx( OldKey,
  143. DfsFtDfsValueName,
  144. NULL,
  145. &DataType,
  146. (LPBYTE)FtDfsValue,
  147. &FtDfsValueSize);
  148. //
  149. // At this point we do know we have a machine that
  150. // needs to be migrated. If the machine was hosting
  151. // a standalone root, call MigrateFTDfs to take care
  152. // of the domain based dfs root migration. Else, this
  153. // is a standalone root, so call the standalone root
  154. // migration routine.
  155. //
  156. if (Status == ERROR_SUCCESS) {
  157. Status = MigrateFTDfs( MachineName,
  158. OldKey,
  159. FtDfsValue,
  160. DfsRootShare );
  161. }
  162. else {
  163. Status = MigrateStdDfs( MachineName,
  164. OldKey,
  165. DfsRootShare,
  166. DfsRootShare,
  167. FALSE );
  168. }
  169. if (Status == ERROR_SUCCESS)
  170. {
  171. DWORD DfsMigrated = 1;
  172. //
  173. // ignore error returns here...
  174. //
  175. RegSetValueEx( OldKey,
  176. DfsMigratedValueName,
  177. 0,
  178. REG_DWORD,
  179. (PBYTE)&DfsMigrated,
  180. sizeof(DfsMigrated));
  181. }
  182. }
  183. } else {
  184. //
  185. // Already Migrated
  186. // dfsutil from creating an old fashioned root.
  187. //
  188. Status = ERROR_SUCCESS;
  189. }
  190. }else {
  191. //
  192. // there is no root here: do whatever is necessary to block
  193. // dfsutil from creating an old fashioned root.
  194. //
  195. Status = ERROR_SUCCESS;
  196. }
  197. //
  198. // We are done, close the key we opened.
  199. //
  200. RegCloseKey( OldKey );
  201. }
  202. //
  203. // dfsdev: if we fail, we need to cleanup any of the work we have
  204. // done so far!
  205. //
  206. //
  207. // release any of the resources we had allocated, since we are
  208. // about to return back to the caller.
  209. //
  210. if ( DfsRootShare != NULL ) {
  211. delete [] DfsRootShare;
  212. }
  213. if ( FtDfsValue != NULL ) {
  214. delete [] FtDfsValue;
  215. }
  216. return Status;
  217. }
  218. //+----------------------------------------------------------------------------
  219. //
  220. // Function: MigratefFTDfs
  221. //
  222. // Arguments:
  223. // HKEY DfsKey - The open key to the top of DFS registry hierarchy
  224. // LPWSTR DfsLogicalShare - the logical domain based share.
  225. // LPWSTR DfsRootShare - the share on this machine backing the name
  226. // LPWSTR FtDfsDN - The distinguished name in the AD for the DFS.
  227. //
  228. // Returns: ERROR_SUCCESS
  229. // Error code other wise.
  230. //
  231. // Description: This routine moves the domain based DFS root information
  232. // in the registry under a new key, so that we can support
  233. // multiple roots per machine.
  234. //
  235. //-----------------------------------------------------------------------------
  236. DFSSTATUS
  237. MigrateFTDfs(
  238. LPWSTR MachineName,
  239. HKEY DfsKey,
  240. LPWSTR DfsLogicalShare,
  241. LPWSTR DfsRootShare )
  242. {
  243. DWORD Status;
  244. HKEY NewBlobKey;
  245. //
  246. // We open the ft parent, which holds all the ft roots.
  247. //
  248. DFSLOG("Migrating FT Dfs\n");
  249. Status = DfsStore::GetNewADBlobRegistryKey( MachineName,
  250. TRUE,
  251. NULL,
  252. &NewBlobKey );
  253. if (Status == ERROR_SUCCESS)
  254. {
  255. Status = DfsStore::SetupADBlobRootKeyInformation( NewBlobKey,
  256. DfsLogicalShare,
  257. DfsRootShare );
  258. RegCloseKey( NewBlobKey );
  259. }
  260. //
  261. // dfsdev: if we fail, we need to cleanup any of the work we have
  262. // done so far!
  263. //
  264. if (Status == ERROR_SUCCESS) {
  265. RegDeleteValue( DfsKey,
  266. DfsFtDfsConfigDNValueName);
  267. RegDeleteValue( DfsKey,
  268. DfsFtDfsValueName );
  269. }
  270. DFSLOG("Migrating FT Dfs: Status %x\n", Status);
  271. return Status;
  272. }
  273. //+----------------------------------------------------------------------------
  274. //
  275. // Function: MigratefStdDfs
  276. //
  277. // Arguments:
  278. // HKEY DfsKey - The open key to the top of DFS registry hierarchy
  279. // LPWSTR DfsLogicalShare - the logical dfs share.
  280. // LPWSTR DfsRootShare - the share on this machine backing the name
  281. //
  282. // Returns: ERROR_SUCCESS
  283. // Error code other wise.
  284. //
  285. // Description: This routine moves the registry based DFS root information
  286. // in the registry under a new key, so that we can support
  287. // multiple roots per machine.
  288. //
  289. //-----------------------------------------------------------------------------
  290. DFSSTATUS
  291. MigrateStdDfs(
  292. LPWSTR MachineName,
  293. HKEY DfsKey,
  294. LPWSTR DfsLogicalShare,
  295. LPWSTR DfsRootShare,
  296. BOOLEAN fDoCleanup)
  297. {
  298. DWORD Status = ERROR_SUCCESS;
  299. HKEY StdDfsKey = NULL;
  300. HKEY StdDfsShareKey = NULL;
  301. ULONG RootShareValue = 1;
  302. size_t LogicalShareCchLength = 0;
  303. size_t PhysicalShareCchLength = 0;
  304. DFSLOG("Migrating Std Dfs\n");
  305. //
  306. // Open the new standalone DFS parent, which holds all the
  307. // standalone roots and their metadata as its children.
  308. //
  309. Status = DfsStore::GetNewStandaloneRegistryKey( MachineName,
  310. TRUE,
  311. NULL,
  312. &StdDfsKey );
  313. //
  314. // We now create an unique metadata name for our root, and add
  315. // it as a child to the parent key we created.
  316. //
  317. if (Status == ERROR_SUCCESS) {
  318. Status = RegCreateKeyEx( StdDfsKey,
  319. DfsLogicalShare,
  320. 0,
  321. L"",
  322. REG_OPTION_NON_VOLATILE,
  323. KEY_READ | KEY_WRITE,
  324. NULL,
  325. &StdDfsShareKey,
  326. NULL );
  327. //
  328. // We have successfully created the child root. Now, just copy
  329. // all the link information under the old root key to the new
  330. // root key. If we successfully copy, we can delete the old
  331. // standalone root and all its children.
  332. //
  333. if (Status == ERROR_SUCCESS) {
  334. Status = SHCopyKey( DfsKey,
  335. DfsOldStandaloneChild,
  336. StdDfsShareKey,
  337. NULL );
  338. if (Status == ERROR_SUCCESS)
  339. {
  340. if(fDoCleanup)
  341. {
  342. Status = SHDeleteKey( DfsKey,
  343. DfsOldStandaloneChild );
  344. }
  345. }
  346. //
  347. // Now setup the values for the new root so that we know
  348. // the shares that are backing this new root.
  349. //
  350. if (Status == ERROR_SUCCESS) {
  351. Status = DfsStringCchLength( DfsRootShare,
  352. MAXUSHORT,
  353. &PhysicalShareCchLength );
  354. if (Status == ERROR_SUCCESS)
  355. {
  356. // Allow an extra character for NULL terminator.
  357. PhysicalShareCchLength++;
  358. Status = RegSetValueEx( StdDfsShareKey,
  359. DfsRootShareValueName,
  360. 0,
  361. REG_SZ,
  362. (PBYTE)DfsRootShare,
  363. PhysicalShareCchLength * sizeof(WCHAR) );
  364. }
  365. }
  366. if (Status == ERROR_SUCCESS) {
  367. Status = DfsStringCchLength( DfsRootShare,
  368. MAXUSHORT,
  369. &LogicalShareCchLength );
  370. if (Status == ERROR_SUCCESS)
  371. {
  372. // Allow an extra character for NULL terminator.
  373. LogicalShareCchLength++;
  374. Status = RegSetValueEx( StdDfsShareKey,
  375. DfsLogicalShareValueName,
  376. 0,
  377. REG_SZ,
  378. (PBYTE)DfsLogicalShare,
  379. LogicalShareCchLength * sizeof(WCHAR) );
  380. }
  381. }
  382. RegCloseKey( StdDfsShareKey );
  383. }
  384. RegCloseKey( StdDfsKey );
  385. }
  386. DFSLOG("Migrating Std Dfs: Status %x\n", Status);
  387. return Status;
  388. }