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.

2895 lines
74 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * evthandler.cpp
  7. *
  8. * Abstract:
  9. * CEventHandler class methods
  10. *
  11. * Revision History:
  12. * Brijesh Krishnaswami (brijeshk) 03/17/2000
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include "precomp.h"
  17. #include "..\rstrcore\resource.h"
  18. #include "ntservmsg.h"
  19. #ifdef THIS_FILE
  20. #undef THIS_FILE
  21. #endif
  22. static char __szTraceSourceFile[] = __FILE__;
  23. #define THIS_FILE __szTraceSourceFile
  24. #define IDLE_STACKSIZE 32768 // 32K stack for idle thread
  25. CEventHandler *g_pEventHandler;
  26. BOOL CallerIsAdminOrSystem ()
  27. {
  28. BOOL fAdminOrSystem = TRUE; // impersonation will fail if from service
  29. if (RPC_S_OK == RpcImpersonateClient (NULL))
  30. {
  31. fAdminOrSystem = IsAdminOrSystem();
  32. RpcRevertToSelf();
  33. }
  34. return fAdminOrSystem;
  35. };
  36. BOOL CallerIsAdminOrSystemOrPowerUsers()
  37. {
  38. BOOL fPowerUsers = TRUE; // impersonation will fail if from service
  39. if (RPC_S_OK == RpcImpersonateClient (NULL))
  40. {
  41. fPowerUsers = IsAdminOrSystem() || IsPowerUsers();
  42. RpcRevertToSelf();
  43. }
  44. return fPowerUsers;
  45. }
  46. // constructor
  47. CEventHandler::CEventHandler()
  48. {
  49. m_hTimerQueue = m_hTimer = NULL;
  50. m_hIdle = NULL;
  51. m_fNoRpOnSystem = TRUE;
  52. m_fIdleSrvStarted = FALSE;
  53. m_ftFreeze.dwLowDateTime = 0;
  54. m_ftFreeze.dwHighDateTime = 0;
  55. m_nNestedCallCount = 0;
  56. m_hCOMDll = NULL;
  57. m_hIdleRequestHandle = NULL;
  58. m_hIdleStartHandle = NULL;
  59. m_hIdleStopHandle = NULL;
  60. m_fCreateRpASAP = FALSE;
  61. }
  62. // destructor
  63. CEventHandler::~CEventHandler()
  64. {
  65. }
  66. // the RPC API
  67. DWORD
  68. CEventHandler::DisableSRS(LPWSTR pszDrive)
  69. {
  70. DWORD dwRc = ERROR_SUCCESS;
  71. BOOL fHaveLock = FALSE;
  72. HANDLE hEventSource = NULL;
  73. tenter("CEventHandler::DisableSRS");
  74. if (!CallerIsAdminOrSystem())
  75. {
  76. dwRc = ERROR_ACCESS_DENIED;
  77. trace(0, "DisableSRS: Caller is not admin or system -- Access denied");
  78. goto done;
  79. }
  80. LOCKORLEAVE(fHaveLock);
  81. ASSERT(g_pDataStoreMgr && g_pSRConfig);
  82. // if whole of SR is disabled, then
  83. // - set firstrun and cleanup flag to yes
  84. // - set stop event
  85. if (! pszDrive || IsSystemDrive(pszDrive))
  86. {
  87. trace(0, "Disabling all of SR");
  88. dwRc = SrStopMonitoring(g_pSRConfig->GetFilter());
  89. if (dwRc != ERROR_SUCCESS)
  90. {
  91. trace(0, "! SrStopMonitoring : %ld", dwRc);
  92. goto done;
  93. }
  94. dwRc = g_pSRConfig->SetFirstRun(SR_FIRSTRUN_YES);
  95. if (dwRc != ERROR_SUCCESS)
  96. {
  97. trace(0, "! SetFirstRun : %ld", dwRc);
  98. goto done;
  99. }
  100. g_pDataStoreMgr->DestroyDataStore(NULL);
  101. if (dwRc != ERROR_SUCCESS)
  102. {
  103. trace(0, "! DestroyDataStore : %ld", dwRc);
  104. goto done;
  105. }
  106. // set the filter start to disabled only if this is a
  107. // real disable
  108. // if it's a reset, filter needs to start the next boot
  109. if (g_pSRConfig->GetResetFlag() == FALSE)
  110. {
  111. dwRc = SetServiceStartup(s_cszFilterName, SERVICE_DISABLED);
  112. if (ERROR_SUCCESS != dwRc)
  113. {
  114. trace(0, "! SetServiceStartup : %ld", dwRc);
  115. goto done;
  116. }
  117. // done, we are disabled
  118. dwRc = g_pSRConfig->SetDisableFlag(TRUE);
  119. if (dwRc != ERROR_SUCCESS)
  120. {
  121. trace(0, "! SetDisableFlag : %ld", dwRc);
  122. goto done;
  123. }
  124. }
  125. // set the stop event
  126. // this will bring us down gracefully
  127. SignalStop();
  128. if (g_pSRConfig->m_dwTestBroadcast)
  129. PostTestMessage(g_pSRConfig->m_uiTMDisable, NULL, NULL);
  130. // write to event log
  131. hEventSource = RegisterEventSource(NULL, s_cszServiceName);
  132. if (hEventSource != NULL)
  133. {
  134. SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, EVMSG_SYSDRIVE_DISABLED,
  135. NULL, 0, NULL, NULL, NULL);
  136. DeregisterEventSource(hEventSource);
  137. }
  138. trace(0, "SR disabled");
  139. }
  140. else
  141. {
  142. trace(0, "Disabling drive %S", pszDrive);
  143. // first tell filter to stop monitoring,
  144. // then build _filelst.cfg and pass down
  145. dwRc = g_pDataStoreMgr->MonitorDrive(pszDrive, FALSE);
  146. if (ERROR_SUCCESS != dwRc)
  147. {
  148. trace(0, "! g_pDataStoreMgr->MonitorDrive for %s : %ld", pszDrive, dwRc);
  149. goto done;
  150. }
  151. }
  152. done:
  153. UNLOCK(fHaveLock);
  154. tleave();
  155. return dwRc;
  156. }
  157. DWORD
  158. CEventHandler::EnableSRS(LPWSTR pszDrive)
  159. {
  160. tenter("CEventHandler::EnableSRS");
  161. BOOL fHaveLock = FALSE;
  162. DWORD dwRc = ERROR_SUCCESS;
  163. if (!CallerIsAdminOrSystem())
  164. {
  165. dwRc = ERROR_ACCESS_DENIED;
  166. goto done;
  167. }
  168. LOCKORLEAVE(fHaveLock);
  169. trace(0, "EnableSRS");
  170. ASSERT(g_pSRConfig);
  171. if (! pszDrive || IsSystemDrive(pszDrive))
  172. {
  173. //
  174. // if safe mode, then don't
  175. //
  176. if (TRUE == g_pSRConfig->GetSafeMode())
  177. {
  178. DebugTrace(0, "Cannot enable SR in safemode");
  179. dwRc = ERROR_BAD_ENVIRONMENT;
  180. goto done;
  181. }
  182. // system drive
  183. g_pSRConfig->SetDisableFlag(FALSE);
  184. dwRc = SetServiceStartup(s_cszFilterName, SERVICE_BOOT_START);
  185. if (ERROR_SUCCESS != dwRc)
  186. {
  187. trace(0, "! SetServiceStartup : %ld", dwRc);
  188. goto done;
  189. }
  190. dwRc = SetServiceStartup(s_cszServiceName, SERVICE_AUTO_START);
  191. if (ERROR_SUCCESS != dwRc)
  192. {
  193. trace(0, "! SetServiceStartup : %ld", dwRc);
  194. goto done;
  195. }
  196. }
  197. else
  198. {
  199. ASSERT(g_pDataStoreMgr);
  200. // build _filelst.cfg and pass down
  201. dwRc = g_pDataStoreMgr->MonitorDrive(pszDrive, TRUE);
  202. if (ERROR_SUCCESS != dwRc)
  203. {
  204. trace(0, "! g_pDataStoreMgr->MonitorDrive for %s : %ld", pszDrive, dwRc);
  205. goto done;
  206. }
  207. }
  208. done:
  209. UNLOCK(fHaveLock);
  210. tleave();
  211. return dwRc;
  212. }
  213. DWORD
  214. CEventHandler::DisableFIFOS(DWORD dwRPNum)
  215. {
  216. tenter("CEventHandler::DisableFIFOS");
  217. BOOL fHaveLock = FALSE;
  218. DWORD dwRc = ERROR_SUCCESS;
  219. if (!CallerIsAdminOrSystem())
  220. {
  221. dwRc = ERROR_ACCESS_DENIED;
  222. goto done;
  223. }
  224. LOCKORLEAVE(fHaveLock);
  225. ASSERT(g_pSRConfig);
  226. g_pSRConfig->SetFifoDisabledNum(dwRPNum);
  227. trace(0, "Disabled FIFO from RP%ld", dwRPNum);
  228. done:
  229. UNLOCK(fHaveLock);
  230. tleave();
  231. return dwRc;
  232. }
  233. DWORD
  234. CEventHandler::EnableFIFOS()
  235. {
  236. tenter("CEventHandler::EnableFIFOS");
  237. BOOL fHaveLock = FALSE;
  238. DWORD dwRc = ERROR_SUCCESS;
  239. if (!CallerIsAdminOrSystem())
  240. {
  241. dwRc = ERROR_ACCESS_DENIED;
  242. goto done;
  243. }
  244. LOCKORLEAVE(fHaveLock);
  245. ASSERT(g_pSRConfig);
  246. g_pSRConfig->SetFifoDisabledNum(0);
  247. trace(0, "Reenabled FIFO");
  248. done:
  249. UNLOCK(fHaveLock);
  250. tleave();
  251. return dwRc;
  252. }
  253. // API and internal method to create a new restore point -
  254. // this will ask filter to create a restore point folder,
  255. // take the system snapshot, and write the restore point log
  256. BOOL
  257. CEventHandler::SRSetRestorePointS(
  258. PRESTOREPOINTINFOW pRPInfo,
  259. PSTATEMGRSTATUS pSmgrStatus )
  260. {
  261. tenter("CEventHandler::SRSetRestorePointS");
  262. DWORD dwRc = ERROR_SUCCESS;
  263. WCHAR szRPDir[MAX_RP_PATH];
  264. DWORD dwRPNum = 1;
  265. BOOL fHaveLock = FALSE;
  266. HKEY hKey = NULL;
  267. CRestorePoint rpLast;
  268. BOOL fSnapshot = TRUE;
  269. DWORD dwSaveType;
  270. BOOL fUpdateMonitoredList = FALSE;
  271. DWORD dwSnapshotResult = ERROR_SUCCESS;
  272. BOOL fSerialized;
  273. if (! pRPInfo || ! pSmgrStatus)
  274. {
  275. trace(0, "Invalid arguments");
  276. dwRc = ERROR_INVALID_DATA;
  277. goto done;
  278. }
  279. if (pRPInfo->dwRestorePtType > MAX_RPT)
  280. {
  281. trace(0, "Restore point type out of valid range");
  282. dwRc = ERROR_INVALID_DATA;
  283. goto done;
  284. }
  285. if (pRPInfo->dwEventType < MIN_EVENT ||
  286. pRPInfo->dwEventType > MAX_EVENT)
  287. {
  288. trace(0, "Event type out of valid range");
  289. dwRc = ERROR_INVALID_DATA;
  290. goto done;
  291. }
  292. LOCKORLEAVE(fHaveLock);
  293. ASSERT(g_pDataStoreMgr && g_pSRConfig);
  294. //
  295. // special processing for FIRSTRUN checkpoint
  296. //
  297. if (pRPInfo->dwRestorePtType == FIRSTRUN)
  298. {
  299. // first remove the Run key if it exists
  300. // the function run from the Run entry in srclient.dll may not have been
  301. // able to delete itself if it was run in non-admin context
  302. // so we will make sure we delete it here
  303. HKEY hKey;
  304. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE,
  305. L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
  306. &hKey))
  307. {
  308. RegDeleteValue(hKey, L"SRFirstRun");
  309. RegCloseKey(hKey);
  310. }
  311. // if this is really the first checkpoint
  312. // then allow it no matter who's trying to create it
  313. // if not, then bail
  314. if (m_fNoRpOnSystem == FALSE)
  315. {
  316. trace(0, "Trying to create FirstRun rp when an rp already exists");
  317. dwRc = ERROR_ALREADY_EXISTS;
  318. goto done;
  319. }
  320. }
  321. else
  322. {
  323. // this is not FIRSTRUN, so check for privileges
  324. if (!CallerIsAdminOrSystemOrPowerUsers())
  325. {
  326. dwRc = ERROR_ACCESS_DENIED;
  327. trace(0, "SRSetRestorePointS: Caller is not admin or system or power users -- Access denied");
  328. goto done;
  329. }
  330. }
  331. //
  332. // if this is a restore restore point or system checkpoint,
  333. // then erase any nested rp context
  334. // this will make sure that restore can happen
  335. // even if some erratic client failed to call END_NESTED
  336. //
  337. if (pRPInfo->dwRestorePtType == RESTORE ||
  338. pRPInfo->dwRestorePtType == CHECKPOINT ||
  339. pRPInfo->dwRestorePtType == FIRSTRUN)
  340. {
  341. trace(0, "Resetting nested refcount to 0");
  342. m_nNestedCallCount = 0;
  343. }
  344. //
  345. // get the current rp number
  346. // dwRPNum will be overwritten if a new restore point is created
  347. // after all the prelim checks
  348. //
  349. dwRPNum = (m_fNoRpOnSystem == FALSE) ? m_CurRp.GetNum() : 0;
  350. //
  351. // if this is a nested call
  352. // then don't create nested rps
  353. //
  354. if (pRPInfo->dwEventType == END_NESTED_SYSTEM_CHANGE)
  355. {
  356. // adjust refcount only if called for the current restore point
  357. if (pRPInfo->llSequenceNumber == 0 ||
  358. pRPInfo->llSequenceNumber == dwRPNum)
  359. {
  360. dwRc = ERROR_SUCCESS;
  361. if (m_nNestedCallCount > 0)
  362. m_nNestedCallCount--;
  363. }
  364. else if (pRPInfo->llSequenceNumber < dwRPNum)
  365. {
  366. dwRc = ERROR_SUCCESS;
  367. trace(0, "END_NESTED called for older rp - not adjusting refcount");
  368. }
  369. else
  370. {
  371. dwRc = ERROR_INVALID_DATA;
  372. trace(0, "END_NESTED called for non-existent rp - not adjusting refcount");
  373. }
  374. if (pRPInfo->dwRestorePtType != CANCELLED_OPERATION)
  375. {
  376. goto done;
  377. }
  378. }
  379. else if (pRPInfo->dwEventType == BEGIN_NESTED_SYSTEM_CHANGE)
  380. {
  381. if (m_nNestedCallCount > 0)
  382. {
  383. dwRc = ERROR_SUCCESS;
  384. m_nNestedCallCount++;
  385. goto done;
  386. }
  387. }
  388. // check if this is a request to remove restore point
  389. // provided for backward compat only
  390. // new clients should use SRRemoveRestorePoint
  391. if (pRPInfo->dwEventType == END_SYSTEM_CHANGE ||
  392. pRPInfo->dwEventType == END_NESTED_SYSTEM_CHANGE)
  393. {
  394. if (pRPInfo->dwRestorePtType == CANCELLED_OPERATION)
  395. {
  396. dwRc = SRRemoveRestorePointS((DWORD) pRPInfo->llSequenceNumber);
  397. goto done;
  398. }
  399. else
  400. {
  401. dwRc = ERROR_SUCCESS;
  402. goto done;
  403. }
  404. }
  405. // if this is safe mode, don't create restore point
  406. //
  407. // however, allow restore UI to be able to create a hidden restore point in safemode
  408. //
  409. if (g_pSRConfig->GetSafeMode() == TRUE)
  410. {
  411. if (pRPInfo->dwRestorePtType == CANCELLED_OPERATION)
  412. {
  413. // we need this rp only for undo in case of failure
  414. // so we don't need snapshot (snapshotting will fail in safemode)
  415. trace(0, "Restore rp - creating snapshot in safemode");
  416. }
  417. else
  418. {
  419. trace(0, "Cannot create restore point in safemode");
  420. dwRc = ERROR_BAD_ENVIRONMENT;
  421. goto done;
  422. }
  423. }
  424. //
  425. // if system drive is frozen,
  426. // then see if it can be thawed
  427. // if not, then cannot create rp
  428. //
  429. if (g_pDataStoreMgr->IsDriveFrozen(g_pSRConfig->GetSystemDrive()))
  430. {
  431. if (ERROR_SUCCESS != g_pDataStoreMgr->ThawDrives(TRUE))
  432. {
  433. trace(0, "Cannot create rp when system drive is frozen");
  434. dwRc = ERROR_DISK_FULL;
  435. goto done;
  436. }
  437. }
  438. if (hKey)
  439. RegCloseKey(hKey);
  440. // ask filter to create restore point
  441. // filter will return the restore point number - i for RPi - in dwRPNum
  442. dwRc = SrCreateRestorePoint( g_pSRConfig->GetFilter(), &dwRPNum );
  443. if (ERROR_SUCCESS != dwRc)
  444. {
  445. trace(0, "! SrCreateRestorePoint : %ld", dwRc);
  446. goto done;
  447. }
  448. wsprintf( szRPDir, L"%s%ld", s_cszRPDir, dwRPNum );
  449. //
  450. // update the current restore point object
  451. // write rp.log with cancelled restorepoint type
  452. //
  453. if (m_fNoRpOnSystem == FALSE)
  454. {
  455. rpLast.SetDir(m_CurRp.GetDir());
  456. }
  457. m_CurRp.SetDir(szRPDir);
  458. dwSaveType = pRPInfo->dwRestorePtType;
  459. pRPInfo->dwRestorePtType = CANCELLED_OPERATION;
  460. m_CurRp.Load(pRPInfo);
  461. dwRc = m_CurRp.WriteLog();
  462. if ( ERROR_SUCCESS != dwRc )
  463. {
  464. trace(0, "! WriteLog : %ld", dwRc);
  465. goto done;
  466. }
  467. // create system snapshot
  468. // if there is no explicit regkey that disabled it
  469. if (fSnapshot)
  470. {
  471. WCHAR szFullPath[MAX_PATH];
  472. CSnapshot Snapshot;
  473. if (m_hCOMDll == NULL)
  474. {
  475. m_hCOMDll = LoadLibrary(s_cszCOMDllName);
  476. if (NULL == m_hCOMDll)
  477. {
  478. dwRc = GetLastError();
  479. trace(0, "LoadLibrary of %S failed ec=%d", s_cszCOMDllName, dwRc);
  480. goto done;
  481. }
  482. }
  483. // BUGBUG - this does not seem to make any difference
  484. // so remove it
  485. #if 0
  486. if (FALSE == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL))
  487. {
  488. trace(0, "! SetThreadPriority first");
  489. }
  490. #endif
  491. if (dwSaveType == RESTORE ||
  492. dwSaveType == CANCELLED_OPERATION)
  493. {
  494. fSerialized = TRUE;
  495. trace(0, "Setting fSerialized to TRUE");
  496. }
  497. else
  498. {
  499. fSerialized = FALSE;
  500. trace(0, "Setting fSerialized to FALSE");
  501. }
  502. MakeRestorePath (szFullPath, g_pSRConfig->GetSystemDrive(), szRPDir);
  503. dwRc = Snapshot.CreateSnapshot(szFullPath,
  504. m_hCOMDll,
  505. m_fNoRpOnSystem ? NULL : rpLast.GetDir(),
  506. fSerialized);
  507. #if 0
  508. if (FALSE == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL))
  509. {
  510. trace(0, "! SetThreadPriority second");
  511. }
  512. #endif
  513. dwSnapshotResult = dwRc;
  514. }
  515. // ask the datastoremgr to persist drivetable for old restore point
  516. // and reset per-rp flags for the new restore point
  517. dwRc = g_pDataStoreMgr->SwitchRestorePoint(m_fNoRpOnSystem ? NULL : &rpLast);
  518. if (dwRc != ERROR_SUCCESS)
  519. {
  520. trace(0, "! SwitchRestorePoint : %ld", dwRc);
  521. goto done;
  522. }
  523. m_fNoRpOnSystem = FALSE;
  524. //
  525. // restore point is fully created
  526. // write rp.log again
  527. // this time with the real restorepoint type
  528. //
  529. if (dwSnapshotResult == ERROR_SUCCESS)
  530. {
  531. pRPInfo->dwRestorePtType = dwSaveType;
  532. m_CurRp.Load(pRPInfo);
  533. dwRc = m_CurRp.WriteLog();
  534. if ( ERROR_SUCCESS != dwRc )
  535. {
  536. trace(0, "! WriteLog : %ld", dwRc);
  537. goto done;
  538. }
  539. trace(0, "****Created %S %S****", szRPDir, pRPInfo->szDescription);
  540. }
  541. else
  542. {
  543. trace(0, "****Cancelled %S - snapshot failed", szRPDir);
  544. }
  545. // if drives need to be thawed, then recreate blob
  546. // and deactivate thaw timer
  547. if ( TRUE == g_pDataStoreMgr->IsDriveFrozen(NULL) )
  548. {
  549. if (ERROR_SUCCESS == g_pDataStoreMgr->ThawDrives(FALSE))
  550. {
  551. m_ftFreeze.dwLowDateTime = 0;
  552. m_ftFreeze.dwHighDateTime = 0;
  553. fUpdateMonitoredList = TRUE;
  554. }
  555. else
  556. {
  557. dwRc = ERROR_DISK_FULL;
  558. goto done;
  559. }
  560. }
  561. // Also update the filter monitored list blob if this is an idle
  562. // time restore point or if this is the first run restore
  563. // point. We update the monitored list at first run since the
  564. // initial blob is created before the first user logs on to the
  565. // machine and before the first user's profile exists. So we want
  566. // to update rhe monitored list at first run since by now the
  567. // user's profile has been created.
  568. if (fUpdateMonitoredList ||
  569. (pRPInfo->dwRestorePtType == CHECKPOINT) ||
  570. (pRPInfo->dwRestorePtType == FIRSTRUN) )
  571. {
  572. dwRc = SRUpdateMonitoredListS(NULL);
  573. }
  574. //
  575. // if rp creation succeeded,
  576. // and this is the outermost nested call
  577. // then bump refcount to 1
  578. //
  579. if (dwRc == ERROR_SUCCESS &&
  580. pRPInfo->dwEventType == BEGIN_NESTED_SYSTEM_CHANGE)
  581. {
  582. m_nNestedCallCount = 1;
  583. }
  584. //
  585. // send thaw complete test message
  586. //
  587. if (fUpdateMonitoredList)
  588. {
  589. if (g_pSRConfig->m_dwTestBroadcast)
  590. PostTestMessage(g_pSRConfig->m_uiTMThaw, NULL, NULL);
  591. }
  592. // if WMI is serialized, then check fifo conditions here
  593. // else this would happen in DoWMISnapshot
  594. if (fSerialized)
  595. {
  596. g_pDataStoreMgr->TriggerFreezeOrFifo();
  597. }
  598. done:
  599. trace(0, "Nest level : %d", m_nNestedCallCount);
  600. if (dwSnapshotResult != ERROR_SUCCESS)
  601. dwRc = dwSnapshotResult;
  602. // populate return struct
  603. if (pSmgrStatus)
  604. {
  605. pSmgrStatus->nStatus = dwRc;
  606. pSmgrStatus->llSequenceNumber = (INT64) dwRPNum;
  607. }
  608. UNLOCK( fHaveLock );
  609. tleave();
  610. return ( dwRc == ERROR_SUCCESS ) ? TRUE : FALSE;
  611. }
  612. // this api is provided to remove a restore point
  613. // removing a restore point simply takes away the ability to restore
  614. // to this point - all the changes in this restore point are preserved
  615. DWORD
  616. CEventHandler::SRRemoveRestorePointS(
  617. DWORD dwRPNum)
  618. {
  619. tenter("CEventHandler::SRRemoveRestorePointS");
  620. BOOL fHaveLock = FALSE;
  621. WCHAR szRPDir[MAX_PATH];
  622. WCHAR szFullPath[MAX_PATH];
  623. DWORD dwRc = ERROR_SUCCESS;
  624. CSnapshot Snapshot;
  625. CRestorePoint rp;
  626. CDataStore *pds = NULL;
  627. INT64 llOld, llNew;
  628. if (!CallerIsAdminOrSystemOrPowerUsers())
  629. {
  630. dwRc = ERROR_ACCESS_DENIED;
  631. trace(0, "SRRemoveRestorePointS: Caller is not admin or system or power users -- Access denied");
  632. goto done;
  633. }
  634. if (dwRPNum < 1)
  635. {
  636. dwRc = ERROR_INVALID_DATA;
  637. goto done;
  638. }
  639. LOCKORLEAVE(fHaveLock);
  640. ASSERT(g_pSRConfig);
  641. // if there is no rp, then no-op
  642. if (m_fNoRpOnSystem)
  643. {
  644. dwRc = ERROR_INVALID_DATA;
  645. goto done;
  646. }
  647. wsprintf(szRPDir, L"%s%ld", s_cszRPDir, dwRPNum);
  648. // read the restore point log
  649. rp.SetDir(szRPDir);
  650. dwRc = rp.ReadLog();
  651. if (ERROR_SUCCESS != dwRc)
  652. {
  653. trace(0, "! rp.ReadLog : %ld", dwRc);
  654. dwRc = ERROR_INVALID_DATA;
  655. goto done;
  656. }
  657. // delete snapshot
  658. MakeRestorePath (szFullPath, g_pSRConfig->GetSystemDrive(), szRPDir);
  659. dwRc = Snapshot.DeleteSnapshot(szFullPath);
  660. if (dwRc != ERROR_SUCCESS)
  661. goto done;
  662. // cancel this restore point
  663. rp.Cancel();
  664. //
  665. // adjust the restorepointsize file
  666. // and the in-memory counters in the service
  667. //
  668. pds = g_pDataStoreMgr->GetDriveTable()->FindSystemDrive();
  669. if (! pds)
  670. {
  671. trace(0, "! FindSystemDrive");
  672. goto done;
  673. }
  674. llOld = 0;
  675. dwRc = rp.ReadSize(g_pSRConfig->GetSystemDrive(), &llOld);
  676. if (dwRc != ERROR_SUCCESS)
  677. {
  678. trace(0, "! rp.ReadSize : %ld", dwRc);
  679. goto done;
  680. }
  681. llNew = 0;
  682. dwRc = pds->CalculateRpUsage(&rp, &llNew, TRUE, FALSE);
  683. if (dwRc != ERROR_SUCCESS)
  684. {
  685. trace(0, "! CalculateRpUsage : %ld", dwRc);
  686. goto done;
  687. }
  688. trace(0, "llOld = %I64d, llNew = %I64d", llOld, llNew);
  689. //
  690. // now update the correct variable in the correct object
  691. //
  692. pds->UpdateDataStoreUsage (llNew - llOld, rp.GetNum() == m_CurRp.GetNum());
  693. done:
  694. UNLOCK(fHaveLock);
  695. tleave();
  696. return dwRc;
  697. }
  698. DWORD
  699. CEventHandler::SRUpdateMonitoredListS(
  700. LPWSTR pszXMLFile)
  701. {
  702. tenter("CEventHandler::SRUpdateMonitoredListS");
  703. DWORD dwRc = ERROR_INTERNAL_ERROR;
  704. BOOL fHaveLock = FALSE;
  705. if (!CallerIsAdminOrSystem())
  706. {
  707. dwRc = ERROR_ACCESS_DENIED;
  708. goto done;
  709. }
  710. LOCKORLEAVE(fHaveLock);
  711. ASSERT(g_pDataStoreMgr && g_pSRConfig);
  712. // convert xml to blob
  713. dwRc = XmlToBlob(pszXMLFile);
  714. if (ERROR_SUCCESS != dwRc)
  715. goto done;
  716. // reload to filter
  717. dwRc = SrReloadConfiguration(g_pSRConfig->GetFilter());
  718. if (ERROR_SUCCESS != dwRc)
  719. {
  720. trace(0, "! SrReloadConfiguration : %ld", dwRc);
  721. goto done;
  722. }
  723. trace(0, "****Reloaded config file****");
  724. done:
  725. UNLOCK(fHaveLock);
  726. tleave();
  727. return dwRc;
  728. }
  729. DWORD
  730. CEventHandler::SRUpdateDSSizeS(LPWSTR pwszVolumeGuid, UINT64 ullSizeLimit)
  731. {
  732. tenter("CEventHandler::SRUpdateDSSizeS");
  733. UINT64 ullTemp;
  734. DWORD dwRc = ERROR_SUCCESS;
  735. CDataStore *pds = NULL;
  736. BOOL fHaveLock = FALSE;
  737. BOOL fSystem;
  738. if (!CallerIsAdminOrSystem())
  739. {
  740. dwRc = ERROR_ACCESS_DENIED;
  741. goto done;
  742. }
  743. LOCKORLEAVE(fHaveLock);
  744. ASSERT(g_pDataStoreMgr);
  745. pds = g_pDataStoreMgr->GetDriveTable()->FindDriveInTable(pwszVolumeGuid);
  746. if (! pds)
  747. {
  748. trace(0, "Volume not in drivetable : %S", pwszVolumeGuid);
  749. dwRc = ERROR_INVALID_DRIVE;
  750. goto done;
  751. }
  752. fSystem = pds->GetFlags() & SR_DRIVE_SYSTEM;
  753. if (ullSizeLimit < (g_pSRConfig ? g_pSRConfig->GetDSMin(fSystem) :
  754. (fSystem ? SR_DEFAULT_DSMIN:SR_DEFAULT_DSMIN_NONSYSTEM)
  755. * MEGABYTE))
  756. {
  757. trace(0, "SRUpdateDSSizeS %I64d less than dwDSMin", ullSizeLimit);
  758. dwRc = ERROR_INVALID_PARAMETER;
  759. goto done;
  760. }
  761. ullTemp = pds->GetSizeLimit(); // save previous size
  762. pds->SetSizeLimit(0); // reset the datastore size
  763. pds->UpdateDiskFree (NULL); // calculate the default size
  764. if (ullSizeLimit > pds->GetSizeLimit())
  765. {
  766. pds->SetSizeLimit (ullTemp);
  767. trace(0, "SRUpdateDSSizeS %I64d greater than limit", ullSizeLimit);
  768. dwRc = ERROR_INVALID_PARAMETER;
  769. goto done;
  770. }
  771. pds->SetSizeLimit(ullSizeLimit);
  772. g_pDataStoreMgr->GetDriveTable()->SaveDriveTable((CRestorePoint *) NULL);
  773. //
  774. // this might change fifo conditions
  775. // so check and trigger fifo if necessary
  776. //
  777. g_pDataStoreMgr->TriggerFreezeOrFifo();
  778. done:
  779. UNLOCK(fHaveLock);
  780. tleave();
  781. return dwRc;
  782. }
  783. DWORD
  784. CEventHandler::SRSwitchLogS()
  785. {
  786. tenter("CEventHandler::SRSwitchLogS");
  787. DWORD dwRc = ERROR_SUCCESS;
  788. BOOL fHaveLock;
  789. LOCKORLEAVE(fHaveLock);
  790. ASSERT(g_pSRConfig);
  791. dwRc = SrSwitchAllLogs(g_pSRConfig->GetFilter());
  792. if (ERROR_SUCCESS != dwRc)
  793. trace(0, "! SrSwitchLog : %ld", dwRc);
  794. done:
  795. UNLOCK(fHaveLock);
  796. tleave();
  797. return dwRc;
  798. }
  799. DWORD
  800. CEventHandler::XmlToBlob(LPWSTR pszwXml)
  801. {
  802. tenter("CEventHandler::XmlToBlob");
  803. DWORD dwRc = ERROR_INTERNAL_ERROR;
  804. WCHAR szwDat[MAX_PATH], szwXml[MAX_PATH];
  805. CFLDatBuilder FLDatBuilder;
  806. ASSERT(g_pSRConfig);
  807. MakeRestorePath(szwDat, g_pSRConfig->GetSystemDrive(), s_cszFilelistDat);
  808. if (0 == ExpandEnvironmentStrings(s_cszWinRestDir, szwXml, sizeof(szwXml) / sizeof(WCHAR)))
  809. {
  810. dwRc = GetLastError();
  811. trace(0, "! ExpandEnvironmentStrings");
  812. goto done;
  813. }
  814. lstrcat(szwXml, s_cszFilelistXml);
  815. if ( ! pszwXml )
  816. {
  817. pszwXml = szwXml;
  818. }
  819. if (FALSE == FLDatBuilder.BuildTree(pszwXml, szwDat))
  820. {
  821. trace(0, "! FLDatBuilder.BuildTree");
  822. goto done;
  823. }
  824. if (pszwXml && pszwXml != szwXml && 0 != lstrcmpi(pszwXml, szwXml))
  825. {
  826. // copy the new filelist
  827. SetFileAttributes(szwXml, FILE_ATTRIBUTE_NORMAL);
  828. if (FALSE == CopyFile(pszwXml, szwXml, FALSE))
  829. {
  830. dwRc = GetLastError();
  831. trace(0, "! CopyFile : %ld", dwRc);
  832. goto done;
  833. }
  834. }
  835. // set filelist.xml to be S+H+R
  836. SetFileAttributes(szwXml, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
  837. dwRc = ERROR_SUCCESS;
  838. done:
  839. tleave();
  840. return dwRc;
  841. }
  842. // SR ACTIONS
  843. DWORD
  844. CEventHandler::OnFirstRun()
  845. {
  846. tenter("CEventHandler::OnFirstRun");
  847. DWORD dwRc = ERROR_SUCCESS;
  848. RESTOREPOINTINFO RPInfo;
  849. STATEMGRSTATUS SmgrStatus;
  850. LPSTR pszDat = NULL, pszXml = NULL;
  851. WCHAR szwDat[MAX_PATH], szwXml[MAX_PATH];
  852. trace(0, "Firstrun detected");
  853. dwRc = XmlToBlob(NULL);
  854. if (ERROR_SUCCESS != dwRc)
  855. goto done;
  856. // ask filter to start monitoring
  857. dwRc = SrStartMonitoring(g_pSRConfig->GetFilter());
  858. if (ERROR_SUCCESS != dwRc)
  859. {
  860. trace(0, "! SrStartMonitoring : %ld", dwRc);
  861. goto done;
  862. }
  863. // change firstrun in the registry
  864. dwRc = g_pSRConfig->SetFirstRun(SR_FIRSTRUN_NO);
  865. if ( dwRc != ERROR_SUCCESS )
  866. {
  867. trace(0, "! g_pSRConfig->SetFirstRun : %ld", dwRc);
  868. goto done;
  869. }
  870. // create firstrun restore point
  871. if (! g_pDataStoreMgr->IsDriveFrozen(g_pSRConfig->GetSystemDrive()) &&
  872. g_pSRConfig->GetCreateFirstRunRp() != 0)
  873. {
  874. RPInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
  875. RPInfo.dwRestorePtType = FIRSTRUN;
  876. if (ERROR_SUCCESS != SRLoadString(L"srrstr.dll", IDS_SYSTEM_CHECKPOINT_TEXT, RPInfo.szDescription, MAX_PATH))
  877. {
  878. trace(0, "Using default hardcoded text");
  879. lstrcpy(RPInfo.szDescription, s_cszSystemCheckpointName);
  880. }
  881. if ( FALSE == SRSetRestorePointS( &RPInfo, &SmgrStatus ))
  882. {
  883. //
  884. // even if this fails
  885. // keep the service running
  886. //
  887. trace(0, "Cannot create firstrun restore point : %ld", SmgrStatus.nStatus);
  888. }
  889. }
  890. //
  891. // in future re-enables, service should create firstrun rp
  892. //
  893. if (g_pSRConfig->m_dwCreateFirstRunRp == 0)
  894. g_pSRConfig->SetCreateFirstRunRp(TRUE);
  895. done:
  896. tleave();
  897. return dwRc;
  898. }
  899. // stuff to do at boot
  900. // read in all the config values from registry
  901. // initialize communication with filter
  902. // call OnFirstRun if necessary
  903. // setup timer & idle detection
  904. // start RPC server
  905. DWORD
  906. CEventHandler::OnBoot()
  907. {
  908. BOOL fHaveLock = FALSE;
  909. DWORD dwRc = ERROR_INTERNAL_ERROR;
  910. BOOL fSendEnableMessage = FALSE;
  911. DWORD dwFlags;
  912. tenter("CEventHandler::OnBoot");
  913. dwRc = m_DSLock.Init();
  914. if (dwRc != ERROR_SUCCESS)
  915. {
  916. trace(0, "m_DSLock.Init() : %ld", dwRc);
  917. goto done;
  918. }
  919. LOCKORLEAVE(fHaveLock);
  920. // initialize the counter
  921. dwRc = m_Counter.Init();
  922. if ( ERROR_SUCCESS != dwRc )
  923. {
  924. trace(0, "! CCounter::Init : %ld", dwRc);
  925. goto done;
  926. }
  927. // read all values from registry
  928. // create global events
  929. g_pSRConfig = new CSRConfig;
  930. if ( ! g_pSRConfig )
  931. {
  932. dwRc = ERROR_NOT_ENOUGH_MEMORY;
  933. trace(0, "Out of Memory");
  934. goto done;
  935. }
  936. dwRc = g_pSRConfig->Initialize();
  937. if ( ERROR_SUCCESS != dwRc )
  938. {
  939. trace(0, "! g_pSRConfig->Initialize : %ld", dwRc);
  940. goto done;
  941. }
  942. trace(0, "SRBoottask: SRConfig initialized");
  943. if ( g_pSRConfig->GetDisableFlag() == TRUE )
  944. {
  945. // check if we're forced to enable
  946. if ( g_pSRConfig->GetDisableFlag_GroupPolicy() == FALSE )
  947. {
  948. dwRc = EnableSRS(NULL);
  949. if (ERROR_SUCCESS != dwRc)
  950. {
  951. trace(0, "! EnableSRS : %ld", dwRc);
  952. goto done;
  953. }
  954. }
  955. else
  956. {
  957. // we are not forced to enable
  958. // so we don't need to check if group policy is not configured or is disabling us
  959. // since we are disabled anyway
  960. trace(0, "SR is disabled - stopping");
  961. dwRc = ERROR_SERVICE_DISABLED;
  962. goto done;
  963. }
  964. }
  965. // open the filter handle
  966. // this will load the filter if not already loaded
  967. dwRc = g_pSRConfig->OpenFilter();
  968. if ( ERROR_SUCCESS != dwRc )
  969. {
  970. trace(0, "! g_pSRConfig->OpenFilter : %ld", dwRc);
  971. goto done;
  972. }
  973. trace(0, "SRBoottask: Filter handle opened");
  974. //
  975. // we might do a firstrun if the datastore is corrupted
  976. // (_filelst.cfg missing)
  977. // in this case, the filter might be ON
  978. // turn off the filter
  979. //
  980. if ( g_pSRConfig->GetFirstRun() == SR_FIRSTRUN_YES )
  981. {
  982. dwRc = SrStopMonitoring(g_pSRConfig->GetFilter());
  983. trace(0, "SrStopMonitoring returned : %ld", dwRc);
  984. }
  985. // initialize the datastore
  986. g_pDataStoreMgr = new CDataStoreMgr;
  987. if ( ! g_pDataStoreMgr )
  988. {
  989. trace(0, "Out of Memory");
  990. dwRc = ERROR_NOT_ENOUGH_MEMORY;
  991. goto done;
  992. }
  993. dwRc = g_pDataStoreMgr->Initialize (g_pSRConfig->GetFirstRun() == SR_FIRSTRUN_YES);
  994. if ( ERROR_SUCCESS != dwRc )
  995. {
  996. trace(0, "! g_pDataStore.Initialize : %ld", dwRc);
  997. goto done;
  998. }
  999. trace(0, "SRBoottask: Datastore initialized");
  1000. // check if we are newly disabled from group policy
  1001. if ( g_pSRConfig->GetDisableFlag_GroupPolicy() == TRUE &&
  1002. g_pSRConfig->GetDisableFlag() == FALSE )
  1003. {
  1004. DisableSRS (NULL);
  1005. dwRc = ERROR_SERVICE_DISABLED;
  1006. goto done;
  1007. }
  1008. // check if this is first run
  1009. if ( g_pSRConfig->GetFirstRun() == SR_FIRSTRUN_YES )
  1010. {
  1011. fSendEnableMessage = TRUE;
  1012. dwRc = OnFirstRun( );
  1013. if ( ERROR_SUCCESS != dwRc )
  1014. {
  1015. trace(0, "! OnFirstRun : %ld", dwRc);
  1016. goto done;
  1017. }
  1018. trace(0, "SRBoottask: FirstRun completed");
  1019. }
  1020. // remember the latest restore point
  1021. RefreshCurrentRp(TRUE);
  1022. if (ERROR_SUCCESS == g_pDataStoreMgr->GetFlags(g_pSRConfig->GetSystemDrive(), &dwFlags))
  1023. {
  1024. if (dwFlags & SR_DRIVE_ERROR)
  1025. {
  1026. // a volume error happened in the last session
  1027. // we should create a restore point at next idle time
  1028. m_fCreateRpASAP = TRUE;
  1029. trace(0, "Volume error occurred in last session - create rp at next idle");
  1030. }
  1031. }
  1032. else
  1033. {
  1034. trace(0, "! g_pDataStoreMgr->GetFlags()");
  1035. }
  1036. // register filter ioctls
  1037. if (! QueueUserWorkItem(PostFilterIo, (PVOID) MAX_IOCTLS, WT_EXECUTEDEFAULT))
  1038. {
  1039. dwRc = GetLastError();
  1040. trace(0, "! QueueUserWorkItem : %ld", dwRc);
  1041. goto done;
  1042. }
  1043. // start idle time detection
  1044. // register idle callback
  1045. if (FALSE == RegisterWaitForSingleObject(&m_hIdleRequestHandle,
  1046. g_pSRConfig->m_hIdleRequestEvent,
  1047. (WAITORTIMERCALLBACK) IdleRequestCallback,
  1048. NULL,
  1049. g_pSRConfig->m_dwIdleInterval*1000,
  1050. WT_EXECUTEDEFAULT))
  1051. {
  1052. dwRc = GetLastError();
  1053. trace(0, "! RegisterWaitForSingleObject : %ld", dwRc);
  1054. goto done;
  1055. }
  1056. // now request for idle
  1057. SetEvent(g_pSRConfig->m_hIdleRequestEvent);
  1058. //
  1059. // if there are no mounted drives
  1060. // shell will give us all the notifications
  1061. // so don't start timer thread
  1062. //
  1063. // BUGBUG - keep this?
  1064. // don't start timer at all
  1065. // if (FALSE == g_pDataStoreMgr->GetDriveTable()->AnyMountedDrives())
  1066. // {
  1067. g_pSRConfig->m_dwTimerInterval = 0;
  1068. // }
  1069. // set up timer
  1070. dwRc = InitTimer();
  1071. if ( ERROR_SUCCESS != dwRc )
  1072. {
  1073. trace(0, "! InitTimer : %ld", dwRc);
  1074. goto done;
  1075. }
  1076. // start rpc server
  1077. dwRc = RpcServerStart();
  1078. if (ERROR_SUCCESS != dwRc)
  1079. {
  1080. trace(0, "! RpcServerStart : %ld", dwRc);
  1081. goto done;
  1082. }
  1083. // all initialization complete
  1084. SetEvent( g_pSRConfig->m_hSRInitEvent );
  1085. if (fSendEnableMessage)
  1086. {
  1087. // write to event log
  1088. HANDLE hEventSource = RegisterEventSource(NULL, s_cszServiceName);
  1089. if (hEventSource != NULL)
  1090. {
  1091. SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, EVMSG_SYSDRIVE_ENABLED,
  1092. NULL, 0, NULL, NULL, NULL);
  1093. DeregisterEventSource(hEventSource);
  1094. }
  1095. if (g_pSRConfig->m_dwTestBroadcast)
  1096. PostTestMessage(g_pSRConfig->m_uiTMEnable, NULL, NULL);
  1097. }
  1098. done:
  1099. UNLOCK(fHaveLock);
  1100. tleave( );
  1101. return dwRc;
  1102. }
  1103. // method to shutdown the service gracefully
  1104. void
  1105. CEventHandler::OnStop()
  1106. {
  1107. DWORD dwRc;
  1108. tenter("CEventHandler::OnStop");
  1109. if (g_pSRConfig == NULL)
  1110. {
  1111. trace(0, "g_pSRConfig = NULL");
  1112. goto Err;
  1113. }
  1114. // stop everything
  1115. // BUGBUG - do we need to take the lock here?
  1116. // since all the stops are blocking in themselves
  1117. // and this has to preempt any running activity,
  1118. // blocking here is not such a good idea
  1119. // stop the rpc server
  1120. RpcServerShutdown();
  1121. trace(0, "SRShutdowntask: RPC server shutdown");
  1122. // kill the timer and timer queue
  1123. EndTimer();
  1124. trace(0, "SRShutdownTask: Timer stopped");
  1125. //
  1126. // blocking calls to unregister idle event callbacks
  1127. //
  1128. if (m_hIdleRequestHandle != NULL)
  1129. {
  1130. if (FALSE == UnregisterWaitEx(m_hIdleRequestHandle, INVALID_HANDLE_VALUE))
  1131. {
  1132. trace(0, "! UnregisterWaitEx : %ld", GetLastError());
  1133. }
  1134. m_hIdleRequestHandle = NULL;
  1135. }
  1136. if (m_hIdleStartHandle != NULL)
  1137. {
  1138. if (FALSE == UnregisterWaitEx(m_hIdleStartHandle, INVALID_HANDLE_VALUE))
  1139. {
  1140. trace(0, "! UnregisterWaitEx : %ld", GetLastError());
  1141. }
  1142. m_hIdleStartHandle = NULL;
  1143. }
  1144. if (m_hIdleStopHandle != NULL)
  1145. {
  1146. if (FALSE == UnregisterWaitEx(m_hIdleStopHandle, INVALID_HANDLE_VALUE))
  1147. {
  1148. trace(0, "! UnregisterWaitEx : %ld", GetLastError());
  1149. }
  1150. m_hIdleStopHandle = NULL;
  1151. }
  1152. // we are done with the filter
  1153. g_pSRConfig->CloseFilter();
  1154. trace(0, "Filter handle closed");
  1155. // wait for any queued user work items and pending IOCTLs to complete
  1156. m_Counter.WaitForZero();
  1157. trace(0, "SRShutdownTask: Pending ioctls + work items completed");
  1158. //
  1159. // free the COM+ db dll
  1160. //
  1161. if (NULL != m_hCOMDll)
  1162. {
  1163. _VERIFY(TRUE==FreeLibrary(m_hCOMDll));
  1164. m_hCOMDll = NULL;
  1165. }
  1166. // kill the datastoremgr
  1167. if (g_pDataStoreMgr)
  1168. {
  1169. g_pDataStoreMgr->SignalStop();
  1170. delete g_pDataStoreMgr;
  1171. g_pDataStoreMgr = NULL;
  1172. }
  1173. // kill SRConfig
  1174. if (g_pSRConfig)
  1175. {
  1176. delete g_pSRConfig;
  1177. g_pSRConfig = NULL;
  1178. }
  1179. Err:
  1180. tleave();
  1181. return;
  1182. }
  1183. DWORD
  1184. CEventHandler::OnFreeze( LPWSTR pszDrive )
  1185. {
  1186. tenter("CEventHandler::OnFreeze");
  1187. DWORD dwRc = ERROR_INTERNAL_ERROR;
  1188. BOOL fHaveLock;
  1189. LOCKORLEAVE(fHaveLock);
  1190. ASSERT(g_pDataStoreMgr);
  1191. //
  1192. // if drive is already frozen, no-op
  1193. //
  1194. if (g_pDataStoreMgr->IsDriveFrozen(pszDrive))
  1195. {
  1196. dwRc = ERROR_SUCCESS;
  1197. goto done;
  1198. }
  1199. dwRc = g_pDataStoreMgr->FreezeDrive( pszDrive );
  1200. if ( ERROR_SUCCESS != dwRc )
  1201. {
  1202. trace(0, "! g_pDataStoreMgr->FreezeDrive : %ld", dwRc);
  1203. }
  1204. done:
  1205. UNLOCK( fHaveLock );
  1206. tleave();
  1207. return dwRc;
  1208. }
  1209. DWORD
  1210. CEventHandler::OnReset(LPWSTR pszDrive)
  1211. {
  1212. tenter("CEventHandler::OnReset");
  1213. BOOL fHaveLock;
  1214. DWORD dwRc = ERROR_INTERNAL_ERROR;
  1215. ASSERT(g_pSRConfig);
  1216. LOCKORLEAVE(fHaveLock);
  1217. g_pSRConfig->SetResetFlag(TRUE);
  1218. dwRc = DisableSRS(pszDrive);
  1219. if (ERROR_SUCCESS != dwRc)
  1220. goto done;
  1221. // if not system drive, enable this drive
  1222. // else, the service will stop
  1223. // and do a firstrun the next boot
  1224. if (pszDrive && ! IsSystemDrive(pszDrive))
  1225. {
  1226. dwRc = EnableSRS(pszDrive);
  1227. }
  1228. done:
  1229. UNLOCK(fHaveLock);
  1230. tleave();
  1231. return dwRc;
  1232. }
  1233. DWORD
  1234. CEventHandler::OnFifo(
  1235. LPWSTR pszDrive,
  1236. DWORD dwTargetRp,
  1237. int nTargetPercent,
  1238. BOOL fIncludeCurrentRp,
  1239. BOOL fFifoAtleastOneRp)
  1240. {
  1241. tenter("CEventHandler::OnFifo");
  1242. BOOL fHaveLock;
  1243. DWORD dwRc = ERROR_INTERNAL_ERROR;
  1244. LOCKORLEAVE(fHaveLock);
  1245. ASSERT(g_pDataStoreMgr);
  1246. dwRc = g_pDataStoreMgr->Fifo(pszDrive, dwTargetRp, nTargetPercent, fIncludeCurrentRp, fFifoAtleastOneRp);
  1247. if (dwRc != ERROR_SUCCESS)
  1248. {
  1249. trace(0, "! g_pDataStoreMgr->Fifo : %ld", dwRc);
  1250. }
  1251. done:
  1252. UNLOCK(fHaveLock);
  1253. tleave();
  1254. return dwRc;
  1255. }
  1256. DWORD
  1257. CEventHandler::OnCompress(LPWSTR pszDrive)
  1258. {
  1259. tenter("CEventHandler::OnCompress");
  1260. BOOL fHaveLock;
  1261. DWORD dwRc = ERROR_INTERNAL_ERROR;
  1262. LOCKORLEAVE(fHaveLock);
  1263. ASSERT(g_pDataStoreMgr && g_pSRConfig);
  1264. dwRc = g_pDataStoreMgr->Compress(pszDrive,
  1265. g_pSRConfig->m_dwCompressionBurst);
  1266. if (ERROR_SUCCESS != dwRc)
  1267. {
  1268. trace(0, "! g_pDataStoreMgr->Compress : %ld", dwRc);
  1269. }
  1270. done:
  1271. UNLOCK(fHaveLock);
  1272. tleave();
  1273. return dwRc;
  1274. }
  1275. DWORD
  1276. CEventHandler::SRPrintStateS()
  1277. {
  1278. tenter("CEventHandler::SRPrintStateS");
  1279. BOOL fHaveLock;
  1280. DWORD dwRc = ERROR_SUCCESS;
  1281. HANDLE hFile = INVALID_HANDLE_VALUE;
  1282. WCHAR wcsPath[MAX_PATH];
  1283. LOCKORLEAVE(fHaveLock);
  1284. ASSERT(g_pDataStoreMgr);
  1285. if (0 == ExpandEnvironmentStrings(L"%temp%\\sr.txt", wcsPath, MAX_PATH))
  1286. {
  1287. dwRc = GetLastError();
  1288. trace(0, "! ExpandEnvironmentStrings : %ld", dwRc);
  1289. goto done;
  1290. }
  1291. hFile = CreateFileW (wcsPath, // file name
  1292. GENERIC_WRITE, // file access
  1293. 0, // share mode
  1294. NULL, // SD
  1295. CREATE_ALWAYS, // how to create
  1296. 0, // file attributes
  1297. NULL); // handle to template file
  1298. if (INVALID_HANDLE_VALUE == hFile)
  1299. {
  1300. dwRc = GetLastError();
  1301. trace(0, "! CreateFileW : %ld", dwRc);
  1302. goto done;
  1303. }
  1304. trace(0, "**** SR State ****");
  1305. dwRc = g_pDataStoreMgr->GetDriveTable()->ForAllDrives(CDataStore::Print, (LONG_PTR) hFile);
  1306. trace(0, "**** SR State ****");
  1307. done:
  1308. if (hFile != INVALID_HANDLE_VALUE)
  1309. CloseHandle(hFile);
  1310. UNLOCK(fHaveLock);
  1311. tleave();
  1312. return dwRc;
  1313. }
  1314. // timer
  1315. // this needs to monitor datastore size and free disk space on all drives
  1316. // and trigger fifo/freeze if needed
  1317. DWORD
  1318. CEventHandler::OnTimer(
  1319. LPVOID lpParam,
  1320. BOOL fTimeout)
  1321. {
  1322. DWORD dwRc = ERROR_SUCCESS;
  1323. LPWSTR pszDrive = NULL;
  1324. DWORD dwFlags;
  1325. BOOL fHaveLock;
  1326. SDriveTableEnumContext dtec = {NULL, 0};
  1327. tenter("CEventHandler::OnTimer");
  1328. // get the lock within 5 seconds
  1329. // if we can't get the lock, then don't block
  1330. // we shall come back 2 minutes later and try again
  1331. // the wait times are such that idle callback has a somewhat
  1332. // higher priority than timer to get the lock
  1333. LOCKORLEAVE_EX(fHaveLock, 5000);
  1334. // got the lock - no one else is doing anything
  1335. ASSERT(g_pDataStoreMgr && g_pSRConfig);
  1336. // trigger freeze or fifo on each drive
  1337. // this will :
  1338. // a. check free space and trigger freeze or fifo
  1339. // b. check datastore usage percent and trigger fifo
  1340. g_pDataStoreMgr->TriggerFreezeOrFifo();
  1341. done:
  1342. UNLOCK(fHaveLock);
  1343. tleave();
  1344. return dwRc;
  1345. }
  1346. // open filter handle and register ioctls
  1347. DWORD WINAPI
  1348. PostFilterIo(PVOID pNum)
  1349. {
  1350. tenter("CEventHandler::SendIOCTLs");
  1351. DWORD dwRc = ERROR_SUCCESS;
  1352. INT index;
  1353. ASSERT(g_pSRConfig && g_pEventHandler);
  1354. //
  1355. // if shutting down, don't bother to post
  1356. //
  1357. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  1358. {
  1359. trace(0, "Stop signalled - not posting io requests");
  1360. goto done;
  1361. }
  1362. //
  1363. // bind the completion to a callback
  1364. //
  1365. if ( ! BindIoCompletionCallback(g_pSRConfig->GetFilter(),
  1366. IoCompletionCallback,
  1367. 0) )
  1368. {
  1369. dwRc = GetLastError();
  1370. trace(0, "! BindIoCompletionCallback : %ld", dwRc);
  1371. goto done;
  1372. }
  1373. //
  1374. // post io completion requests
  1375. //
  1376. for (index = 0; index < (INT_PTR) pNum; index++)
  1377. {
  1378. CHAR pszEventName[MAX_PATH];
  1379. LPSR_OVERLAPPED pOverlap = NULL;
  1380. DWORD nBytes =0 ;
  1381. pOverlap = (LPSR_OVERLAPPED) SRMemAlloc( sizeof(SR_OVERLAPPED) );
  1382. if (! pOverlap)
  1383. {
  1384. trace(0, "! Out of memory");
  1385. dwRc = ERROR_NOT_ENOUGH_MEMORY;
  1386. goto done;
  1387. }
  1388. // create an event, a handle, and put it in the completion port.
  1389. memset( &pOverlap->m_overlapped, 0, sizeof(OVERLAPPED) );
  1390. pOverlap->m_dwRecordLength = sizeof(SR_NOTIFICATION_RECORD)
  1391. + (SR_MAX_FILENAME_LENGTH*sizeof(WCHAR));
  1392. pOverlap->m_pRecord =
  1393. (PSR_NOTIFICATION_RECORD) SRMemAlloc(pOverlap->m_dwRecordLength);
  1394. ASSERT(g_pSRConfig);
  1395. pOverlap->m_hDriver = g_pSRConfig->GetFilter();
  1396. // post ioctl - this should return ERROR_IO_PENDING
  1397. dwRc = SrWaitForNotification( pOverlap->m_hDriver,
  1398. pOverlap->m_pRecord ,
  1399. pOverlap->m_dwRecordLength,
  1400. (LPOVERLAPPED) pOverlap );
  1401. if ( dwRc != 0 && dwRc != ERROR_IO_PENDING )
  1402. {
  1403. trace(0, "! SrWaitForNotification : %ld", dwRc);
  1404. goto done;
  1405. }
  1406. g_pEventHandler->GetCounter()->Up( ); // one more pending ioctl
  1407. }
  1408. trace(0, "Filter Io posted");
  1409. done:
  1410. tleave();
  1411. return dwRc;
  1412. }
  1413. // FILTER NOTIFICATION HANDLERS
  1414. // generic notification handler
  1415. extern "C" void CALLBACK
  1416. IoCompletionCallback(
  1417. DWORD dwErrorCode,
  1418. DWORD dwBytesTrns,
  1419. LPOVERLAPPED pOverlapped )
  1420. {
  1421. ULONG uError = 0;
  1422. LPSR_OVERLAPPED pSROverlapped = (LPSR_OVERLAPPED) pOverlapped;
  1423. BOOL fResubmit = FALSE;
  1424. WCHAR szVolumeGuid[MAX_PATH], szTemp[MAX_PATH];
  1425. tenter("IoCompletionCallback");
  1426. if (! pSROverlapped || pSROverlapped->m_hDriver == INVALID_HANDLE_VALUE)
  1427. {
  1428. trace(0, "! Null overlapped or driver handle");
  1429. goto done;
  1430. }
  1431. trace(0, "Received filter notification : errorcode=%08x, type=%08x",
  1432. dwErrorCode, pSROverlapped->m_pRecord->NotificationType);
  1433. if ( dwErrorCode != 0 ) // we cancelled it
  1434. {
  1435. trace(0, "Cancelled operation");
  1436. goto done;
  1437. }
  1438. UnicodeStringToWchar(pSROverlapped->m_pRecord->VolumeName, szTemp);
  1439. wsprintf(szVolumeGuid, L"\\\\?\\Volume%s\\", szTemp);
  1440. // handle notification
  1441. ASSERT(g_pEventHandler);
  1442. ASSERT(g_pSRConfig);
  1443. if (! g_pEventHandler || ! g_pSRConfig)
  1444. {
  1445. trace(0, "global is NULL");
  1446. goto done;
  1447. }
  1448. switch( pSROverlapped->m_pRecord->NotificationType )
  1449. {
  1450. case SrNotificationVolumeFirstWrite:
  1451. g_pEventHandler->OnFirstWrite_Notification(szVolumeGuid);
  1452. break;
  1453. case SrNotificationVolume25MbWritten:
  1454. g_pEventHandler->OnSize_Notification(szVolumeGuid,
  1455. pSROverlapped->m_pRecord->Context);
  1456. break;
  1457. case SrNotificationVolumeError:
  1458. g_pEventHandler->OnVolumeError_Notification(szVolumeGuid,
  1459. pSROverlapped->m_pRecord->Context);
  1460. break;
  1461. default:
  1462. trace(0, "Unknown notification");
  1463. ASSERT(0);
  1464. break;
  1465. }
  1466. // check for stop signal
  1467. ASSERT(g_pSRConfig);
  1468. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  1469. goto done;
  1470. // re-submit the ioctl to the driver
  1471. memset( &pSROverlapped->m_overlapped, 0, sizeof(OVERLAPPED) );
  1472. pSROverlapped->m_dwRecordLength = sizeof(SR_NOTIFICATION_RECORD)
  1473. + (SR_MAX_FILENAME_LENGTH*sizeof(WCHAR));
  1474. memset( pSROverlapped->m_pRecord, 0, pSROverlapped->m_dwRecordLength);
  1475. pSROverlapped->m_hDriver = g_pSRConfig->GetFilter();
  1476. uError = SrWaitForNotification( pSROverlapped->m_hDriver,
  1477. pSROverlapped->m_pRecord ,
  1478. pSROverlapped->m_dwRecordLength,
  1479. (LPOVERLAPPED) pSROverlapped );
  1480. if ( uError != 0 && uError != ERROR_IO_PENDING )
  1481. {
  1482. trace(0, "! SrWaitForNotification : %ld", uError);
  1483. goto done;
  1484. }
  1485. fResubmit = TRUE;
  1486. done:
  1487. // if we didn't resubmit, there is one less io request pending
  1488. if (FALSE == fResubmit && g_pEventHandler != NULL)
  1489. g_pEventHandler->GetCounter()->Down();
  1490. tleave();
  1491. return;
  1492. }
  1493. // first write notification handler
  1494. // this will be sent when the first monitored op happens on a new drive
  1495. // or a newly created restore point
  1496. // RESPONSE: update the drive table to indicate that this is a new drive
  1497. // and/or that this drive is a participant in this restore point
  1498. void
  1499. CEventHandler::OnFirstWrite_Notification(LPWSTR pszGuid)
  1500. {
  1501. DWORD dwRc = ERROR_SUCCESS;
  1502. WCHAR szMount[MAX_PATH];
  1503. BOOL fHaveLock;
  1504. CDataStore *pdsNew = NULL, *pds=NULL;
  1505. tenter("CEventHandler::OnFirstWrite_Notification");
  1506. trace(0, "First write on %S", pszGuid);
  1507. LOCKORLEAVE(fHaveLock);
  1508. ASSERT(g_pDataStoreMgr);
  1509. ASSERT(g_pSRConfig);
  1510. dwRc = g_pDataStoreMgr->GetDriveTable()->FindMountPoint(pszGuid, szMount);
  1511. if (ERROR_BAD_PATHNAME == dwRc)
  1512. {
  1513. // the mountpoint path is too long for us to support
  1514. // so disable the filter on this volume
  1515. CDataStore ds(NULL);
  1516. ds.LoadDataStore(NULL, pszGuid, NULL, 0, 0, 0);
  1517. dwRc = SrDisableVolume(g_pSRConfig->GetFilter(), ds.GetNTName());
  1518. if (dwRc != ERROR_SUCCESS)
  1519. {
  1520. trace(0, "! SrDisableVolume : %ld", dwRc);
  1521. }
  1522. else
  1523. {
  1524. WCHAR wcsPath[MAX_PATH];
  1525. MakeRestorePath (wcsPath, pszGuid, L"");
  1526. // delete the restore directory
  1527. dwRc = Delnode_Recurse (wcsPath, TRUE,
  1528. g_pDataStoreMgr->GetStopFlag());
  1529. if (dwRc != ERROR_SUCCESS)
  1530. {
  1531. trace(0, "! Delnode_Recurse : %ld", dwRc);
  1532. }
  1533. trace(0, "Mountpoint too long - disabled volume %S", pszGuid);
  1534. }
  1535. goto done;
  1536. }
  1537. if (ERROR_SUCCESS != dwRc)
  1538. {
  1539. trace(0, "! FindMountPoint on %S : %ld", pszGuid, dwRc);
  1540. goto done;
  1541. }
  1542. pdsNew = g_pDataStoreMgr->GetDriveTable()->FindDriveInTable(pszGuid);
  1543. dwRc = g_pDataStoreMgr->GetDriveTable()->AddDriveToTable(szMount, pszGuid);
  1544. if (ERROR_SUCCESS != dwRc)
  1545. {
  1546. trace(0, "! AddDriveToTable on %S", pszGuid);
  1547. goto done;
  1548. }
  1549. if (ERROR_SUCCESS != g_pDataStoreMgr->SetDriveParticipation (pszGuid, TRUE))
  1550. trace(0, "! SetDriveParticipation on %S", pszGuid);
  1551. //
  1552. // if less than 50mb free, or if SR is already frozen, then freeze
  1553. //
  1554. pds = g_pDataStoreMgr->GetDriveTable()->FindDriveInTable(pszGuid);
  1555. if (pds)
  1556. {
  1557. // update the active bit too
  1558. pds->SetActive(TRUE);
  1559. // then check diskfree
  1560. pds->UpdateDiskFree(NULL);
  1561. if ( (pds->GetDiskFree() <= THRESHOLD_FREEZE_DISKSPACE * MEGABYTE) ||
  1562. (g_pDataStoreMgr->IsDriveFrozen(g_pSRConfig->GetSystemDrive())) )
  1563. {
  1564. g_pDataStoreMgr->FreezeDrive(pszGuid);
  1565. }
  1566. }
  1567. else
  1568. {
  1569. //
  1570. // we just added the drive, so should never get here
  1571. //
  1572. ASSERT(0);
  1573. }
  1574. done:
  1575. UNLOCK(fHaveLock);
  1576. tleave();
  1577. return;
  1578. }
  1579. // 25MB notification handler
  1580. // this will be sent when the filter has copied 25MB of data to the datastore
  1581. // on some drive
  1582. // RESPONSE: update the datastore size and check fifo conditions
  1583. void
  1584. CEventHandler::OnSize_Notification(LPWSTR pszGuid, ULONG ulRp)
  1585. {
  1586. tenter("CEventHandler::OnSize_Notification");
  1587. int nPercent = 0;
  1588. BOOL fHaveLock;
  1589. DWORD dwRc = ERROR_SUCCESS;
  1590. LOCKORLEAVE(fHaveLock);
  1591. trace(0, "25mb copied on drive %S", pszGuid);
  1592. trace(0, "for RP%ld", ulRp);
  1593. if ((DWORD) ulRp != m_CurRp.GetNum())
  1594. {
  1595. trace(0, "This is an obsolete notification");
  1596. goto done;
  1597. }
  1598. ASSERT(g_pDataStoreMgr);
  1599. g_pDataStoreMgr->UpdateDataStoreUsage(pszGuid, SR_NOTIFY_BYTE_COUNT);
  1600. if ( ERROR_SUCCESS == g_pDataStoreMgr->GetUsagePercent(pszGuid, &nPercent)
  1601. && nPercent >= THRESHOLD_FIFO_PERCENT )
  1602. {
  1603. OnFifo(pszGuid,
  1604. 0, // no target rp
  1605. TARGET_FIFO_PERCENT, // target percent
  1606. TRUE, // fifo current rp if necessary (freeze)
  1607. FALSE);
  1608. }
  1609. done:
  1610. UNLOCK(fHaveLock);
  1611. tleave();
  1612. return;
  1613. }
  1614. // disk full notification handler
  1615. // this will be sent when the filter encounters an error on a volume
  1616. // ideally, this should never be sent
  1617. // if diskfull, freeze SR on this drive
  1618. // else disable SR on this drive
  1619. void
  1620. CEventHandler::OnVolumeError_Notification(LPWSTR pszGuid, ULONG ulError)
  1621. {
  1622. tenter("CEventHandler::OnVolumeError_Notification");
  1623. BOOL fHaveLock;
  1624. DWORD dwRc = ERROR_SUCCESS;
  1625. LOCKORLEAVE(fHaveLock);
  1626. trace(0, "Volume Error on %S", pszGuid);
  1627. trace(0, "Error : %ld", ulError);
  1628. ASSERT(g_pDataStoreMgr);
  1629. ASSERT(g_pSRConfig);
  1630. if (ulError == ERROR_DISK_FULL)
  1631. {
  1632. // no more disk space - freeze
  1633. // NOTE: we don't check to see if the drive is already
  1634. // frozen here. If for some reason we are out of sync with
  1635. // the driver, this will fix it
  1636. g_pDataStoreMgr->FreezeDrive(pszGuid);
  1637. }
  1638. else
  1639. {
  1640. // fifo all restore points prior to the current one
  1641. dwRc = g_pDataStoreMgr->Fifo(g_pSRConfig->GetSystemDrive(), 0, 0, FALSE, FALSE);
  1642. if (dwRc != ERROR_SUCCESS)
  1643. {
  1644. trace(0, "! Fifo : %ld", dwRc);
  1645. }
  1646. // make the current rp a cancelled rp
  1647. // so that UI will not display it
  1648. if (! m_fNoRpOnSystem)
  1649. {
  1650. SRRemoveRestorePointS(m_CurRp.GetNum());
  1651. // m_CurRp.Cancel();
  1652. }
  1653. // log the error in the drivetable
  1654. dwRc = g_pDataStoreMgr->SetDriveError(pszGuid);
  1655. if (dwRc != ERROR_SUCCESS)
  1656. {
  1657. trace(0, "! SetDriveError : %ld", dwRc);
  1658. }
  1659. }
  1660. done:
  1661. UNLOCK(fHaveLock);
  1662. tleave();
  1663. return;
  1664. }
  1665. // disk space notifications sent by the shell
  1666. DWORD WINAPI
  1667. OnDiskFree_200(PVOID pszDrive)
  1668. {
  1669. // thaw
  1670. ASSERT(g_pEventHandler);
  1671. (g_pEventHandler->GetCounter())->Down();
  1672. return 0;
  1673. }
  1674. DWORD WINAPI
  1675. OnDiskFree_80(PVOID pszDrive)
  1676. {
  1677. // fifo
  1678. ASSERT(g_pEventHandler);
  1679. g_pEventHandler->OnFifo((LPWSTR) pszDrive,
  1680. 0, // no target rp
  1681. TARGET_FIFO_PERCENT, // target percent
  1682. TRUE, // fifo current rp if necessary (freeze)
  1683. TRUE); // fifo atleast one restore point
  1684. (g_pEventHandler->GetCounter())->Down();
  1685. return 0;
  1686. }
  1687. DWORD WINAPI
  1688. OnDiskFree_50(PVOID pszDrive)
  1689. {
  1690. TENTER("OnDiskFree_50");
  1691. DWORD dwRc = ERROR_SUCCESS;
  1692. // freeze
  1693. ASSERT(g_pEventHandler);
  1694. ASSERT(g_pDataStoreMgr);
  1695. //
  1696. // check if there is some rp directory
  1697. // if none, then don't bother
  1698. //
  1699. CRestorePointEnum *prpe = new CRestorePointEnum((LPWSTR) pszDrive, FALSE, FALSE); // backward, include current
  1700. CRestorePoint *prp = new CRestorePoint;
  1701. if (!prpe || !prp)
  1702. {
  1703. trace(0, "Cannot allocate memory for restore point enum");
  1704. goto done;
  1705. }
  1706. dwRc = prpe->FindFirstRestorePoint(*prp);
  1707. if (dwRc == ERROR_SUCCESS || dwRc == ERROR_FILE_NOT_FOUND)
  1708. {
  1709. g_pEventHandler->OnFreeze((LPWSTR) pszDrive);
  1710. }
  1711. else
  1712. {
  1713. trace(0, "Nothing in datastore -- so not freezing");
  1714. }
  1715. if (prpe)
  1716. delete prpe;
  1717. if (prp)
  1718. delete prp;
  1719. (g_pEventHandler->GetCounter())->Down();
  1720. done:
  1721. TLEAVE();
  1722. return 0;
  1723. }
  1724. // stop event management
  1725. void
  1726. CEventHandler::SignalStop()
  1727. {
  1728. if ( g_pSRConfig )
  1729. {
  1730. SetEvent( g_pSRConfig->m_hSRStopEvent );
  1731. }
  1732. }
  1733. DWORD
  1734. CEventHandler::WaitForStop()
  1735. {
  1736. if ( g_pSRConfig )
  1737. {
  1738. WaitForSingleObject( g_pSRConfig->m_hSRStopEvent, INFINITE );
  1739. return g_pSRConfig->GetResetFlag() ? ERROR_NO_SHUTDOWN_IN_PROGRESS : ERROR_SHUTDOWN_IN_PROGRESS;
  1740. }
  1741. else
  1742. return ERROR_INTERNAL_ERROR;
  1743. }
  1744. //
  1745. // perform idle tasks
  1746. //
  1747. DWORD
  1748. CEventHandler::OnIdle()
  1749. {
  1750. DWORD dwThawStatus = ERROR_NO_MORE_ITEMS;
  1751. DWORD dwRc = ERROR_NO_MORE_ITEMS;
  1752. BOOL fCreateAuto = FALSE;
  1753. ULARGE_INTEGER *pulFreeze = NULL;
  1754. tenter("CEventHandler::OnIdle");
  1755. trace(0, "Idleness detected");
  1756. ASSERT(g_pSRConfig);
  1757. ASSERT(g_pDataStoreMgr);
  1758. //
  1759. // check thaw timer to see if
  1760. // there are frozen drives
  1761. //
  1762. pulFreeze = (ULARGE_INTEGER *) &m_ftFreeze;
  1763. if (pulFreeze->QuadPart != 0)
  1764. {
  1765. FILETIME ftNow;
  1766. ULARGE_INTEGER *pulNow;
  1767. GetSystemTimeAsFileTime(&ftNow);
  1768. pulNow = (ULARGE_INTEGER *) &ftNow;
  1769. //
  1770. // if more than 15 minutes since freeze happened
  1771. // try to thaw
  1772. //
  1773. if (pulNow->QuadPart - pulFreeze->QuadPart >=
  1774. ((INT64) g_pSRConfig->m_dwThawInterval * 1000 * 1000 * 10))
  1775. {
  1776. dwThawStatus = g_pDataStoreMgr->ThawDrives(TRUE);
  1777. if (dwThawStatus != ERROR_SUCCESS)
  1778. {
  1779. trace(0, "Cannot thaw drives yet");
  1780. }
  1781. }
  1782. }
  1783. else
  1784. {
  1785. fCreateAuto = IsTimeForAutoRp();
  1786. }
  1787. // make periodic checkpoint if it is time to make an auto-rp or
  1788. // time to thaw drives or
  1789. // a volume error happened in the previous session
  1790. if ( dwThawStatus == ERROR_SUCCESS ||
  1791. fCreateAuto == TRUE ||
  1792. m_fCreateRpASAP == TRUE )
  1793. {
  1794. RESTOREPOINTINFO RPInfo;
  1795. STATEMGRSTATUS SmgrStatus;
  1796. RPInfo.dwEventType = BEGIN_SYSTEM_CHANGE;
  1797. RPInfo.dwRestorePtType = m_fNoRpOnSystem ? FIRSTRUN : CHECKPOINT;
  1798. if (ERROR_SUCCESS != SRLoadString(L"srrstr.dll", IDS_SYSTEM_CHECKPOINT_TEXT, RPInfo.szDescription, MAX_PATH))
  1799. {
  1800. lstrcpy(RPInfo.szDescription, s_cszSystemCheckpointName);
  1801. }
  1802. SRSetRestorePointS(&RPInfo, &SmgrStatus);
  1803. dwRc = SmgrStatus.nStatus;
  1804. if (dwRc != ERROR_SUCCESS)
  1805. goto done;
  1806. m_fCreateRpASAP = FALSE;
  1807. // we made a restore point and perhaps thawed some drives
  1808. // let's not push it any further
  1809. // compress on next idle opportunity
  1810. }
  1811. else
  1812. {
  1813. // if system is running on battery
  1814. // skip these tasks
  1815. if (g_pSRConfig->IsSystemOnBattery())
  1816. {
  1817. trace(0, "System on battery -- skipping idle tasks");
  1818. goto done;
  1819. }
  1820. // fifo restore points older than a specified age
  1821. // if the fifo age is set to 0, that means this feature
  1822. // is turned off
  1823. if (g_pSRConfig->m_dwRPLifeInterval > 0)
  1824. {
  1825. g_pDataStoreMgr->FifoOldRps(g_pSRConfig->m_dwRPLifeInterval);
  1826. }
  1827. // compress backed up files - pick any drive
  1828. dwRc = OnCompress( NULL );
  1829. //
  1830. // if we have more to compress, request idle again
  1831. //
  1832. if (dwRc == ERROR_OPERATION_ABORTED)
  1833. {
  1834. SetEvent(g_pSRConfig->m_hIdleRequestEvent);
  1835. }
  1836. }
  1837. done:
  1838. tleave();
  1839. return dwRc;
  1840. }
  1841. extern "C" void CALLBACK
  1842. IdleRequestCallback(PVOID pContext, BOOLEAN fTimerFired)
  1843. {
  1844. BOOL fRegistered = FALSE;
  1845. HANDLE *pWaitHandle = NULL;
  1846. DWORD dwErr = ERROR_SUCCESS;
  1847. BOOL fHaveLock = FALSE;
  1848. tenter("CEventHandler::IdleRequestCallback");
  1849. ASSERT(g_pEventHandler);
  1850. ASSERT(g_pSRConfig);
  1851. if (g_pEventHandler == NULL || g_pSRConfig == NULL)
  1852. {
  1853. trace(0, "global is Null");
  1854. goto Err;
  1855. }
  1856. fHaveLock = g_pEventHandler->GetLock()->Lock(CLock::TIMEOUT);
  1857. if (! fHaveLock)
  1858. {
  1859. trace(0, "Cannot get lock");
  1860. goto Err;
  1861. }
  1862. //
  1863. // first off, if the stop event is triggered
  1864. // and we are here for some reason,
  1865. // bail blindly
  1866. //
  1867. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  1868. {
  1869. trace(0, "Stop event signalled - bailing out of idle");
  1870. goto Err;
  1871. }
  1872. //
  1873. // idleness is requested or timer fired
  1874. // re-register for idle again
  1875. //
  1876. if (fTimerFired)
  1877. trace(0, "Timed out");
  1878. else
  1879. trace(0, "Idle request event received");
  1880. //
  1881. // if already registered for idle
  1882. // then do nothing
  1883. //
  1884. if (g_pEventHandler->m_hIdleStartHandle != NULL)
  1885. {
  1886. trace(0, "Already registered for idle");
  1887. goto Err;
  1888. }
  1889. dwErr = RegisterIdleTask(ItSystemRestoreIdleTaskId,
  1890. &(g_pSRConfig->m_hIdle),
  1891. &(g_pSRConfig->m_hIdleStartEvent),
  1892. &(g_pSRConfig->m_hIdleStopEvent));
  1893. if (dwErr != ERROR_SUCCESS)
  1894. {
  1895. trace(0, "! RegisterIdleTask : %ld", dwErr);
  1896. }
  1897. else
  1898. {
  1899. trace(0, "Registered for idle");
  1900. //
  1901. // register idle callback
  1902. //
  1903. if (FALSE == RegisterWaitForSingleObject(&g_pEventHandler->m_hIdleStartHandle,
  1904. g_pSRConfig->m_hIdleStartEvent,
  1905. (WAITORTIMERCALLBACK) IdleStartCallback,
  1906. NULL,
  1907. INFINITE,
  1908. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
  1909. {
  1910. dwErr = GetLastError();
  1911. trace(0, "! RegisterWaitForSingleObject for startidle: %ld", dwErr);
  1912. goto Err;
  1913. }
  1914. if (FALSE == RegisterWaitForSingleObject(&g_pEventHandler->m_hIdleStopHandle,
  1915. g_pSRConfig->m_hIdleStopEvent,
  1916. (WAITORTIMERCALLBACK) IdleStopCallback,
  1917. NULL,
  1918. INFINITE,
  1919. WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
  1920. {
  1921. dwErr = GetLastError();
  1922. trace(0, "! RegisterWaitForSingleObject for stopidle: %ld", dwErr);
  1923. goto Err;
  1924. }
  1925. }
  1926. Err:
  1927. if (g_pEventHandler)
  1928. {
  1929. if (fHaveLock)
  1930. g_pEventHandler->GetLock()->Unlock();
  1931. }
  1932. return;
  1933. }
  1934. extern "C" void CALLBACK
  1935. IdleStartCallback(PVOID pContext, BOOLEAN fTimerFired)
  1936. {
  1937. DWORD dwErr = ERROR_SUCCESS;
  1938. BOOL fHaveLock = FALSE;
  1939. tenter("CEventHandler::IdleStartCallback");
  1940. ASSERT(g_pEventHandler);
  1941. ASSERT(g_pSRConfig);
  1942. if (g_pEventHandler == NULL || g_pSRConfig == NULL)
  1943. {
  1944. trace(0, "global is Null");
  1945. goto Err;
  1946. }
  1947. fHaveLock = g_pEventHandler->GetLock()->Lock(CLock::TIMEOUT);
  1948. if (! fHaveLock)
  1949. {
  1950. trace(0, "Cannot get lock");
  1951. goto Err;
  1952. }
  1953. //
  1954. // first off, if the stop event is triggered
  1955. // and we are here for some reason,
  1956. // bail blindly
  1957. //
  1958. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  1959. {
  1960. trace(0, "Stop event signalled - bailing out of idle");
  1961. goto Err;
  1962. }
  1963. //
  1964. // idleness occurred
  1965. //
  1966. trace(0, "fTimerFired = %d", fTimerFired);
  1967. g_pEventHandler->OnIdle();
  1968. dwErr = UnregisterIdleTask(g_pSRConfig->m_hIdle,
  1969. g_pSRConfig->m_hIdleStartEvent,
  1970. g_pSRConfig->m_hIdleStopEvent);
  1971. if (dwErr != ERROR_SUCCESS)
  1972. {
  1973. trace(0, "! UnregisterIdleTask : %ld", dwErr);
  1974. }
  1975. else
  1976. {
  1977. trace(0, "Unregistered from idle");
  1978. }
  1979. //
  1980. // we are done - record this
  1981. // since we registered for this callback only once,
  1982. // we don't have to call UnregisterWait on this handle -
  1983. // or so I hope
  1984. //
  1985. g_pEventHandler->m_hIdleStartHandle = NULL;
  1986. Err:
  1987. if (g_pEventHandler)
  1988. {
  1989. if (fHaveLock)
  1990. g_pEventHandler->GetLock()->Unlock();
  1991. }
  1992. return;
  1993. }
  1994. extern "C" void CALLBACK
  1995. IdleStopCallback(PVOID pContext, BOOLEAN fTimerFired)
  1996. {
  1997. tenter("IdleStopCallback");
  1998. BOOL fHaveLock = FALSE;
  1999. if (g_pEventHandler == NULL)
  2000. {
  2001. trace(0, "global is Null");
  2002. goto Err;
  2003. }
  2004. fHaveLock = g_pEventHandler->GetLock()->Lock(CLock::TIMEOUT);
  2005. if (! fHaveLock)
  2006. {
  2007. trace(0, "Cannot get lock");
  2008. goto Err;
  2009. }
  2010. trace(0, "Idle Stop event signalled");
  2011. g_pEventHandler->m_hIdleStopHandle = NULL;
  2012. Err:
  2013. if (g_pEventHandler)
  2014. {
  2015. if (fHaveLock)
  2016. g_pEventHandler->GetLock()->Unlock();
  2017. }
  2018. tleave();
  2019. }
  2020. // set up timer
  2021. DWORD
  2022. CEventHandler::InitTimer()
  2023. {
  2024. DWORD dwRc = ERROR_SUCCESS;
  2025. tenter("CEventHandler::InitTimer");
  2026. ASSERT(g_pSRConfig);
  2027. //
  2028. // if the timer interval is specified as 0,
  2029. // then don't create timer
  2030. //
  2031. if (g_pSRConfig->m_dwTimerInterval == 0)
  2032. {
  2033. trace(0, "Not starting timer");
  2034. goto done;
  2035. }
  2036. m_hTimerQueue = CreateTimerQueue();
  2037. if (! m_hTimerQueue)
  2038. {
  2039. dwRc = GetLastError();
  2040. trace(0, " ! CreateTimerQueue : %ld", dwRc);
  2041. goto done;
  2042. }
  2043. if (FALSE == CreateTimerQueueTimer(&m_hTimer,
  2044. m_hTimerQueue,
  2045. TimerCallback,
  2046. NULL,
  2047. g_pSRConfig->m_dwTimerInterval * 1000, // milliseconds
  2048. g_pSRConfig->m_dwTimerInterval * 1000, // periodic
  2049. WT_EXECUTEINIOTHREAD))
  2050. {
  2051. dwRc = GetLastError();
  2052. trace(0, "! CreateTimerQueueTimer : %ld", dwRc);
  2053. goto done;
  2054. }
  2055. trace(0, "SRBoottask: Timer started");
  2056. done:
  2057. tleave();
  2058. return dwRc;
  2059. }
  2060. // end timer
  2061. BOOL
  2062. CEventHandler::EndTimer()
  2063. {
  2064. DWORD dwRc;
  2065. BOOL fRc = TRUE;
  2066. tenter("CEventHandler::EndTimer");
  2067. if ( ! m_hTimerQueue )
  2068. {
  2069. trace(0 , "! m_hTimerQueue = NULL");
  2070. goto done;
  2071. }
  2072. // delete timer queue should wait for current timer tasks to end
  2073. if (FALSE == (fRc = DeleteTimerQueueEx( m_hTimerQueue, INVALID_HANDLE_VALUE )))
  2074. {
  2075. trace(0, "! DeleteTimerQueueEx : %ld", GetLastError());
  2076. }
  2077. m_hTimerQueue = NULL;
  2078. m_hTimer = NULL;
  2079. done:
  2080. tleave( );
  2081. return fRc;
  2082. }
  2083. BOOL
  2084. CEventHandler::IsTimeForAutoRp()
  2085. {
  2086. tenter("CEventHandler::IsTimeForAutoRp");
  2087. FILETIME *pftRp, ftNow;
  2088. ULARGE_INTEGER *pulRp, *pulNow;
  2089. BOOL fRc = FALSE;
  2090. INT64 llInterval, llSession;
  2091. ASSERT(g_pSRConfig && g_pDataStoreMgr);
  2092. if (m_fNoRpOnSystem)
  2093. {
  2094. // if SR is frozen, we will create a restore point via the thaw codepath in OnIdle
  2095. // we will get here ONLY if we get idle time before we have created the firstrun checkpoint -
  2096. // we won't create an idle checkpoint before the firstrun checkpoint if we have a Run key waiting
  2097. // to create one
  2098. HKEY hKey;
  2099. DWORD dwRet = RegOpenKey(HKEY_LOCAL_MACHINE,
  2100. L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
  2101. &hKey);
  2102. if (dwRet == ERROR_SUCCESS)
  2103. {
  2104. dwRet = RegQueryValueEx(hKey, L"SRFirstRun", NULL, NULL, NULL, NULL);
  2105. RegCloseKey(hKey);
  2106. }
  2107. if (dwRet == ERROR_SUCCESS)
  2108. {
  2109. trace(0, "Run entry exists to create firstrun checkpoint - not creating idle checkpoint");
  2110. fRc = FALSE;
  2111. goto done;
  2112. }
  2113. else
  2114. {
  2115. fRc = TRUE;
  2116. goto done;
  2117. }
  2118. }
  2119. // get the last restore point creation time and the current time
  2120. pftRp = m_CurRp.GetTime();
  2121. GetSystemTimeAsFileTime(&ftNow);
  2122. pulRp = (ULARGE_INTEGER *) pftRp;
  2123. pulNow = (ULARGE_INTEGER *) &ftNow;
  2124. // check the last restore point time with current time
  2125. // if the difference is greater than GlobalInterval, it's time to make a new one
  2126. // all comparisions in filetime units - i.e. 100's of nanoseconds
  2127. // if GlobalInterval is 0, this is turned off
  2128. llInterval = (INT64) g_pSRConfig->m_dwRPGlobalInterval * 10 * 1000 * 1000;
  2129. if ( llInterval > 0 &&
  2130. pulNow->QuadPart - pulRp->QuadPart >= llInterval )
  2131. {
  2132. trace(0, "24 hrs elapsed since last restore point");
  2133. fRc = TRUE;
  2134. goto done;
  2135. }
  2136. // if the last restore point was more than 10hrs ago,
  2137. // and the current session began more than 10hrs ago,
  2138. // then we haven't made a restore point for the last 10hrs in the current session
  2139. // again, it's time to make a new one
  2140. // this will ensure that we keep making checkpoints every 10hrs of session time,
  2141. // idleness permitting
  2142. // if SessionInterval is 0, this is turned off
  2143. // if system is on battery, skip creating session rp
  2144. if (g_pSRConfig->IsSystemOnBattery())
  2145. {
  2146. trace(0, "System on battery -- skipping session rp check");
  2147. goto done;
  2148. }
  2149. llSession = (INT64) GetTickCount() * 10 * 1000;
  2150. llInterval = (INT64) g_pSRConfig->m_dwRPSessionInterval * 10 * 1000 * 1000;
  2151. if ( llInterval > 0 &&
  2152. llSession >= llInterval &&
  2153. pulNow->QuadPart - pulRp->QuadPart >= llInterval )
  2154. {
  2155. trace(0, "10 hrs elapsed in current session since last restore point");
  2156. fRc = TRUE;
  2157. goto done;
  2158. }
  2159. // if we reach here, no restore point needs to be created now
  2160. // fRc is already FALSE
  2161. done:
  2162. tleave();
  2163. return fRc;
  2164. }
  2165. void
  2166. CEventHandler::RefreshCurrentRp(BOOL fScanAllDrives)
  2167. {
  2168. tenter("CEventHandler::RefreshCurrentRp");
  2169. DWORD dwErr;
  2170. SDriveTableEnumContext dtec = {NULL, 0};
  2171. CDataStore *pds = NULL;
  2172. ASSERT(g_pSRConfig && g_pDataStoreMgr);
  2173. //
  2174. // get the most recent valid restore point
  2175. // cancelled restore points are considered valid as well
  2176. // if rp.log is missing, we will enumerate back up to the point where it exists
  2177. // and consider that the most recent restore point
  2178. //
  2179. CRestorePointEnum *prpe = new CRestorePointEnum(g_pSRConfig->GetSystemDrive(), FALSE, FALSE);
  2180. if (!prpe)
  2181. {
  2182. trace(0, "Cannot allocate memory for restore point enum");
  2183. goto done;
  2184. }
  2185. dwErr = prpe->FindFirstRestorePoint(m_CurRp);
  2186. while (dwErr == ERROR_FILE_NOT_FOUND)
  2187. {
  2188. fScanAllDrives = FALSE;
  2189. dwErr = prpe->FindNextRestorePoint(m_CurRp);
  2190. }
  2191. if (dwErr == ERROR_SUCCESS)
  2192. {
  2193. trace(0, "Current Restore Point: %S", m_CurRp.GetDir());
  2194. m_fNoRpOnSystem = FALSE;
  2195. // update the participate bits on each datastore -
  2196. // we need to do this every time we come up
  2197. // because we might have missed filter firstwrite
  2198. // notifications
  2199. if (fScanAllDrives)
  2200. {
  2201. dwErr = g_pDataStoreMgr->UpdateDriveParticipation(NULL, m_CurRp.GetDir());
  2202. if (dwErr != ERROR_SUCCESS)
  2203. {
  2204. trace(0, "UpdateDriveParticipation : %ld", dwErr);
  2205. }
  2206. }
  2207. }
  2208. else
  2209. {
  2210. trace(0, "No live restore points on system");
  2211. m_fNoRpOnSystem = TRUE;
  2212. }
  2213. //
  2214. // if any drive is newly frozen,
  2215. // record freeze time
  2216. //
  2217. if (m_ftFreeze.dwLowDateTime == 0 &&
  2218. m_ftFreeze.dwHighDateTime == 0 &&
  2219. g_pDataStoreMgr->IsDriveFrozen(NULL))
  2220. {
  2221. GetSystemTimeAsFileTime(&m_ftFreeze);
  2222. }
  2223. else // not frozen
  2224. {
  2225. m_ftFreeze.dwLowDateTime = 0;
  2226. m_ftFreeze.dwHighDateTime = 0;
  2227. }
  2228. prpe->FindClose ();
  2229. delete prpe;
  2230. done:
  2231. tleave();
  2232. }
  2233. // queue a work item to a thread from the thread pool
  2234. // keep a count of all such queued items
  2235. DWORD
  2236. CEventHandler::QueueWorkItem(WORKITEMFUNC pFunc, PVOID pv)
  2237. {
  2238. m_Counter.Up();
  2239. if (! QueueUserWorkItem(pFunc, pv, WT_EXECUTELONGFUNCTION))
  2240. m_Counter.Down();
  2241. return GetLastError();
  2242. }
  2243. // CALLBACK functions
  2244. // calls through to eventhandler methods
  2245. // timer
  2246. extern "C" void CALLBACK
  2247. TimerCallback(
  2248. PVOID lpParam,
  2249. BOOLEAN fTimeout)
  2250. {
  2251. if ( g_pEventHandler )
  2252. g_pEventHandler->OnTimer( lpParam, fTimeout );
  2253. }