Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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