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.

817 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. /////////////////////////////////////////////////////////////////////////////
  174. //
  175. extern "C" int
  176. WINAPI wWinMain(
  177. HINSTANCE hInstance,
  178. HINSTANCE /*hPrevInstance*/,
  179. LPSTR /*lpCmdLine*/,
  180. int /*nShowCmd*/
  181. )
  182. {
  183. HRESULT hr;
  184. int nRet = 0;
  185. DWORD dwRet=0;
  186. LPWSTR szCmdLine;
  187. LPCWSTR szToken;
  188. const WCHAR cszPrefix[] = L"-/";
  189. int nStartMode = SRASM_NORMAL;
  190. BOOL fLoadRes = FALSE;
  191. int nTries = 0;
  192. BOOL fRebootSystem = FALSE;
  193. DWORD dwCmd;
  194. DWORD dwRP = 0xFFFFFFFF;
  195. BOOL fWasSilent = FALSE;
  196. BOOL fWasUndo = FALSE;
  197. DWORD dwEventID = 0;
  198. DWORD dwDisable = 0;
  199. BOOL fSendFeedback = FALSE;
  200. WCHAR szPFString[MAX_PATH];
  201. DWORD dwPFID = 0;
  202. #if !NOTRACE
  203. InitAsyncTrace();
  204. #endif
  205. TraceFunctEnter("_tWinMain");
  206. g_hInst = hInstance;
  207. // Load SRClient
  208. g_CSRClientLoader.LoadSrClient();
  209. //szCmdLine = ::GetCommandLine(); //this line necessary for _ATL_MIN_CRT
  210. //szToken = ::PathGetArgs( szCmdLine );
  211. // Check credential and set necessary privileges
  212. if ( !::CheckPrivilegesForRestore() )
  213. {
  214. ::ShowSRErrDlg( IDS_ERR_LOW_PRIVILEGE );
  215. goto Exit;
  216. }
  217. // Parse command line parameter
  218. dwCmd = ParseCommandParameter( &dwRP );
  219. // Initialize class objects
  220. if ( !::CreateSRExternalWrapper( FALSE, &g_pExternal ) )
  221. goto Exit;
  222. if ( !::CreateSRFrameInstance( &g_pMainFrm ) )
  223. goto Exit;
  224. if ( !g_pMainFrm->InitInstance( hInstance ) )
  225. goto Exit;
  226. if ( !::CreateRestoreManagerInstance( &g_pRstrMgr ) )
  227. goto Exit;
  228. // if the registry says that SR is enabled, make sure we are
  229. // enabled correctly (service is started, startup mode is correct)
  230. // if registry says we are enabled, but service start type is disabled
  231. // disable us now
  232. if (::SRGetRegDword( HKEY_LOCAL_MACHINE,
  233. s_cszSRRegKey,
  234. s_cszDisableSR,
  235. &dwDisable ) )
  236. {
  237. DWORD dwStart;
  238. if (0 == dwDisable)
  239. {
  240. if (ERROR_SUCCESS == GetServiceStartup(s_cszServiceName, &dwStart) &&
  241. (dwStart == SERVICE_DISABLED || dwStart == SERVICE_DEMAND_START))
  242. {
  243. EnableSR(NULL);
  244. DisableSR(NULL);
  245. }
  246. else
  247. {
  248. EnableSR(NULL);
  249. }
  250. }
  251. }
  252. switch ( dwCmd )
  253. {
  254. case CMDPARAM_NORMAL :
  255. break;
  256. case CMDPARAM_REGSERVER :
  257. dwRet = g_pMainFrm->RegisterServer();
  258. #if DBG==1
  259. if ( dwRet == ERROR_CALL_NOT_IMPLEMENTED )
  260. ::MessageBox(NULL, L"/RegServer is not supported...", L"CommandLine Options", MB_OK);
  261. #endif
  262. goto Exit;
  263. case CMDPARAM_UNREGSERVER :
  264. dwRet = g_pMainFrm->UnregisterServer();
  265. #if DBG==1
  266. if ( dwRet == ERROR_CALL_NOT_IMPLEMENTED )
  267. ::MessageBox(NULL, L"/UnregServer is not supported", L"CommandLine Options", MB_OK);
  268. #endif
  269. goto Exit;
  270. case CMDPARAM_SILENT :
  271. g_pRstrMgr->SilentRestore( dwRP );
  272. goto Exit;
  273. case CMDPARAM_CHECK :
  274. case CMDPARAM_HIDERESULT :
  275. // check result of MoveFileEx, if it's possible...
  276. if ( ValidateLogFile( &fWasSilent, &fWasUndo ) )
  277. {
  278. nStartMode = SRASM_SUCCESS;
  279. }
  280. else
  281. {
  282. // Cancel restore point of "Restore" type
  283. ::CancelRestorePoint();
  284. nStartMode = SRASM_FAIL;
  285. }
  286. g_pRstrMgr->SetIsUndo(fWasUndo);
  287. break;
  288. case CMDPARAM_INTERRUPTED :
  289. // read the log file to get the new restore point
  290. if (ValidateLogFile( &fWasSilent, &fWasUndo ))
  291. {
  292. nStartMode = SRASM_FAIL;
  293. }
  294. else
  295. {
  296. nStartMode = SRASM_FAIL;
  297. }
  298. g_pRstrMgr->SetIsUndo(fWasUndo);
  299. break;
  300. case CMDPARAM_RESULT_S :
  301. // read the log file, but ignore the result
  302. ValidateLogFile( NULL, &fWasUndo );
  303. nStartMode = SRASM_SUCCESS;
  304. g_pRstrMgr->SetIsUndo(fWasUndo);
  305. break;
  306. case CMDPARAM_RESULT_F :
  307. // read the log file, but ignore the result
  308. ValidateLogFile( NULL, &fWasUndo );
  309. nStartMode = SRASM_FAIL;
  310. g_pRstrMgr->SetIsUndo(fWasUndo);
  311. ::CancelRestorePoint();
  312. break;
  313. case CMDPARAM_RESULT_LD :
  314. // read the log file, but ignore the result
  315. ValidateLogFile( NULL, &fWasUndo );
  316. nStartMode = SRASM_FAILLOWDISK;
  317. g_pRstrMgr->SetIsUndo(fWasUndo);
  318. ::CancelRestorePoint();
  319. break;
  320. default :
  321. // Invalid Parameter, simply invoke regular UI
  322. #if DBG==1
  323. ::MessageBox(NULL, L"Unknown Option", L"CommandLine Options", MB_OK);
  324. #endif
  325. break;
  326. }
  327. // also check to see if the Winlogon key to call restore has been
  328. // removed. In normal circumstances, this key should have been
  329. // deleted during the restore but if the machine was not shutdown
  330. // cleanly, this key can remain causing the machine to again
  331. // initiate restore on the next reboot.
  332. ::SHDeleteValue( HKEY_LOCAL_MACHINE, s_cszSRRegKey,s_cszRestoreInProgress);
  333. // if start mode is SRASM_FAIL, check to see if we failed becuase
  334. // of low disk space. If this is the case, show the low disk
  335. // space message. Else check for the interrupted case.
  336. if (nStartMode == SRASM_FAIL)
  337. {
  338. DWORD dwRestoreStatus = ERROR_INTERNAL_ERROR;
  339. ::SRGetRegDword( HKEY_LOCAL_MACHINE,
  340. s_cszSRRegKey,
  341. s_cszRestoreStatus,
  342. &dwRestoreStatus );
  343. if (dwRestoreStatus != 0) // interrupted
  344. {
  345. nStartMode = SRASM_FAILINTERRUPTED;
  346. }
  347. else // Cancel restore point of "Restore" type
  348. {
  349. if (TRUE == CheckForDiskSpaceError())
  350. {
  351. nStartMode = SRASM_FAILLOWDISK;
  352. }
  353. ::CancelRestorePoint();
  354. }
  355. }
  356. switch ( nStartMode )
  357. {
  358. case SRASM_FAIL:
  359. dwEventID = EVMSG_RESTORE_FAILED;
  360. dwPFID = IDS_PFFAILED;
  361. break;
  362. case SRASM_FAILLOWDISK:
  363. dwEventID = EVMSG_RESTORE_FAILED;
  364. dwPFID = IDS_PFFAILEDLOWDISK;
  365. break;
  366. case SRASM_FAILINTERRUPTED:
  367. dwEventID = EVMSG_RESTORE_INTERRUPTED;
  368. dwPFID = IDS_PFINTERRUPTED;
  369. break;
  370. case SRASM_SUCCESS:
  371. dwEventID = EVMSG_RESTORE_SUCCESS;
  372. dwPFID = IDS_PFSUCCESS;
  373. break;
  374. default:
  375. break;
  376. }
  377. if (dwEventID != 0)
  378. {
  379. WCHAR szUnknownRP [MAX_PATH];
  380. const WCHAR *pwszUsedName = g_pRstrMgr->GetUsedName();
  381. HANDLE hEventSource = RegisterEventSource(NULL, s_cszServiceName);
  382. DWORD dwType = g_pRstrMgr->GetUsedType() + 1;
  383. WCHAR szRPType[100], szTime1[50], szTime2[50];
  384. if (NULL == pwszUsedName)
  385. {
  386. PCHLoadString(IDS_UNKNOWN_RP, szUnknownRP, MAX_PATH-1);
  387. pwszUsedName = szUnknownRP;
  388. }
  389. if (hEventSource != NULL)
  390. {
  391. SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, dwEventID,
  392. NULL, 0, pwszUsedName, NULL, NULL);
  393. DeregisterEventSource(hEventSource);
  394. }
  395. // construct a string for PF
  396. if (! fWasSilent)
  397. {
  398. PCHLoadString(IDS_UNKNOWN_RP + dwType, szRPType, sizeof(szRPType)/sizeof(WCHAR));
  399. GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, szTime1, sizeof(szTime1)/sizeof(WCHAR));
  400. GetTimeFormat(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, NULL, NULL, szTime2, sizeof(szTime2)/sizeof(WCHAR));
  401. if (SRFormatMessage(szPFString, dwPFID, szTime1, szTime2, pwszUsedName, szRPType, g_pRstrMgr->GetUsedType(), dwPFID-IDS_PFFAILED))
  402. {
  403. fSendFeedback = TRUE;
  404. }
  405. else
  406. {
  407. trace(0, "! SRFormatMessage");
  408. }
  409. }
  410. {
  411. WCHAR szWMIRepository [MAX_PATH];
  412. GetSystemDirectory (szWMIRepository, MAX_PATH);
  413. lstrcatW (szWMIRepository, L"\\Wbem\\Repository.bak");
  414. Delnode_Recurse (szWMIRepository, TRUE, NULL);
  415. }
  416. }
  417. //
  418. // Before this, perform any necessary bookeeping operations those
  419. // are necessary for both of Normal & Silent Restore
  420. //
  421. if ( fWasSilent )
  422. goto Exit;
  423. // Maybe explicit registration is not really necessary... Doing it here always
  424. // if UI is going to be displayed.
  425. g_pMainFrm->RegisterServer();
  426. // Check if SR is frozen or disabled.
  427. if ( nStartMode == SRASM_NORMAL )
  428. if ( !g_pRstrMgr->CanRunRestore( TRUE ) )
  429. goto Exit;
  430. HWND hwnd;
  431. TCHAR szMainWndTitle[MAX_PATH+1];
  432. PCHLoadString(IDS_RESTOREUI_TITLE, szMainWndTitle, MAX_PATH);
  433. // Find Previous Instance.
  434. hwnd = ::FindWindow(CLSNAME_RSTRSHELL, szMainWndTitle);
  435. if (hwnd != NULL)
  436. {
  437. // If exist, activate it.
  438. ::ShowWindow(hwnd, SW_SHOWNORMAL);
  439. ::SetForegroundWindow(hwnd);
  440. }
  441. else
  442. {
  443. if ( g_pMainFrm != NULL )
  444. {
  445. nRet = g_pMainFrm->RunUI( szMainWndTitle, nStartMode );
  446. }
  447. }
  448. Exit:
  449. //if (fSendFeedback)
  450. // ProductFeedback(szPFString);
  451. if ( g_pRstrMgr != NULL )
  452. {
  453. fRebootSystem = g_pRstrMgr->NeedReboot();
  454. g_pRstrMgr->Release();
  455. g_pRstrMgr = NULL;
  456. }
  457. if ( g_pMainFrm != NULL )
  458. {
  459. g_pMainFrm->ExitInstance();
  460. g_pMainFrm->Release();
  461. g_pMainFrm = NULL;
  462. }
  463. if ( g_pExternal != NULL )
  464. {
  465. if ( !fRebootSystem )
  466. {
  467. //
  468. // Since FIFO has been disabled in the UI, if for any reason the UI crashes or
  469. // something bad happens we will come here and give FIFO a chance to resume
  470. //
  471. if ( g_pExternal->EnableFIFO() != ERROR_SUCCESS )
  472. {
  473. ErrorTrace(TRACE_ID, "EnableFIFO() failed");
  474. }
  475. }
  476. g_pExternal->Release();
  477. }
  478. DebugTrace(0, "Closing rstrui.exe...");
  479. TraceFunctLeave();
  480. #if !NOTRACE
  481. TermAsyncTrace();
  482. #endif
  483. if ( fRebootSystem )
  484. {
  485. ::ExitWindowsEx( EWX_REBOOT | EWX_FORCE, 0 );
  486. }
  487. return(nRet);
  488. }
  489. /******************************************************************************/
  490. #if HANDLE_FIRST_RP
  491. #define FIRSTRUN_MAX_RETRY 5
  492. #define FIRSTRUN_SLEEP_LEN 2000
  493. BOOL
  494. CreateFirstRestorePoint()
  495. {
  496. TraceFunctEnter("CreateFirstRestorePoint");
  497. BOOL fRet = FALSE;
  498. DWORD dwRes;
  499. HKEY hKey = NULL;
  500. DWORD dwType;
  501. char szData[MAX_PATH];
  502. DWORD dwDelay;
  503. DWORD cbData;
  504. BOOL fDelayDeleted = FALSE;
  505. int i;
  506. RESTOREPOINTINFO sRPInfo;
  507. STATEMGRSTATUS sSmgrStatus;
  508. dwRes = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, s_cszIDSVXDKEY, 0, NULL, &hKey );
  509. if ( dwRes != ERROR_SUCCESS )
  510. {
  511. ErrorTrace(TRACE_ID, "RegOpenKeyEx('%s') failed, ret=%u", s_cszIDSVXDKEY, dwRes );
  512. goto Exit;
  513. }
  514. // Check DelayFirstRstpt registry key and delete it if exists
  515. dwType = REG_DWORD;
  516. cbData = sizeof(DWORD);
  517. dwRes = ::RegQueryValueEx( hKey, s_cszIDSDelayFirstRstpt, NULL, &dwType, (LPBYTE)&dwDelay, &cbData );
  518. if ( dwRes != ERROR_SUCCESS || dwType != REG_DWORD || cbData == 0 )
  519. {
  520. DebugTrace(TRACE_ID, "DelayFirstRstpt flag does not exist");
  521. goto Ignored;
  522. }
  523. if ( dwDelay != 1 )
  524. {
  525. DebugTrace(TRACE_ID, "DelayFirstRstpt flag is '%d'", dwDelay);
  526. goto Ignored;
  527. }
  528. // Check OOBEInProgress registry key and do nothing if it exists
  529. dwType = REG_SZ;
  530. cbData = MAX_PATH;
  531. dwRes = ::RegQueryValueEx( hKey, s_cszIDSOOBEInProgress, NULL, &dwType, (LPBYTE)szData, &cbData );
  532. if ( dwRes == ERROR_SUCCESS )
  533. {
  534. DebugTrace(TRACE_ID, "OOBEInProgress flag exists");
  535. goto Ignored;
  536. }
  537. // This should be before deleting DelayFirstRstpt because of the logic of
  538. // SRSetRestorePoint API.
  539. EnsureStateMgr();
  540. // Delete DelayFirstRstpt flag
  541. dwRes = ::RegDeleteValue( hKey, s_cszIDSDelayFirstRstpt );
  542. if ( dwRes == ERROR_SUCCESS )
  543. fDelayDeleted = TRUE;
  544. else
  545. ErrorTrace(TRACE_ID, "RegSetValueEx('%s') failed, ret=%u", s_cszIDSDelayFirstRstpt, dwRes );
  546. // Now set FirstRun restore point
  547. ::ZeroMemory( &sRPInfo, sizeof(sRPInfo) );
  548. sRPInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
  549. sRPInfo.dwRestorePtType = FIRSTRUN;
  550. ::lstrcpy( sRPInfo.szDescription, "CHECKPOINT" );
  551. for ( i = 0; i < FIRSTRUN_MAX_RETRY; i++ )
  552. {
  553. if ( i > 0 )
  554. ::Sleep( FIRSTRUN_SLEEP_LEN );
  555. if ( ::SRSetRestorePoint( &sRPInfo, &sSmgrStatus ) )
  556. {
  557. DebugTrace(TRACE_ID, "FirstRun restore point has been created!!!");
  558. break;
  559. }
  560. DebugTrace(TRACE_ID, "SRSetRestorePoint failed, i=%d, nStatus=%d", i, sSmgrStatus.nStatus);
  561. }
  562. Ignored:
  563. fRet = TRUE;
  564. Exit:
  565. if ( hKey != NULL )
  566. {
  567. if ( !fDelayDeleted )
  568. {
  569. dwRes = ::RegDeleteValue( hKey, s_cszIDSDelayFirstRstpt );
  570. if ( dwRes != ERROR_SUCCESS )
  571. ErrorTrace(TRACE_ID, "RegSetValueEx('%s') failed, ret=%u", s_cszIDSDelayFirstRstpt, dwRes );
  572. }
  573. ::RegCloseKey( hKey );
  574. }
  575. TraceFunctLeave();
  576. return( fRet );
  577. }
  578. #endif //HANDLE_FIRST_RP
  579. /******************************************************************************/
  580. //
  581. // Note:
  582. // =====
  583. // This function loads the error message from resource only dll
  584. // If the resource only dll could not be loaded, this function must not be
  585. // used to display the error
  586. //
  587. void
  588. ShowErrorMessage(
  589. HRESULT hr
  590. )
  591. {
  592. TraceFunctEnter("ShowErrorMessage");
  593. int nErrorMessageID = FALSE ;
  594. TCHAR szErrorTitle[MAX_PATH+1];
  595. TCHAR szErrorMessage[MAX_ERROR_STRING_LENGTH+1];
  596. // display error message and shut down gracefully
  597. switch (hr)
  598. {
  599. default:
  600. case E_UNEXPECTED:
  601. case E_FAIL:
  602. nErrorMessageID = IDS_ERR_RSTR_UNKNOWN;
  603. break;
  604. case E_OUTOFMEMORY:
  605. nErrorMessageID = IDS_ERR_RSTR_OUT_OF_MEMORY;
  606. break;
  607. case E_RSTR_CANNOT_CREATE_DOMDOC:
  608. nErrorMessageID = IDS_ERR_RSTR_CANNOT_CREATE_DOMDOC;
  609. break;
  610. case E_RSTR_INVALID_CONFIG_FILE:
  611. case E_RSTR_NO_PROBLEM_AREAS:
  612. case E_RSTR_NO_PROBLEM_AREA_ATTRS:
  613. case E_RSTR_NO_REQUIRED_ATTR:
  614. nErrorMessageID = IDS_ERR_RSTR_INVALID_CONFIG_FILE;
  615. break;
  616. }
  617. PCHLoadString(IDS_ERR_RSTR_TITLE, szErrorTitle, MAX_PATH);
  618. PCHLoadString(nErrorMessageID, szErrorMessage, MAX_ERROR_STRING_LENGTH);
  619. //
  620. // no owner window (use NULL)
  621. // we could use the GetDesktopWindow() and use that as the owner
  622. // if necessary
  623. //
  624. if ( nErrorMessageID )
  625. {
  626. ::MessageBox(NULL, szErrorMessage, szErrorTitle, MB_OK);
  627. }
  628. TraceFunctLeave();
  629. }
  630. /////////////////////////////////////////////////////////////////////////////
  631. DWORD
  632. ParseCommandParameter( DWORD *pdwRP )
  633. {
  634. TraceFunctEnter("ParseCommandParameter");
  635. DWORD dwCmd = CMDPARAM_INVALID;
  636. LPCWSTR cszCmd;
  637. cszCmd = ::PathGetArgs( ::GetCommandLine() );
  638. DebugTrace(0, "Cmd='%ls'", cszCmd);
  639. if ( ( cszCmd == NULL ) || ( *cszCmd == L'\0' ) )
  640. {
  641. dwCmd = CMDPARAM_NORMAL;
  642. goto Exit;
  643. }
  644. if ( ( *cszCmd == L'-' ) || ( *cszCmd == L'/' ) )
  645. {
  646. cszCmd++;
  647. DebugTrace(0, "Option='%ls'", cszCmd);
  648. if ( *cszCmd != L'\0' )
  649. {
  650. if ( ::StrCmpI( cszCmd, L"c" ) == 0 )
  651. dwCmd = CMDPARAM_CHECK;
  652. else if ( ::StrCmpI( cszCmd, L"regserver" ) == 0 )
  653. dwCmd = CMDPARAM_REGSERVER;
  654. else if ( ::StrCmpI( cszCmd, L"unregserver" ) == 0 )
  655. dwCmd = CMDPARAM_UNREGSERVER;
  656. else if ( ::ChrCmpI( *cszCmd, L'v' ) == 0 )
  657. {
  658. dwCmd = CMDPARAM_SILENT;
  659. cszCmd++;
  660. while ( ( *cszCmd != L'\0' ) &&
  661. ( ( *cszCmd == L' ' ) || ( *cszCmd == L'\t' ) ) )
  662. cszCmd++;
  663. if ( *cszCmd >= L'0' && *cszCmd <= L'9' )
  664. *pdwRP = ::StrToInt( cszCmd );
  665. }
  666. else if ( ::StrCmpI( cszCmd, L"b" ) == 0 )
  667. dwCmd = CMDPARAM_HIDERESULT;
  668. else if ( ::StrCmpNI( cszCmd, L"result:", 7 ) == 0 )
  669. {
  670. cszCmd += 7;
  671. if ( ::StrCmpIW( cszCmd, L"s" ) == 0 )
  672. dwCmd = CMDPARAM_RESULT_S;
  673. else if ( ::StrCmpIW( cszCmd, L"f" ) == 0 )
  674. dwCmd = CMDPARAM_RESULT_F;
  675. else if ( ::StrCmpIW( cszCmd, L"ld" ) == 0 )
  676. dwCmd = CMDPARAM_RESULT_LD;
  677. }
  678. else if ( ::StrCmpI( cszCmd, L"i" ) == 0 )
  679. dwCmd = CMDPARAM_INTERRUPTED;
  680. }
  681. }
  682. Exit:
  683. DebugTrace(0, "m_dwCmd=%d, dwRP=%d", dwCmd, *pdwRP);
  684. TraceFunctLeave();
  685. return( dwCmd );
  686. }
  687. // end of file