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.

1925 lines
55 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. dll.c
  5. Abstract:
  6. main file for the cross language migration tool
  7. Author:
  8. Xiaofeng Zang (xiaoz) 17-Sep-2001 Created
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "StdAfx.h"
  13. #include "clmt.h"
  14. #include <winbase.h>
  15. #include "clmtmsg.h"
  16. BOOL CheckOS(DWORD);
  17. HRESULT DoRegistryAnalyze();
  18. LONG AddEventSource(VOID);
  19. LONG CLMTReportEvent(WORD, WORD, DWORD, WORD, LPCTSTR*);
  20. void Deinit(BOOL);
  21. HRESULT DoCLMTCureProgramFiles();
  22. HRESULT DoCLMTCleanUpAfterFirstReboot();
  23. HRESULT DoCLMTCleanUpAfterDotNetUpgrade();
  24. HRESULT DeleteUnwantedFilesPerUser(HKEY, LPCTSTR, LPCTSTR, LPTSTR);
  25. HRESULT DeleteUnwantedFiles(HINF, LPCTSTR);
  26. HRESULT AddRunValueToRegistry(LPCTSTR);
  27. INT DoCLMTDisplayAccountChangeDialog();
  28. BOOL CALLBACK AccountChangeDlgProc(HWND, UINT, WPARAM, LPARAM);
  29. HRESULT UpdateHardLinkInfoPerUser(HKEY, LPCTSTR, LPCTSTR, LPTSTR);
  30. VOID RemoveFromRunKey(LPCTSTR);
  31. /*++
  32. Routine Description:
  33. main entry point for the program
  34. Arguments:
  35. if dwUndo != 0, we are in undo mode, otherwise...
  36. Return Value:
  37. TRUE - if succeeds
  38. --*/
  39. LONG
  40. DoMig(DWORD dwMode)
  41. {
  42. HRESULT hr;
  43. HINF hMigrateInf = INVALID_HANDLE_VALUE;
  44. TCHAR szInfFile[MAX_PATH],*p;
  45. UINT iYesNo;
  46. DWORD dwRunStatus;
  47. DWORD dwCurrentState;
  48. DWORD dwNextState;
  49. TCHAR szProfileRoot[MAX_PATH];
  50. DWORD cchLen;
  51. BOOL bOleInit = FALSE;
  52. DWORD dwOrgWinstationsState = 1;
  53. TCHAR szBackupDir[2*MAX_PATH];
  54. TCHAR szRunOnce[2*MAX_PATH];
  55. TCHAR szRun[2 * MAX_PATH];
  56. HANDLE hExe = GetModuleHandle(NULL);
  57. UINT nRet;
  58. BOOL bMsgPopuped = FALSE;
  59. BOOL bWinStationChanged = FALSE;
  60. ULONG uErrMsgID;
  61. LONG err;
  62. TCHAR szSecDatabase[MAX_PATH];
  63. BOOL bCleanupFailed;
  64. INT iRet;
  65. LCID lcid;
  66. DPF(APPmsg, L"DoMig with dwMode = %d", dwMode);
  67. //
  68. // Only one instance of CLMT is allowed to run on the system
  69. //
  70. if (!IsOneInstance())
  71. {
  72. return FALSE;
  73. }
  74. //
  75. // Only users with admin privilege can run the tool
  76. //
  77. if (!CheckAdminPrivilege())
  78. {
  79. return FALSE;
  80. }
  81. //
  82. // Check if there are other tasks running on the system, quit CLMT
  83. //
  84. if (dwMode == CLMT_DOMIG && (!IsDebuggerPresent() && !g_fNoAppChk) && DisplayTaskList())
  85. {
  86. return ERROR_SUCCESS;
  87. }
  88. //
  89. // Display Start Up dialog
  90. //
  91. if (dwMode == CLMT_DOMIG)
  92. {
  93. iRet = ShowStartUpDialog();
  94. if (iRet == ID_STARTUP_DLG_CANCEL)
  95. {
  96. return ERROR_SUCCESS;
  97. }
  98. }
  99. //
  100. // Check to see if the operation is legal or not
  101. //
  102. hr = CheckCLMTStatus(&dwCurrentState, &dwNextState, &uErrMsgID);
  103. if (SUCCEEDED(hr))
  104. {
  105. if (hr == S_OK)
  106. {
  107. DPF(dlInfo,
  108. TEXT("Operation [0x%X] is legal with current machine state [0x%X]"),
  109. g_dwRunningStatus,
  110. dwCurrentState);
  111. SetCLMTStatus(g_dwRunningStatus);
  112. }
  113. else
  114. {
  115. DPF(dlFail,
  116. TEXT("Operation [0x%X] is illegal with current machine state [0x%X]"),
  117. g_dwRunningStatus,
  118. dwCurrentState);
  119. DoMessageBox(GetConsoleWindow(),
  120. uErrMsgID,
  121. IDS_MAIN_TITLE,
  122. MB_OK | MB_SYSTEMMODAL);
  123. return FALSE;
  124. }
  125. }
  126. else
  127. {
  128. DPF(dlError,
  129. TEXT("Error occurred when trying to check CLMT and machine status - hr = 0x%X"),
  130. hr);
  131. return FALSE;
  132. }
  133. //
  134. // Verify the system if it is eligible to run CLMT
  135. //
  136. if (!CheckSystemCriteria())
  137. {
  138. DPF(APPerr, TEXT("System Verification Failed!"));
  139. hr = E_FAIL;
  140. bMsgPopuped = TRUE;
  141. goto Exit;
  142. }
  143. hr = InitDebugSupport(dwMode);
  144. if (FAILED(hr))
  145. {
  146. DPF (APPerr, L"DLL.C: InitDebugSupport! Error: %d (%#x)", hr, hr);
  147. goto Exit;
  148. }
  149. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  150. if (FAILED(hr))
  151. {
  152. DPF (APPerr, L"DLL.C: CoInitialize Failed! Error: %d (%#x)\n", hr, hr);
  153. goto Exit;
  154. }
  155. else
  156. {
  157. bOleInit = TRUE;
  158. }
  159. // Initialize global variables
  160. if (!InitGlobals(dwMode))
  161. {
  162. hr = E_OUTOFMEMORY;
  163. DPF (APPerr, L"DLL.C: InitGlobal failure, out of memory!");
  164. goto Exit;
  165. }
  166. //we do not care the return value for LogMachineInfo
  167. LogMachineInfo();
  168. // Block new TS connections to be made during running CLMT
  169. hr = DisableWinstations(1, &dwOrgWinstationsState);
  170. if (SUCCEEDED(hr))
  171. {
  172. bWinStationChanged = TRUE;
  173. }
  174. else
  175. {
  176. //BUGBUG:Xiaoz:Add DLG pop up for failure
  177. DPF (APPerr, L"DLL.C: Block new TS session failed: %d (%#x)\n", hr, hr);
  178. goto Exit;
  179. }
  180. if (g_dwRunningStatus == CLMT_REMINDER)
  181. {
  182. BOOL bIsNTFS;
  183. hr = IsSysVolNTFS(&bIsNTFS);
  184. if ( (S_OK == hr) && !bIsNTFS)
  185. {
  186. //make sure hr is S_FALSE so that it will not pop up reboot dlg
  187. hr = S_FALSE;
  188. DoMessageBox(GetConsoleWindow(), IDS_ASKING_CONVERT_TO_NTFS, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  189. goto Exit;
  190. }
  191. hr = S_FALSE;
  192. DoMessageBox(GetConsoleWindow(), IDS_REMIND_HARDLINK, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  193. goto Exit;
  194. }
  195. else if ( (g_dwRunningStatus == CLMT_CURE_PROGRAM_FILES)
  196. || (g_dwRunningStatus == CLMT_CURE_ALL)
  197. || (g_dwRunningStatus == CLMT_CURE_AND_CLEANUP) )
  198. {
  199. hr = EnsureDoItemInfFile(g_szToDoINFFileName,ARRAYSIZE(g_szToDoINFFileName));
  200. if (SUCCEEDED(hr))
  201. {
  202. WritePrivateProfileSection(TEXT("Folder.ObjectRename"),NULL,g_szToDoINFFileName);
  203. WritePrivateProfileSection(TEXT("REG.Update.Sys"),NULL,g_szToDoINFFileName);
  204. WritePrivateProfileSection(TEXT("UserGrp.ObjectRename"),NULL,g_szToDoINFFileName);
  205. WritePrivateProfileSection(TEXT("LNK"),NULL,g_szToDoINFFileName);
  206. }
  207. LoopUser(UpdateHardLinkInfoPerUser);
  208. hr = DoCLMTCureProgramFiles();
  209. if (hr == S_OK)
  210. {
  211. // We are done with curing Program Files hard link
  212. CLMTSetMachineState(CLMT_STATE_PROGRAMFILES_CURED);
  213. // remove "/CURE" rom Run registry key
  214. RemoveFromRunKey(TEXT("/CURE"));
  215. // Make sure hr = S_FALSE so that it will not pop up reboot dlg
  216. hr = S_FALSE;
  217. }
  218. if (g_dwRunningStatus == CLMT_CURE_AND_CLEANUP)
  219. {
  220. // Do the cleanup also if machine is already upgraded to .NET
  221. // This scenario will happen only when Win2K FAT --> .NET FAT
  222. // then run /CURE /FINAL in .NET
  223. if (IsDotNet())
  224. {
  225. CheckCLMTStatus(&dwCurrentState, &dwNextState, &uErrMsgID);
  226. hr = DoCLMTCleanUpAfterDotNetUpgrade();
  227. if (hr == S_OK)
  228. {
  229. CLMTSetMachineState(dwNextState);
  230. // Remove "/FINAL" from Run registry key
  231. RemoveFromRunKey(TEXT("/FINAL"));
  232. // Make sure hr = S_FALSE so that it will not pop up reboot dlg
  233. hr = S_FALSE;
  234. }
  235. }
  236. }
  237. goto Exit;
  238. }
  239. else if (g_dwRunningStatus == CLMT_CLEANUP_AFTER_UPGRADE)
  240. {
  241. hr = DoCLMTCleanUpAfterDotNetUpgrade();
  242. if (hr == S_OK)
  243. {
  244. // If the cleanup finished successfully
  245. CLMTSetMachineState(dwNextState);
  246. // Make sure hr = S_FALSE so that it will not pop up reboot dlg
  247. hr = S_FALSE;
  248. }
  249. goto Exit;
  250. }
  251. hr = GetInfFilePath(szInfFile, ARRAYSIZE(szInfFile));
  252. if (FAILED(hr))
  253. {
  254. DPF(APPerr,TEXT("[CLMT : get inf file name failed !"));
  255. DoMessageBox(GetConsoleWindow(), IDS_CREATE_INF_FAILURE, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  256. bMsgPopuped = TRUE;
  257. goto Exit;
  258. }
  259. hr = UpdateINFFileSys(szInfFile);
  260. if (FAILED(hr))
  261. {
  262. DPF(APPerr,TEXT("CLMT : can not update per system settings in %s!"),szInfFile);
  263. switch (hr)
  264. {
  265. case E_NOTIMPL:
  266. DoMessageBox(GetDesktopWindow(), IDS_LANG_NOTSUPPORTED, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  267. break;
  268. default:
  269. DoMessageBox(GetConsoleWindow(), IDS_GENERAL_WRITE_FAILURE, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  270. break;
  271. }
  272. bMsgPopuped = TRUE;
  273. goto Exit;
  274. }
  275. hMigrateInf = SetupOpenInfFile(szInfFile,
  276. NULL,
  277. INF_STYLE_WIN4,
  278. NULL);
  279. if (hMigrateInf != INVALID_HANDLE_VALUE)
  280. {
  281. g_hInf = hMigrateInf;
  282. }
  283. else
  284. {
  285. DPF(APPerr,TEXT("CLMT : can not open inf file %s!"),szInfFile);
  286. DoMessageBox(GetConsoleWindow(), IDS_OPEN_INF_FAILURE, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  287. hr = E_FAIL;
  288. bMsgPopuped = TRUE;
  289. goto Exit;
  290. }
  291. //Copy myself to %windir%\$CLMT_BACKUP$ for future use, eg, runonce
  292. if (!GetSystemWindowsDirectory(szBackupDir, ARRAYSIZE(szBackupDir)))
  293. {
  294. //BUGBUG:Xiaoz:Add DLG pop up for failure
  295. DPF(APPerr, TEXT("Failed to get WINDIR"));
  296. hr = HRESULT_FROM_WIN32(GetLastError());
  297. goto Exit;
  298. }
  299. ConcatenatePaths(szBackupDir,CLMT_BACKUP_DIR,ARRAYSIZE(szBackupDir));
  300. if (S_OK != (hr = CopyMyselfTo(szBackupDir)))
  301. {
  302. //If can not copy, we will bail out, since most likely error is disk full
  303. DPF(APPerr,TEXT("CLMT : can not copy clmt.exe to %s, error code = %d"),szBackupDir,HRESULT_CODE(hr));
  304. goto Exit;
  305. }
  306. //
  307. // Run Winnt32 /Checkupgrade to check the system compatibility
  308. //
  309. if (g_fRunWinnt32)
  310. {
  311. if (!IsUserOKWithCheckUpgrade())
  312. {
  313. hr = S_FALSE;
  314. goto Exit;
  315. }
  316. }
  317. hr = EnsureDoItemInfFile(g_szToDoINFFileName,MAX_PATH);
  318. if (FAILED(hr))
  319. {
  320. //BUGBUG:Xiaoz:Add DLG pop up for failure
  321. DPF(APPerr,TEXT("CLMT : can not create global Todo list INF file !"));
  322. goto Exit;
  323. }
  324. #ifdef NEVER
  325. err = SDBCleanup(szSecDatabase,ARRAYSIZE(szSecDatabase),&bCleanupFailed);
  326. if ( (err != ERROR_SUCCESS) || bCleanupFailed )
  327. {
  328. TCHAR szErrorMessage[2*MAX_PATH],szErrorTemplate[MAX_PATH],szCaption[MAX_PATH];
  329. LoadString((HINSTANCE)g_hInstDll, IDS_SDBERROR, szErrorTemplate, ARRAYSIZE(szErrorTemplate)-1);
  330. hr = StringCchPrintf(szErrorMessage,ARRAYSIZE(szErrorMessage),szErrorTemplate,szSecDatabase);
  331. LoadString(g_hInstDll, IDS_MAIN_TITLE, szCaption, ARRAYSIZE(szCaption)-1);
  332. MessageBox(GetConsoleWindow(),szErrorMessage,szCaption, MB_OK|MB_SYSTEMMODAL);
  333. bMsgPopuped = TRUE;
  334. hr = E_FAIL;
  335. goto Exit;
  336. }
  337. #endif
  338. #ifdef CONSOLE_UI
  339. wprintf(TEXT("Analyzing all user shell folders ......\n"));
  340. #endif
  341. hr = DoShellFolderRename(hMigrateInf,NULL,TEXT("System"));
  342. if (FAILED(hr))
  343. {
  344. //BUGBUG:Xiaoz:Add DLG pop up for failure
  345. DPF (APPerr, L"DLL.C: DoShellFolderRename Failed! Error: %d (%#x)\n", hr, hr);
  346. goto Exit;
  347. }
  348. #ifdef CONSOLE_UI
  349. wprintf(TEXT("Analyzing per user shell folders ......\n"));
  350. #endif
  351. if (!LoopUser(MigrateShellPerUser))
  352. {
  353. //BUGBUG:Xiaoz:Add DLG pop up for failure
  354. DPF (APPerr, L"DLL.C: LoopUser with MigrateShellPerUser Failed");
  355. hr = E_FAIL;
  356. goto Exit;
  357. }
  358. #ifdef CONSOLE_UI
  359. wprintf(TEXT("Analyzing user and group name changes ......\n"));
  360. #endif
  361. hr = UsrGrpAndDoc_and_SettingsRename(hMigrateInf,TRUE);
  362. if (FAILED(hr))
  363. {
  364. //BUGBUG:Xiaoz:Add DLG pop up for failure
  365. DPF (APPerr, L"DLL.C: UsrGrpAndDoc_and_SettingsRename Failed! Error: %d (%#x)", hr, hr);
  366. goto Exit;
  367. }
  368. if (!LoopUser(MigrateRegSchemesPerUser))
  369. {
  370. //BUGBUG:Xiaoz:Add DLG pop up for failure
  371. DPF (APPerr, L"DLL.C: LoopUser with MigrateRegSchemesPerUser Failed");
  372. goto Exit;
  373. }
  374. hr = MigrateRegSchemesPerSystem(hMigrateInf);
  375. if (FAILED(hr))
  376. {
  377. //BUGBUG:Xiaoz:Add DLG pop up for failure
  378. DPF (APPerr, L"DLL.C: MigrateRegSchemesPerSystem Failed! Error: %d (%#x)\n", hr, hr);
  379. goto Exit;
  380. }
  381. #ifdef CONSOLE_UI
  382. wprintf(TEXT("Analyzing IIS metabase ......\n"));
  383. #endif
  384. hr = MigrateMetabaseSettings(hMigrateInf);
  385. if (FAILED(hr))
  386. {
  387. //BUGBUG:Xiaoz:Add DLG pop up for failure
  388. DPF (APPerr, L"DLL.C: MigrateMetabaseSettings! Error: %d (%#x)\n", hr, hr);
  389. goto Exit;
  390. }
  391. hr = MetabaseAnalyze(NULL, &g_StrReplaceTable, TRUE);
  392. if (FAILED(hr))
  393. {
  394. //BUGBUG:Xiaoz:Add DLG pop up for failure
  395. DPF (APPerr, L"DLL.C: MetabaseAnalyze Failed! Error: %d (%#x)\n", hr, hr);
  396. goto Exit;
  397. }
  398. // This EnumUserProfile will be enable after RC 1
  399. //
  400. //hr = EnumUserProfile(AnalyzeMiscProfilePathPerUser);
  401. //if (FAILED(hr))
  402. //{
  403. // DPF (APPerr, L"DLL.C: EnumUserProfile with AnalyzeMiscProfilePathPerUser Failed");
  404. // goto Exit;
  405. //}
  406. #ifdef CONSOLE_UI
  407. wprintf(TEXT("Analyzing the entire registry ......\n"));
  408. #endif
  409. hr = DoRegistryAnalyze();
  410. if (FAILED(hr))
  411. {
  412. //BUGBUG:Xiaoz:Add DLG pop up for failure
  413. DPF (APPerr, L"DLL.C: DoRegistryAnalyze Failed! Error: %d (%#x)\n", hr, hr);
  414. goto Exit;
  415. }
  416. #ifdef CONSOLE_UI
  417. //wprintf(TEXT("Analyzing lnk files under profile directories ......\n"));
  418. wprintf(TEXT("Analyzing LNK files under profile directories, please wait as this may\n"));
  419. wprintf(TEXT("take a few minutes ......\n"));
  420. #endif
  421. //make sure the link file under profile dirrectory is updated
  422. cchLen = ARRAYSIZE(szProfileRoot);
  423. if (GetProfilesDirectory(szProfileRoot,&cchLen))
  424. {
  425. if (!MyEnumFiles(szProfileRoot,TEXT("lnk"),LnkFileUpdate))
  426. {
  427. //BUGBUG:Xiaoz:Add DLG pop up for failure
  428. hr = HRESULT_FROM_WIN32(GetLastError());
  429. DPF (APPerr, L"DLL.C: EnumFiles Lnk File Failed! Error: %d (%#x)\n", hr, hr);
  430. goto Exit;
  431. }
  432. }
  433. if (GetEnvironmentVariable(L"windir", szProfileRoot, MAX_PATH))
  434. {
  435. hr = StringCchCat(szProfileRoot, MAX_PATH, TEXT("\\security\\templates"));
  436. if (!MyEnumFiles(szProfileRoot,TEXT("inf"),SecTempUpdate))
  437. {
  438. //BUGBUG:Xiaoz:Add DLG pop up for failure
  439. hr = HRESULT_FROM_WIN32(GetLastError());
  440. DPF (APPerr, L"DLL.C: EnumFiles security template File Failed! Error: %d (%#x)\n", hr, hr);
  441. goto Exit;
  442. }
  443. }
  444. hr = FolderMove(hMigrateInf,TEXT("Generic.Folder.ObjectRename.PerSystem"),TRUE);
  445. if (FAILED(hr))
  446. {
  447. DPF (APPerr, L"DLL.C: FolderMove Failed! Error: %d (%#x)\n", hr, hr);
  448. goto Exit;
  449. }
  450. FRSUpdate();
  451. Ex2000Update();
  452. // Analyze the services reconfiguration
  453. DoServicesAnalyze();
  454. // Add event log source to registry
  455. AddEventSource();
  456. // Log an event into event log
  457. CLMTReportEvent(EVENTLOG_INFORMATION_TYPE,
  458. STATUS_SEVERITY_INFORMATIONAL,
  459. MSG_CLMT_STARTED,
  460. 0,
  461. NULL);
  462. // Display the Administrator Account Change dialog
  463. GetSavedInstallLocale(&lcid);
  464. if (lcid != 0x411)
  465. {
  466. // we ignore displaying this dialog on JPN
  467. iRet = DoCLMTDisplayAccountChangeDialog();
  468. if (iRet == ID_STARTUP_DLG_CANCEL)
  469. {
  470. iRet = DoMessageBox(GetConsoleWindow(),
  471. IDS_CONFIRM_OPERATION,
  472. IDS_MAIN_TITLE,
  473. MB_OKCANCEL);
  474. if (iRet == IDCANCEL)
  475. {
  476. goto Exit;
  477. }
  478. }
  479. }
  480. //
  481. // Do the critical system changes here...
  482. //
  483. nRet = (UINT) DialogBoxParam(hExe,
  484. MAKEINTRESOURCE(IDD_UPDATESYSTEM),
  485. GetConsoleWindow(),
  486. (DLGPROC) DoCriticalDlgProc,
  487. (LPARAM) NULL);
  488. if (nRet == ID_UPDATE_DONE)
  489. {
  490. hr = S_OK;
  491. }
  492. else
  493. {
  494. hr = S_FALSE;
  495. }
  496. // Set machine state after operation is done
  497. if (hr == S_OK)
  498. {
  499. // Add cure program files switch to Run key
  500. AddRunValueToRegistry(TEXT("/CURE /FINAL"));
  501. // Set machine to next state
  502. CLMTSetMachineState(dwNextState);
  503. // Tool has finished, report to event log
  504. CLMTReportEvent(EVENTLOG_INFORMATION_TYPE,
  505. STATUS_SEVERITY_INFORMATIONAL,
  506. MSG_CLMT_FINISHED,
  507. 0,
  508. NULL);
  509. }
  510. Exit:
  511. if (bWinStationChanged)
  512. {
  513. // Return the WinStations status to original state
  514. DisableWinstations(dwOrgWinstationsState, NULL);
  515. }
  516. if (hMigrateInf != INVALID_HANDLE_VALUE)
  517. {
  518. SetupCloseInfFile(hMigrateInf);
  519. g_hInf = INVALID_HANDLE_VALUE ;
  520. }
  521. Deinit(bOleInit);
  522. CloseDebug();
  523. EnablePrivilege(SE_SHUTDOWN_NAME,FALSE);
  524. EnablePrivilege(SE_BACKUP_NAME,FALSE);
  525. EnablePrivilege(SE_RESTORE_NAME,FALSE);
  526. EnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,FALSE);
  527. if (hr == S_OK)
  528. {
  529. ReStartSystem(EWX_REBOOT);
  530. }
  531. else if ( FAILED(hr) && !bMsgPopuped)
  532. {
  533. DoMessageBox(GetConsoleWindow(), IDS_FATALERROR, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  534. }
  535. return HRESULT_CODE(hr);
  536. }
  537. //-----------------------------------------------------------------------------
  538. //
  539. // Function: MigrateShellPerUser
  540. //
  541. // Synopsis: Rename shell folders for each user
  542. //
  543. // Returns: HRESULT
  544. //
  545. // History: 03/08/2002 Rerkboos Add log + code clean up
  546. //
  547. // Notes: None.
  548. //
  549. //-----------------------------------------------------------------------------
  550. HRESULT MigrateShellPerUser(
  551. HKEY hKeyUser,
  552. LPCTSTR UserName,
  553. LPCTSTR DomainName,
  554. LPTSTR UserSid
  555. )
  556. {
  557. TCHAR InfoBuff[1000];
  558. HINF hMigrateInf = INVALID_HANDLE_VALUE;
  559. TCHAR szInfFile[MAX_PATH];
  560. HRESULT hr;
  561. DPF(APPmsg, TEXT("Enter MigrateShellPerUser:"));
  562. // Get per-user temporary INF file name
  563. hr = GetInfFilePath(szInfFile, ARRAYSIZE(szInfFile));
  564. if (SUCCEEDED(hr))
  565. {
  566. // Update per-syste data to temp INF file
  567. hr = UpdateINFFileSys(szInfFile);
  568. if (SUCCEEDED(hr))
  569. {
  570. // Update per-user data to temp INF file
  571. hr = UpdateINFFilePerUser(szInfFile, UserName, UserSid, FALSE);
  572. if (SUCCEEDED(hr))
  573. {
  574. DPF(APPmsg, TEXT("Per-user INF file was updated successfully"));
  575. }
  576. else
  577. {
  578. DPF(APPerr, TEXT("Failed to update per-user data in INF"));
  579. }
  580. }
  581. else
  582. {
  583. DPF(APPerr, TEXT("Failed to update per-system data in INF"));
  584. }
  585. }
  586. else
  587. {
  588. DPF(APPerr, TEXT("Faild to get per-user INF file name"));
  589. }
  590. #ifdef CONSOLE_UI
  591. wprintf(TEXT("analyzing settings for user %s \n"), UserName);
  592. #endif
  593. if (SUCCEEDED(hr))
  594. {
  595. // Open per-user INF file
  596. hMigrateInf = SetupOpenInfFile(szInfFile,
  597. NULL,
  598. INF_STYLE_WIN4,
  599. NULL);
  600. if (hMigrateInf != INVALID_HANDLE_VALUE)
  601. {
  602. // Rename shell folders for the user
  603. hr = DoShellFolderRename(hMigrateInf, hKeyUser, (LPTSTR) UserName);
  604. SetupCloseInfFile(hMigrateInf);
  605. DeleteFile(szInfFile);
  606. if (SUCCEEDED(hr))
  607. {
  608. DPF(APPmsg, TEXT("Rename per-user shell folders successfully"));
  609. }
  610. else
  611. {
  612. DPF(APPerr, TEXT("Rename per-user shell folders Failed"));
  613. }
  614. }
  615. else
  616. {
  617. hr = HRESULT_FROM_WIN32(GetLastError());
  618. DPF(APPerr, TEXT("Failed to open per-user INF file"));
  619. }
  620. }
  621. DPF(APPmsg, TEXT("Exit MigrateShellPerUser:"));
  622. return hr;
  623. }
  624. /*++
  625. Routine Description:
  626. This routine initializes the global variables used in the program
  627. Arguments:
  628. Return Value:
  629. TRUE - if succeeds
  630. --*/
  631. BOOL InitGlobals(DWORD dwRunStatus)
  632. {
  633. BOOL bRet = TRUE;
  634. int i, n;
  635. DWORD dwMachineState;
  636. HRESULT hr;
  637. // Get the module handle to ourself
  638. g_hInstDll = GetModuleHandle(NULL);
  639. // Check if the machine has not run CLMT yet
  640. hr = CLMTGetMachineState(&dwMachineState);
  641. g_bBeforeMig = (SUCCEEDED(hr) && dwMachineState == CLMT_STATE_ORIGINAL);
  642. //Init the global string search-replacement table
  643. if(!InitStrRepaceTable())
  644. {
  645. DoMessageBox(GetConsoleWindow(), IDS_OUT_OF_MEMORY, IDS_MAIN_TITLE, MB_OK|MB_SYSTEMMODAL);
  646. bRet = FALSE;
  647. }
  648. return bRet;
  649. }
  650. /*++
  651. Routine Description:
  652. This routine checks the various OS properties to make sure that the tool cab be run
  653. Arguments:
  654. Return Value:
  655. TRUE - if the clmt tool can be run on the current platform .
  656. --*/
  657. BOOL CheckOS(DWORD dwMode)
  658. {
  659. TCHAR Text[MAX_PATH];
  660. BOOL bRet = TRUE;
  661. LCID lcid;
  662. HRESULT hr;
  663. BOOL bIsAdmin;
  664. OSVERSIONINFOEX osviex;
  665. if (FAILED(StringCchPrintf (Text, ARRAYSIZE(Text), TEXT("Global\\%s"), TEXT("CLMT Is Running"))))
  666. {
  667. bRet = FALSE;
  668. goto Cleanup;
  669. }
  670. g_hMutex = CreateMutex(NULL,FALSE,Text);
  671. if ((g_hMutex == NULL) && (GetLastError() == ERROR_PATH_NOT_FOUND))
  672. {
  673. g_hMutex = CreateMutex(NULL,FALSE,TEXT("CLMT Is Running"));
  674. if(g_hMutex == NULL)
  675. {
  676. //
  677. // An error (like out of memory) has occurred.
  678. // Bail now.
  679. //
  680. DoMessageBox(GetConsoleWindow(), IDS_OUT_OF_MEMORY, IDS_MAIN_TITLE, MB_OK);
  681. bRet = FALSE;
  682. goto Cleanup;
  683. }
  684. }
  685. //
  686. // Make sure we are the only process with a handle to our named mutex.
  687. //
  688. if ((g_hMutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS))
  689. {
  690. DoMessageBox(GetConsoleWindow(), IDS_ALREADY_RUNNING, IDS_MAIN_TITLE, MB_OK);
  691. bRet = FALSE;
  692. goto Cleanup;
  693. }
  694. if (dwMode == CLMT_DOMIG)
  695. {
  696. if (!IsNT5())
  697. {
  698. DoMessageBox(GetConsoleWindow(), IDS_NT5, IDS_MAIN_TITLE, MB_OK);
  699. bRet = FALSE;
  700. goto Cleanup;
  701. }
  702. if (IsDomainController())
  703. {
  704. //
  705. // If this machine is a domain controller, we need W2K SP2
  706. //
  707. ZeroMemory(&osviex, sizeof(OSVERSIONINFOEX));
  708. osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  709. GetVersionEx((LPOSVERSIONINFO) &osviex);
  710. bRet = (osviex.wServicePackMajor >= 2 ? TRUE : FALSE);
  711. if (!bRet)
  712. {
  713. DoMessageBox(GetConsoleWindow(), IDS_NT5SP2, IDS_MAIN_TITLE, MB_OK);
  714. goto Cleanup;
  715. }
  716. //
  717. // Also pop up the message asking admin to take machine
  718. // off the network if it is in DC replication servers
  719. //
  720. DoMessageBox(GetConsoleWindow(),
  721. IDS_DC_REPLICA_OFFLINE,
  722. IDS_MAIN_TITLE,
  723. MB_OK);
  724. }
  725. }
  726. else if (dwMode == CLMT_CLEANUP_AFTER_UPGRADE)
  727. {
  728. if (!IsDotNet())
  729. {
  730. bRet = FALSE;
  731. goto Cleanup;
  732. }
  733. }
  734. else
  735. {
  736. //for undo code here
  737. //BUGBUG:XIAOZ Adding code here
  738. }
  739. if (IsNEC98())
  740. {
  741. DoMessageBox(GetConsoleWindow(), IDS_NEC98, IDS_MAIN_TITLE, MB_OK);
  742. bRet = FALSE;
  743. goto Cleanup;
  744. }
  745. if (IsIA64())
  746. {
  747. DoMessageBox(GetConsoleWindow(), IDS_IA64, IDS_MAIN_TITLE, MB_OK);
  748. bRet = FALSE;
  749. goto Cleanup;
  750. }
  751. if (IsOnTSClient())
  752. {
  753. DoMessageBox(GetConsoleWindow(), IDS_ON_TS_CLIENT, IDS_MAIN_TITLE, MB_OK);
  754. bRet = FALSE;
  755. goto Cleanup;
  756. }
  757. //if (IsTSServiceRunning() && IsTSConnectionEnabled())
  758. //{
  759. // DoMessageBox(GetConsoleWindow(), IDS_TS_ENABLED, IDS_MAIN_TITLE, MB_OK);
  760. // bRet = FALSE;
  761. // goto Cleanup;
  762. //}
  763. if (IsOtherSessionOnTS())
  764. {
  765. DoMessageBox(GetConsoleWindow(), IDS_TS_CLOSE_SESSION, IDS_MAIN_TITLE, MB_OK);
  766. bRet = FALSE;
  767. goto Cleanup;
  768. }
  769. bIsAdmin = IsAdmin();
  770. if (dwMode == CLMT_DOMIG)
  771. {
  772. if (!bIsAdmin)
  773. {
  774. DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
  775. bRet = FALSE;
  776. goto Cleanup;
  777. }
  778. if (g_fRunWinnt32)
  779. {
  780. if (!IsUserOKWithCheckUpgrade())
  781. {
  782. bRet = FALSE;
  783. goto Cleanup;
  784. }
  785. }
  786. hr = GetSavedInstallLocale(&lcid);
  787. if (HRESULT_CODE(hr) == ERROR_FILE_NOT_FOUND)
  788. {
  789. hr = SaveInstallLocale();
  790. if (FAILED(hr))
  791. {
  792. bRet = FALSE;
  793. }
  794. }
  795. }
  796. else if ( (dwMode == CLMT_CURE_PROGRAM_FILES)
  797. || (dwMode == CLMT_CURE_ALL) )
  798. {
  799. if (!bIsAdmin)
  800. {
  801. DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
  802. bRet = FALSE;
  803. goto Cleanup;
  804. }
  805. }
  806. else if (dwMode == CLMT_CLEANUP_AFTER_UPGRADE)
  807. {
  808. if (!bIsAdmin)
  809. {
  810. DoMessageBox(GetConsoleWindow(), IDS_ADMIN_LOGON_DOTNET, IDS_MAIN_TITLE, MB_OK);
  811. bRet = FALSE;
  812. goto Cleanup;
  813. }
  814. }
  815. if(!DoesUserHavePrivilege(SE_SHUTDOWN_NAME)
  816. || !DoesUserHavePrivilege(SE_BACKUP_NAME)
  817. || !DoesUserHavePrivilege(SE_RESTORE_NAME)
  818. || !DoesUserHavePrivilege(SE_SYSTEM_ENVIRONMENT_NAME))
  819. {
  820. DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
  821. bRet = FALSE;
  822. goto Cleanup;
  823. }
  824. if(!EnablePrivilege(SE_SHUTDOWN_NAME,TRUE)
  825. || !EnablePrivilege(SE_BACKUP_NAME,TRUE)
  826. || !EnablePrivilege(SE_RESTORE_NAME,TRUE)
  827. || !EnablePrivilege(SE_SYSTEM_ENVIRONMENT_NAME,TRUE))
  828. {
  829. DoMessageBox(GetConsoleWindow(), IDS_ADMIN, IDS_MAIN_TITLE, MB_OK);
  830. bRet = FALSE;
  831. goto Cleanup;
  832. }
  833. //else //This means undo which we do not need user to provide .net CD
  834. //{
  835. // DWORD dwStatusinReg;
  836. // hr = CLMTGetMachineState(&dwStatusinReg);
  837. // if ( (hr != S_OK) || (CLMT_STATE_MIGRATION_DONE != dwStatusinReg))
  838. // {
  839. // DPF (APPerr, L"DLL.C: can not get the CLMT status from registry or you have not run the clmt tools!");
  840. // //BUGBUG:XIAOZ:ADD a DLG here
  841. // bRet = FALSE;
  842. // goto Cleanup;
  843. // }
  844. //}
  845. Cleanup:
  846. return bRet;
  847. }
  848. /*++
  849. Routine Description:
  850. This routine does system wide registry search and replace, the string replace table
  851. is in global variable g_StrReplaceTable
  852. Arguments:
  853. hKeyUser - user registry key handle
  854. UserName - user name that hKeyUser belongs to
  855. DomainName - domain name the UserName belongs to
  856. Return Value:
  857. TRUE - if succeeds.
  858. --*/
  859. HRESULT DoRegistryAnalyze()
  860. {
  861. LPTSTR lpUser,lpSearchStr,lpReplaceStr,lpFullPath;
  862. UINT i;
  863. //TCHAR szExcludeList[] = TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\0\0");
  864. TCHAR szExcludeList[] = TEXT("HKLM\\Software\\Microsoft\\Shared Tools\\Stationery\0\0");
  865. LPTSTR lpszExcludeList = NULL;
  866. HRESULT hr ;
  867. {
  868. HKEY hkey;
  869. LONG lRes;
  870. lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  871. TEXT("SOFTWARE\\Microsoft\\DRM"),
  872. 0,KEY_ALL_ACCESS,&hkey);
  873. if (ERROR_SUCCESS == lRes)
  874. {
  875. hr = RegistryAnalyze(hkey,NULL,NULL,&g_StrReplaceTable,lpszExcludeList,REG_SZ,
  876. TEXT("HKLM\\SOFTWARE\\Microsoft\\DRM"),TRUE);
  877. RegCloseKey(hkey);
  878. }
  879. }
  880. if (!LoopUser(UpdateRegPerUser))
  881. {
  882. hr = E_FAIL;
  883. }
  884. else
  885. {
  886. lpszExcludeList = malloc(MultiSzLen(szExcludeList)*sizeof(TCHAR));
  887. if (lpszExcludeList)
  888. {
  889. memmove((LPBYTE)lpszExcludeList,(LPBYTE)szExcludeList,MultiSzLen(szExcludeList)*sizeof(TCHAR));
  890. //hr = RegistryAnalyze(HKEY_LOCAL_MACHINE,NULL,NULL,&g_StrReplaceTable,lpszExcludeList,FALSE,NULL);
  891. hr = RegistryAnalyze(HKEY_LOCAL_MACHINE,NULL,NULL,&g_StrReplaceTable,NULL,FALSE,NULL,TRUE);
  892. free(lpszExcludeList);
  893. }
  894. else
  895. {
  896. hr = E_OUTOFMEMORY;
  897. }
  898. }
  899. return hr;
  900. }
  901. //-----------------------------------------------------------------------
  902. //
  903. // Function: AddEventSource
  904. //
  905. // Descrip: Add EventLog source to registry
  906. //
  907. // Returns: Win32 Error Code
  908. //
  909. // Notes:
  910. //
  911. // History: 03/05/2002 rerkboos Created
  912. //
  913. // Notes: none.
  914. //
  915. //-----------------------------------------------------------------------
  916. LONG AddEventSource(VOID)
  917. {
  918. HKEY hKey;
  919. LONG lRet;
  920. TCHAR szMessageFile[MAX_PATH+1];
  921. if (GetModuleFileName(NULL, szMessageFile, ARRAYSIZE(szMessageFile)-1))
  922. {
  923. szMessageFile[ARRAYSIZE(szMessageFile)-1] = TEXT('\0');
  924. lRet = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  925. TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\CLMT"),
  926. 0,
  927. NULL,
  928. 0,
  929. KEY_WRITE,
  930. NULL,
  931. &hKey,
  932. NULL);
  933. if (lRet == ERROR_SUCCESS)
  934. {
  935. lRet = RegSetValueEx(hKey,
  936. TEXT("EventMessageFile"),
  937. 0,
  938. REG_EXPAND_SZ,
  939. (LPBYTE) szMessageFile,
  940. sizeof(szMessageFile));
  941. if (lRet == ERROR_SUCCESS)
  942. {
  943. DWORD dwData = EVENTLOG_ERROR_TYPE |
  944. EVENTLOG_WARNING_TYPE |
  945. EVENTLOG_INFORMATION_TYPE;
  946. lRet = RegSetValueEx(hKey,
  947. TEXT("TypesSupported"),
  948. 0,
  949. REG_DWORD,
  950. (LPBYTE) &dwData,
  951. sizeof(dwData));
  952. }
  953. RegCloseKey(hKey);
  954. }
  955. }
  956. else
  957. {
  958. lRet = GetLastError();
  959. }
  960. return lRet;
  961. }
  962. //-----------------------------------------------------------------------
  963. //
  964. // Function: ReportEvent
  965. //
  966. // Descrip: Report event to Event Log
  967. //
  968. // Returns: Win32 Error Code
  969. //
  970. // Notes:
  971. //
  972. // History: 03/05/2002 rerkboos Created
  973. //
  974. // Notes: none.
  975. //
  976. //-----------------------------------------------------------------------
  977. LONG CLMTReportEvent(
  978. WORD wType, // Event type
  979. WORD wCategory, // Event category
  980. DWORD dwEventID, // Event identifier
  981. WORD wNumSubstitute, // Number of strings to merge
  982. LPCTSTR *lplpMessage // Pointer to message string array
  983. )
  984. {
  985. HANDLE hEventLog;
  986. LONG lRet;
  987. TCHAR szUserName[UNLEN + 1];
  988. DWORD cchUserName = ARRAYSIZE(szUserName);
  989. hEventLog = RegisterEventSource(NULL, TEXT("CLMT"));
  990. if (hEventLog)
  991. {
  992. // Get the user name who run the tool
  993. if (GetUserName(szUserName, &cchUserName))
  994. {
  995. LPVOID lpSidCurrentUser;
  996. DWORD cbSid;
  997. TCHAR szDomainName[MAX_PATH];
  998. DWORD cbDomainName = ARRAYSIZE(szDomainName) * sizeof(TCHAR);
  999. SID_NAME_USE sidNameUse;
  1000. // Allocate enough memory for largest possible SID
  1001. cbSid = SECURITY_MAX_SID_SIZE;
  1002. lpSidCurrentUser = MEMALLOC(cbSid);
  1003. if (lpSidCurrentUser)
  1004. {
  1005. if (LookupAccountName(NULL,
  1006. szUserName,
  1007. (PSID) lpSidCurrentUser,
  1008. &cbSid,
  1009. szDomainName,
  1010. &cbDomainName,
  1011. &sidNameUse))
  1012. {
  1013. if (ReportEvent(hEventLog,
  1014. wType,
  1015. wCategory,
  1016. dwEventID,
  1017. (PSID) lpSidCurrentUser,
  1018. wNumSubstitute,
  1019. 0,
  1020. lplpMessage,
  1021. NULL))
  1022. {
  1023. lRet = ERROR_SUCCESS;
  1024. }
  1025. else
  1026. {
  1027. lRet = GetLastError();
  1028. }
  1029. }
  1030. else
  1031. {
  1032. lRet = GetLastError();
  1033. }
  1034. MEMFREE(lpSidCurrentUser);
  1035. }
  1036. }
  1037. else
  1038. {
  1039. if (ReportEvent(hEventLog,
  1040. wType,
  1041. wCategory,
  1042. dwEventID,
  1043. NULL,
  1044. wNumSubstitute,
  1045. 0,
  1046. lplpMessage,
  1047. NULL))
  1048. {
  1049. lRet = ERROR_SUCCESS;
  1050. }
  1051. else
  1052. {
  1053. lRet = GetLastError();
  1054. }
  1055. }
  1056. DeregisterEventSource(hEventLog);
  1057. }
  1058. else
  1059. {
  1060. lRet = GetLastError();
  1061. }
  1062. return lRet;
  1063. }
  1064. void Deinit(BOOL bOleInit)
  1065. {
  1066. if (g_hMutex)
  1067. {
  1068. CloseHandle(g_hMutex);
  1069. }
  1070. if (INVALID_HANDLE_VALUE != g_hInf)
  1071. {
  1072. SetupCloseInfFile(g_hInf);
  1073. }
  1074. DeInitStrRepaceTable();
  1075. if (bOleInit)
  1076. {
  1077. CoUninitialize();
  1078. }
  1079. }
  1080. //-----------------------------------------------------------------------
  1081. //
  1082. // Function: DoCLMTCleanUpAfterFirstReboot
  1083. //
  1084. // Descrip: Do the clean up after the machine has been run CLMT and
  1085. // reboot (before upgraded to .NET)
  1086. //
  1087. // Returns: S_OK if cure Program Files successfully
  1088. // S_FALSE if Program Files cannot be cured (no error)
  1089. // Else if error occurred
  1090. //
  1091. // History: 07/18/2002 rerkboos Created
  1092. //
  1093. // Notes: none.
  1094. //
  1095. //-----------------------------------------------------------------------
  1096. HRESULT DoCLMTCureProgramFiles()
  1097. {
  1098. HRESULT hr;
  1099. BOOL bIsNTFS;
  1100. LONG lRet;
  1101. HKEY hRunKey;
  1102. hr = IsSysVolNTFS(&bIsNTFS);
  1103. if ((S_OK == hr) && !bIsNTFS)
  1104. {
  1105. hr = S_FALSE;
  1106. DoMessageBox(GetConsoleWindow(),
  1107. IDS_ASKING_CONVERT_TO_NTFS,
  1108. IDS_MAIN_TITLE,
  1109. MB_OK | MB_SYSTEMMODAL);
  1110. goto EXIT;
  1111. }
  1112. hr = INFCreateHardLink(INVALID_HANDLE_VALUE, FOLDER_CREATE_HARDLINK, TRUE);
  1113. if (FAILED(hr))
  1114. {
  1115. DPF(APPerr, L"DLL.C: INFCreateHardLink returned error: %d (%#x)\n", hr, hr);
  1116. hr = S_FALSE;
  1117. }
  1118. else
  1119. {
  1120. hr = S_OK;
  1121. }
  1122. EXIT:
  1123. return hr;
  1124. }
  1125. //-----------------------------------------------------------------------
  1126. //
  1127. // Function: DoCLMTCleanUpAfterFirstReboot
  1128. //
  1129. // Descrip: Do the clean up after the machine has been run CLMT and
  1130. // reboot (before upgraded to .NET)
  1131. //
  1132. // Returns: S_OK if no error occured
  1133. //
  1134. // History: 07/18/2002 rerkboos Created
  1135. //
  1136. // Notes: none.
  1137. //
  1138. //-----------------------------------------------------------------------
  1139. HRESULT DoCLMTCleanUpAfterFirstReboot()
  1140. {
  1141. HRESULT hr;
  1142. TCHAR szInfFile[MAX_PATH];
  1143. HKEY hRunKey;
  1144. LONG lRet;
  1145. g_hInf = INVALID_HANDLE_VALUE;
  1146. // Load INF
  1147. hr = GetInfFilePath(szInfFile, ARRAYSIZE(szInfFile));
  1148. if (SUCCEEDED(hr))
  1149. {
  1150. hr = UpdateINFFileSys(szInfFile);
  1151. if (SUCCEEDED(hr))
  1152. {
  1153. g_hInf = SetupOpenInfFile(szInfFile,
  1154. NULL,
  1155. INF_STYLE_WIN4,
  1156. NULL);
  1157. if (g_hInf == INVALID_HANDLE_VALUE)
  1158. {
  1159. hr = HRESULT_FROM_WIN32(GetLastError());
  1160. }
  1161. }
  1162. }
  1163. if (FAILED(hr))
  1164. {
  1165. return hr;
  1166. }
  1167. //
  1168. // do the per-system clean up stuffs here...
  1169. //
  1170. // Close the current INF file to update settings in INF
  1171. // Here, each callback function of LoopUser() must call UpdateINFFilePerUser
  1172. // to update per-user settings
  1173. SetupCloseInfFile(g_hInf);
  1174. g_hInf = INVALID_HANDLE_VALUE;
  1175. //
  1176. // do the per-user clean up stuffs here...
  1177. //
  1178. LoopUser(DeleteUnwantedFilesPerUser);
  1179. // Cleanup the variables
  1180. if (g_hInf != INVALID_HANDLE_VALUE)
  1181. {
  1182. SetupCloseInfFile(g_hInf);
  1183. g_hInf = INVALID_HANDLE_VALUE;
  1184. }
  1185. // Return S_FALSE because we don't want to reboot the machine
  1186. return S_FALSE;
  1187. }
  1188. //-----------------------------------------------------------------------
  1189. //
  1190. // Function: DoCLMTCleanUpAfterDotNetUpgrade
  1191. //
  1192. // Descrip: Do the clean up after the machine has been run CLMT and
  1193. // upgraded to .NET
  1194. //
  1195. // Returns: S_OK if no error occured
  1196. //
  1197. // History: 07/09/2002 rerkboos Created
  1198. //
  1199. // Notes: none.
  1200. //
  1201. //-----------------------------------------------------------------------
  1202. HRESULT DoCLMTCleanUpAfterDotNetUpgrade()
  1203. {
  1204. HRESULT hr = S_OK;
  1205. TCHAR szInfFile[MAX_PATH];
  1206. TCHAR szToDoInfFile[MAX_PATH];
  1207. HKEY hRunKey;
  1208. LONG lRet;
  1209. g_hInf = INVALID_HANDLE_VALUE;
  1210. g_hInfDoItem = INVALID_HANDLE_VALUE;
  1211. DPF(APPmsg, TEXT("[Enter CleanupAfterDotNetUpgrade]"));
  1212. //
  1213. // Load Migrate INF
  1214. //
  1215. hr = GetInfFilePath(szInfFile, ARRAYSIZE(szInfFile));
  1216. if (SUCCEEDED(hr))
  1217. {
  1218. hr = UpdateINFFileSys(szInfFile);
  1219. if (SUCCEEDED(hr))
  1220. {
  1221. g_hInf = SetupOpenInfFile(szInfFile,
  1222. NULL,
  1223. INF_STYLE_WIN4,
  1224. NULL);
  1225. if (g_hInf == INVALID_HANDLE_VALUE)
  1226. {
  1227. hr = HRESULT_FROM_WIN32(GetLastError());
  1228. }
  1229. }
  1230. }
  1231. if (g_hInf == INVALID_HANDLE_VALUE)
  1232. {
  1233. return hr;
  1234. }
  1235. //
  1236. // Load ClmtDo.inf
  1237. //
  1238. if (GetSystemWindowsDirectory(szToDoInfFile, ARRAYSIZE(szToDoInfFile)))
  1239. {
  1240. if (ConcatenatePaths(szToDoInfFile, CLMT_BACKUP_DIR, ARRAYSIZE(szToDoInfFile)))
  1241. {
  1242. if (ConcatenatePaths(szToDoInfFile, TEXT("CLMTDO.INF"), ARRAYSIZE(szToDoInfFile)))
  1243. {
  1244. g_hInfDoItem = SetupOpenInfFile(szToDoInfFile,
  1245. NULL,
  1246. INF_STYLE_WIN4,
  1247. NULL);
  1248. }
  1249. }
  1250. }
  1251. if (g_hInfDoItem == INVALID_HANDLE_VALUE)
  1252. {
  1253. hr = HRESULT_FROM_WIN32(GetLastError());
  1254. return hr;
  1255. }
  1256. //
  1257. // Do the CLMT Cleanup (Per System) stuffs here...
  1258. //
  1259. ResetServicesStatus(g_hInfDoItem, TEXT_SERVICE_STATUS_CLEANUP_SECTION);
  1260. ResetServicesStartUp(g_hInfDoItem, TEXT_SERVICE_STARTUP_CLEANUP_SECTION);
  1261. DeleteUnwantedFiles(g_hInf, TEXT("Folders.PerSystem.Cleanup"));
  1262. INFVerifyHardLink(g_hInfDoItem,TEXT("Folder.HardLink"));
  1263. // Close the current INF file to update settings in INF
  1264. // Each Call back function of LoopUser() must call UpdateINFFilePerUser
  1265. // to update per-user settings
  1266. SetupCloseInfFile(g_hInf);
  1267. g_hInf = INVALID_HANDLE_VALUE;
  1268. // Close ClmtDo.inf handle, as we don't need it anymore
  1269. SetupCloseInfFile(g_hInfDoItem);
  1270. //
  1271. // Do the CLMT Cleanup (Per User) stuffs here...
  1272. //
  1273. LoopUser(DeleteUnwantedFilesPerUser);
  1274. // Remove CLMT from registry Run key
  1275. lRet = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT_RUN_KEY, &hRunKey);
  1276. if (lRet == ERROR_SUCCESS)
  1277. {
  1278. RemoveFromRunKey(TEXT("/FINAL"));
  1279. RegCloseKey(hRunKey);
  1280. }
  1281. //
  1282. // Cleanup the variables
  1283. //
  1284. if (g_hInf != INVALID_HANDLE_VALUE)
  1285. {
  1286. SetupCloseInfFile(g_hInf);
  1287. }
  1288. DPF(APPmsg, TEXT("[Exit CleanupAfterDotNetUpgrade]"));
  1289. return S_OK;
  1290. }
  1291. //-----------------------------------------------------------------------
  1292. //
  1293. // Function: DeleteUnwantedFiles
  1294. //
  1295. // Descrip: Delete unwanted files and directories after the machine
  1296. // has been upgraded to .NET. The list of files/directories
  1297. // are listed in INF.
  1298. // File/directory will be deleted if and only if Loc file name
  1299. // does not match the expected English file name. This prevents
  1300. // deleting English file/directory.
  1301. //
  1302. // Returns: S_OK if no error occured
  1303. //
  1304. // History: 07/09/2002 rerkboos Created
  1305. //
  1306. // Notes: Format in INF:
  1307. // <FileType>, <Loc File to be deleted>, <Expected Eng File>
  1308. //
  1309. // FileType:- 0 = Directory
  1310. // 1 = File
  1311. //
  1312. //-----------------------------------------------------------------------
  1313. HRESULT DeleteUnwantedFiles(
  1314. HINF hInf,
  1315. LPCTSTR lpInfSection
  1316. )
  1317. {
  1318. HRESULT hr = S_OK;
  1319. BOOL bRet = TRUE;
  1320. LONG lLineCount;
  1321. LONG lLineIndex;
  1322. INT iFileType;
  1323. TCHAR szFileName[2 * MAX_PATH];
  1324. TCHAR szEngFileName[2 * MAX_PATH];
  1325. INFCONTEXT context;
  1326. if (hInf == INVALID_HANDLE_VALUE || lpInfSection == NULL)
  1327. {
  1328. return E_INVALIDARG;
  1329. }
  1330. // Read the list of services to be reset from INF
  1331. lLineCount = SetupGetLineCount(hInf, lpInfSection);
  1332. if (lLineCount >= 0)
  1333. {
  1334. for (lLineIndex = 0 ; lLineIndex < lLineCount && bRet ; lLineIndex++)
  1335. {
  1336. bRet = SetupGetLineByIndex(hInf,
  1337. lpInfSection,
  1338. (DWORD) lLineIndex,
  1339. &context);
  1340. if (bRet)
  1341. {
  1342. bRet = SetupGetIntField(&context, 1, &iFileType)
  1343. && SetupGetStringField(&context,
  1344. 2,
  1345. szFileName,
  1346. ARRAYSIZE(szFileName),
  1347. NULL)
  1348. && SetupGetStringField(&context,
  1349. 3,
  1350. szEngFileName,
  1351. ARRAYSIZE(szEngFileName),
  1352. NULL);
  1353. if (bRet
  1354. && MyStrCmpI(szFileName, szEngFileName) != LSTR_EQUAL)
  1355. {
  1356. switch (iFileType)
  1357. {
  1358. case 0:
  1359. // Directories
  1360. hr = DeleteDirectory(szFileName);
  1361. if (FAILED(hr) && HRESULT_CODE(hr) != ERROR_PATH_NOT_FOUND)
  1362. {
  1363. goto EXIT;
  1364. }
  1365. break;
  1366. case 1:
  1367. // Files
  1368. hr = MyDeleteFile(szFileName);
  1369. if (FAILED(hr) && HRESULT_CODE(hr) != ERROR_PATH_NOT_FOUND)
  1370. {
  1371. goto EXIT;
  1372. }
  1373. break;
  1374. }
  1375. }
  1376. }
  1377. }
  1378. }
  1379. hr = (bRet ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
  1380. EXIT:
  1381. return hr;
  1382. }
  1383. //-----------------------------------------------------------------------
  1384. //
  1385. // Function: DeleteUnwantedFilesPerUser
  1386. //
  1387. // Descrip: This is a call back function for LoopUser().
  1388. //
  1389. // Returns: S_OK if no error occured
  1390. //
  1391. // History: 07/09/2002 rerkboos Created
  1392. //
  1393. // Notes: Format in INF:
  1394. // <FileType>, <Loc File to be deleted>, <Expected Eng File>
  1395. //
  1396. // FileType:- 0 = Directory
  1397. // 1 = File
  1398. //
  1399. //-----------------------------------------------------------------------
  1400. HRESULT DeleteUnwantedFilesPerUser(
  1401. HKEY hKeyUser,
  1402. LPCTSTR UserName,
  1403. LPCTSTR DomainName,
  1404. LPTSTR UserSid
  1405. )
  1406. {
  1407. HRESULT hr = S_OK;
  1408. hr = UpdateINFFilePerUser(g_szInfFile, UserName ,UserSid , FALSE);
  1409. if (SUCCEEDED(hr))
  1410. {
  1411. g_hInf = SetupOpenInfFile(g_szInfFile,
  1412. NULL,
  1413. INF_STYLE_WIN4,
  1414. NULL);
  1415. if (g_hInf != INVALID_HANDLE_VALUE)
  1416. {
  1417. // Delete files/directories here
  1418. hr = DeleteUnwantedFiles(g_hInf, TEXT("Folders.PerUser.Cleanup"));
  1419. // Close Inf file for this user
  1420. SetupCloseInfFile(g_hInf);
  1421. g_hInf = INVALID_HANDLE_VALUE;
  1422. }
  1423. else
  1424. {
  1425. hr = HRESULT_FROM_WIN32(GetLastError());
  1426. }
  1427. }
  1428. return hr;
  1429. }
  1430. //-----------------------------------------------------------------------
  1431. //
  1432. // Function: AddRunValueToRegistry
  1433. //
  1434. // Descrip: This will add "CLMT /switch" to Run key. So CLMT can
  1435. // do the cleanup stuffs after next reboot.
  1436. //
  1437. // Returns: S_OK if no error occured
  1438. //
  1439. // History: 07/29/2002 rerkboos Created
  1440. //
  1441. // Notes: lpCmdSwitch should be supplied in format "/something"
  1442. //
  1443. //-----------------------------------------------------------------------
  1444. HRESULT AddRunValueToRegistry(
  1445. LPCTSTR lpCmdSwitch
  1446. )
  1447. {
  1448. HRESULT hr = S_FALSE;
  1449. TCHAR szBackupDir[MAX_PATH];
  1450. TCHAR szRun[MAX_PATH];
  1451. DPF(dlInfo, TEXT("Add CLMT with switch '%s' to Run key"), lpCmdSwitch);
  1452. if (GetSystemWindowsDirectory(szBackupDir, ARRAYSIZE(szBackupDir)))
  1453. {
  1454. if (ConcatenatePaths(szBackupDir,
  1455. CLMT_BACKUP_DIR,
  1456. ARRAYSIZE(szBackupDir)))
  1457. {
  1458. hr = StringCchCopy(szRun, ARRAYSIZE(szRun), szBackupDir);
  1459. if (SUCCEEDED(hr))
  1460. {
  1461. if (ConcatenatePaths(szRun, TEXT("\\CLMT.EXE "), ARRAYSIZE(szRun)))
  1462. {
  1463. hr = StringCchCat(szRun, ARRAYSIZE(szRun), lpCmdSwitch);
  1464. if (SUCCEEDED(hr))
  1465. {
  1466. SetRunValue(TEXT_CLMT_RUN_VALUE, szRun);
  1467. }
  1468. }
  1469. }
  1470. }
  1471. }
  1472. return hr;
  1473. }
  1474. //-----------------------------------------------------------------------
  1475. //
  1476. // Function: DoCLMTDisplayAccountChangeDialog
  1477. //
  1478. // Descrip: Display the dialog notify user of Administrator account
  1479. // name change.
  1480. //
  1481. // Returns: n/a
  1482. //
  1483. // History: 07/29/2002 rerkboos Created
  1484. //
  1485. // Notes: none.
  1486. //
  1487. //-----------------------------------------------------------------------
  1488. INT DoCLMTDisplayAccountChangeDialog()
  1489. {
  1490. return (INT) DialogBoxParam(GetModuleHandle(NULL),
  1491. MAKEINTRESOURCE(IDD_STARTUP_DLG),
  1492. GetConsoleWindow(),
  1493. (DLGPROC) AccountChangeDlgProc,
  1494. (LPARAM) NULL);
  1495. }
  1496. //-----------------------------------------------------------------------------
  1497. //
  1498. // Function: AccountChangeDlgProc
  1499. //
  1500. // Synopsis: Dialog box procedure
  1501. //
  1502. // Returns:
  1503. //
  1504. // History: 9/02/2002 rerkboos created
  1505. //
  1506. // Notes: none
  1507. //
  1508. //-----------------------------------------------------------------------------
  1509. BOOL
  1510. CALLBACK
  1511. AccountChangeDlgProc(
  1512. HWND hwndDlg,
  1513. UINT uMsg,
  1514. WPARAM wParam,
  1515. LPARAM lParam
  1516. )
  1517. {
  1518. BOOL bRet;
  1519. DWORD dwErr;
  1520. TCHAR szOldAdminName[64];
  1521. TCHAR szAdminChange[1024];
  1522. LPTSTR lpArgs[1];
  1523. switch (uMsg)
  1524. {
  1525. case WM_INITDIALOG:
  1526. // Init the dialog
  1527. ShowWindow(hwndDlg, SW_SHOWNORMAL);
  1528. bRet = GetUserNameChangeLog(TEXT("Administrator"),
  1529. szOldAdminName,
  1530. ARRAYSIZE(szOldAdminName));
  1531. if (bRet)
  1532. {
  1533. lpArgs[0] = szOldAdminName;
  1534. dwErr = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1535. NULL,
  1536. MSG_CLMT_ADMIN_ACCT_CHANGE,
  1537. 0,
  1538. szAdminChange,
  1539. ARRAYSIZE(szAdminChange),
  1540. (va_list *) lpArgs);
  1541. }
  1542. else
  1543. {
  1544. dwErr = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1545. NULL,
  1546. MSG_CLMT_ACCT_CHANGE,
  1547. 0,
  1548. szAdminChange,
  1549. ARRAYSIZE(szAdminChange),
  1550. NULL);
  1551. }
  1552. SendMessage(GetDlgItem(hwndDlg, ID_STARTUP_DLG_INFO),
  1553. WM_SETTEXT,
  1554. wParam,
  1555. (LPARAM) szAdminChange);
  1556. case WM_COMMAND:
  1557. // Handle command buttons
  1558. switch (wParam)
  1559. {
  1560. case ID_STARTUP_DLG_NEXT:
  1561. EndDialog(hwndDlg, ID_STARTUP_DLG_NEXT);
  1562. break;
  1563. case ID_STARTUP_DLG_CANCEL:
  1564. EndDialog(hwndDlg, ID_STARTUP_DLG_CANCEL);
  1565. break;
  1566. case ID_STARTUP_DLG_README:
  1567. ShowReadMe();
  1568. break;
  1569. }
  1570. break;
  1571. case WM_CLOSE:
  1572. EndDialog(hwndDlg, ID_STARTUP_DLG_CANCEL);
  1573. break;
  1574. default:
  1575. break;
  1576. }
  1577. return FALSE;
  1578. }
  1579. HRESULT UpdateHardLinkInfoPerUser(
  1580. HKEY hKeyUser,
  1581. LPCTSTR UserName,
  1582. LPCTSTR DomainName,
  1583. LPTSTR UserSid)
  1584. {
  1585. HRESULT hr;
  1586. HINF hInf;
  1587. if (!MyStrCmpI(UserSid,TEXT("Default_User_SID")))
  1588. {
  1589. return S_OK;
  1590. }
  1591. hr = EnsureDoItemInfFile(g_szToDoINFFileName,ARRAYSIZE(g_szToDoINFFileName));
  1592. if (FAILED(hr))
  1593. {
  1594. goto Cleanup;
  1595. }
  1596. hr = UpdateINFFilePerUser(g_szToDoINFFileName, UserName , UserSid, FALSE);
  1597. hInf = SetupOpenInfFile(g_szToDoINFFileName, NULL, INF_STYLE_WIN4,NULL);
  1598. if (hInf != INVALID_HANDLE_VALUE)
  1599. {
  1600. INT LineCount,LineNo;
  1601. INFCONTEXT InfContext;
  1602. LineCount = (UINT)SetupGetLineCount(hInf,TEXT("Folder.HardLink.Peruser"));
  1603. if ((LONG)LineCount > 0)
  1604. {
  1605. for (LineNo = 0; LineNo < LineCount; LineNo++)
  1606. {
  1607. BOOL b0, b1, b2, b3;
  1608. TCHAR szKeyName[MAX_PATH], szType[10],
  1609. szFileName[MAX_PATH+1], szExistingFileName[MAX_PATH+1];
  1610. if (!SetupGetLineByIndex(hInf,TEXT("Folder.HardLink.Peruser"),LineNo,&InfContext))
  1611. {
  1612. continue;
  1613. }
  1614. b0 = SetupGetStringField(&InfContext,0,szKeyName,ARRAYSIZE(szKeyName),NULL);
  1615. b1 = SetupGetStringField(&InfContext,1,szType,ARRAYSIZE(szType),NULL);
  1616. b2 = SetupGetStringField(&InfContext,2,szFileName,ARRAYSIZE(szFileName),NULL);
  1617. b3 = SetupGetStringField(&InfContext,3,szExistingFileName,ARRAYSIZE(szExistingFileName),NULL);
  1618. if (!b0 || !b1 || !b2 || !b3)
  1619. {
  1620. continue;
  1621. }
  1622. AddHardLinkEntry(szFileName,szExistingFileName,szType,NULL,NULL,szKeyName);
  1623. }
  1624. }
  1625. SetupCloseInfFile(hInf);
  1626. }
  1627. Cleanup :
  1628. return hr;
  1629. }
  1630. VOID RemoveFromRunKey(
  1631. LPCTSTR lpCLMTOption // Option to be deleted from Run key
  1632. )
  1633. {
  1634. HKEY hRunKey;
  1635. LONG lRet;
  1636. TCHAR szRunValue[MAX_PATH];
  1637. DWORD cbRunValue;
  1638. DWORD dwType;
  1639. // Remove CLMT from registry Run key
  1640. lRet = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT_RUN_KEY, &hRunKey);
  1641. if (lRet == ERROR_SUCCESS)
  1642. {
  1643. cbRunValue = sizeof(szRunValue);
  1644. lRet = RegQueryValueEx(hRunKey,
  1645. TEXT_CLMT_RUN_VALUE,
  1646. NULL,
  1647. &dwType,
  1648. (LPBYTE) szRunValue,
  1649. &cbRunValue);
  1650. if (lRet == ERROR_SUCCESS)
  1651. {
  1652. RemoveSubString(szRunValue, lpCLMTOption);
  1653. // Search if there is another option or not
  1654. // If none, we can safely delete Run key
  1655. if (StrChr(szRunValue, TEXT('/')) == NULL)
  1656. {
  1657. RegDeleteValue(hRunKey, TEXT_CLMT_RUN_VALUE);
  1658. }
  1659. else
  1660. {
  1661. // Other option exists, save the new Run value to registry
  1662. RegSetValueEx(hRunKey,
  1663. TEXT_CLMT_RUN_VALUE,
  1664. 0,
  1665. REG_SZ,
  1666. (CONST BYTE *) szRunValue,
  1667. lstrlen(szRunValue) * sizeof(TCHAR));
  1668. }
  1669. }
  1670. RegCloseKey(hRunKey);
  1671. }
  1672. }