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.

577 lines
18 KiB

  1. extern "C" {
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <stddef.h>
  9. #include <shellapi.h>
  10. }
  11. #include <ole2.h>
  12. #include <activeds.h>
  13. #include <dfsprefix.h>
  14. #include <DfsServerLibrary.hxx>
  15. #include <DfsRegStrings.hxx>
  16. #include <dfsutil.hxx>
  17. #include <dfsmisc.h>
  18. #include <dfspathname.hxx>
  19. #include <struct.hxx>
  20. LPWSTR UtilRegistryHostLocation = DFS_REG_HOST_LOCATION;
  21. LPWSTR UtilVolumesLocation = DFS_REG_VOLUMES_LOCATION;
  22. LPWSTR UtilFtDfsConfigDNValueName = DFS_REG_FT_DFS_CONFIG_DN_VALUE;
  23. LPWSTR DfsHostLastDomainValueName = DFS_REG_HOST_LAST_DOMAIN_VALUE;
  24. LPWSTR DfsDriverLocalVolumesLocation = DFS_REG_LOCAL_VOLUMES_LOCATION;
  25. LPWSTR DfsDriverLocalVolumesEntryPath = DFS_REG_ENTRY_PATH;
  26. LPWSTR DfsDriverLocalVolumesShortEntryPath = DFS_REG_SHORT_ENTRY_PATH;
  27. DFSSTATUS
  28. DfsFixupRegistryValues(
  29. IN LPWSTR DfsPathString,
  30. IN LPWSTR RootName,
  31. IN LPWSTR OldDomainName,
  32. IN LPWSTR NewDomainName);
  33. DFSSTATUS
  34. DfsRenameRegistries(
  35. IN DfsPathName *pPathName,
  36. IN LPWSTR OldDomainName,
  37. IN LPWSTR NewDomainName);
  38. DFSSTATUS
  39. GetCurrentRegDomainName(
  40. IN HKEY VolumeKey,
  41. IN LPWSTR DfsHostValueName,
  42. OUT LPWSTR *pValueString);
  43. DFSSTATUS
  44. DfsSetRegDomainName(
  45. IN const HKEY DfsKey,
  46. IN const LPWSTR RegValueName,
  47. IN const LPWSTR DomainString);
  48. BOOLEAN
  49. DfsRenameFTConfigValueName(
  50. IN LPWSTR DNString,
  51. IN LPWSTR NewDomainString,
  52. IN PUNICODE_STRING OldDomain,
  53. OUT LPWSTR *NewDNString);
  54. DFSSTATUS
  55. GetRegVolumesHKey(
  56. IN LPWSTR MachineName,
  57. OUT HKEY *VolumeKey);
  58. DFSSTATUS
  59. GetRegLocalVolumesHKey(
  60. IN LPWSTR MachineName,
  61. OUT HKEY *LocalVolumeKey);
  62. //
  63. // DfsRenameRegistries
  64. //
  65. // This contacts all root targets affected by the rename
  66. // operation to possibly change their registry references
  67. // to the obsolete domain name.
  68. //
  69. DFSSTATUS
  70. DfsRenameRegistries(
  71. IN DfsPathName *pPathName,
  72. IN LPWSTR OldDomainName,
  73. IN LPWSTR NewDomainName)
  74. {
  75. DFSSTATUS Status;
  76. LPBYTE pBuffer = NULL;
  77. DWORD ResumeHandle = 0;
  78. DWORD EntriesRead = 0;
  79. DWORD PrefMaxLen = 1;
  80. DWORD Level = 4;
  81. PDFS_INFO_4 pCurrentBuffer;
  82. DWORD i;
  83. PDFS_STORAGE_INFO pStorage;
  84. //
  85. // We are reading in just the ROOT.
  86. // supw: DfsGetInfo is a better way to do this.
  87. //
  88. Status = DfsApiEnumerate( MODE_DIRECT,
  89. pPathName->GetPathString(),
  90. Level,
  91. PrefMaxLen,
  92. &pBuffer,
  93. &EntriesRead,
  94. &ResumeHandle);
  95. if ((Status == ERROR_SUCCESS) && EntriesRead != 0)
  96. {
  97. pCurrentBuffer = (PDFS_INFO_4)pBuffer;
  98. for( i = 0, pStorage = pCurrentBuffer->Storage;
  99. i < pCurrentBuffer->NumberOfStorages;
  100. i++, pStorage = pCurrentBuffer->Storage + i )
  101. {
  102. DebugInformation((L"DfsUtil: RenameRegistries: TARGET SERVER \\\\%ws\\%ws\n",
  103. pStorage->ServerName, pStorage->ShareName));
  104. //
  105. // Now contact the appropriate server(s) for the root replicas
  106. // and fix up their registry values if they happen to still
  107. // point back at the obsolete domain name. Only the pre-Whistler
  108. // servers do that currently.
  109. // Errors are ignored entirely. The target server may or may not be a
  110. // W2K machine.
  111. //
  112. // xxx supw: skip duplicate servernames here.
  113. (VOID)DfsFixupRegistryValues(pStorage->ServerName,
  114. pPathName->GetShareString(),
  115. OldDomainName,
  116. NewDomainName);
  117. //
  118. // Don't bother to resynchrnoize. W2K systems don't respond to RESYNCHRONIZE calls.
  119. // Besides, the administrator is supposed to reboot all root servers.
  120. //
  121. // (VOID)SetInfoReSynchronize( pStorage->ServerName, pStorage->ShareName );
  122. }
  123. //
  124. // Free the allocated memory.
  125. //
  126. DfsFreeApiBuffer(pBuffer);
  127. }
  128. return Status;
  129. }
  130. DFSSTATUS
  131. DfsFixupRegistryValues(
  132. IN LPWSTR MachineName,
  133. IN LPWSTR RootName,
  134. IN LPWSTR OldDomainName,
  135. IN LPWSTR NewDomainName)
  136. {
  137. HKEY VolumeKey, LocalVolKey;
  138. LPWSTR DNString = NULL;
  139. LPWSTR EntryString = NULL;
  140. DFSSTATUS Status;
  141. DFSSTATUS RetStatus = ERROR_SUCCESS;
  142. UNICODE_STRING OldDomUnicode;
  143. UNICODE_STRING DomUnicode;
  144. BOOLEAN Changed = FALSE;
  145. Status = GetRegVolumesHKey( MachineName, &VolumeKey );
  146. if (Status != ERROR_SUCCESS)
  147. {
  148. if (fSwDebug) {
  149. DebugInformation((L"DfsUtil: RegOpen of DfsHost Volumes failed for machine %ws, with error 0x%x\n",
  150. MachineName, Status));
  151. }
  152. //
  153. // Only return fatal conditions that'll prompt us to abort.
  154. //
  155. return RetStatus;
  156. }
  157. RtlInitUnicodeString( &OldDomUnicode, OldDomainName );
  158. //
  159. // The \DfsHost\volumes\FTDfsObjectDN may need fixing.
  160. //
  161. Status = GetCurrentRegDomainName( VolumeKey,
  162. UtilFtDfsConfigDNValueName,
  163. &DNString);
  164. if (Status == ERROR_SUCCESS)
  165. {
  166. LPWSTR NewDNString;
  167. //
  168. // The DNString is of the form "CN=,CN=,...DC=DomainName,DC=..."
  169. // See if the substring DC=DomainName matches the OldDomainName.
  170. // If so substitute it with the NewDomainName and get a new DN string.
  171. //
  172. //if (DfsRenameFTConfigValueName( DNString, NewDomainName, &OldDomUnicode, &NewDNString ))
  173. //
  174. // Simply replace the existing string with a new DN string we generate.
  175. // This assumes that the system has already rebooted since the DC was renamed.
  176. //
  177. {
  178. Status = DfsGenerateDNPathString( RootName, &NewDNString );
  179. if (Status == ERROR_SUCCESS)
  180. {
  181. Status = DfsSetRegDomainName( VolumeKey, UtilFtDfsConfigDNValueName, NewDNString );
  182. if (Status == ERROR_SUCCESS)
  183. {
  184. Changed = TRUE;
  185. DebugInformation((L"FTDfsObjectDN = %ws\n", NewDNString));
  186. }
  187. DfsDeleteDNPathString( NewDNString );
  188. }
  189. }
  190. delete [] DNString;
  191. }
  192. //
  193. // The \DfsHost\volumes\LastDomainName shouldn't mention the old domain name.
  194. //
  195. if (Status == ERROR_SUCCESS)
  196. {
  197. Status = GetCurrentRegDomainName( VolumeKey,
  198. DfsHostLastDomainValueName,
  199. &DNString );
  200. if (Status == ERROR_SUCCESS)
  201. {
  202. RtlInitUnicodeString( &DomUnicode, DNString );
  203. if (RtlEqualDomainName( &DomUnicode, &OldDomUnicode ))
  204. {
  205. //
  206. // Go ahead and make the substitution in the registry.
  207. //
  208. Status = DfsSetRegDomainName( VolumeKey,
  209. DfsHostLastDomainValueName,
  210. NewDomainName );
  211. if (Status == ERROR_SUCCESS)
  212. {
  213. Changed = TRUE;
  214. DebugInformation((L"DfsUtil: Rename of LastDomainName RegKey to %ws successful\n",
  215. NewDomainName));
  216. }
  217. }
  218. delete [] DNString;
  219. }
  220. }
  221. RegCloseKey( VolumeKey );
  222. Status = GetRegLocalVolumesHKey( MachineName, &LocalVolKey );
  223. if (Status != ERROR_SUCCESS)
  224. {
  225. if (fSwDebug) {
  226. DebugInformation((L"DfsUtil: RegOpen of Services\\DfsDriver\\LocalVolume failed for machine %ws, with error 0x%x\n",
  227. MachineName, Status));
  228. }
  229. //
  230. // Only return fatal conditions that'll prompt us to abort.
  231. //
  232. return RetStatus;
  233. }
  234. //
  235. // The HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DfsDriver\LocalVolume
  236. // shouldn't mention the old domain name.
  237. //
  238. Status = GetCurrentRegDomainName( LocalVolKey,
  239. DfsDriverLocalVolumesEntryPath,
  240. &EntryString );
  241. if (Status == ERROR_SUCCESS)
  242. {
  243. DfsPathName EntryPath;
  244. Status = EntryPath.CreatePathName(EntryString );
  245. if (Status == ERROR_SUCCESS)
  246. {
  247. if (RtlEqualDomainName( EntryPath.GetServerCountedString(), &OldDomUnicode ))
  248. {
  249. DfsPathName NewEntryPath;
  250. //
  251. // Go ahead and make the substitution in the registry.
  252. // But first recreate the EntryPath using the new domain name.
  253. //
  254. NewEntryPath.SetPathName( NewDomainName,
  255. EntryPath.GetShareString(),
  256. 1);
  257. Status = DfsSetRegDomainName( LocalVolKey,
  258. DfsDriverLocalVolumesEntryPath,
  259. NewEntryPath.GetPathString() );
  260. if (Status == ERROR_SUCCESS)
  261. {
  262. Changed = TRUE;
  263. DebugInformation((L"DfsUtil: Rename of EntryPath RegKey from %ws to %ws successful\n",
  264. EntryPath.GetPathString(), NewEntryPath.GetPathString()));
  265. }
  266. }
  267. }
  268. delete [] EntryString;
  269. }
  270. Status = GetCurrentRegDomainName( LocalVolKey,
  271. DfsDriverLocalVolumesShortEntryPath,
  272. &EntryString );
  273. if (Status == ERROR_SUCCESS)
  274. {
  275. DfsPathName ShortEntryPath;
  276. Status = ShortEntryPath.CreatePathName(EntryString );
  277. if (Status == ERROR_SUCCESS)
  278. {
  279. if (RtlEqualDomainName( ShortEntryPath.GetServerCountedString(), &OldDomUnicode ))
  280. {
  281. //
  282. // Go ahead and make the substitution in the registry.
  283. // But first recreate the EntryPath using the new domain name.
  284. //
  285. DfsPathName NewEntryPath;
  286. //
  287. // Go ahead and make the substitution in the registry.
  288. // But first recreate the EntryPath using the new domain name.
  289. //
  290. NewEntryPath.SetPathName( NewDomainName,
  291. ShortEntryPath.GetShareString(),
  292. 1 );
  293. Status = DfsSetRegDomainName( LocalVolKey,
  294. DfsDriverLocalVolumesShortEntryPath,
  295. NewEntryPath.GetPathString() );
  296. if (Status == ERROR_SUCCESS)
  297. {
  298. Changed = TRUE;
  299. DebugInformation((L"DfsUtil: Rename of ShortEntryPath RegKey From %ws to %ws successful\n",
  300. ShortEntryPath.GetPathString(),
  301. NewEntryPath.GetPathString()));
  302. }
  303. }
  304. }
  305. delete [] EntryString;
  306. }
  307. RegCloseKey( LocalVolKey );
  308. if (Changed) {
  309. DebugInformation((L"DfsUtil: Renamed registry references in root target system %wS\n", MachineName));
  310. }
  311. return RetStatus;
  312. }
  313. DFSSTATUS
  314. GetCurrentRegDomainName(
  315. IN HKEY VolumeKey,
  316. IN LPWSTR DfsHostValueName,
  317. OUT LPWSTR *pValueString)
  318. {
  319. LPWSTR FtDfsValue = NULL;
  320. ULONG DataSize, DataType;
  321. ULONG FtDfsValueSize;
  322. DWORD Status;
  323. *pValueString = NULL;
  324. //
  325. // If we opened the DFS hierarchy key properly, get the maximum
  326. // size of any of the values under this key. This is so that we
  327. // know how much memory to allocate, so that we can read any of
  328. // the values we desire.
  329. //
  330. //
  331. Status = RegQueryInfoKey( VolumeKey, // Key
  332. NULL, // Class string
  333. NULL, // Size of class string
  334. NULL, // Reserved
  335. NULL, // # of subkeys
  336. NULL, // max size of subkey name
  337. NULL, // max size of class name
  338. NULL, // # of values
  339. NULL, // max size of value name
  340. &DataSize, // max size of value data,
  341. NULL, // security descriptor
  342. NULL ); // Last write time
  343. //
  344. // check if the value is a string.
  345. //
  346. if (Status == ERROR_SUCCESS)
  347. {
  348. FtDfsValueSize = DataSize;
  349. FtDfsValue = (LPWSTR) new BYTE[DataSize];
  350. if (FtDfsValue == NULL) {
  351. Status = ERROR_NOT_ENOUGH_MEMORY;
  352. }
  353. else {
  354. //
  355. // Now check if this is a Domain Based root.
  356. //
  357. Status = RegQueryValueEx( VolumeKey,
  358. DfsHostValueName,
  359. NULL,
  360. &DataType,
  361. (LPBYTE)FtDfsValue,
  362. &FtDfsValueSize);
  363. if (Status == ERROR_SUCCESS) {
  364. *pValueString = FtDfsValue;
  365. } else {
  366. delete [] FtDfsValue;
  367. }
  368. }
  369. }
  370. return Status;
  371. }
  372. DFSSTATUS
  373. DfsSetRegDomainName(
  374. IN const HKEY DfsKey,
  375. IN const LPWSTR RegValueName,
  376. IN const LPWSTR DomainString)
  377. {
  378. DFSSTATUS Status;
  379. Status = RegSetValueEx( DfsKey,
  380. RegValueName,
  381. 0,
  382. REG_SZ,
  383. (PBYTE)DomainString,
  384. wcslen(DomainString) * sizeof(WCHAR) );
  385. return Status;
  386. }
  387. DFSSTATUS
  388. GetRegVolumesHKey(
  389. IN LPWSTR MachineName,
  390. OUT HKEY *VolumeKey)
  391. {
  392. DFSSTATUS Status;
  393. HKEY RootKey;
  394. HKEY HostKey;
  395. Status = RegConnectRegistry( MachineName,
  396. HKEY_LOCAL_MACHINE,
  397. &RootKey );
  398. if ( Status != ERROR_SUCCESS )
  399. {
  400. return Status;
  401. }
  402. Status = RegOpenKeyEx( RootKey,
  403. UtilRegistryHostLocation,
  404. 0,
  405. KEY_READ|KEY_WRITE,
  406. &HostKey );
  407. if (RootKey != HKEY_LOCAL_MACHINE)
  408. {
  409. RegCloseKey( RootKey );
  410. }
  411. if (Status == ERROR_SUCCESS)
  412. {
  413. Status = RegOpenKeyEx( HostKey,
  414. UtilVolumesLocation,
  415. 0,
  416. KEY_READ|KEY_WRITE,
  417. VolumeKey );
  418. RegCloseKey( HostKey );
  419. }
  420. return Status;
  421. }
  422. DFSSTATUS
  423. GetRegLocalVolumesHKey(
  424. IN LPWSTR MachineName,
  425. OUT HKEY *LocalVolumeKey)
  426. {
  427. DFSSTATUS Status;
  428. HKEY RootKey;
  429. HKEY LocalParentKey;
  430. Status = RegConnectRegistry( MachineName,
  431. HKEY_LOCAL_MACHINE,
  432. &RootKey );
  433. if ( Status != ERROR_SUCCESS )
  434. {
  435. return Status;
  436. }
  437. Status = RegOpenKeyEx( RootKey,
  438. DfsDriverLocalVolumesLocation,
  439. 0,
  440. KEY_READ|KEY_WRITE,
  441. &LocalParentKey );
  442. if (RootKey != HKEY_LOCAL_MACHINE)
  443. {
  444. RegCloseKey( RootKey );
  445. }
  446. //
  447. // We know for a fact that the old W2K servers can
  448. // host only one root. Therefore, there can only be one
  449. // child here.
  450. //
  451. if (Status == ERROR_SUCCESS) {
  452. DWORD ChildNameLen = MAX_PATH;
  453. WCHAR ChildName[MAX_PATH];
  454. Status = RegEnumKeyEx( LocalParentKey,
  455. 0,
  456. ChildName,
  457. &ChildNameLen,
  458. NULL,
  459. NULL,
  460. NULL,
  461. NULL );
  462. if ( Status == ERROR_SUCCESS )
  463. {
  464. //
  465. // We have the name of a child, so open the key to
  466. // that root.
  467. //
  468. Status = RegOpenKeyEx( LocalParentKey,
  469. ChildName,
  470. 0,
  471. KEY_READ|KEY_WRITE,
  472. LocalVolumeKey );
  473. }
  474. RegCloseKey( LocalParentKey );
  475. }
  476. return Status;
  477. }
  478. DFSSTATUS
  479. DfsRenameLinksToDomain(
  480. IN DfsPathName *pDfsPath,
  481. IN LPWSTR OldDomainName,
  482. IN LPWSTR NewDomainName)
  483. {
  484. DFSSTATUS Status;
  485. DebugInformation((L"DfsUtil: Starting renaming links from %ws to %ws in ROOT %ws\n",
  486. OldDomainName, NewDomainName, pDfsPath->GetPathString()));
  487. Status = DfsRenameLinks( pDfsPath->GetPathString(), OldDomainName, NewDomainName );
  488. if (Status == ERROR_SUCCESS)
  489. {
  490. (VOID)DfsRenameRegistries( pDfsPath, OldDomainName, NewDomainName );
  491. CommandSucceeded = TRUE;
  492. }
  493. return Status;
  494. }