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.

860 lines
24 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. api.cpp
  5. Abstract:
  6. This file contains the top level APIs, InitiateRestore and ResumeRestore.
  7. Revision History:
  8. Seong Kook Khang (SKKhang) 06/20/00
  9. created
  10. ******************************************************************************/
  11. #include "stdwin.h"
  12. #include "rstrcore.h"
  13. #include "resource.h"
  14. extern CSRClientLoader g_CSRClientLoader;
  15. /////////////////////////////////////////////////////////////////////////////
  16. //
  17. // EnsureTrace
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. //static BOOL s_fTraceEnabled = FALSE;
  21. static DWORD s_dwTraceCount = 0;
  22. void EnsureTrace()
  23. {
  24. if ( s_dwTraceCount++ == 0 )
  25. {
  26. ::InitAsyncTrace();
  27. }
  28. }
  29. void ReleaseTrace()
  30. {
  31. if ( --s_dwTraceCount == 0 )
  32. {
  33. ::TermAsyncTrace();
  34. }
  35. }
  36. /////////////////////////////////////////////////////////////////////////////
  37. //
  38. // CRestoreContext
  39. //
  40. /////////////////////////////////////////////////////////////////////////////
  41. class CRestoreContext : public IRestoreContext
  42. {
  43. public:
  44. CRestoreContext();
  45. protected:
  46. ~CRestoreContext();
  47. // operations - IRestoreContext methods
  48. public:
  49. BOOL IsAnyDriveOfflineOrDisabled( LPWSTR szOffline );
  50. void SetSilent();
  51. void SetUndo();
  52. BOOL Release();
  53. // attributes
  54. public:
  55. int m_nRP;
  56. CRDIArray m_aryDrv;
  57. BOOL m_fSilent;
  58. BOOL m_fUndo;
  59. };
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CRestoreContext - construction / destruction
  62. CRestoreContext::CRestoreContext()
  63. {
  64. m_nRP = -1;
  65. m_fSilent = FALSE;
  66. m_fUndo = FALSE;
  67. }
  68. CRestoreContext::~CRestoreContext()
  69. {
  70. m_aryDrv.DeleteAll();
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CRestoreContext - IRestoreContext methods
  74. BOOL
  75. CRestoreContext::IsAnyDriveOfflineOrDisabled( LPWSTR szOffline )
  76. {
  77. TraceFunctEnter("CRestoreContext::IsAnyDriveOffline");
  78. BOOL fRet = FALSE;
  79. szOffline[0] = L'\0';
  80. for ( int i = m_aryDrv.GetUpperBound(); i >= 0; i-- )
  81. {
  82. if ( m_aryDrv[i]->IsOffline() || m_aryDrv[i]->IsExcluded())
  83. {
  84. ::lstrcat( szOffline, L" " );
  85. ::lstrcat( szOffline, m_aryDrv[i]->GetMount() );
  86. fRet = TRUE;
  87. }
  88. }
  89. TraceFunctLeave();
  90. return( fRet );
  91. }
  92. /////////////////////////////////////////////////////////////////////////////
  93. void
  94. CRestoreContext::SetSilent()
  95. {
  96. TraceFunctEnter("CRestoreContext::SetSilent");
  97. m_fSilent = TRUE;
  98. TraceFunctLeave();
  99. }
  100. /////////////////////////////////////////////////////////////////////////////
  101. void
  102. CRestoreContext::SetUndo()
  103. {
  104. TraceFunctEnter("CRestoreContext::SetUndo");
  105. m_fUndo = TRUE;
  106. TraceFunctLeave();
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. BOOL
  110. CRestoreContext::Release()
  111. {
  112. TraceFunctEnter("CRestoreContext::Release");
  113. delete this;
  114. TraceFunctLeave();
  115. return( TRUE );
  116. }
  117. /////////////////////////////////////////////////////////////////////////////
  118. //
  119. // Helper Functions
  120. //
  121. /////////////////////////////////////////////////////////////////////////////
  122. BOOL
  123. IsAdminUser()
  124. {
  125. TraceFunctEnter("IsAdminUser");
  126. BOOL fRet = FALSE;
  127. LPCWSTR cszErr;
  128. PSID pSidAdmin = NULL;
  129. SID_IDENTIFIER_AUTHORITY cSIA = SECURITY_NT_AUTHORITY;
  130. BOOL fRes;
  131. if ( !::AllocateAndInitializeSid( &cSIA, 2,
  132. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  133. 0, 0, 0, 0, 0, 0, &pSidAdmin ) )
  134. {
  135. cszErr = ::GetSysErrStr();
  136. ErrorTrace(0, "::AllocateAndInitializeSid failed - %ls", cszErr);
  137. goto Exit;
  138. }
  139. if ( !::CheckTokenMembership( NULL, pSidAdmin, &fRes ) )
  140. {
  141. cszErr = ::GetSysErrStr();
  142. ErrorTrace(0, "::CheckMembership failed - %ls", cszErr);
  143. goto Exit;
  144. }
  145. DebugTrace(0, "IsAdminUser = %d", fRes);
  146. fRet = fRes;
  147. Exit:
  148. if ( pSidAdmin != NULL )
  149. ::FreeSid( pSidAdmin );
  150. TraceFunctLeave();
  151. return( fRet );
  152. }
  153. //
  154. // NOTE: 7/28/00 - skkhang
  155. // Behavior of AdjustTokenPrivilege is a little bit confusing.
  156. // It returns TRUE if given privilege does not exist at all, so you need to
  157. // call GetLastError to see if it's ERROR_SUCCESS or ERROR_NOT_ALL_ASSIGNED
  158. // (meaning the privilege does not exist.)
  159. // Also, if the privilege was already enabled, tpOld will be empty. You
  160. // don't need to restore the privilege in that case.
  161. //
  162. BOOL
  163. CheckPrivilege( LPCWSTR szPriv, BOOL fCheckOnly )
  164. {
  165. TraceFunctEnter("CheckPrivilege");
  166. BOOL fRet = FALSE;
  167. LPCWSTR cszErr;
  168. HANDLE hToken = NULL;
  169. LUID luid;
  170. TOKEN_PRIVILEGES tpNew;
  171. TOKEN_PRIVILEGES tpOld;
  172. DWORD dwRes;
  173. // Prepare Process Token
  174. if ( !::OpenProcessToken( ::GetCurrentProcess(),
  175. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  176. &hToken ) )
  177. {
  178. cszErr = ::GetSysErrStr();
  179. ErrorTrace(0, "::OpenProcessToken failed - %ls", cszErr);
  180. goto Exit;
  181. }
  182. // Get Luid
  183. if ( !::LookupPrivilegeValue( NULL, szPriv, &luid ) )
  184. {
  185. cszErr = ::GetSysErrStr();
  186. ErrorTrace(0, "::LookupPrivilegeValue failed - %ls", cszErr);
  187. goto Exit;
  188. }
  189. // Try to enable the privilege
  190. tpNew.PrivilegeCount = 1;
  191. tpNew.Privileges[0].Luid = luid;
  192. tpNew.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  193. if ( !::AdjustTokenPrivileges( hToken, FALSE, &tpNew, sizeof(tpNew), &tpOld, &dwRes ) )
  194. {
  195. cszErr = ::GetSysErrStr();
  196. ErrorTrace(0, "::AdjustTokenPrivileges(ENABLE) failed - %ls", cszErr);
  197. goto Exit;
  198. }
  199. if ( ::GetLastError() == ERROR_NOT_ALL_ASSIGNED )
  200. {
  201. // This means process does not even have the privilege so
  202. // AdjustTokenPrivilege simply ignored the request.
  203. ErrorTrace(0, "Privilege '%ls' does not exist, probably user is not an admin.", szPriv);
  204. goto Exit;
  205. }
  206. if ( fCheckOnly )
  207. {
  208. // Restore the privilege if it was not enabled
  209. if ( tpOld.PrivilegeCount > 0 )
  210. {
  211. if ( !::AdjustTokenPrivileges( hToken, FALSE, &tpOld, sizeof(tpOld), NULL, NULL ) )
  212. {
  213. cszErr = ::GetSysErrStr();
  214. ErrorTrace(0, "::AdjustTokenPrivileges(RESTORE) failed - %ls", cszErr);
  215. goto Exit;
  216. }
  217. }
  218. }
  219. fRet = TRUE;
  220. Exit:
  221. if ( hToken != NULL )
  222. ::CloseHandle( hToken );
  223. return( fRet );
  224. }
  225. /////////////////////////////////////////////////////////////////////////////
  226. //
  227. // IsSRFrozen
  228. //
  229. // This routine checks if SR is frozen. If any error happens during Drive
  230. // Table creation or System Drive does not exist (broken drive table???),
  231. // return value is FALSE.
  232. //
  233. /////////////////////////////////////////////////////////////////////////////
  234. BOOL APIENTRY
  235. IsSRFrozen()
  236. {
  237. EnsureTrace();
  238. TraceFunctEnter("IsSRFrozen");
  239. BOOL fRet = FALSE;
  240. CRDIArray aryDrv;
  241. int i;
  242. // Load SRClient
  243. g_CSRClientLoader.LoadSrClient();
  244. if ( !::CreateDriveList( 0, aryDrv, TRUE ) )
  245. goto Exit;
  246. for ( i = aryDrv.GetUpperBound(); i >= 0; i-- )
  247. {
  248. if ( aryDrv[i]->IsSystem() )
  249. {
  250. fRet = aryDrv[i]->IsFrozen();
  251. goto Exit;
  252. }
  253. }
  254. Exit:
  255. TraceFunctLeave();
  256. ReleaseTrace();
  257. return( fRet );
  258. }
  259. /////////////////////////////////////////////////////////////////////////////
  260. //
  261. // CheckPrivilegesForRestore
  262. //
  263. // This routine checks if necessary privileges can be set, to verify if
  264. // logon user has necessary credential (Administrators or Backup Operators.)
  265. //
  266. /////////////////////////////////////////////////////////////////////////////
  267. BOOL APIENTRY
  268. CheckPrivilegesForRestore()
  269. {
  270. EnsureTrace();
  271. TraceFunctEnter("CheckPrivilegesForRestore");
  272. BOOL fRet = FALSE;
  273. // Load SRClient
  274. g_CSRClientLoader.LoadSrClient();
  275. // NOTE: 8/17/00 - skkhang
  276. //
  277. // Backup operator does not have below two privileges... SE_SECURITY_NAME
  278. // is enabled by default for SYSTEM so probably can simply removed, but
  279. // SE_TAKE_OWNERSHIP is off for SYSTEM and needs to be turned on. To solve
  280. // the problem, this routine should accept parameter to distinguish
  281. // "Check"(from UI) and "Set"(from ResumeRestore.)
  282. //
  283. if ( !::CheckPrivilege( SE_SECURITY_NAME, FALSE ) )
  284. {
  285. ErrorTrace(0, "Cannot enable SE_SECURITY_NAME privilege...");
  286. goto Exit;
  287. }
  288. if ( !::CheckPrivilege( SE_TAKE_OWNERSHIP_NAME, FALSE ) )
  289. {
  290. ErrorTrace(0, "Cannot enable SE_SHUTDOWN_NAME privilege...");
  291. goto Exit;
  292. }
  293. if ( !::CheckPrivilege( SE_BACKUP_NAME, FALSE ) )
  294. {
  295. ErrorTrace(0, "Cannot enable SE_BACKUP_NAME privilege...");
  296. goto Exit;
  297. }
  298. if ( !::CheckPrivilege( SE_RESTORE_NAME, FALSE ) )
  299. {
  300. ErrorTrace(0, "Cannot enable SE_RESTORE_NAME privilege...");
  301. goto Exit;
  302. }
  303. if ( !::CheckPrivilege( SE_SHUTDOWN_NAME, FALSE ) )
  304. {
  305. ErrorTrace(0, "Cannot enable SE_SHUTDOWN_NAME privilege...");
  306. goto Exit;
  307. }
  308. fRet = TRUE;
  309. Exit:
  310. TraceFunctLeave();
  311. ReleaseTrace();
  312. return( fRet );
  313. }
  314. /////////////////////////////////////////////////////////////////////////////
  315. //
  316. // InvokeDiskCleanup
  317. //
  318. // This routine invokes Disk Cleanup Utility. A specific drive can be
  319. // provided.
  320. //
  321. /////////////////////////////////////////////////////////////////////////////
  322. static LPCWSTR s_cszDCUPath = L"%windir%\\system32\\cleanmgr.exe";
  323. static LPCWSTR s_cszDCUName = L"cleanmgr.exe";
  324. static LPCWSTR s_cszDCUOptDrv = L" /d ";
  325. BOOL APIENTRY
  326. InvokeDiskCleanup( LPCWSTR cszDrive )
  327. {
  328. TraceFunctEnter("InvokeDiskCleanup");
  329. // Load SRClient
  330. g_CSRClientLoader.LoadSrClient();
  331. BOOL fRet = FALSE;
  332. LPCWSTR cszErr;
  333. WCHAR szCmdLine[MAX_PATH];
  334. STARTUPINFO sSI;
  335. PROCESS_INFORMATION sPI;
  336. if ( ::ExpandEnvironmentStrings( s_cszDCUPath, szCmdLine, MAX_PATH ) == 0 )
  337. {
  338. cszErr = ::GetSysErrStr();
  339. ErrorTrace(0, "::GetFullPathName failed - %ls", cszErr);
  340. ::lstrcpy( szCmdLine, s_cszDCUName );
  341. }
  342. if ( cszDrive != NULL && cszDrive[0] != L'\0' )
  343. {
  344. ::lstrcat( szCmdLine, s_cszDCUOptDrv );
  345. ::lstrcat( szCmdLine, cszDrive );
  346. }
  347. DebugTrace(0, "szCmdLine='%s'", szCmdLine);
  348. ::ZeroMemory( &sSI, sizeof(sSI ) );
  349. sSI.cb = sizeof(sSI);
  350. if ( !::CreateProcess( NULL, szCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &sSI, &sPI ) )
  351. {
  352. cszErr = ::GetSysErrStr();
  353. ErrorTrace(0, "::CreateProcess failed - %ls", cszErr);
  354. goto Exit;
  355. }
  356. ::CloseHandle( sPI.hThread );
  357. ::CloseHandle( sPI.hProcess );
  358. // Should I wait for DCU to finish???
  359. fRet = TRUE;
  360. Exit:
  361. TraceFunctLeave();
  362. return( TRUE );
  363. }
  364. #ifdef DBG
  365. /////////////////////////////////////////////////////////////////////////////
  366. //
  367. // TestRestore
  368. //
  369. // This routine performs core restoration functionality, without reboot or
  370. // snapshot restoration.
  371. //
  372. /////////////////////////////////////////////////////////////////////////////
  373. extern "C" __declspec(dllexport)
  374. BOOL APIENTRY
  375. TestRestore( int nRP )
  376. {
  377. EnsureTrace();
  378. TraceFunctEnter("TestRestore");
  379. BOOL fRet = FALSE;
  380. CRDIArray aryDrv;
  381. RESTOREPOINTINFO sRPI;
  382. STATEMGRSTATUS sStatus;
  383. SRstrLogHdrV3 sLogHdr;
  384. CRestoreOperationManager *pROMgr = NULL;
  385. // Load SRClient
  386. g_CSRClientLoader.LoadSrClient();
  387. if ( !::CheckPrivilegesForRestore() )
  388. goto Exit;
  389. // Create Drive Table
  390. if ( !::CreateDriveList( nRP, aryDrv, FALSE ) )
  391. goto Exit;
  392. // Create Restore Point
  393. sRPI.dwEventType = BEGIN_SYSTEM_CHANGE;
  394. sRPI.dwRestorePtType = RESTORE;
  395. sRPI.llSequenceNumber = 0;
  396. ::LoadString( g_hInst, IDS_RESTORE_POINT_TEXT, sRPI.szDescription, MAX_DESC );
  397. if ( !::SRSetRestorePoint( &sRPI, &sStatus ) )
  398. {
  399. ErrorTrace(0, "::SRSetRestorePoint failed, nStatus=%d", sStatus.nStatus);
  400. goto Exit;
  401. }
  402. // Create the log file
  403. sLogHdr.dwRPNum = nRP;
  404. sLogHdr.dwRPNew = sStatus.llSequenceNumber;
  405. sLogHdr.dwDrives = aryDrv.GetSize();
  406. if ( !::CreateRestoreLogFile( &sLogHdr, aryDrv ) )
  407. goto Exit;
  408. // also call TS folks to get them to preserve RA keys on restore
  409. _VERIFY(TRUE==RemoteAssistancePrepareSystemRestore(SERVERNAME_CURRENT));
  410. // Create CRestoreOperationManager object
  411. if ( !::CreateRestoreOperationManager( &pROMgr ) )
  412. goto Exit;
  413. // Perform the Restore Operation.
  414. if ( !pROMgr->Run( FALSE ) )
  415. goto Exit;
  416. fRet = TRUE;
  417. Exit:
  418. SAFE_RELEASE(pROMgr);
  419. TraceFunctLeave();
  420. ReleaseTrace();
  421. return( fRet );
  422. }
  423. #endif
  424. #ifdef DBG
  425. #define TIMEOUT_PROGRESSTHREAD 5000
  426. #define TESTPROG_COUNT_CHGLOG 300
  427. #define TESTPROG_TIME_PREPARE 1
  428. #define TESTPROG_COUNT_RESTORE 100
  429. #define TESTPROG_TIME_RESTORE 1
  430. #define TESTPROG_TIME_SNAPSHOT 2000
  431. DWORD WINAPI
  432. TestProgressWindowThreadProc( LPVOID lpParam )
  433. {
  434. CRestoreProgressWindow *pProgress = (CRestoreProgressWindow*)lpParam;
  435. int i, j;
  436. // Stage 1. Prepare (change log enumeration)
  437. pProgress->SetStage( RPS_PREPARE, 0 );
  438. for ( i = 0; i < TESTPROG_COUNT_CHGLOG; i++ )
  439. {
  440. ::Sleep( TESTPROG_TIME_PREPARE );
  441. for ( j = 0; j < 10; j++ )
  442. pProgress->Increment();
  443. }
  444. // Stage 2. Restore
  445. pProgress->SetStage( RPS_RESTORE, TESTPROG_COUNT_RESTORE );
  446. for ( i = 0; i < TESTPROG_COUNT_RESTORE; i++ )
  447. {
  448. ::Sleep( TESTPROG_TIME_RESTORE );
  449. pProgress->Increment();
  450. }
  451. // Stage 3. Snapshot
  452. pProgress->SetStage( RPS_SNAPSHOT, 0 );
  453. ::Sleep( TESTPROG_TIME_SNAPSHOT );
  454. pProgress->Close();
  455. return( 0 );
  456. }
  457. /////////////////////////////////////////////////////////////////////////////
  458. //
  459. // TestProgressWindow
  460. //
  461. // This routine invokes Progress Window and simulates progress change
  462. //
  463. /////////////////////////////////////////////////////////////////////////////
  464. extern "C" __declspec(dllexport)
  465. BOOL APIENTRY
  466. TestProgressWindow()
  467. {
  468. EnsureTrace();
  469. TraceFunctEnter("TestProgressWindow");
  470. BOOL fRet = FALSE;
  471. CRestoreProgressWindow *pProgress = NULL;
  472. HANDLE hThread = NULL;
  473. DWORD dwRet;
  474. // Load SRClient
  475. g_CSRClientLoader.LoadSrClient();
  476. // Create progress window object
  477. if ( !::CreateRestoreProgressWindow( &pProgress ) )
  478. goto Exit;
  479. // Create progress window
  480. if ( !pProgress->Create() )
  481. goto Exit;
  482. // Create secondary thread for main restore operation
  483. hThread = ::CreateThread( NULL, 0, TestProgressWindowThreadProc, pProgress, 0, NULL );
  484. if ( hThread == NULL )
  485. {
  486. LPCWSTR cszErr = ::GetSysErrStr();
  487. ErrorTrace(0, "::CreateThread failed - %ls", cszErr);
  488. goto Exit;
  489. }
  490. // Message loop, wait until restore thread closes progress window
  491. if ( !pProgress->Run() )
  492. goto Exit;
  493. // Double check if thread has been terminated
  494. dwRet = ::WaitForSingleObject( hThread, TIMEOUT_PROGRESSTHREAD );
  495. if ( dwRet == WAIT_FAILED )
  496. {
  497. LPCWSTR cszErr = ::GetSysErrStr();
  498. ErrorTrace(0, "::WaitForSingleObject failed - %ls", cszErr);
  499. goto Exit;
  500. }
  501. else if ( dwRet == WAIT_TIMEOUT )
  502. {
  503. ErrorTrace(0, "Timeout while waiting for the restore thread finishes...");
  504. goto Exit;
  505. }
  506. pProgress->Close();
  507. fRet = TRUE;
  508. Exit:
  509. if ( hThread != NULL )
  510. ::CloseHandle( hThread );
  511. SAFE_RELEASE(pProgress);
  512. TraceFunctLeave();
  513. ReleaseTrace();
  514. return( fRet );
  515. }
  516. #endif
  517. /////////////////////////////////////////////////////////////////////////////
  518. //
  519. // PrepareRestore
  520. //
  521. // This routine creates a IRestoreContext for use by InitiateRestore.
  522. // IRestoreContext contains chosen restore point ID, drive list, etc.
  523. //
  524. /////////////////////////////////////////////////////////////////////////////
  525. BOOL APIENTRY
  526. PrepareRestore( int nRP, IRestoreContext **ppCtx )
  527. {
  528. EnsureTrace();
  529. TraceFunctEnter("PrepareRestore");
  530. BOOL fRet = FALSE;
  531. CRestoreContext *pRC = NULL;
  532. // Load SRClient
  533. g_CSRClientLoader.LoadSrClient();
  534. if ( ppCtx == NULL )
  535. {
  536. ErrorTrace(0, "Invalid parameter, ppCtx is NULL.");
  537. goto Exit;
  538. }
  539. *ppCtx = NULL;
  540. if ( !::IsAdminUser() )
  541. {
  542. ErrorTrace(0, "Not an admin user");
  543. goto Exit;
  544. }
  545. pRC = new CRestoreContext;
  546. if ( pRC == NULL )
  547. {
  548. ErrorTrace(0, "Insufficient memory...");
  549. goto Exit;
  550. }
  551. pRC->m_nRP = nRP;
  552. if ( !::CreateDriveList( nRP, pRC->m_aryDrv, FALSE ) )
  553. {
  554. ErrorTrace(0, "Creating drive list failed");
  555. goto Exit;
  556. }
  557. *ppCtx = pRC;
  558. fRet = TRUE;
  559. Exit:
  560. if ( !fRet )
  561. SAFE_RELEASE(pRC);
  562. TraceFunctLeave();
  563. ReleaseTrace();
  564. return( fRet );
  565. }
  566. /////////////////////////////////////////////////////////////////////////////
  567. //
  568. // InitiateRestore
  569. //
  570. // This routine creates a temporary persistent storage with informations
  571. // like restore point ID. The storage will be used by ResumeRestore later.
  572. //
  573. /////////////////////////////////////////////////////////////////////////////
  574. static LPCWSTR s_cszRunOnceValueName = L"*Restore";
  575. static LPCWSTR s_cszRestoreUIPath = L"%SystemRoot%\\system32\\restore\\rstrui.exe";
  576. static LPCWSTR s_cszRunOnceOptInterrupted = L" -i";
  577. BOOL APIENTRY
  578. InitiateRestore( IRestoreContext *pCtx, DWORD *pdwNewRP )
  579. {
  580. EnsureTrace();
  581. TraceFunctEnter("InitiateRestore");
  582. // Load SRClient
  583. g_CSRClientLoader.LoadSrClient();
  584. BOOL fRet = FALSE;
  585. HCURSOR hCursor = NULL;
  586. RESTOREPOINTINFO sRPI;
  587. STATEMGRSTATUS sStatus;
  588. SRstrLogHdrV3 sLogHdr;
  589. CRestoreContext *pRC;
  590. DWORD dwVal;
  591. WCHAR szUIPath[MAX_PATH];
  592. BOOL fCreatedRp = FALSE;
  593. if ( !::IsAdminUser() )
  594. goto Exit;
  595. // Set RunOnce key for interrupted case...
  596. // Doing this here before anything else so result screen would appear.
  597. ::ExpandEnvironmentStrings( s_cszRestoreUIPath, szUIPath, MAX_PATH );
  598. ::lstrcat( szUIPath, s_cszRunOnceOptInterrupted );
  599. if ( !::SRSetRegStr( HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, s_cszRunOnceValueName, szUIPath ) )
  600. goto Exit;
  601. // similarly, set RestoreStatus key in SystemRestore
  602. // so that test tools can know status of silent restores
  603. // set this to indicate interrrupted status
  604. // if restore succeeds or reverts, this value will be updated
  605. if ( !::SRSetRegDword( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszRestoreStatus, 2 ) )
  606. goto Exit;
  607. // Create Restore Point
  608. hCursor = ::SetCursor( ::LoadCursor( NULL, IDC_WAIT ) );
  609. // make this a nested restore point so that
  610. // no other app can create a restore point between here and a reboot
  611. sRPI.dwEventType = BEGIN_NESTED_SYSTEM_CHANGE;
  612. if (0 != GetSystemMetrics(SM_CLEANBOOT)) // safe mode
  613. {
  614. sRPI.dwRestorePtType = CANCELLED_OPERATION;
  615. }
  616. else // normal mode
  617. {
  618. sRPI.dwRestorePtType = RESTORE;
  619. }
  620. sRPI.llSequenceNumber = 0;
  621. ::LoadString( g_hInst, IDS_RESTORE_POINT_TEXT, sRPI.szDescription, MAX_DESC );
  622. if ( !::SRSetRestorePoint( &sRPI, &sStatus ) )
  623. {
  624. ErrorTrace(0, "::SRSetRestorePoint failed, nStatus=%d", sStatus.nStatus);
  625. goto Exit;
  626. }
  627. if ( pdwNewRP != NULL )
  628. *pdwNewRP = sStatus.llSequenceNumber;
  629. fCreatedRp = TRUE;
  630. // Create the log file
  631. pRC = (CRestoreContext*)pCtx;
  632. sLogHdr.dwFlags = pRC->m_fSilent ? RLHF_SILENT : 0;
  633. sLogHdr.dwFlags |= pRC->m_fUndo ? RLHF_UNDO : 0;
  634. sLogHdr.dwRPNum = pRC->m_nRP;
  635. sLogHdr.dwRPNew = sStatus.llSequenceNumber;
  636. sLogHdr.dwDrives = pRC->m_aryDrv.GetSize();
  637. if ( !::CreateRestoreLogFile( &sLogHdr, pRC->m_aryDrv ) )
  638. goto Exit;
  639. // also call TS folks to get them to preserve RA keys on restore
  640. _VERIFY(TRUE==RemoteAssistancePrepareSystemRestore(SERVERNAME_CURRENT));
  641. // Set RestoreInProgress registry key so winlogon would invoke us
  642. if ( !::SRSetRegDword( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszRestoreInProgress, 1 ) )
  643. goto Exit;
  644. fRet = TRUE;
  645. Exit:
  646. if (fRet == FALSE)
  647. {
  648. // if something failed and we had set a nested restore point,
  649. // end the nesting now
  650. if (fCreatedRp == TRUE)
  651. {
  652. sRPI.dwRestorePtType = RESTORE;
  653. sRPI.dwEventType = END_NESTED_SYSTEM_CHANGE;
  654. SRSetRestorePoint( &sRPI, &sStatus );
  655. }
  656. // delete the runonce key
  657. SHDeleteValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_RUNONCE, s_cszRunOnceValueName);
  658. }
  659. if ( hCursor != NULL )
  660. ::SetCursor( hCursor );
  661. TraceFunctLeave();
  662. ReleaseTrace();
  663. return( fRet );
  664. }
  665. /////////////////////////////////////////////////////////////////////////////
  666. //
  667. // ResumeRestore
  668. //
  669. // This routine is the main routine to run the restore operation.
  670. //
  671. /////////////////////////////////////////////////////////////////////////////
  672. BOOL APIENTRY
  673. ResumeRestore()
  674. {
  675. EnsureTrace();
  676. TraceFunctEnter("ResumeRestore");
  677. // Load SRClient
  678. g_CSRClientLoader.LoadSrClient();
  679. BOOL fRet = FALSE;
  680. LPCWSTR cszErr;
  681. DWORD dwInRestore, dwType, dwSize, dwRes;
  682. CRestoreOperationManager *pROMgr = NULL;
  683. if ( !::CheckPrivilegesForRestore() )
  684. goto Exit;
  685. // 1. Even though winlogon would check the registry before calling this
  686. // API, double check the registry key and then delete it.
  687. dwType = REG_DWORD;
  688. dwSize = sizeof(DWORD);
  689. dwRes = ::SHGetValue( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszRestoreInProgress, &dwType, &dwInRestore, &dwSize );
  690. if ( dwRes != ERROR_SUCCESS )
  691. {
  692. cszErr = ::GetSysErrStr();
  693. DebugTrace(0, "::SHGetValue failed - %ls", cszErr);
  694. goto Exit;
  695. }
  696. dwRes = ::SHDeleteValue( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszRestoreInProgress );
  697. if ( dwRes != ERROR_SUCCESS )
  698. {
  699. cszErr = ::GetSysErrStr();
  700. ErrorTrace(0, "::SHDeleteValue failed - %ls", cszErr);
  701. goto Exit;
  702. }
  703. if ( dwInRestore == 0 )
  704. {
  705. DebugTrace(0, "RestoreInProgress is 0");
  706. goto Exit;
  707. }
  708. // 1. Create CRestoreOperationManager object.
  709. if ( !::CreateRestoreOperationManager( &pROMgr ) )
  710. goto Exit;
  711. // 2. Perform the Restore Operation.
  712. if ( !pROMgr->Run( TRUE ) )
  713. goto Exit;
  714. fRet = TRUE;
  715. Exit:
  716. SAFE_RELEASE(pROMgr);
  717. TraceFunctLeave();
  718. ReleaseTrace();
  719. return( fRet );
  720. }
  721. // end of file