Source code of Windows XP (NT5)
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.

1156 lines
30 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: moveme.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 5-21-97 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "moveme.h"
  18. #include "dialogs.h"
  19. #include <stdlib.h>
  20. #define APPNAME TEXT("fail")
  21. #define FILENAME TEXT("moveme.ini")
  22. ULONG MoveOptions = MOVE_UPDATE_SECURITY | MOVE_DO_PROFILE ;
  23. WCHAR MachDomain[ DNLEN * 2 ];
  24. WCHAR SourceDomain[ DNLEN * 2 ];
  25. WCHAR DestDomain[ DNLEN * 2 ];
  26. WCHAR UserName[ UNLEN * 2 ];
  27. PSID OldSid ;
  28. PSID NewSid ;
  29. HICON MyIcon ;
  30. PDOMAIN_CONTROLLER_INFO DcInfo ;
  31. PDOMAIN_CONTROLLER_INFO DestDcInfo ;
  32. OSVERSIONINFOEX VersionInfo ;
  33. DWORD ProfileSection[] = { IDD_RADIO_MAKECOPY, IDD_RADIO_REFER_TO_SAME, IDD_RADIO_MAKE_ROAM };
  34. VOID
  35. EnableSection(
  36. HWND hDlg,
  37. BOOL Enable,
  38. PDWORD IdList,
  39. DWORD Count
  40. )
  41. {
  42. DWORD i ;
  43. for ( i = 0 ; i < Count ; i++ )
  44. {
  45. EnableWindow( GetDlgItem( hDlg, IdList[ i ]), Enable );
  46. }
  47. }
  48. VOID
  49. DumpState(
  50. VOID
  51. )
  52. {
  53. UNICODE_STRING Sid ;
  54. WCHAR PrivateInt[ 16 ];
  55. swprintf( PrivateInt, L"%d", VersionInfo.dwBuildNumber );
  56. WritePrivateProfileString( APPNAME, TEXT("Build"), PrivateInt, FILENAME );
  57. WritePrivateProfileString( APPNAME, TEXT("MachDomain"), MachDomain, FILENAME);
  58. WritePrivateProfileString( APPNAME, TEXT("SourceDomain"), SourceDomain, FILENAME );
  59. WritePrivateProfileString( APPNAME, TEXT("DestDomain"), DestDomain, FILENAME );
  60. WritePrivateProfileString( APPNAME, TEXT("UserName"), UserName, FILENAME );
  61. if ( DcInfo )
  62. {
  63. WritePrivateProfileString( APPNAME, TEXT("DcInfo.name"), DcInfo->DomainControllerName, FILENAME);
  64. WritePrivateProfileString( APPNAME, TEXT("DcInfo.address"), DcInfo->DomainControllerAddress, FILENAME );
  65. WritePrivateProfileString( APPNAME, TEXT("DcInfo.domainname"), DcInfo->DomainName, FILENAME );
  66. WritePrivateProfileString( APPNAME, TEXT("DcInfo.treename"), DcInfo->DnsForestName, FILENAME );
  67. WritePrivateProfileString( APPNAME, TEXT("DcInfo.dcsite"), DcInfo->DcSiteName, FILENAME );
  68. WritePrivateProfileString( APPNAME, TEXT("DcInfo.clientsite"), DcInfo->ClientSiteName, FILENAME );
  69. //WritePrivateProfileInt( APPNAME, TEXT("DcInfo.Flags"), DcInfo->Flags, FILENAME );
  70. }
  71. if ( DestDcInfo )
  72. {
  73. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.name"), DestDcInfo->DomainControllerName, FILENAME);
  74. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.address"), DestDcInfo->DomainControllerAddress, FILENAME );
  75. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.domainname"), DestDcInfo->DomainName, FILENAME );
  76. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.treename"), DestDcInfo->DnsForestName, FILENAME );
  77. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.dcsite"), DestDcInfo->DcSiteName, FILENAME );
  78. WritePrivateProfileString( APPNAME, TEXT("DestDcInfo.clientsite"), DestDcInfo->ClientSiteName, FILENAME );
  79. }
  80. if ( OldSid )
  81. {
  82. RtlConvertSidToUnicodeString( &Sid, OldSid, TRUE );
  83. WritePrivateProfileString( APPNAME, TEXT("OldSid"), Sid.Buffer, FILENAME );
  84. RtlFreeUnicodeString( &Sid );
  85. }
  86. else
  87. {
  88. WritePrivateProfileString( APPNAME, TEXT("OldSid"), TEXT("<none>"), FILENAME );
  89. }
  90. if ( NewSid )
  91. {
  92. RtlConvertSidToUnicodeString( &Sid, NewSid, TRUE );
  93. WritePrivateProfileString( APPNAME, TEXT("NewSid"), Sid.Buffer, FILENAME );
  94. RtlFreeUnicodeString( &Sid );
  95. }
  96. else
  97. {
  98. WritePrivateProfileString( APPNAME, TEXT("NewSid"), TEXT("<none>"), FILENAME );
  99. }
  100. }
  101. VOID
  102. Fail(
  103. HWND hWnd,
  104. PWSTR Failure,
  105. PWSTR Description,
  106. DWORD Code,
  107. PWSTR Message
  108. )
  109. {
  110. UNICODE_STRING Sid ;
  111. WCHAR Msg[MAX_PATH];
  112. WCHAR foo[MAX_PATH];
  113. UpdateUi(0,100);
  114. StopUiThread();
  115. DumpState();
  116. WritePrivateProfileString( APPNAME, TEXT("Failure"), Failure, FILENAME );
  117. WritePrivateProfileString( APPNAME, TEXT("Desc"), Description, FILENAME );
  118. wsprintf( Msg, L"%d (%#x)", Code, Code );
  119. WritePrivateProfileString( APPNAME, TEXT("Code"), Msg, FILENAME );
  120. ExpandEnvironmentStrings( TEXT("%windir%"), foo, MAX_PATH );
  121. _snwprintf( Msg, MAX_PATH, TEXT("%ws Please mail the file %ws in %ws to 'ntdsbug'"),
  122. Message ? Message : TEXT("An unrecoverable error occurred, and has prevented you from joining the NTDEV rollout."),
  123. FILENAME, foo );
  124. MessageBox( hWnd, Msg, TEXT("Error"), MB_ICONSTOP | MB_OK );
  125. ExitProcess( GetLastError() );
  126. }
  127. PSECURITY_DESCRIPTOR
  128. MakeUserSD(
  129. PSID UserSid,
  130. ACCESS_MASK Mask
  131. )
  132. {
  133. PSECURITY_DESCRIPTOR psd ;
  134. PACL Dacl ;
  135. DWORD DaclLen ;
  136. PACCESS_ALLOWED_ACE Ace ;
  137. PSID LocalSystem ;
  138. SID_IDENTIFIER_AUTHORITY NtAuth = SECURITY_NT_AUTHORITY ;
  139. AllocateAndInitializeSid( &NtAuth, 1,
  140. SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
  141. &LocalSystem );
  142. psd = LocalAlloc( LMEM_FIXED, sizeof( SECURITY_DESCRIPTOR ) );
  143. DaclLen = (sizeof( ACCESS_ALLOWED_ACE ) + RtlLengthSid( UserSid )) * 2 ;
  144. Dacl = LocalAlloc( LMEM_FIXED, DaclLen );
  145. if ( !psd || !Dacl)
  146. {
  147. return NULL ;
  148. }
  149. InitializeSecurityDescriptor( psd, SECURITY_DESCRIPTOR_REVISION );
  150. InitializeAcl( Dacl, DaclLen, ACL_REVISION );
  151. SetSecurityDescriptorDacl( psd, TRUE, Dacl, FALSE );
  152. AddAccessAllowedAce( Dacl, ACL_REVISION, Mask, UserSid );
  153. GetAce( Dacl, 0, &Ace );
  154. Ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE ;
  155. AddAccessAllowedAce( Dacl, ACL_REVISION, Mask, LocalSystem );
  156. GetAce( Dacl, 1, &Ace );
  157. Ace->Header.AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE ;
  158. return psd ;
  159. }
  160. RecurseWhackKey(
  161. HKEY ParentKey,
  162. PWSTR SubKey,
  163. PSECURITY_DESCRIPTOR psd
  164. )
  165. {
  166. HKEY Key ;
  167. int err ;
  168. NTSTATUS Status ;
  169. WCHAR SubKeys[ 128 ];
  170. DWORD dwSize ;
  171. DWORD dwIndex ;
  172. FILETIME ftTime ;
  173. err = RegOpenKeyEx(
  174. ParentKey,
  175. SubKey,
  176. 0,
  177. WRITE_DAC | WRITE_OWNER,
  178. &Key );
  179. if ( err == 0 )
  180. {
  181. Status = NtSetSecurityObject( Key,
  182. OWNER_SECURITY_INFORMATION |
  183. DACL_SECURITY_INFORMATION,
  184. psd );
  185. if ( NT_SUCCESS( Status ) )
  186. {
  187. RegCloseKey( Key );
  188. err = RegOpenKeyEx(
  189. ParentKey,
  190. SubKey,
  191. 0,
  192. KEY_READ | KEY_WRITE,
  193. &Key );
  194. if ( err )
  195. {
  196. return err;
  197. }
  198. dwIndex = 0 ;
  199. dwSize = sizeof( SubKeys ) / sizeof( WCHAR );
  200. while ( RegEnumKeyEx( Key,
  201. dwIndex,
  202. SubKeys,
  203. &dwSize,
  204. NULL,
  205. NULL,
  206. NULL,
  207. &ftTime ) == ERROR_SUCCESS )
  208. {
  209. RecurseWhackKey( Key, SubKeys, psd );
  210. dwIndex++ ;
  211. dwSize = sizeof( SubKeys ) / sizeof( WCHAR );
  212. }
  213. }
  214. RegCloseKey( Key );
  215. }
  216. return err ;
  217. }
  218. VOID
  219. DealWithPstore(
  220. PSID UserSid
  221. )
  222. {
  223. HKEY hKey = NULL;
  224. int err ;
  225. BOOLEAN WasEnabled ;
  226. NTSTATUS Status ;
  227. PSECURITY_DESCRIPTOR psd ;
  228. Status = RtlAdjustPrivilege( SE_TAKE_OWNERSHIP_PRIVILEGE, TRUE, FALSE, &WasEnabled );
  229. if ( !NT_SUCCESS( Status ))
  230. {
  231. return ;
  232. }
  233. err = RegOpenKeyEx(
  234. HKEY_CURRENT_USER,
  235. TEXT("Software\\Microsoft"),
  236. 0,
  237. KEY_READ | KEY_WRITE,
  238. &hKey );
  239. if( err != 0 )
  240. {
  241. return ;
  242. }
  243. psd = MakeUserSD( UserSid, KEY_ALL_ACCESS );
  244. SetSecurityDescriptorOwner( psd, UserSid, FALSE );
  245. RecurseWhackKey( hKey, TEXT("Protected Storage System Provider"), psd );
  246. }
  247. BOOL
  248. MoveMe(
  249. HWND hWnd,
  250. LPWSTR OldProfile,
  251. LPWSTR NewProfile
  252. )
  253. {
  254. HKEY hKeyCU ;
  255. int err ;
  256. WCHAR TempPath[ MAX_PATH ];
  257. WCHAR TempFile[ MAX_PATH ];
  258. WCHAR TempPath2[ MAX_PATH ];
  259. HANDLE Token ;
  260. DWORD PathLength ;
  261. BOOL Ret ;
  262. WCHAR UserNameEx[ 64 ];
  263. DWORD Index = 0 ;
  264. SECURITY_ATTRIBUTES sa ;
  265. if ( MoveOptions & MOVE_MAKE_ROAM )
  266. {
  267. GetTempPath( MAX_PATH, TempPath );
  268. GetTempFileName( TempPath, TEXT("prf"), GetTickCount() & 0xFFFF, TempFile );
  269. UpdateUi( IDS_COPYING_USER_HIVE, 30 );
  270. err = MyRegSaveKey( HKEY_CURRENT_USER,
  271. TempFile,
  272. NULL );
  273. if ( err )
  274. {
  275. Fail( hWnd, TEXT("Save HKCU failed"), TEXT(""), err, NULL);
  276. return err ;
  277. }
  278. if (OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token ))
  279. {
  280. PathLength = MAX_PATH ;
  281. if (!GetUserProfileDirectory( Token, TempPath, &PathLength ))
  282. {
  283. Fail( hWnd, TEXT("Can't get current profile dir"), TEXT(""),
  284. GetLastError(), NULL );
  285. }
  286. }
  287. else
  288. {
  289. Fail( hWnd, TEXT("Can't open process token?"), TEXT(""), GetLastError(), NULL );
  290. }
  291. UpdateUi( IDS_CREATING_NEW_PROFILE, 60 );
  292. Index = 64 ;
  293. GetUserName( UserNameEx, &Index );
  294. swprintf( TempPath2, TEXT("\\\\scratch\\scratch\\%ws\\Profile"), UserNameEx );
  295. sa.nLength = sizeof( sa );
  296. sa.bInheritHandle = FALSE ;
  297. sa.lpSecurityDescriptor = MakeUserSD( NewSid, FILE_ALL_ACCESS );
  298. if ( CreateDirectory( TempPath2, NULL ) )
  299. {
  300. UpdateUi( IDS_CREATING_NEW_PROFILE, 70 );
  301. if ( ! CopyProfileDirectory( TempPath,
  302. TempPath2,
  303. CPD_FORCECOPY |
  304. CPD_IGNORECOPYERRORS |
  305. CPD_IGNOREHIVE |
  306. CPD_SHOWSTATUS ) )
  307. {
  308. if ( GetLastError() == 997 )
  309. {
  310. //
  311. // Looks like the dreaded pstore key problem. Sigh.
  312. //
  313. DealWithPstore( NewSid );
  314. if ( ! CopyProfileDirectory( TempPath,
  315. TempPath2,
  316. CPD_FORCECOPY |
  317. CPD_IGNORECOPYERRORS |
  318. CPD_IGNOREHIVE |
  319. CPD_SHOWSTATUS ) )
  320. {
  321. //
  322. // Terminal, now bail:
  323. //
  324. Fail( hWnd, TEXT("Can't copy profile dir, even after whacking pstore key"), TempPath2, GetLastError(), NULL );
  325. return GetLastError() ;
  326. }
  327. }
  328. else
  329. {
  330. Fail( hWnd, TEXT("Can't copy profile directory"), TempPath2, GetLastError(), NULL );
  331. return GetLastError() ;
  332. }
  333. }
  334. }
  335. else
  336. {
  337. Fail( hWnd, TEXT("Can't create new directory"), TempPath2, GetLastError(), NULL );
  338. return GetLastError() ;
  339. }
  340. wcscat( TempPath2, TEXT("\\ntuser.dat") );
  341. if ( ! CopyFile( TempFile, TempPath2, FALSE ) )
  342. {
  343. Fail( hWnd, TEXT("Can't copy hive"), TempPath2, GetLastError(), NULL );
  344. }
  345. DeleteFile( TempFile );
  346. return GetLastError() ;
  347. }
  348. if ( MoveOptions & MOVE_COPY_PROFILE )
  349. {
  350. GetTempPath( MAX_PATH, TempPath );
  351. GetTempFileName( TempPath, TEXT("prf"), GetTickCount() & 0xFFFF, TempFile );
  352. UpdateUi( IDS_COPYING_USER_HIVE, 30 );
  353. err = MyRegSaveKey( HKEY_CURRENT_USER,
  354. TempFile,
  355. NULL );
  356. if ( err )
  357. {
  358. Fail( hWnd, TEXT("Save HKCU failed"), TEXT(""), err, NULL);
  359. return err ;
  360. }
  361. if (OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &Token ))
  362. {
  363. PathLength = MAX_PATH ;
  364. if (!GetUserProfileDirectory( Token, TempPath, &PathLength ))
  365. {
  366. Fail( hWnd, TEXT("Can't get current profile dir"), TEXT(""),
  367. GetLastError(), NULL );
  368. }
  369. }
  370. else
  371. {
  372. Fail( hWnd, TEXT("Can't open process token?"), TEXT(""), GetLastError(), NULL );
  373. }
  374. UpdateUi( IDS_CREATING_NEW_PROFILE, 60 );
  375. Ret = CreateUserProfile( NewSid, UserName, TempFile, NULL, 0 );
  376. if ( !Ret )
  377. {
  378. if ( GetLastError() == 997 )
  379. {
  380. //
  381. // Looks like the dreaded pstore key problem. Sigh.
  382. //
  383. DeleteFile( TempFile );
  384. DealWithPstore( OldSid );
  385. err = MyRegSaveKey( HKEY_CURRENT_USER,
  386. TempFile,
  387. NULL );
  388. if ( ! CreateUserProfile( NewSid, UserName, TempFile, NULL, 0 ) )
  389. {
  390. //
  391. // Terminal, now bail:
  392. //
  393. DeleteFile( TempFile );
  394. Fail( hWnd, TEXT("Can't copy profile dir, even after whacking pstore key"), TEXT(""), GetLastError(), NULL );
  395. return GetLastError() ;
  396. }
  397. Ret = TRUE ;
  398. }
  399. else
  400. {
  401. DeleteFile( TempFile );
  402. Fail( hWnd, TEXT( "CreateUserProfile failed"), TEXT(""), GetLastError(), NULL );
  403. }
  404. }
  405. DeleteFile( TempFile );
  406. UpdateUi( IDS_CREATING_NEW_PROFILE, 65 );
  407. if ( Ret )
  408. {
  409. //
  410. // Okay, we have created a shell profile based on the current
  411. // profile. Now, copy the rest of the gunk over it:
  412. //
  413. PathLength = MAX_PATH ;
  414. GetUserProfileDirectoryFromSid( NewSid, TempPath2, &PathLength );
  415. UpdateUi( IDS_COPYING_OLD_PROFILE, 90 );
  416. if ( !CopyProfileDirectory( TempPath,
  417. TempPath2,
  418. CPD_FORCECOPY |
  419. CPD_IGNORECOPYERRORS |
  420. CPD_IGNOREHIVE ) )
  421. {
  422. Fail( hWnd, TEXT("CopyProfileDirectory failed"), TEXT(""), GetLastError(), NULL );
  423. }
  424. }
  425. else
  426. {
  427. //
  428. // Failed to create the shell profile. Why?
  429. //
  430. Fail( hWnd, TEXT("Failed to create profile"), TEXT(""), GetLastError(), NULL );
  431. }
  432. }
  433. else
  434. {
  435. SetUserProfileDirectory( OldSid, NewSid );
  436. }
  437. if ( MoveOptions & MOVE_CHANGE_DOMAIN )
  438. {
  439. NET_API_STATUS NetStatus ;
  440. UpdateUi( IDS_MOVE_DOMAIN, 50 );
  441. NetStatus = NetJoinDomain( NULL, DestDomain,NULL,
  442. TEXT("ntdev"), TEXT("ntdev"),
  443. NETSETUP_JOIN_DOMAIN |
  444. NETSETUP_ACCT_CREATE );
  445. UpdateUi( IDS_MOVE_DOMAIN, 95 );
  446. }
  447. return TRUE ;
  448. }
  449. VOID
  450. DoSecurity(
  451. HWND hDlg
  452. )
  453. {
  454. int err ;
  455. HKEY hKey ;
  456. DWORD Disp ;
  457. NET_API_STATUS NetStatus ;
  458. LOCALGROUP_MEMBERS_INFO_0 LocalGroupInfo0 ;
  459. UpdateUi( IDS_SEC_LOCAL_SETTINGS, 50 );
  460. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  461. TEXT("System\\CurrentControlSet\\Control\\Lsa\\MSV1_0"),
  462. 0,
  463. TEXT(""),
  464. REG_OPTION_NON_VOLATILE,
  465. KEY_READ | KEY_WRITE,
  466. NULL,
  467. &hKey,
  468. &Disp );
  469. if ( err == 0 )
  470. {
  471. err = RegSetValueEx( hKey,
  472. TEXT("PreferredDomain"),
  473. 0,
  474. REG_SZ,
  475. (PUCHAR) SourceDomain,
  476. (wcslen( SourceDomain ) + 1) * 2 );
  477. if ( err == 0 )
  478. {
  479. err = RegSetValueEx( hKey,
  480. TEXT("MappedDomain"),
  481. 0,
  482. REG_SZ,
  483. (PUCHAR) DestDomain,
  484. (wcslen( DestDomain ) + 1 ) * 2 );
  485. }
  486. RegCloseKey( hKey );
  487. }
  488. else
  489. {
  490. Fail( hDlg, TEXT("Unable to open LSA key"), TEXT(""), err, TEXT("Unable to update rollout keys, you may not have permission.") );
  491. }
  492. UpdateUi( IDS_SEC_LOCAL_ADMIN, 90 );
  493. LocalGroupInfo0.lgrmi0_sid = NewSid ;
  494. NetStatus = NetLocalGroupAddMembers(
  495. NULL,
  496. L"Administrators",
  497. 0,
  498. (LPBYTE) &LocalGroupInfo0,
  499. 1 );
  500. }
  501. BOOL
  502. Initialize(
  503. VOID
  504. )
  505. {
  506. ULONG Length ;
  507. HANDLE hToken ;
  508. PUNICODE_STRING User ;
  509. PUNICODE_STRING Domain ;
  510. UNICODE_STRING TargetDomainStr ;
  511. NTSTATUS Status ;
  512. PSID Sid ;
  513. PSID AdminSid ;
  514. PTOKEN_USER UserSid ;
  515. DWORD SidLength ;
  516. PBYTE DCName ;
  517. NET_API_STATUS NetStatus ;
  518. WCHAR RefDomain[ DNLEN + 2 ];
  519. ULONG RefDomainLength ;
  520. SID_NAME_USE NameUse ;
  521. BOOL IsMember ;
  522. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY ;
  523. RaiseUi( NULL, L"Initializing..." );
  524. UpdateUi( IDS_INIT_READ_NAMES, 5 );
  525. Status = NtOpenProcessToken( NtCurrentProcess(),
  526. TOKEN_QUERY,
  527. &hToken );
  528. if ( NT_SUCCESS( Status ) )
  529. {
  530. UserSid = LocalAlloc( LMEM_FIXED, 64 );
  531. if ( UserSid )
  532. {
  533. Status = NtQueryInformationToken( hToken,
  534. TokenUser,
  535. UserSid,
  536. 64,
  537. &SidLength );
  538. if ( NT_SUCCESS( Status ) )
  539. {
  540. OldSid = UserSid->User.Sid ;
  541. }
  542. }
  543. AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
  544. DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0 ,0, 0,
  545. &AdminSid );
  546. if ( CheckTokenMembership( hToken, AdminSid, &IsMember ) )
  547. {
  548. if ( !IsMember )
  549. {
  550. Fail( NULL, TEXT("Not an administrator"), TEXT(""), GetLastError(),
  551. TEXT( "You must be an administrator on this machine to run this utility." ) );
  552. }
  553. }
  554. NtClose( hToken );
  555. }
  556. if ( !NT_SUCCESS( Status ) )
  557. {
  558. Fail( NULL, TEXT("Reading SID"), TEXT(""), Status, NULL );
  559. }
  560. UpdateUi( IDS_INIT_READ_NAMES, 25 );
  561. Status = LsaGetUserName( &User, &Domain );
  562. if ( !NT_SUCCESS( Status ) )
  563. {
  564. Fail( NULL, TEXT("Getting user name"), TEXT(""), Status, NULL );
  565. return FALSE ;
  566. }
  567. RtlInitUnicodeString( &TargetDomainStr, DestDomain );
  568. if ( RtlEqualUnicodeString( &TargetDomainStr, Domain, TRUE ) )
  569. {
  570. MoveOptions &= ~MOVE_DO_PROFILE ;
  571. MoveOptions |= MOVE_NO_PROFILE ;
  572. }
  573. UpdateUi( IDS_INIT_READ_NAMES, 35 );
  574. GetPrimaryDomain( MachDomain );
  575. UpdateUi( IDS_INIT_READ_NAMES, 45 );
  576. NetStatus = DsGetDcName( NULL, MachDomain, NULL, NULL,
  577. DS_FORCE_REDISCOVERY |
  578. DS_DIRECTORY_SERVICE_REQUIRED |
  579. DS_KDC_REQUIRED,
  580. &DcInfo );
  581. UpdateUi( IDS_INIT_READ_NAMES, 55 );
  582. if ( (MoveOptions & MOVE_SOURCE_SUPPLIED) == 0)
  583. {
  584. CopyMemory( SourceDomain, Domain->Buffer, Domain->Length );
  585. SourceDomain[ Domain->Length / sizeof(WCHAR) ] = L'\0';
  586. }
  587. CopyMemory( UserName, User->Buffer, User->Length );
  588. UserName[ User->Length / sizeof(WCHAR) ] = L'\0';
  589. LsaFreeMemory( User );
  590. LsaFreeMemory( Domain );
  591. //
  592. // Dest Domain must be filled in by caller. So, try to look up
  593. // the new SID:
  594. //
  595. SidLength = RtlLengthRequiredSid( 6 );
  596. Sid = LocalAlloc( LMEM_FIXED, SidLength );
  597. if ( !Sid )
  598. {
  599. return FALSE ;
  600. }
  601. UpdateUi( IDS_INIT_DISCOVER_DCS, 75 );
  602. RefDomainLength = DNLEN + 2 ;
  603. NetStatus = DsGetDcName( NULL, DestDomain, NULL, NULL,
  604. DS_FORCE_REDISCOVERY |
  605. DS_DIRECTORY_SERVICE_REQUIRED |
  606. DS_KDC_REQUIRED,
  607. &DestDcInfo );
  608. if ( NetStatus == 0 )
  609. {
  610. UpdateUi( IDS_INIT_LOOKUP_ACCOUNTS, 95 );
  611. if ( LookupAccountName( (PWSTR) DestDcInfo->DomainControllerAddress,
  612. UserName,
  613. Sid,
  614. &SidLength,
  615. RefDomain,
  616. &RefDomainLength,
  617. &NameUse )
  618. )
  619. {
  620. if (_wcsicmp( RefDomain, DestDomain ) == 0 )
  621. {
  622. NewSid = Sid ;
  623. }
  624. else
  625. {
  626. Fail( NULL, TEXT("No account for user"), UserName, GetLastError(),
  627. TEXT( "There is no account for you on the destination domain. Please contact NUTS for an account." ) );
  628. }
  629. }
  630. else
  631. {
  632. Fail( NULL, TEXT("Can't look up account name"), TEXT(""), GetLastError(), NULL );
  633. }
  634. }
  635. else
  636. {
  637. Fail( NULL, TEXT("No DC available"), DestDomain, NetStatus,
  638. TEXT("No Domain Controllers were available for the destination domain. Please try again later."));
  639. }
  640. UpdateUi( IDS_INIT_LOOKUP_ACCOUNTS, 100 );
  641. return TRUE ;
  642. }
  643. VOID
  644. Usage(
  645. VOID
  646. )
  647. {
  648. wprintf( TEXT("Usage:\n"));
  649. wprintf( TEXT("\tmoveme DOMAINNAME\n"));
  650. exit( 0 );
  651. }
  652. VOID
  653. DoArgs(
  654. int argc,
  655. WCHAR * argv[]
  656. )
  657. {
  658. int i;
  659. PWSTR Scan;
  660. wcscpy( DestDomain, L"NTDEV");
  661. i = 1 ;
  662. while ( i < argc )
  663. {
  664. if ( (*argv[i] != L'-') &&
  665. (*argv[i] != L'/') )
  666. {
  667. wcscpy( DestDomain, argv[i] );
  668. }
  669. else
  670. {
  671. switch ( *(argv[i]+1) )
  672. {
  673. case L'F':
  674. case L'f':
  675. MoveOptions |= MOVE_NO_UI ;
  676. break;
  677. case L'D':
  678. case L'd':
  679. MoveOptions |= MOVE_SOURCE_SUPPLIED ;
  680. Scan = argv[i];
  681. while ( *Scan && (*Scan != ':'))
  682. {
  683. Scan++;
  684. }
  685. if ( *Scan )
  686. {
  687. Scan++;
  688. wcscpy( SourceDomain, Scan );
  689. }
  690. break;
  691. case L'P':
  692. case L'p':
  693. if ( *(argv[i]+2) == L'-' )
  694. {
  695. MoveOptions &= ~MOVE_DO_PROFILE ;
  696. }
  697. else
  698. {
  699. MoveOptions |= MOVE_DO_PROFILE ;
  700. }
  701. break;
  702. case L'W':
  703. case L'w':
  704. MoveOptions = MOVE_WHACK_PSTORE ;
  705. break;
  706. default:
  707. Usage();
  708. }
  709. }
  710. i++ ;
  711. }
  712. }
  713. BOOL
  714. DoIt(
  715. HWND hDlg
  716. )
  717. {
  718. RaiseUi( hDlg, L"Migrating User Information...");
  719. if ( MoveOptions & MOVE_DO_PROFILE )
  720. {
  721. MoveMe( hDlg, NULL, NULL );
  722. }
  723. if ( MoveOptions & MOVE_UPDATE_SECURITY )
  724. {
  725. DoSecurity( hDlg );
  726. }
  727. UpdateUi( 0, 100 );
  728. return TRUE ;
  729. }
  730. INT_PTR
  731. WINAPI
  732. PromptDlg(
  733. HWND hDlg,
  734. UINT Message,
  735. WPARAM wParam,
  736. LPARAM lParam)
  737. {
  738. WCHAR Buffer[ MAX_PATH ];
  739. switch ( Message )
  740. {
  741. case WM_INITDIALOG:
  742. MyIcon = LoadImage( GetModuleHandle(NULL),
  743. MAKEINTRESOURCE( 1 ),
  744. IMAGE_ICON,
  745. 64, 72,
  746. LR_DEFAULTCOLOR );
  747. if ( MyIcon )
  748. {
  749. SendMessage( GetDlgItem( hDlg, IDD_MAIN_ICON ),
  750. STM_SETICON,
  751. (WPARAM) MyIcon, 0 );
  752. }
  753. swprintf( Buffer, TEXT("Account Domain: %ws"), SourceDomain );
  754. SetDlgItemText( hDlg, IDD_DOMAIN_LINE, Buffer );
  755. swprintf( Buffer, TEXT("Machine Domain: %ws"), MachDomain );
  756. SetDlgItemText( hDlg, IDD_WKSTA_DOMAIN, Buffer );
  757. swprintf( Buffer, TEXT("This tool will adjust a number of settings on your machine to move to the %ws domain."),
  758. DestDomain );
  759. SetDlgItemText( hDlg, IDD_ABOUT, Buffer );
  760. CheckDlgButton( hDlg, IDD_RADIO_MAKECOPY, BST_CHECKED );
  761. if ( MoveOptions & MOVE_NO_PROFILE )
  762. {
  763. CheckDlgButton( hDlg, IDD_PROFILE_CHECK, BST_UNCHECKED );
  764. EnableSection( hDlg, FALSE, ProfileSection,
  765. sizeof( ProfileSection ) /sizeof(DWORD) );
  766. }
  767. else
  768. {
  769. CheckDlgButton( hDlg, IDD_PROFILE_CHECK, BST_CHECKED );
  770. }
  771. CheckDlgButton( hDlg, IDD_UPDATE_SEC, BST_CHECKED );
  772. EnableWindow( GetDlgItem( hDlg, IDD_UPDATE_SEC ), FALSE );
  773. //
  774. // If we're already there, forget it.
  775. //
  776. if ( _wcsicmp( MachDomain, DestDomain ) == 0 )
  777. {
  778. EnableWindow( GetDlgItem( hDlg, IDD_MOVE_MACHINE), FALSE );
  779. }
  780. //
  781. // If the domain already has a DS DC, forget it.
  782. //
  783. if ( DcInfo && DcInfo->Flags & DS_DS_FLAG )
  784. {
  785. EnableWindow( GetDlgItem( hDlg, IDD_MOVE_MACHINE), FALSE );
  786. }
  787. return FALSE ;
  788. case WM_COMMAND:
  789. switch (LOWORD( wParam ) )
  790. {
  791. case IDCANCEL:
  792. EndDialog( hDlg, IDCANCEL );
  793. break;
  794. case IDOK:
  795. //
  796. // Gather settings
  797. //
  798. if ( IsDlgButtonChecked( hDlg, IDD_PROFILE_CHECK ) == BST_CHECKED )
  799. {
  800. MoveOptions |= MOVE_DO_PROFILE ;
  801. if ( IsDlgButtonChecked( hDlg, IDD_RADIO_MAKECOPY ) == BST_CHECKED )
  802. {
  803. MoveOptions |= MOVE_COPY_PROFILE ;
  804. }
  805. if ( IsDlgButtonChecked( hDlg, IDD_RADIO_MAKE_ROAM ) == BST_CHECKED )
  806. {
  807. MoveOptions |= MOVE_MAKE_ROAM ;
  808. }
  809. }
  810. if ( IsDlgButtonChecked( hDlg, IDD_MOVE_MACHINE ) == BST_CHECKED )
  811. {
  812. MoveOptions |= MOVE_CHANGE_DOMAIN ;
  813. }
  814. if ( IsDlgButtonChecked( hDlg, IDD_UPDATE_SEC ) == BST_CHECKED )
  815. {
  816. MoveOptions |= MOVE_UPDATE_SECURITY ;
  817. }
  818. DumpState();
  819. DoIt( hDlg );
  820. EndDialog( hDlg, IDOK );
  821. break;
  822. case IDD_PROFILE_CHECK:
  823. if ( HIWORD( wParam ) == BN_CLICKED )
  824. {
  825. if ( IsDlgButtonChecked( hDlg, IDD_PROFILE_CHECK )
  826. == BST_CHECKED )
  827. {
  828. EnableSection( hDlg,
  829. TRUE,
  830. ProfileSection,
  831. sizeof( ProfileSection ) / sizeof(DWORD) );
  832. }
  833. else
  834. {
  835. EnableSection( hDlg, FALSE, ProfileSection,
  836. sizeof( ProfileSection ) /sizeof(DWORD) );
  837. }
  838. return TRUE ;
  839. }
  840. break;
  841. }
  842. return TRUE ;
  843. default:
  844. return FALSE ;
  845. }
  846. }
  847. void
  848. __cdecl
  849. wmain (int argc, WCHAR *argv[])
  850. {
  851. int Result ;
  852. NTSTATUS Status ;
  853. BOOLEAN WasEnabled ;
  854. VersionInfo.dwOSVersionInfoSize = sizeof( VersionInfo );
  855. GetVersionEx( (LPOSVERSIONINFOW) &VersionInfo );
  856. #if DBG
  857. InitDebugSupport();
  858. #endif
  859. InitCommonControls();
  860. DoArgs( argc, argv );
  861. CreateUiThread();
  862. if (!Initialize())
  863. {
  864. StopUiThread();
  865. ExitProcess( GetLastError() );
  866. }
  867. if ( MoveOptions & MOVE_WHACK_PSTORE )
  868. {
  869. DealWithPstore( NewSid );
  870. }
  871. if ( MoveOptions & MOVE_NO_UI )
  872. {
  873. MoveOptions |= MOVE_COPY_PROFILE | MOVE_UPDATE_SECURITY ;
  874. DoIt( NULL );
  875. }
  876. Result = (int)DialogBox( GetModuleHandle( NULL ),
  877. MAKEINTRESOURCE( IDD_MAIN_DLG ),
  878. NULL,
  879. PromptDlg );
  880. if ( Result == IDOK )
  881. {
  882. Result = MessageBox( NULL, L"The changes require a reboot. Reboot now?",
  883. L"Move Tool",
  884. MB_ICONINFORMATION | MB_YESNO );
  885. if ( Result == IDYES )
  886. {
  887. Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
  888. TRUE, FALSE,
  889. &WasEnabled );
  890. if ( NT_SUCCESS( Status ) )
  891. {
  892. ExitWindowsEx( EWX_FORCE | EWX_REBOOT, 0 );
  893. }
  894. }
  895. }
  896. }