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.

841 lines
24 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. main.cpp
  5. Abstract:
  6. This file contains the implementation of WinMain
  7. Revision History:
  8. Seong Kook Khang (skkhang) 06/07/99
  9. created
  10. Seong Kook Khang (skkhang) 05/10/00
  11. Restructured and cleaned up for Whistler
  12. ******************************************************************************/
  13. // Note: Proxy/Stub Information
  14. // To build a separate proxy/stub DLL,
  15. // run nmake -f PCHealthps.mk in the project directory.
  16. #include "stdwin.h"
  17. #include "resource.h" // resource include for this module
  18. #include "rstrpriv.h"
  19. #include "rstrerr.h"
  20. #include "rstrmgr.h"
  21. #include "extwrap.h"
  22. #include "rstrmap.h"
  23. #include "FrmBase.h"
  24. #include <respoint.h>
  25. #include <enumlogs.h>
  26. #include "srrpcapi.h"
  27. #include "NTServMsg.h" // generated from the MC message compiler
  28. #define RSTRUI_RETURN_CODE_SR_DISABLED 1
  29. #define RSTRUI_RETURN_CODE_NO_DISK_SPACE 3
  30. #define RSTRUI_RETURN_CODE_SMFROZEN 4
  31. #define RSTRUI_RETURN_CODE_SMGR_NOT_ALIVE 5
  32. #define SMGR_INIT_TIMEOUT 2000 // 2 seconds to wait after starting Stmgr to let it initialize itself
  33. // try thrice
  34. enum
  35. {
  36. CMDPARAM_INVALID = 0, // invalid parameter...
  37. // initiating phase
  38. CMDPARAM_NORMAL, // normal UI without any parameter
  39. CMDPARAM_REGSERVER, // register COM server
  40. CMDPARAM_UNREGSERVER, // unregister COM server
  41. CMDPARAM_SILENT, // Silent Restore
  42. // after-boot phase
  43. CMDPARAM_CHECK, // check log file and show result page (normal)
  44. CMDPARAM_INTERRUPTED, // abnormal shutdown, initiate undo
  45. CMDPARAM_HIDERESULT, // do not show success result page for Silent Restore
  46. // commands for debug
  47. CMDPARAM_RESULT_S, // show success result page
  48. CMDPARAM_RESULT_F, // show failure result page
  49. CMDPARAM_RESULT_LD, // show low disk result page
  50. CMDPARAM_SENTINEL
  51. };
  52. // Forward declarations for file static functions
  53. DWORD ParseCommandParameter( DWORD *pdwRP );
  54. void ShowErrorMessage(HRESULT hr);
  55. BOOL IsFreeSpaceOnWindowsDrive( void );
  56. extern BOOL CheckWininitErr();
  57. extern BOOL ValidateLogFile( BOOL *pfSilent, BOOL *pfUndo );
  58. // Application Instance
  59. HINSTANCE g_hInst = NULL;
  60. // External Wrapper Instance
  61. ISRExternalWrapper *g_pExternal = NULL;
  62. // Main Frame Instance
  63. ISRFrameBase *g_pMainFrm = NULL;
  64. // Restore Manager Instance
  65. CRestoreManager *g_pRstrMgr = NULL;
  66. CSRClientLoader g_CSRClientLoader;
  67. /////////////////////////////////////////////////////////////////////////////
  68. BOOL CancelRestorePoint()
  69. {
  70. TraceFunctEnter("CancelRestorePoint");
  71. BOOL fRet = TRUE;
  72. int nUsedRP;
  73. nUsedRP = g_pRstrMgr->GetNewRP();
  74. if (nUsedRP == -1) // not initialized, see if it's the current one
  75. {
  76. CRestorePoint rp;
  77. GetCurrentRestorePoint (rp);
  78. if (rp.GetType() == RESTORE)
  79. nUsedRP = rp.GetNum();
  80. }
  81. DebugTrace(0, "Deleting RP %d", nUsedRP);
  82. if ( nUsedRP > 0 )
  83. fRet = g_pExternal->RemoveRestorePoint( nUsedRP );
  84. TraceFunctLeave();
  85. return( fRet );
  86. }
  87. DWORD ProductFeedback (LPWSTR pszString)
  88. {
  89. TraceFunctEnter("Product Feedback");
  90. HANDLE hFile = INVALID_HANDLE_VALUE;
  91. PROCESS_INFORMATION pi;
  92. STARTUPINFOW si;
  93. DWORD dwErr = ERROR_SUCCESS;
  94. DWORD cbWritten = 0;
  95. const int MAX_STR = 1024;
  96. WCHAR wcsSystem[MAX_PATH];
  97. WCHAR wcsBuffer[MAX_STR];
  98. WCHAR wcsDataFile[MAX_PATH];
  99. const WCHAR c_wcsCommand[] = L"%s\\dwwin.exe -d %s\\%s";
  100. const WCHAR c_wcsManifest[] = L"restore\\rstrdw.txt";
  101. const WCHAR c_wcsData[] = L"restore\\srpfdata.txt";
  102. if (0 == GetSystemDirectoryW (wcsSystem, MAX_PATH))
  103. {
  104. dwErr = GetLastError();
  105. goto Err;
  106. }
  107. // construct the data file to be uploaded
  108. wsprintf (wcsDataFile, L"%s\\%s", wcsSystem, c_wcsData);
  109. hFile = CreateFileW ( wcsDataFile, // file name
  110. GENERIC_WRITE, // file access
  111. 0, // share mode
  112. NULL, // SD
  113. CREATE_ALWAYS, // how to create
  114. 0, // file attributes
  115. NULL); // handle to template file
  116. if (hFile == INVALID_HANDLE_VALUE)
  117. {
  118. dwErr = GetLastError();
  119. trace(0, "! CreateFile : %ld", dwErr);
  120. goto Err;
  121. }
  122. if (FALSE == WriteFile (hFile, (BYTE *) pszString,
  123. lstrlenW(pszString)*sizeof(WCHAR), &cbWritten, NULL))
  124. {
  125. dwErr = GetLastError();
  126. trace(0, "! WriteFile : %ld", dwErr);
  127. goto Err;
  128. }
  129. CloseHandle (hFile);
  130. hFile = INVALID_HANDLE_VALUE;
  131. wsprintf (wcsBuffer, L"%s\\%s", wcsSystem, c_wcsManifest);
  132. hFile = CreateFileW ( wcsBuffer, // file name
  133. GENERIC_WRITE, // file access
  134. 0, // share mode
  135. NULL, // SD
  136. CREATE_ALWAYS, // how to create
  137. 0, // file attributes
  138. NULL); // handle to template file
  139. if (hFile == INVALID_HANDLE_VALUE)
  140. {
  141. dwErr = GetLastError();
  142. trace(0, "! CreateFile : %ld", dwErr);
  143. goto Err;
  144. }
  145. PCHLoadString(IDS_PRODUCTFEEDBACK, wcsBuffer, MAX_STR-1);
  146. lstrcat(wcsBuffer, L"DataFiles=");
  147. lstrcat(wcsBuffer, wcsDataFile);
  148. if (FALSE == WriteFile (hFile, (BYTE *) wcsBuffer,
  149. lstrlenW(wcsBuffer)*sizeof(WCHAR), &cbWritten, NULL))
  150. {
  151. dwErr = GetLastError();
  152. trace(0, "! WriteFile : %ld", dwErr);
  153. goto Err;
  154. }
  155. CloseHandle (hFile);
  156. hFile = INVALID_HANDLE_VALUE;
  157. wsprintf (wcsBuffer, c_wcsCommand, wcsSystem, wcsSystem, c_wcsManifest);
  158. ZeroMemory (&pi, sizeof(pi));
  159. ZeroMemory (&si, sizeof(si));
  160. if (CreateProcessW (NULL, wcsBuffer, NULL, NULL, TRUE,
  161. CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
  162. NULL, wcsSystem, &si, &pi))
  163. {
  164. CloseHandle (pi.hThread);
  165. CloseHandle (pi.hProcess);
  166. }
  167. Err:
  168. if (hFile != INVALID_HANDLE_VALUE)
  169. CloseHandle (hFile);
  170. TraceFunctLeave();
  171. return dwErr;
  172. }
  173. DWORD RestoreHTCKey ()
  174. {
  175. DWORD dwErr = ERROR_SUCCESS;
  176. HKEY hKey = NULL;
  177. WCHAR wszValue[] = L"text/x-component";
  178. if (ERROR_SUCCESS != RegOpenKeyEx (HKEY_CLASSES_ROOT, L".htc", 0,
  179. KEY_READ, &hKey))
  180. {
  181. dwErr = RegCreateKey(HKEY_CLASSES_ROOT, L".htc", &hKey);
  182. if (ERROR_SUCCESS == dwErr)
  183. {
  184. dwErr = RegSetValueEx ( hKey, L"Content Type", 0, REG_SZ,
  185. (BYTE *) wszValue, sizeof(wszValue));
  186. RegCloseKey (hKey);
  187. }
  188. }
  189. return dwErr;
  190. }
  191. /////////////////////////////////////////////////////////////////////////////
  192. //
  193. extern "C" int
  194. WINAPI wWinMain(
  195. HINSTANCE hInstance,
  196. HINSTANCE /*hPrevInstance*/,
  197. LPSTR /*lpCmdLine*/,
  198. int /*nShowCmd*/
  199. )
  200. {
  201. HRESULT hr;
  202. int nRet = 0;
  203. DWORD dwRet=0;
  204. LPWSTR szCmdLine;
  205. LPCWSTR szToken;
  206. const WCHAR cszPrefix[] = L"-/";
  207. int nStartMode = SRASM_NORMAL;
  208. BOOL fLoadRes = FALSE;
  209. int nTries = 0;
  210. BOOL fRebootSystem = FALSE;
  211. DWORD dwCmd;
  212. DWORD dwRP = 0xFFFFFFFF;
  213. BOOL fWasSilent = FALSE;
  214. BOOL fWasUndo = FALSE;
  215. DWORD dwEventID = 0;
  216. DWORD dwDisable = 0;
  217. BOOL fSendFeedback = FALSE;
  218. WCHAR szPFString[MAX_PATH];
  219. DWORD dwPFID = 0;
  220. #if !NOTRACE
  221. InitAsyncTrace();
  222. #endif
  223. TraceFunctEnter("_tWinMain");
  224. g_hInst = hInstance;
  225. // Load SRClient
  226. g_CSRClientLoader.LoadSrClient();
  227. //szCmdLine = ::GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  228. //szToken = ::PathGetArgs( szCmdLine );
  229. // Check credential and set necessary privileges
  230. if ( !::CheckPrivilegesForRestore() )
  231. {
  232. ::ShowSRErrDlg( IDS_ERR_LOW_PRIVILEGE );
  233. goto Exit;
  234. }
  235. // Parse command line parameter
  236. dwCmd = ParseCommandParameter( &dwRP );
  237. // Initialize class objects
  238. if ( !::CreateSRExternalWrapper( FALSE, &g_pExternal ) )
  239. goto Exit;
  240. if ( !::CreateSRFrameInstance( &g_pMainFrm ) )
  241. goto Exit;
  242. if ( !g_pMainFrm->InitInstance( hInstance ) )
  243. goto Exit;
  244. if ( !::CreateRestoreManagerInstance( &g_pRstrMgr ) )
  245. goto Exit;
  246. // if the registry says that SR is enabled, make sure we are
  247. // enabled correctly (service is started, startup mode is correct)
  248. // if registry says we are enabled, but service start type is disabled
  249. // disable us now
  250. if (::SRGetRegDword( HKEY_LOCAL_MACHINE,
  251. s_cszSRRegKey,
  252. s_cszDisableSR,
  253. &dwDisable ) )
  254. {
  255. DWORD dwStart;
  256. if (0 == dwDisable)
  257. {
  258. if (ERROR_SUCCESS == GetServiceStartup(s_cszServiceName, &dwStart) &&
  259. (dwStart == SERVICE_DISABLED || dwStart == SERVICE_DEMAND_START))
  260. {
  261. EnableSR(NULL);
  262. DisableSR(NULL);
  263. }
  264. else
  265. {
  266. EnableSR(NULL);
  267. }
  268. }
  269. }
  270. switch ( dwCmd )
  271. {
  272. case CMDPARAM_NORMAL :
  273. break;
  274. case CMDPARAM_REGSERVER :
  275. dwRet = g_pMainFrm->RegisterServer();
  276. #if DBG==1
  277. if ( dwRet == ERROR_CALL_NOT_IMPLEMENTED )
  278. ::MessageBox(NULL, L"/RegServer is not supported...", L"CommandLine Options", MB_OK);
  279. #endif
  280. goto Exit;
  281. case CMDPARAM_UNREGSERVER :
  282. dwRet = g_pMainFrm->UnregisterServer();
  283. #if DBG==1
  284. if ( dwRet == ERROR_CALL_NOT_IMPLEMENTED )
  285. ::MessageBox(NULL, L"/UnregServer is not supported", L"CommandLine Options", MB_OK);
  286. #endif
  287. goto Exit;
  288. case CMDPARAM_SILENT :
  289. g_pRstrMgr->SilentRestore( dwRP );
  290. goto Exit;
  291. case CMDPARAM_CHECK :
  292. case CMDPARAM_HIDERESULT :
  293. // check result of MoveFileEx, if it's possible...
  294. if ( ValidateLogFile( &fWasSilent, &fWasUndo ) )
  295. {
  296. nStartMode = SRASM_SUCCESS;
  297. }
  298. else
  299. {
  300. // Cancel restore point of "Restore" type
  301. ::CancelRestorePoint();
  302. nStartMode = SRASM_FAIL;
  303. }
  304. g_pRstrMgr->SetIsUndo(fWasUndo);
  305. break;
  306. case CMDPARAM_INTERRUPTED :
  307. // read the log file to get the new restore point
  308. if (ValidateLogFile( &fWasSilent, &fWasUndo ))
  309. {
  310. nStartMode = SRASM_FAIL;
  311. }
  312. else
  313. {
  314. nStartMode = SRASM_FAIL;
  315. }
  316. g_pRstrMgr->SetIsUndo(fWasUndo);
  317. break;
  318. case CMDPARAM_RESULT_S :
  319. // read the log file, but ignore the result
  320. ValidateLogFile( NULL, &fWasUndo );
  321. nStartMode = SRASM_SUCCESS;
  322. g_pRstrMgr->SetIsUndo(fWasUndo);
  323. break;
  324. case CMDPARAM_RESULT_F :
  325. // read the log file, but ignore the result
  326. ValidateLogFile( NULL, &fWasUndo );
  327. nStartMode = SRASM_FAIL;
  328. g_pRstrMgr->SetIsUndo(fWasUndo);
  329. ::CancelRestorePoint();
  330. break;
  331. case CMDPARAM_RESULT_LD :
  332. // read the log file, but ignore the result
  333. ValidateLogFile( NULL, &fWasUndo );
  334. nStartMode = SRASM_FAILLOWDISK;
  335. g_pRstrMgr->SetIsUndo(fWasUndo);
  336. ::CancelRestorePoint();
  337. break;
  338. default :
  339. // Invalid Parameter, simply invoke regular UI
  340. #if DBG==1
  341. ::MessageBox(NULL, L"Unknown Option", L"CommandLine Options", MB_OK);
  342. #endif
  343. break;
  344. }
  345. // also check to see if the Winlogon key to call restore has been
  346. // removed. In normal circumstances, this key should have been
  347. // deleted during the restore but if the machine was not shutdown
  348. // cleanly, this key can remain causing the machine to again
  349. // initiate restore on the next reboot.
  350. ::SHDeleteValue( HKEY_LOCAL_MACHINE, s_cszSRRegKey,s_cszRestoreInProgress);
  351. // if start mode is SRASM_FAIL, check to see if we failed becuase
  352. // of low disk space. If this is the case, show the low disk
  353. // space message. Else check for the interrupted case.
  354. if (nStartMode == SRASM_FAIL)
  355. {
  356. DWORD dwRestoreStatus = ERROR_INTERNAL_ERROR;
  357. ::SRGetRegDword( HKEY_LOCAL_MACHINE,
  358. s_cszSRRegKey,
  359. s_cszRestoreStatus,
  360. &dwRestoreStatus );
  361. if (dwRestoreStatus != 0) // interrupted
  362. {
  363. nStartMode = SRASM_FAILINTERRUPTED;
  364. }
  365. else // Cancel restore point of "Restore" type
  366. {
  367. if (TRUE == CheckForDiskSpaceError())
  368. {
  369. nStartMode = SRASM_FAILLOWDISK;
  370. }
  371. ::CancelRestorePoint();
  372. }
  373. }
  374. switch ( nStartMode )
  375. {
  376. case SRASM_FAIL:
  377. dwEventID = EVMSG_RESTORE_FAILED;
  378. dwPFID = IDS_PFFAILED;
  379. break;
  380. case SRASM_FAILLOWDISK:
  381. dwEventID = EVMSG_RESTORE_FAILED;
  382. dwPFID = IDS_PFFAILEDLOWDISK;
  383. break;
  384. case SRASM_FAILINTERRUPTED:
  385. dwEventID = EVMSG_RESTORE_INTERRUPTED;
  386. dwPFID = IDS_PFINTERRUPTED;
  387. break;
  388. case SRASM_SUCCESS:
  389. dwEventID = EVMSG_RESTORE_SUCCESS;
  390. dwPFID = IDS_PFSUCCESS;
  391. break;
  392. default:
  393. break;
  394. }
  395. if (dwEventID != 0)
  396. {
  397. WCHAR szUnknownRP [MAX_PATH];
  398. const WCHAR *pwszUsedName = g_pRstrMgr->GetUsedName();
  399. HANDLE hEventSource = RegisterEventSource(NULL, s_cszServiceName);
  400. DWORD dwType = g_pRstrMgr->GetUsedType() + 1;
  401. WCHAR szRPType[100], szTime1[50], szTime2[50];
  402. if (NULL == pwszUsedName)
  403. {
  404. PCHLoadString(IDS_UNKNOWN_RP, szUnknownRP, MAX_PATH-1);
  405. pwszUsedName = szUnknownRP;
  406. }
  407. if (hEventSource != NULL)
  408. {
  409. SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, dwEventID,
  410. NULL, 0, pwszUsedName, NULL, NULL);
  411. DeregisterEventSource(hEventSource);
  412. }
  413. // construct a string for PF
  414. if (! fWasSilent)
  415. {
  416. PCHLoadString(IDS_UNKNOWN_RP + dwType, szRPType, sizeof(szRPType)/sizeof(WCHAR));
  417. GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, szTime1, sizeof(szTime1)/sizeof(WCHAR));
  418. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, NULL, NULL, szTime2, sizeof(szTime2)/sizeof(WCHAR));
  419. if (SRFormatMessage(szPFString, dwPFID, szTime1, szTime2, pwszUsedName, szRPType, g_pRstrMgr->GetUsedType(), dwPFID-IDS_PFFAILED))
  420. {
  421. fSendFeedback = TRUE;
  422. }
  423. else
  424. {
  425. trace(0, "! SRFormatMessage");
  426. }
  427. }
  428. {
  429. WCHAR szWMIRepository [MAX_PATH];
  430. GetSystemDirectory (szWMIRepository, MAX_PATH);
  431. lstrcatW (szWMIRepository, L"\\Wbem\\Repository.bak");
  432. Delnode_Recurse (szWMIRepository, TRUE, NULL);
  433. }
  434. }
  435. //
  436. // Before this, perform any necessary bookeeping operations those
  437. // are necessary for both of Normal & Silent Restore
  438. //
  439. if ( fWasSilent )
  440. goto Exit;
  441. // Maybe explicit registration is not really necessary... Doing it here always
  442. // if UI is going to be displayed.
  443. RestoreHTCKey();
  444. g_pMainFrm->RegisterServer();
  445. // Check if SR is frozen or disabled.
  446. if ( nStartMode == SRASM_NORMAL )
  447. if ( !g_pRstrMgr->CanRunRestore( TRUE ) )
  448. goto Exit;
  449. HWND hwnd;
  450. TCHAR szMainWndTitle[MAX_PATH+1];
  451. PCHLoadString(IDS_RESTOREUI_TITLE, szMainWndTitle, MAX_PATH);
  452. // Find Previous Instance.
  453. hwnd = ::FindWindow(CLSNAME_RSTRSHELL, szMainWndTitle);
  454. if (hwnd != NULL)
  455. {
  456. // If exist, activate it.
  457. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  458. ::SetForegroundWindow(hwnd);
  459. }
  460. else
  461. {
  462. if ( g_pMainFrm != NULL )
  463. {
  464. nRet = g_pMainFrm->RunUI( szMainWndTitle, nStartMode );
  465. }
  466. }
  467. Exit:
  468. //if (fSendFeedback)
  469. // ProductFeedback(szPFString);
  470. if ( g_pRstrMgr != NULL )
  471. {
  472. fRebootSystem = g_pRstrMgr->NeedReboot();
  473. g_pRstrMgr->Release();
  474. g_pRstrMgr = NULL;
  475. }
  476. if ( g_pMainFrm != NULL )
  477. {
  478. g_pMainFrm->ExitInstance();
  479. g_pMainFrm->Release();
  480. g_pMainFrm = NULL;
  481. }
  482. if ( g_pExternal != NULL )
  483. {
  484. if ( !fRebootSystem )
  485. {
  486. //
  487. // Since FIFO has been disabled in the UI, if for any reason the UI crashes or
  488. // something bad happens we will come here and give FIFO a chance to resume
  489. //
  490. if ( g_pExternal->EnableFIFO() != ERROR_SUCCESS )
  491. {
  492. ErrorTrace(TRACE_ID, "EnableFIFO() failed");
  493. }
  494. }
  495. g_pExternal->Release();
  496. }
  497. DebugTrace(0, "Closing rstrui.exe...");
  498. TraceFunctLeave();
  499. #if !NOTRACE
  500. TermAsyncTrace();
  501. #endif
  502. if ( fRebootSystem )
  503. {
  504. ::ExitWindowsEx( EWX_REBOOT | EWX_FORCE, 0 );
  505. }
  506. return(nRet);
  507. }
  508. /******************************************************************************/
  509. #if HANDLE_FIRST_RP
  510. #define FIRSTRUN_MAX_RETRY 5
  511. #define FIRSTRUN_SLEEP_LEN 2000
  512. BOOL
  513. CreateFirstRestorePoint()
  514. {
  515. TraceFunctEnter("CreateFirstRestorePoint");
  516. BOOL fRet = FALSE;
  517. DWORD dwRes;
  518. HKEY hKey = NULL;
  519. DWORD dwType;
  520. char szData[MAX_PATH];
  521. DWORD dwDelay;
  522. DWORD cbData;
  523. BOOL fDelayDeleted = FALSE;
  524. int i;
  525. RESTOREPOINTINFO sRPInfo;
  526. STATEMGRSTATUS sSmgrStatus;
  527. dwRes = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_cszIDSVXDKEY, 0, NULL, &hKey );
  528. if ( dwRes != ERROR_SUCCESS )
  529. {
  530. ErrorTrace(TRACE_ID, "RegOpenKeyEx('%s') failed, ret=%u", s_cszIDSVXDKEY, dwRes );
  531. goto Exit;
  532. }
  533. // Check DelayFirstRstpt registry key and delete it if exists
  534. dwType = REG_DWORD;
  535. cbData = sizeof(DWORD);
  536. dwRes = ::RegQueryValueEx( hKey, s_cszIDSDelayFirstRstpt, NULL, &dwType, (LPBYTE)&dwDelay, &cbData );
  537. if ( dwRes != ERROR_SUCCESS || dwType != REG_DWORD || cbData == 0 )
  538. {
  539. DebugTrace(TRACE_ID, "DelayFirstRstpt flag does not exist");
  540. goto Ignored;
  541. }
  542. if ( dwDelay != 1 )
  543. {
  544. DebugTrace(TRACE_ID, "DelayFirstRstpt flag is '%d'", dwDelay);
  545. goto Ignored;
  546. }
  547. // Check OOBEInProgress registry key and do nothing if it exists
  548. dwType = REG_SZ;
  549. cbData = MAX_PATH;
  550. dwRes = ::RegQueryValueEx( hKey, s_cszIDSOOBEInProgress, NULL, &dwType, (LPBYTE)szData, &cbData );
  551. if ( dwRes == ERROR_SUCCESS )
  552. {
  553. DebugTrace(TRACE_ID, "OOBEInProgress flag exists");
  554. goto Ignored;
  555. }
  556. // This should be before deleting DelayFirstRstpt because of the logic of
  557. // SRSetRestorePoint API.
  558. EnsureStateMgr();
  559. // Delete DelayFirstRstpt flag
  560. dwRes = ::RegDeleteValue( hKey, s_cszIDSDelayFirstRstpt );
  561. if ( dwRes == ERROR_SUCCESS )
  562. fDelayDeleted = TRUE;
  563. else
  564. ErrorTrace(TRACE_ID, "RegSetValueEx('%s') failed, ret=%u", s_cszIDSDelayFirstRstpt, dwRes );
  565. // Now set FirstRun restore point
  566. ::ZeroMemory( &sRPInfo, sizeof(sRPInfo) );
  567. sRPInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
  568. sRPInfo.dwRestorePtType = FIRSTRUN;
  569. ::lstrcpy( sRPInfo.szDescription, "CHECKPOINT" );
  570. for ( i = 0; i < FIRSTRUN_MAX_RETRY; i++ )
  571. {
  572. if ( i > 0 )
  573. ::Sleep( FIRSTRUN_SLEEP_LEN );
  574. if ( ::SRSetRestorePoint( &sRPInfo, &sSmgrStatus ) )
  575. {
  576. DebugTrace(TRACE_ID, "FirstRun restore point has been created!!!");
  577. break;
  578. }
  579. DebugTrace(TRACE_ID, "SRSetRestorePoint failed, i=%d, nStatus=%d", i, sSmgrStatus.nStatus);
  580. }
  581. Ignored:
  582. fRet = TRUE;
  583. Exit:
  584. if ( hKey != NULL )
  585. {
  586. if ( !fDelayDeleted )
  587. {
  588. dwRes = ::RegDeleteValue( hKey, s_cszIDSDelayFirstRstpt );
  589. if ( dwRes != ERROR_SUCCESS )
  590. ErrorTrace(TRACE_ID, "RegSetValueEx('%s') failed, ret=%u", s_cszIDSDelayFirstRstpt, dwRes );
  591. }
  592. ::RegCloseKey( hKey );
  593. }
  594. TraceFunctLeave();
  595. return( fRet );
  596. }
  597. #endif //HANDLE_FIRST_RP
  598. /******************************************************************************/
  599. //
  600. // Note:
  601. // =====
  602. // This function loads the error message from resource only dll
  603. // If the resource only dll could not be loaded, this function must not be
  604. // used to display the error
  605. //
  606. void
  607. ShowErrorMessage(
  608. HRESULT hr
  609. )
  610. {
  611. TraceFunctEnter("ShowErrorMessage");
  612. int nErrorMessageID = FALSE ;
  613. TCHAR szErrorTitle[MAX_PATH+1];
  614. TCHAR szErrorMessage[MAX_ERROR_STRING_LENGTH+1];
  615. // display error message and shut down gracefully
  616. switch (hr)
  617. {
  618. default:
  619. case E_UNEXPECTED:
  620. case E_FAIL:
  621. nErrorMessageID = IDS_ERR_RSTR_UNKNOWN;
  622. break;
  623. case E_OUTOFMEMORY:
  624. nErrorMessageID = IDS_ERR_RSTR_OUT_OF_MEMORY;
  625. break;
  626. case E_RSTR_CANNOT_CREATE_DOMDOC:
  627. nErrorMessageID = IDS_ERR_RSTR_CANNOT_CREATE_DOMDOC;
  628. break;
  629. case E_RSTR_INVALID_CONFIG_FILE:
  630. case E_RSTR_NO_PROBLEM_AREAS:
  631. case E_RSTR_NO_PROBLEM_AREA_ATTRS:
  632. case E_RSTR_NO_REQUIRED_ATTR:
  633. nErrorMessageID = IDS_ERR_RSTR_INVALID_CONFIG_FILE;
  634. break;
  635. }
  636. PCHLoadString(IDS_ERR_RSTR_TITLE, szErrorTitle, MAX_PATH);
  637. PCHLoadString(nErrorMessageID, szErrorMessage, MAX_ERROR_STRING_LENGTH);
  638. //
  639. // no owner window (use NULL)
  640. // we could use the GetDesktopWindow() and use that as the owner
  641. // if necessary
  642. //
  643. if ( nErrorMessageID )
  644. {
  645. ::MessageBox(NULL, szErrorMessage, szErrorTitle, MB_OK);
  646. }
  647. TraceFunctLeave();
  648. }
  649. /////////////////////////////////////////////////////////////////////////////
  650. DWORD
  651. ParseCommandParameter( DWORD *pdwRP )
  652. {
  653. TraceFunctEnter("ParseCommandParameter");
  654. DWORD dwCmd = CMDPARAM_INVALID;
  655. LPCWSTR cszCmd;
  656. cszCmd = ::PathGetArgs( ::GetCommandLine() );
  657. DebugTrace(0, "Cmd='%ls'", cszCmd);
  658. if ( ( cszCmd == NULL ) || ( *cszCmd == L'\0' ) )
  659. {
  660. dwCmd = CMDPARAM_NORMAL;
  661. goto Exit;
  662. }
  663. if ( ( *cszCmd == L'-' ) || ( *cszCmd == L'/' ) )
  664. {
  665. cszCmd++;
  666. DebugTrace(0, "Option='%ls'", cszCmd);
  667. if ( *cszCmd != L'\0' )
  668. {
  669. if ( ::StrCmpI( cszCmd, L"c" ) == 0 )
  670. dwCmd = CMDPARAM_CHECK;
  671. else if ( ::StrCmpI( cszCmd, L"regserver" ) == 0 )
  672. dwCmd = CMDPARAM_REGSERVER;
  673. else if ( ::StrCmpI( cszCmd, L"unregserver" ) == 0 )
  674. dwCmd = CMDPARAM_UNREGSERVER;
  675. else if ( ::ChrCmpI( *cszCmd, L'v' ) == 0 )
  676. {
  677. dwCmd = CMDPARAM_SILENT;
  678. cszCmd++;
  679. while ( ( *cszCmd != L'\0' ) &&
  680. ( ( *cszCmd == L' ' ) || ( *cszCmd == L'\t' ) ) )
  681. cszCmd++;
  682. if ( *cszCmd >= L'0' && *cszCmd <= L'9' )
  683. *pdwRP = ::StrToInt( cszCmd );
  684. }
  685. else if ( ::StrCmpI( cszCmd, L"b" ) == 0 )
  686. dwCmd = CMDPARAM_HIDERESULT;
  687. else if ( ::StrCmpNI( cszCmd, L"result:", 7 ) == 0 )
  688. {
  689. cszCmd += 7;
  690. if ( ::StrCmpIW( cszCmd, L"s" ) == 0 )
  691. dwCmd = CMDPARAM_RESULT_S;
  692. else if ( ::StrCmpIW( cszCmd, L"f" ) == 0 )
  693. dwCmd = CMDPARAM_RESULT_F;
  694. else if ( ::StrCmpIW( cszCmd, L"ld" ) == 0 )
  695. dwCmd = CMDPARAM_RESULT_LD;
  696. }
  697. else if ( ::StrCmpI( cszCmd, L"i" ) == 0 )
  698. dwCmd = CMDPARAM_INTERRUPTED;
  699. }
  700. }
  701. Exit:
  702. DebugTrace(0, "m_dwCmd=%d, dwRP=%d", dwCmd, *pdwRP);
  703. TraceFunctLeave();
  704. return( dwCmd );
  705. }
  706. // end of file