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.

2496 lines
67 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * datastormgr.cpp
  7. *
  8. * Abstract:
  9. * CDataStoreMgr class functions
  10. *
  11. * Revision History:
  12. * Brijesh Krishnaswami (brijeshk) 03/28/2000
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include "datastormgr.h"
  17. #include "srapi.h"
  18. #include "srconfig.h"
  19. #include "evthandler.h"
  20. #include "ntservice.h"
  21. #include "ntservmsg.h"
  22. #include <coguid.h>
  23. #include <rpc.h>
  24. #include <stdio.h>
  25. #include <shlwapi.h>
  26. #ifdef THIS_FILE
  27. #undef THIS_FILE
  28. #endif
  29. static char __szTraceSourceFile[] = __FILE__;
  30. #define THIS_FILE __szTraceSourceFile
  31. CDataStoreMgr * g_pDataStoreMgr = NULL; // the global instance
  32. //
  33. // we can't use %s for the volume label because it can contain spaces
  34. // so we look for all characters until the end-of-line
  35. //
  36. static WCHAR gs_wcsScanFormat[] = L"%[^/]/%s %x %i %i %[^\r]\n";
  37. //+-------------------------------------------------------------------------
  38. //
  39. // Function: CDriveTable::CDriveTable ()
  40. //
  41. // Synopsis:
  42. //
  43. // Arguments:
  44. //
  45. // Returns:
  46. //
  47. // History: 13-Apr-2000 HenryLee Created
  48. //
  49. //--------------------------------------------------------------------------
  50. CDriveTable::CDriveTable ()
  51. {
  52. _pdtNext = NULL;
  53. _nLastDrive = 0;
  54. _fDirty = FALSE;
  55. _fLockInit = FALSE;
  56. }
  57. //+-------------------------------------------------------------------------
  58. //
  59. // Function: CDriveTable::~CDriveTable
  60. //
  61. // Synopsis: delete all drive table entries
  62. //
  63. // Arguments:
  64. //
  65. // Returns:
  66. //
  67. // History: 13-Apr-2000 HenryLee Created
  68. //
  69. //--------------------------------------------------------------------------
  70. CDriveTable::~CDriveTable ()
  71. {
  72. for (int i = 0; i < _nLastDrive; i++)
  73. {
  74. if (_rgDriveTable[i] != NULL)
  75. {
  76. delete _rgDriveTable[i];
  77. _rgDriveTable[i] = NULL;
  78. }
  79. }
  80. _nLastDrive = 0;
  81. if (_pdtNext != NULL)
  82. {
  83. delete _pdtNext;
  84. _pdtNext = NULL;
  85. }
  86. }
  87. //+-------------------------------------------------------------------------
  88. //
  89. // Function: CDriveTable::CreateNewEntry
  90. //
  91. // Synopsis: populate the table with this datastore object
  92. //
  93. // Arguments:
  94. //
  95. // Returns:
  96. //
  97. // History: 13-Apr-2000 HenryLee Created
  98. //
  99. //--------------------------------------------------------------------------
  100. DWORD CDriveTable::CreateNewEntry (CDataStore *pds)
  101. {
  102. if (_nLastDrive < DRIVE_TABLE_SIZE)
  103. {
  104. _rgDriveTable[_nLastDrive] = pds;
  105. _nLastDrive++;
  106. return ERROR_SUCCESS;
  107. }
  108. else
  109. {
  110. // this table is full, allocate a new one if needed
  111. if (_pdtNext == NULL)
  112. {
  113. _pdtNext = new CDriveTable();
  114. if (_pdtNext == NULL)
  115. {
  116. return ERROR_NOT_ENOUGH_MEMORY;
  117. }
  118. }
  119. // Now add the entry to the new table
  120. return _pdtNext->CreateNewEntry (pds);
  121. }
  122. }
  123. //+-------------------------------------------------------------------------
  124. //
  125. // Function: CDriveTable::FindDriveInTable
  126. //
  127. // Synopsis: return datastore object matching this drive
  128. //
  129. // Arguments: can pass in dos drive letter, mount point path, or volume guid
  130. //
  131. // Returns: pointer to corresponding datastore object
  132. //
  133. // History: 13-Apr-2000 HenryLee Created
  134. //
  135. //--------------------------------------------------------------------------
  136. CDataStore * CDriveTable::FindDriveInTable (WCHAR *pwszDrive) const
  137. {
  138. if (NULL == pwszDrive) // not a valid drive
  139. return NULL;
  140. if (0 == wcsncmp(pwszDrive, L"\\\\?\\Volume", 10))
  141. return FindGuidInTable(pwszDrive);
  142. for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
  143. {
  144. for (int i = 0; i < pdt->_nLastDrive; i++)
  145. {
  146. if ((pdt->_rgDriveTable[i] != NULL) &&
  147. lstrcmpi (pwszDrive, pdt->_rgDriveTable[i]->GetDrive()) == 0)
  148. {
  149. return pdt->_rgDriveTable[i];
  150. }
  151. }
  152. }
  153. return NULL;
  154. }
  155. //+-------------------------------------------------------------------------
  156. //
  157. // Function: CDriveTable::RemoveDrivesFromTable
  158. //
  159. // Synopsis: remove inactive drive table entries
  160. //
  161. // Arguments:
  162. //
  163. // Returns: Win32 error code
  164. //
  165. // History: 13-Apr-2000 HenryLee Created
  166. //
  167. //--------------------------------------------------------------------------
  168. DWORD CDriveTable::RemoveDrivesFromTable ()
  169. {
  170. DWORD dwErr = ERROR_SUCCESS;
  171. tenter("removedrivesfromtable");
  172. for (CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
  173. {
  174. for (int i = 0; i < pdt->_nLastDrive; i++)
  175. {
  176. if (pdt->_rgDriveTable[i] != NULL &&
  177. pdt->_rgDriveTable[i]->IsVolumeDeleted())
  178. {
  179. trace(0, "removing %S from drivetable", pdt->_rgDriveTable[i]->GetDrive());
  180. delete pdt->_rgDriveTable[i];
  181. pdt->_rgDriveTable[i] = NULL;
  182. if (i == pdt->_nLastDrive - 1)
  183. --(pdt->_nLastDrive);
  184. _fDirty = TRUE;
  185. }
  186. }
  187. }
  188. tleave();
  189. return dwErr;
  190. }
  191. //+-------------------------------------------------------------------------
  192. //
  193. // Function: CDriveTable::FindGuidInTable
  194. //
  195. // Synopsis: get the drive table entry matching the volume GUID
  196. //
  197. // Arguments:
  198. //
  199. // Returns:
  200. //
  201. // History: 13-Apr-2000 HenryLee Created
  202. //
  203. //--------------------------------------------------------------------------
  204. CDataStore * CDriveTable::FindGuidInTable (WCHAR *pwszGuid) const
  205. {
  206. if (NULL == pwszGuid) // not a valid string
  207. return NULL;
  208. for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
  209. {
  210. for (int i = 0; i < pdt->_nLastDrive; i++)
  211. {
  212. if (pdt->_rgDriveTable[i] != NULL &&
  213. lstrcmp (pwszGuid, pdt->_rgDriveTable[i]->GetGuid()) == 0)
  214. {
  215. return pdt->_rgDriveTable[i];
  216. }
  217. }
  218. }
  219. return NULL;
  220. }
  221. //+-------------------------------------------------------------------------
  222. //
  223. // Function: CDriveTable::FindSystemDrive
  224. //
  225. // Synopsis: get the drive table entry for the system drive
  226. //
  227. // Arguments:
  228. //
  229. // Returns:
  230. //
  231. // History: 13-Apr-2000 HenryLee Created
  232. //
  233. //--------------------------------------------------------------------------
  234. CDataStore * CDriveTable::FindSystemDrive () const
  235. {
  236. for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
  237. {
  238. for (int i = 0; i < pdt->_nLastDrive; i++)
  239. {
  240. if (pdt->_rgDriveTable[i] != NULL &&
  241. pdt->_rgDriveTable[i]->GetFlags() & SR_DRIVE_SYSTEM)
  242. {
  243. return pdt->_rgDriveTable[i];
  244. }
  245. }
  246. }
  247. return NULL;
  248. }
  249. //+-------------------------------------------------------------------------
  250. //
  251. // Function: CDriveTable::ForAllDrives
  252. //
  253. // Synopsis: Execute this CDataStore method for all drives
  254. //
  255. // Arguments: [pMethod] -- CDataStore method to call
  256. // [lParam] -- parameter to that method
  257. //
  258. // Returns:
  259. //
  260. // History: 13-Apr-2000 HenryLee Created
  261. //
  262. //--------------------------------------------------------------------------
  263. DWORD CDriveTable::ForAllDrives (PDATASTOREMETHOD pMethod, LONG_PTR lParam)
  264. {
  265. TENTER ("ForAllDrives");
  266. DWORD dwErr = ERROR_SUCCESS;
  267. for (CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
  268. {
  269. for (int i = 0; i < pdt->_nLastDrive; i++)
  270. {
  271. if (pdt->_rgDriveTable[i] != NULL)
  272. {
  273. dwErr = (pdt->_rgDriveTable[i]->*pMethod) (lParam);
  274. if (dwErr != ERROR_SUCCESS)
  275. {
  276. TRACE(0, "%S ForAllDrives failed %x", pdt->_rgDriveTable[i]->GetDrive(), dwErr);
  277. dwErr = ERROR_SUCCESS;
  278. }
  279. }
  280. }
  281. }
  282. if (dwErr == ERROR_SUCCESS && _fDirty)
  283. dwErr = SaveDriveTable ((CRestorePoint *) NULL);
  284. TLEAVE();
  285. return dwErr;
  286. }
  287. //+-------------------------------------------------------------------------
  288. //
  289. // Function: CDriveTable::ForOneOrAllDrives
  290. //
  291. // Synopsis: Execute this CDataStore method for one or all drives
  292. //
  293. // Arguments: [pwszDrive] -- drive to execute method
  294. // [pMethod] -- CDataStore method to call
  295. // [lParam] -- parameter to that method
  296. //
  297. // Returns:
  298. //
  299. // History: 13-Apr-2000 HenryLee Created
  300. //
  301. //--------------------------------------------------------------------------
  302. DWORD CDriveTable::ForOneOrAllDrives (WCHAR *pwszDrive,
  303. PDATASTOREMETHOD pMethod,
  304. LONG_PTR lParam)
  305. {
  306. DWORD dwErr = ERROR_SUCCESS;
  307. if (pwszDrive == NULL)
  308. {
  309. dwErr = ForAllDrives (pMethod, lParam);
  310. }
  311. else
  312. {
  313. CDataStore *pds = FindDriveInTable (pwszDrive);
  314. dwErr = (pds != NULL) ? (pds->*pMethod)(lParam) : ERROR_INVALID_DRIVE;
  315. if (dwErr == ERROR_SUCCESS && _fDirty)
  316. dwErr = SaveDriveTable ((CRestorePoint *) NULL);
  317. }
  318. return dwErr;
  319. }
  320. //+-------------------------------------------------------------------------
  321. //
  322. // Function: CDriveTable::FindMountPoint
  323. //
  324. // Synopsis: Given a volume GUID, find a mount point that points to it
  325. //
  326. // Arguments: [pwszGuid] -- input volume GUID
  327. // [pwszPath] -- output path to mount point
  328. //
  329. // Returns: Win32 error
  330. //
  331. // History: 13-Apr-2000 HenryLee Created
  332. //
  333. //--------------------------------------------------------------------------
  334. DWORD CDriveTable::FindMountPoint (WCHAR *pwszGuid, WCHAR *pwszPath) const
  335. {
  336. TENTER ("CDriveTable::FindMountPoint");
  337. DWORD dwErr = ERROR_MORE_DATA; // initialize for loop
  338. WCHAR * pwszMount = NULL; // MultiSz string
  339. DWORD dwMountLen = MAX_PATH; // initial buffer size
  340. DWORD dwChars = 0;
  341. pwszPath[0] = L'\0';
  342. while (dwErr == ERROR_MORE_DATA)
  343. {
  344. dwErr = ERROR_SUCCESS;
  345. pwszMount = new WCHAR [dwMountLen];
  346. if (pwszMount == NULL)
  347. {
  348. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  349. goto Err;
  350. }
  351. if (FALSE == GetVolumePathNamesForVolumeNameW (pwszGuid,
  352. pwszMount,
  353. dwMountLen,
  354. &dwChars ))
  355. {
  356. dwErr = GetLastError();
  357. delete [] pwszMount; // free the existing buffer
  358. pwszMount = NULL;
  359. dwMountLen *= 2; // double the length
  360. }
  361. }
  362. if (ERROR_SUCCESS == dwErr && pwszMount != NULL)
  363. {
  364. if (L'\0' == pwszMount[0]) // empty string
  365. {
  366. dwErr = ERROR_NOT_DOS_DISK; // no drive letter or mount point
  367. }
  368. else if (lstrlenW (pwszMount) < MAX_MOUNTPOINT_PATH)
  369. {
  370. lstrcpyW (pwszPath, pwszMount); // copy the first string
  371. }
  372. else
  373. {
  374. dwErr = ERROR_BAD_PATHNAME; // 1st path too long
  375. }
  376. }
  377. Err:
  378. if (pwszMount != NULL)
  379. delete [] pwszMount;
  380. TLEAVE();
  381. return dwErr;
  382. }
  383. //+-------------------------------------------------------------------------
  384. //
  385. // Function: CDriveTable::AddDriveToTable
  386. //
  387. // Synopsis: add the volume to the drive table
  388. //
  389. // Arguments: [pwszGuid] -- the volume GUID
  390. //
  391. // Returns: Win32 error code
  392. //
  393. // History: 13-Apr-2000 HenryLee Created
  394. //
  395. //--------------------------------------------------------------------------
  396. DWORD CDriveTable::AddDriveToTable(WCHAR *pwszDrive, WCHAR *pwszGuid)
  397. {
  398. DWORD dwErr = ERROR_SUCCESS;
  399. if (NULL == pwszDrive)
  400. return ERROR_INVALID_DRIVE;
  401. // Eventually, this routine will require pwszGuid to be non-NULL
  402. CDataStore *pds = pwszGuid != NULL ? FindGuidInTable (pwszGuid) :
  403. FindDriveInTable (pwszDrive);
  404. if (pds != NULL) // found the drive already
  405. {
  406. if (lstrcmpiW (pwszDrive, pds->GetDrive()) != 0) // drive rename
  407. pds->SetDrive (pwszDrive);
  408. return dwErr;
  409. }
  410. pds = new CDataStore(this);
  411. if (pds == NULL)
  412. {
  413. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  414. return dwErr;
  415. }
  416. dwErr = pds->Initialize (pwszDrive, pwszGuid);
  417. if (dwErr == ERROR_SUCCESS)
  418. {
  419. dwErr = CreateNewEntry (pds);
  420. _fDirty = TRUE;
  421. }
  422. if (dwErr != ERROR_SUCCESS) // clean up on error
  423. {
  424. delete pds;
  425. }
  426. return dwErr;
  427. }
  428. //+-------------------------------------------------------------------------
  429. //
  430. // Function: CDriveTable::FindFirstDrive
  431. // CDriveTable::FindNextDrive
  432. //
  433. // Synopsis: loop through drive table entries
  434. //
  435. // Arguments: [dtec] -- enumeration context
  436. //
  437. // Returns: CDataStore object pointer
  438. //
  439. // History: 13-Apr-2000 HenryLee Created
  440. //
  441. //--------------------------------------------------------------------------
  442. CDataStore * CDriveTable::FindFirstDrive (SDriveTableEnumContext & dtec) const
  443. {
  444. for (dtec._pdt = this; dtec._pdt != NULL; dtec._pdt = dtec._pdt->_pdtNext)
  445. {
  446. for (dtec._iIndex = 0; dtec._iIndex < dtec._pdt->_nLastDrive; dtec._iIndex++)
  447. {
  448. CDataStore *pds = dtec._pdt->_rgDriveTable[dtec._iIndex];
  449. if (pds != NULL)
  450. {
  451. return pds;
  452. }
  453. }
  454. }
  455. return NULL;
  456. }
  457. CDataStore * CDriveTable::FindNextDrive (SDriveTableEnumContext & dtec) const
  458. {
  459. for (; dtec._pdt != NULL; dtec._pdt = dtec._pdt->_pdtNext)
  460. {
  461. dtec._iIndex++;
  462. for (; dtec._iIndex < dtec._pdt->_nLastDrive; dtec._iIndex++)
  463. {
  464. CDataStore *pds = dtec._pdt->_rgDriveTable[dtec._iIndex];
  465. if (pds != NULL)
  466. {
  467. return pds;
  468. }
  469. }
  470. dtec._iIndex = 0;
  471. }
  472. return NULL;
  473. }
  474. //+-------------------------------------------------------------------------
  475. //
  476. // Function: CDriveTable::Merge
  477. //
  478. // Synopsis: loop through drive table entries and merge
  479. //
  480. // Arguments: [dt] -- drive table read from disk
  481. //
  482. // Returns: Win32 error
  483. //
  484. // History: 13-Apr-2000 HenryLee Created
  485. //
  486. //--------------------------------------------------------------------------
  487. DWORD CDriveTable::Merge (CDriveTable &dt)
  488. {
  489. DWORD dwErr = ERROR_SUCCESS;
  490. BOOL fApplyDefaults = FALSE;
  491. SDriveTableEnumContext dtec = {NULL, 0};
  492. HKEY hKeyGP = NULL;
  493. if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  494. s_cszGroupPolicy,
  495. 0,
  496. KEY_READ,
  497. &hKeyGP))
  498. {
  499. DWORD dwRet = 0;
  500. if (ERROR_SUCCESS == RegReadDWORD(hKeyGP, s_cszDisableConfig, &dwRet))
  501. {
  502. if (dwRet == 0)
  503. fApplyDefaults = TRUE;
  504. }
  505. RegCloseKey (hKeyGP);
  506. }
  507. CDataStore *pds = dt.FindFirstDrive (dtec);
  508. while (pds != NULL)
  509. {
  510. CDataStore *pdsFound = FindGuidInTable (pds->GetGuid());
  511. if (pdsFound != NULL)
  512. {
  513. pds->GetVolumeInfo(); // refresh the volume flags
  514. if (fApplyDefaults)
  515. {
  516. pds->MonitorDrive(TRUE); // make sure drive is monitored
  517. pds->SetSizeLimit(0); // set max datastore size to default
  518. }
  519. // don't overwrite the newer drive letter and label
  520. dwErr = pdsFound->LoadDataStore (NULL, pds->GetGuid(), NULL,
  521. pds->GetFlags() | SR_DRIVE_ACTIVE, pds->GetNumChangeLogs(), pds->GetSizeLimit());
  522. }
  523. else
  524. {
  525. CDataStore *pdsNew = new CDataStore ( this);
  526. if (pdsNew == NULL)
  527. {
  528. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  529. return dwErr;
  530. }
  531. dwErr = pdsNew->LoadDataStore (pds->GetDrive(), pds->GetGuid(),
  532. pds->GetLabel(),
  533. pds->GetFlags() & ~SR_DRIVE_ACTIVE,
  534. pds->GetNumChangeLogs(), pds->GetSizeLimit());
  535. if (dwErr != ERROR_SUCCESS)
  536. {
  537. delete pdsNew;
  538. pdsNew = NULL;
  539. goto Err;
  540. }
  541. dwErr = CreateNewEntry (pdsNew);
  542. }
  543. if (dwErr != ERROR_SUCCESS)
  544. goto Err;
  545. pds = dt.FindNextDrive (dtec);
  546. }
  547. if (fApplyDefaults && g_pEventHandler != NULL)
  548. {
  549. dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
  550. }
  551. Err:
  552. return dwErr;
  553. }
  554. //+-------------------------------------------------------------------------
  555. //
  556. // Function: CDriveTable::IsAdvancedRp()
  557. //
  558. // Synopsis: method to determine if a given restore point is an
  559. // advanced restore point
  560. //
  561. // Arguments: restore point, pointer to flags
  562. //
  563. // Returns:
  564. //
  565. // History: 13-Apr-2000 HenryLee Created
  566. //
  567. //--------------------------------------------------------------------------
  568. DWORD
  569. CDriveTable::IsAdvancedRp(CRestorePoint *prp, PDWORD pdwFlags)
  570. {
  571. TraceFunctEnter("CDriveTable::IsAdvancedRp");
  572. WCHAR szPath[MAX_PATH];
  573. WCHAR szSysDrive[MAX_PATH];
  574. SDriveTableEnumContext dtec = {NULL, 0};
  575. DWORD dwErr = ERROR_SUCCESS;
  576. CDataStore *pds = NULL;
  577. CRestorePoint rp;
  578. CDriveTable dt;
  579. //
  580. // read the drivetable file for this restore point
  581. //
  582. if (FALSE == GetSystemDrive(szSysDrive))
  583. {
  584. dwErr = ERROR_INVALID_DRIVE;
  585. trace(0, "! GetSystemDrive : %ld", dwErr);
  586. goto Err;
  587. }
  588. dwErr = GetCurrentRestorePoint(rp);
  589. if ( dwErr != ERROR_SUCCESS )
  590. goto Err;
  591. //
  592. // if no restore point specified, assume current
  593. //
  594. if (! prp)
  595. prp = &rp;
  596. if (prp->GetNum() == rp.GetNum())
  597. {
  598. MakeRestorePath(szPath, szSysDrive, s_cszDriveTable);
  599. }
  600. else
  601. {
  602. MakeRestorePath(szPath, szSysDrive, prp->GetDir());
  603. PathAppend(szPath, s_cszDriveTable);
  604. }
  605. dwErr = dt.LoadDriveTable(szPath);
  606. if (dwErr != ERROR_SUCCESS)
  607. goto Err;
  608. //
  609. // check if the rp directory exists on all drives
  610. // if it does not, then it is an advanced restore point
  611. //
  612. *pdwFlags = RP_NORMAL;
  613. pds = dt.FindFirstDrive(dtec);
  614. while (pds)
  615. {
  616. //
  617. // is the rp dir supposed to exist?
  618. //
  619. if ((pds->GetFlags() & SR_DRIVE_ACTIVE) &&
  620. (pds->GetFlags() & SR_DRIVE_MONITORED) &&
  621. (pds->GetFlags() & SR_DRIVE_PARTICIPATE) &&
  622. !(pds->GetFlags() & SR_DRIVE_FROZEN))
  623. {
  624. MakeRestorePath(szPath, pds->GetDrive(), rp.GetDir());
  625. if (0xFFFFFFFF == GetFileAttributes(szPath))
  626. {
  627. *pdwFlags = RP_ADVANCED;
  628. break;
  629. }
  630. }
  631. pds = dt.FindNextDrive(dtec);
  632. }
  633. Err:
  634. TraceFunctLeave();
  635. return dwErr;
  636. }
  637. //+-------------------------------------------------------------------------
  638. //
  639. // Function: CDriveTable::AnyMountedDrives()
  640. //
  641. // Synopsis: check if there are any mounted drives
  642. //
  643. // Arguments:
  644. //
  645. // Returns:
  646. //
  647. // History: 25-Oct-2000 Brijeshk Created
  648. //
  649. //--------------------------------------------------------------------------
  650. BOOL CDriveTable::AnyMountedDrives()
  651. {
  652. SDriveTableEnumContext dtec = {NULL, 0};
  653. CDataStore *pds = FindFirstDrive(dtec);
  654. while (pds)
  655. {
  656. //
  657. // get the first '\' in the drive path
  658. // if this is not the last character in the path
  659. // then this is a mount point
  660. //
  661. LPWSTR pszfirst = wcschr(pds->GetDrive(), L'\\');
  662. if (pszfirst &&
  663. pszfirst != pds->GetDrive() + (lstrlen(pds->GetDrive()) - 1))
  664. {
  665. return TRUE;
  666. }
  667. pds = FindNextDrive(dtec);
  668. }
  669. return FALSE;
  670. }
  671. //+-------------------------------------------------------------------------
  672. //
  673. // Function: CDataStoreMgr::CDataStoreMgr()
  674. //
  675. // Synopsis:
  676. //
  677. // Arguments:
  678. //
  679. // Returns:
  680. //
  681. // History: 13-Apr-2000 HenryLee Created
  682. //
  683. //--------------------------------------------------------------------------
  684. CDataStoreMgr::CDataStoreMgr()
  685. {
  686. _fStop = FALSE;
  687. }
  688. //+-------------------------------------------------------------------------
  689. //
  690. // Function: CDataStoreMgr::~CDataStoreMgr()
  691. //
  692. // Synopsis:
  693. //
  694. // Arguments:
  695. //
  696. // Returns:
  697. //
  698. // History: 13-Apr-2000 HenryLee Created
  699. //
  700. //--------------------------------------------------------------------------
  701. CDataStoreMgr::~CDataStoreMgr()
  702. {
  703. }
  704. // helper functions for Fifo
  705. BOOL
  706. IsCurrentRp(CRestorePoint& rp, CRestorePoint& rpCur)
  707. {
  708. return rp.GetNum() == rpCur.GetNum();
  709. }
  710. BOOL
  711. IsTargetPercentMet(int nUsagePercent, int nTargetPercent)
  712. {
  713. return nUsagePercent <= nTargetPercent;
  714. }
  715. BOOL
  716. IsTargetRpMet(DWORD dwRPNum, DWORD dwTargetRPNum)
  717. {
  718. return dwRPNum > dwTargetRPNum;
  719. }
  720. //+-------------------------------------------------------------------------
  721. //
  722. // Function: CDataStoreMgr::Fifo
  723. //
  724. // Synopsis: fifo restore points upto a given percentage
  725. //
  726. // Arguments: drive to fifo, target RP dir, target percentage to stop fifo
  727. // specify only one of both (dwTargetRPNum or nTargetPercent)
  728. // fIncludeCurrentRp = TRUE : fifo current rp if necessary (i.e. freeze)
  729. // fIncludeCurrentRp = FALSE : don't fifo current rp
  730. //
  731. // Returns: Win32 error code
  732. //
  733. // History: 27-Apr-2000 brijeshk Created
  734. //
  735. //--------------------------------------------------------------------------
  736. DWORD CDataStoreMgr::Fifo(
  737. WCHAR *pwszDrive,
  738. DWORD dwTargetRPNum,
  739. int nTargetPercent,
  740. BOOL fIncludeCurrentRp,
  741. BOOL fFifoAtLeastOneRp
  742. )
  743. {
  744. TENTER("CDataStoreMgr::Fifo");
  745. DWORD dwErr = ERROR_SUCCESS;
  746. CDataStore *pds = _dt.FindDriveInTable(pwszDrive);
  747. BOOL fFifoed = FALSE;
  748. DWORD dwLastFifoedRp;
  749. CDataStore *pdsLead = NULL;
  750. BOOL fFirstIteration;
  751. SDriveTableEnumContext dtec = {NULL, 0};
  752. CRestorePointEnum *prpe = NULL;
  753. CRestorePoint *prp = new CRestorePoint;
  754. // can't specify many target criteria
  755. if (dwTargetRPNum != 0 && nTargetPercent != 0)
  756. {
  757. dwErr = ERROR_INVALID_PARAMETER;
  758. goto Err;
  759. }
  760. // can't specify no target criteria
  761. if (fIncludeCurrentRp == TRUE && dwTargetRPNum == 0 && nTargetPercent == 0)
  762. {
  763. dwErr = ERROR_INVALID_PARAMETER;
  764. goto Err;
  765. }
  766. // can't specify bad target criteria
  767. if (dwTargetRPNum > g_pEventHandler->m_CurRp.GetNum() ||
  768. nTargetPercent < 0 ||
  769. nTargetPercent > 100)
  770. {
  771. dwErr = ERROR_INVALID_PARAMETER;
  772. goto Err;
  773. }
  774. if (!prp)
  775. {
  776. trace(0, "cannot allocate memory for restore point");
  777. dwErr = ERROR_OUTOFMEMORY;
  778. goto Err;
  779. }
  780. if (! pds)
  781. {
  782. TRACE(0, "! Drive %S not in drivetable", pwszDrive);
  783. dwErr = ERROR_INVALID_DRIVE;
  784. goto Err;
  785. }
  786. if (! (pds->GetFlags() & SR_DRIVE_MONITORED) ||
  787. (pds->GetFlags() & SR_DRIVE_FROZEN) )
  788. {
  789. trace(0, "Drive %S already frozen/disabled", pwszDrive);
  790. goto Err;
  791. }
  792. if (g_pSRConfig->m_dwTestBroadcast)
  793. PostTestMessage(g_pSRConfig->m_uiTMFifoStart, (WPARAM) NULL, (LPARAM) NULL);
  794. pdsLead = NULL;
  795. fFirstIteration = TRUE;
  796. while (pds)
  797. {
  798. fFifoed = FALSE;
  799. //
  800. // skip the drive we fifoed first
  801. //
  802. if (pds != pdsLead)
  803. {
  804. //
  805. // enum forward, don't skip last
  806. //
  807. prpe = new CRestorePointEnum( pds->GetDrive(), TRUE, FALSE );
  808. if (!prpe)
  809. {
  810. trace(0, "cannot allocate memory for restore point enum");
  811. dwErr = ERROR_OUTOFMEMORY;
  812. goto Err;
  813. }
  814. {
  815. WCHAR szFifoedRpPath[MAX_PATH];
  816. //
  817. // blow away any obsolete "Fifoed" directories
  818. //
  819. MakeRestorePath(szFifoedRpPath, pwszDrive, s_cszFifoedRpDir);
  820. CHECKERR(Delnode_Recurse(szFifoedRpPath, TRUE, &_fStop),
  821. "Denode_Recurse Fifoed");
  822. //
  823. // blow away any obsolete "RP0" directories
  824. //
  825. MakeRestorePath(szFifoedRpPath, pwszDrive, L"RP0");
  826. dwErr = Delnode_Recurse(szFifoedRpPath, TRUE, &_fStop);
  827. if (ERROR_SUCCESS != dwErr)
  828. {
  829. trace (0, "Cannot FIFO RP0 error %d, ignoring", dwErr);
  830. dwErr = ERROR_SUCCESS;
  831. }
  832. }
  833. //
  834. // loop through restore points on this drive
  835. //
  836. dwErr = prpe->FindFirstRestorePoint (*prp);
  837. //
  838. // enumeration can return ERROR_FILE_NOT_FOUND for restorepoints
  839. // that are missing rp.log
  840. // we will just continue in this case
  841. //
  842. while (dwErr == ERROR_SUCCESS || dwErr == ERROR_FILE_NOT_FOUND)
  843. {
  844. //
  845. // check for the stop event
  846. //
  847. ASSERT(g_pSRConfig);
  848. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  849. {
  850. TRACE(0, "Stop signalled - aborting fifo");
  851. dwErr = ERROR_OPERATION_ABORTED;
  852. goto Err;
  853. }
  854. //
  855. // check if fifo is disabled from this restore point
  856. //
  857. if (g_pSRConfig->GetFifoDisabledNum() != 0 &&
  858. prp->GetNum() >= g_pSRConfig->GetFifoDisabledNum())
  859. {
  860. TRACE(0, "Fifo disabled from %S", prp->GetDir());
  861. break;
  862. }
  863. //
  864. // check if we've reached target restore point or percentage
  865. //
  866. if (dwTargetRPNum)
  867. {
  868. if (IsTargetRpMet(prp->GetNum(), dwTargetRPNum))
  869. {
  870. TRACE(0, "Target restore point reached");
  871. break;
  872. }
  873. }
  874. else if (nTargetPercent && FALSE == fFifoAtLeastOneRp)
  875. {
  876. int nUsagePercent = 0;
  877. if (ERROR_SUCCESS == pds->GetUsagePercent(&nUsagePercent) &&
  878. IsTargetPercentMet(nUsagePercent, nTargetPercent))
  879. {
  880. TRACE(0, "Target percentage reached");
  881. break;
  882. }
  883. }
  884. //
  885. // check if we've reached the current rp
  886. //
  887. if (IsCurrentRp(*prp, g_pEventHandler->m_CurRp))
  888. {
  889. if (fIncludeCurrentRp)
  890. {
  891. //
  892. // need to fifo this one too
  893. // this is same as freezing the drive
  894. // so freeze
  895. //
  896. dwErr = FreezeDrive(pwszDrive);
  897. goto Err;
  898. }
  899. else
  900. {
  901. //
  902. // don't fifo current rp
  903. // (usually called from Disk Cleanup)
  904. //
  905. trace(0, "No more rps to fifo");
  906. break;
  907. }
  908. }
  909. //
  910. // throw away this restore point on this drive
  911. //
  912. dwErr = pds->FifoRestorePoint (*prp);
  913. if ( ERROR_SUCCESS != dwErr )
  914. {
  915. TRACE(0, "! FifoRestorePoint on %S on drive %S : %ld",
  916. prp->GetDir(), pwszDrive, dwErr);
  917. goto Err;
  918. }
  919. //
  920. // record in the fifo log
  921. //
  922. WriteFifoLog (prp->GetDir(), pds->GetDrive());
  923. dwLastFifoedRp = prp->GetNum();
  924. fFifoed = TRUE;
  925. fFifoAtLeastOneRp = FALSE;
  926. dwErr = prpe->FindNextRestorePoint(*prp);
  927. }
  928. if (prpe)
  929. {
  930. delete prpe;
  931. prpe = NULL;
  932. }
  933. }
  934. //
  935. // go to next drive
  936. //
  937. if (fFirstIteration)
  938. {
  939. if (! fFifoed) // we did not fifo anything
  940. {
  941. break;
  942. }
  943. pdsLead = pds;
  944. pds = _dt.FindFirstDrive(dtec);
  945. fFirstIteration = FALSE;
  946. dwTargetRPNum = dwLastFifoedRp; // fifo till what we fifoed just now
  947. nTargetPercent = 0;
  948. fIncludeCurrentRp = TRUE;
  949. fFifoAtLeastOneRp = FALSE;
  950. }
  951. else
  952. {
  953. pds = _dt.FindNextDrive(dtec);
  954. }
  955. }
  956. if (dwErr == ERROR_NO_MORE_ITEMS)
  957. dwErr = ERROR_SUCCESS;
  958. if (g_pSRConfig->m_dwTestBroadcast)
  959. PostTestMessage(g_pSRConfig->m_uiTMFifoStop, (WPARAM) dwLastFifoedRp, (LPARAM) NULL);
  960. Err:
  961. if (prpe)
  962. delete prpe;
  963. if (prp)
  964. delete prp;
  965. TLEAVE();
  966. return dwErr;
  967. }
  968. //+-------------------------------------------------------------------------
  969. //
  970. // Function: CDataStoreMgr::WriteFifoLog
  971. //
  972. // Synopsis: appends to the fifo log
  973. //
  974. // Arguments: dir name of restore point fifoed, drive
  975. //
  976. // Returns:
  977. //
  978. // History: 27-Apr-2000 brijeshk Created
  979. //
  980. //--------------------------------------------------------------------------
  981. DWORD
  982. CDataStoreMgr::WriteFifoLog(LPWSTR pwszDir, LPWSTR pwszDrive)
  983. {
  984. FILE *f = NULL;
  985. WCHAR szLog[MAX_PATH];
  986. DWORD dwRc = ERROR_INTERNAL_ERROR;
  987. WCHAR wszTime[MAX_PATH] = L"";
  988. WCHAR wszDate[MAX_PATH] = L"";
  989. CDataStore *pds = NULL;
  990. TENTER("CDataStoreMgr::WriteFifoLog");
  991. TRACE(0, "Fifoed %S on drive %S", pwszDir, pwszDrive);
  992. if (pds = _dt.FindSystemDrive())
  993. {
  994. MakeRestorePath(szLog, pds->GetDrive(), s_cszFifoLog);
  995. f = (FILE *) _wfopen(szLog, L"a");
  996. if (f)
  997. {
  998. _wstrdate(wszDate);
  999. _wstrtime(wszTime);
  1000. fwprintf(f, L"%s-%s : Fifoed %s on drive %s\n", wszDate, wszTime, pwszDir, pwszDrive);
  1001. fclose(f);
  1002. dwRc = ERROR_SUCCESS;
  1003. }
  1004. else
  1005. {
  1006. TRACE(0, "_wfopen failed on %s", szLog);
  1007. }
  1008. }
  1009. TLEAVE();
  1010. return dwRc;
  1011. }
  1012. //+-------------------------------------------------------------------------
  1013. //
  1014. // Function: CDriveTable::EnumAllVolumes
  1015. //
  1016. // Synopsis: enumerates all local volumes and updates the drive table
  1017. //
  1018. // Arguments:
  1019. //
  1020. // Returns: Win32 error code
  1021. //
  1022. // History: 13-Apr-2000 HenryLee Created
  1023. //
  1024. //--------------------------------------------------------------------------
  1025. DWORD CDriveTable::EnumAllVolumes ()
  1026. {
  1027. TENTER("CDriveTable::EnumAllVolumes");
  1028. DWORD dwErr = ERROR_SUCCESS;
  1029. WCHAR wcsVolumeName[MAX_PATH];
  1030. WCHAR wcsDosName[MAX_PATH];
  1031. //
  1032. // Let's first get all the local volumes
  1033. //
  1034. HANDLE hVolume = FindFirstVolume (wcsVolumeName, MAX_PATH);
  1035. // If we can't even find one volume, return an error
  1036. if (hVolume == INVALID_HANDLE_VALUE)
  1037. {
  1038. dwErr = GetLastError();
  1039. return dwErr;
  1040. }
  1041. do
  1042. {
  1043. //
  1044. // We have to find a mount point that points to this volume
  1045. // If there is no such mount point, then the volume is not
  1046. // accessible, and we ignore it
  1047. //
  1048. dwErr = FindMountPoint (wcsVolumeName, wcsDosName);
  1049. if (dwErr == ERROR_SUCCESS)
  1050. {
  1051. dwErr = AddDriveToTable (wcsDosName, wcsVolumeName);
  1052. if (dwErr == ERROR_BAD_DEV_TYPE || //add only fixed drives
  1053. dwErr == ERROR_UNRECOGNIZED_VOLUME) //unformatted
  1054. dwErr = ERROR_SUCCESS;
  1055. if (dwErr != ERROR_SUCCESS)
  1056. {
  1057. goto Err;
  1058. }
  1059. }
  1060. }
  1061. while (FindNextVolume (hVolume, wcsVolumeName, MAX_PATH));
  1062. dwErr = ERROR_SUCCESS;
  1063. Err:
  1064. FindVolumeClose (hVolume);
  1065. TLEAVE();
  1066. return dwErr;
  1067. }
  1068. //+-------------------------------------------------------------------------
  1069. //
  1070. // Function: CDriveTable::LoadDriveTable
  1071. //
  1072. // Synopsis: loads a drive table from a restore point directory
  1073. //
  1074. // Arguments:
  1075. //
  1076. // Returns:
  1077. //
  1078. // History: 13-Apr-2000 HenryLee Created
  1079. //
  1080. //--------------------------------------------------------------------------
  1081. DWORD CDriveTable::LoadDriveTable (WCHAR *pwszPath)
  1082. {
  1083. TENTER ("CDriveTable::LoadDriveTable");
  1084. DWORD dwErr = ERROR_SUCCESS;
  1085. if (FALSE == _fLockInit)
  1086. {
  1087. dwErr = _lock.Init();
  1088. if (dwErr != ERROR_SUCCESS)
  1089. return dwErr;
  1090. _fLockInit = TRUE;
  1091. }
  1092. BOOL fLocked = _lock.Lock(CLock::TIMEOUT);
  1093. if (!fLocked)
  1094. {
  1095. return WAIT_TIMEOUT;
  1096. }
  1097. CDataStore *pds = NULL;
  1098. WCHAR *pwcBuffer = NULL;
  1099. WCHAR *pwszLine = NULL;
  1100. HANDLE hFile = INVALID_HANDLE_VALUE;
  1101. DWORD dwFlags = 0;
  1102. DWORD dwFileSize = 0;
  1103. DWORD cbRead = 0;
  1104. int iChangeLogs = 0;
  1105. WCHAR wcsDrive[MAX_PATH] = L"";
  1106. WCHAR wcsGuid[GUID_STRLEN] = L"";
  1107. WCHAR wcsLabel[CDataStore::LABEL_STRLEN];
  1108. DWORD dwSizeLimit = 0;
  1109. hFile = CreateFileW ( pwszPath, // file name
  1110. GENERIC_READ, // file access
  1111. FILE_SHARE_READ, // share mode
  1112. NULL, // SD
  1113. OPEN_EXISTING, // how to create
  1114. 0, // file attributes
  1115. NULL); // handle to template file
  1116. if (INVALID_HANDLE_VALUE == hFile)
  1117. {
  1118. dwErr = GetLastError();
  1119. goto Err;
  1120. }
  1121. dwFileSize = GetFileSize (hFile, NULL);
  1122. if (dwFileSize > SR_DEFAULT_DSMAX * MEGABYTE)
  1123. {
  1124. dwErr = ERROR_FILE_CORRUPT;
  1125. goto Err;
  1126. }
  1127. pwcBuffer = (WCHAR *) SRMemAlloc (dwFileSize);
  1128. if (pwcBuffer == NULL)
  1129. {
  1130. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1131. goto Err;
  1132. }
  1133. if (FALSE == ReadFile (hFile, (BYTE*)pwcBuffer, dwFileSize, &cbRead, NULL))
  1134. {
  1135. dwErr = GetLastError();
  1136. goto Err;
  1137. }
  1138. pwszLine = pwcBuffer;
  1139. for (UINT i = 0; i < dwFileSize / sizeof(WCHAR); i++)
  1140. {
  1141. if (pwcBuffer[i] == L'\n')
  1142. {
  1143. pwcBuffer[i] = L'\0'; // convert all newlines to terminators
  1144. wcsLabel[0] = L'\0'; // initialize in case scanf terminates early
  1145. if (EOF != swscanf(pwszLine, gs_wcsScanFormat, wcsDrive,
  1146. wcsGuid, &dwFlags, &iChangeLogs,
  1147. &dwSizeLimit, wcsLabel))
  1148. {
  1149. pds = new CDataStore ( this);
  1150. if (pds == NULL)
  1151. {
  1152. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1153. return dwErr;
  1154. }
  1155. dwErr = pds->LoadDataStore (wcsDrive, wcsGuid,
  1156. wcsLabel, dwFlags, iChangeLogs,
  1157. (INT64) dwSizeLimit * MEGABYTE);
  1158. if (dwErr != ERROR_SUCCESS)
  1159. goto Err;
  1160. dwErr = CreateNewEntry (pds);
  1161. if (dwErr != ERROR_SUCCESS)
  1162. goto Err;
  1163. }
  1164. pwszLine = &pwcBuffer[i+1]; // skip to next line
  1165. }
  1166. }
  1167. Err:
  1168. if (hFile != INVALID_HANDLE_VALUE)
  1169. CloseHandle (hFile);
  1170. if (pwcBuffer != NULL)
  1171. SRMemFree (pwcBuffer);
  1172. if (fLocked)
  1173. _lock.Unlock();
  1174. TLEAVE();
  1175. return dwErr;
  1176. }
  1177. //+-------------------------------------------------------------------------
  1178. //
  1179. // Function: CDriveTable::SaveDriveTable
  1180. //
  1181. // Synopsis: saves a drive table into a restore point directory
  1182. //
  1183. // Arguments: [prp] -- restore point to save into
  1184. //
  1185. // Returns:
  1186. //
  1187. // History: 13-Apr-2000 HenryLee Created
  1188. //
  1189. //--------------------------------------------------------------------------
  1190. DWORD CDriveTable::SaveDriveTable (CRestorePoint *prp)
  1191. {
  1192. DWORD dwErr = ERROR_SUCCESS;
  1193. WCHAR wcsPath[MAX_PATH];
  1194. CDataStore *pds = FindSystemDrive();
  1195. if (NULL == pds)
  1196. {
  1197. dwErr = ERROR_INVALID_DRIVE;
  1198. goto Err;
  1199. }
  1200. if (prp == NULL) // no restore point, so save to the datastore directory
  1201. {
  1202. MakeRestorePath(wcsPath, pds->GetDrive(), L"");
  1203. }
  1204. else
  1205. {
  1206. MakeRestorePath(wcsPath, pds->GetDrive(), prp->GetDir());
  1207. }
  1208. lstrcatW (wcsPath, L"\\");
  1209. lstrcatW (wcsPath, s_cszDriveTable);
  1210. dwErr = SaveDriveTable (wcsPath);
  1211. Err:
  1212. return dwErr;
  1213. }
  1214. DWORD CDriveTable::SaveDriveTable (WCHAR *pwszPath)
  1215. {
  1216. TENTER ("CDriveTable::SaveDriveTable");
  1217. DWORD dwErr = ERROR_SUCCESS;
  1218. if (FALSE == _fLockInit)
  1219. {
  1220. dwErr = _lock.Init();
  1221. if (dwErr != ERROR_SUCCESS)
  1222. return dwErr;
  1223. _fLockInit = TRUE;
  1224. }
  1225. BOOL fLocked = _lock.Lock(CLock::TIMEOUT);
  1226. if (!fLocked)
  1227. {
  1228. return WAIT_TIMEOUT;
  1229. }
  1230. BOOL fDirtySave = _fDirty; // save the dirty bit
  1231. HANDLE hFile = CreateFileW ( pwszPath, // file name
  1232. GENERIC_WRITE, // file access
  1233. 0, // share mode
  1234. NULL, // SD
  1235. CREATE_ALWAYS, // how to create
  1236. FILE_FLAG_WRITE_THROUGH, // file attributes
  1237. NULL); // handle to template file
  1238. if (INVALID_HANDLE_VALUE == hFile)
  1239. {
  1240. dwErr = GetLastError();
  1241. goto Err;
  1242. }
  1243. _fDirty = FALSE; // avoid calling back into SaveDriveTable again
  1244. dwErr = ForAllDrives (CDataStore::SaveDataStore, (LONG_PTR) hFile);
  1245. if (dwErr != ERROR_SUCCESS)
  1246. goto Err;
  1247. if (lstrcmp (pwszPath, L"CONOUT$") != 0)
  1248. {
  1249. if (FALSE == FlushFileBuffers (hFile)) // make sure it's on disk
  1250. dwErr = GetLastError();
  1251. }
  1252. Err:
  1253. if (hFile != INVALID_HANDLE_VALUE)
  1254. CloseHandle (hFile);
  1255. if (ERROR_SUCCESS == dwErr)
  1256. _fDirty = FALSE;
  1257. else
  1258. _fDirty = fDirtySave;
  1259. if (fLocked)
  1260. _lock.Unlock();
  1261. TLEAVE();
  1262. return dwErr;
  1263. }
  1264. //+-------------------------------------------------------------------------
  1265. //
  1266. // Function: CDataStoreMgr::Initialize
  1267. //
  1268. // Synopsis:
  1269. //
  1270. // Arguments: fFirstRun -- true if run on first boot
  1271. //
  1272. // Returns:
  1273. //
  1274. // History: 13-Apr-2000 HenryLee Created
  1275. //
  1276. //--------------------------------------------------------------------------
  1277. DWORD CDataStoreMgr::Initialize (BOOL fFirstRun)
  1278. {
  1279. TENTER("CDataStoreMgr::Initialize");
  1280. DWORD dwErr = ERROR_SUCCESS;
  1281. dwErr = _dt.EnumAllVolumes();
  1282. if (dwErr == ERROR_SUCCESS)
  1283. {
  1284. CDataStore *pds = _dt.FindSystemDrive();
  1285. // now create system datastore on firstrun
  1286. if (pds != NULL)
  1287. {
  1288. WCHAR wcsPath[MAX_PATH];
  1289. if (fFirstRun)
  1290. {
  1291. // destroy datastores on all drives and
  1292. // create new on system drive
  1293. SDriveTableEnumContext dtec = {NULL, 0};
  1294. CDataStore *pdsDel = _dt.FindFirstDrive (dtec);
  1295. while (pdsDel != NULL)
  1296. {
  1297. if (pdsDel->GetFlags() & (SR_DRIVE_ACTIVE))
  1298. {
  1299. dwErr = pdsDel->DestroyDataStore (TRUE);
  1300. if (dwErr != ERROR_SUCCESS)
  1301. {
  1302. trace(0, "! DestroyDataStore : %ld", dwErr);
  1303. goto Err;
  1304. }
  1305. }
  1306. pdsDel = _dt.FindNextDrive (dtec);
  1307. }
  1308. dwErr = pds->CreateDataStore (NULL);
  1309. if (dwErr != ERROR_SUCCESS)
  1310. {
  1311. trace(0, "! CreateDataStore : %ld", dwErr);
  1312. goto Err;
  1313. }
  1314. (void) WriteMachineGuid();
  1315. }
  1316. else // verify that the system datastore exists
  1317. {
  1318. CDriveTable dt;
  1319. MakeRestorePath (wcsPath, pds->GetDrive(), L"");
  1320. DWORD dwAttr = GetFileAttributes (wcsPath);
  1321. if (0xFFFFFFFF==dwAttr || !(FILE_ATTRIBUTE_DIRECTORY & dwAttr))
  1322. {
  1323. dwErr = pds->CreateDataStore( NULL );
  1324. }
  1325. MakeRestorePath(wcsPath, pds->GetDrive(), s_cszDriveTable);
  1326. if (ERROR_SUCCESS == dt.LoadDriveTable (wcsPath))
  1327. {
  1328. dwErr = _dt.Merge(dt);
  1329. if (dwErr != ERROR_SUCCESS)
  1330. {
  1331. trace(0, "! CDriveTable::Merge : %ld", dwErr);
  1332. goto Err;
  1333. }
  1334. }
  1335. }
  1336. // update the disk free space variable and
  1337. // set datastore size for each datastore if not already done
  1338. dwErr = UpdateDiskFree(NULL);
  1339. if (dwErr != ERROR_SUCCESS)
  1340. {
  1341. trace(0, "! UpdateDiskFree : %ld", dwErr);
  1342. goto Err;
  1343. }
  1344. // freeze system drive if this is firstrun and disk free is < 200MB
  1345. if (fFirstRun && g_pSRConfig)
  1346. {
  1347. if (pds->GetDiskFree() < (g_pSRConfig->m_dwDSMin * MEGABYTE))
  1348. {
  1349. dwErr = FreezeDrive(pds->GetGuid());
  1350. if (dwErr != ERROR_SUCCESS)
  1351. {
  1352. trace(0, "! FreezeDrive : %ld", dwErr);
  1353. goto Err;
  1354. }
  1355. }
  1356. }
  1357. MakeRestorePath(wcsPath, pds->GetDrive(), s_cszDriveTable);
  1358. dwErr = _dt.SaveDriveTable (wcsPath);
  1359. if (dwErr != ERROR_SUCCESS)
  1360. {
  1361. trace(0, "! SaveDriveTable : %ld", dwErr);
  1362. goto Err;
  1363. }
  1364. }
  1365. else dwErr = ERROR_INVALID_DRIVE;
  1366. }
  1367. Err:
  1368. TLEAVE();
  1369. return dwErr;
  1370. }
  1371. //+-------------------------------------------------------------------------
  1372. //
  1373. // Function: CDataStoreMgr::TriggerFreezeOrFifo
  1374. //
  1375. // Synopsis: checks freedisk space & datastore size,
  1376. // triggering freeze or fifo as required
  1377. // Arguments:
  1378. //
  1379. // Returns:
  1380. //
  1381. // History: 27-Apr-2000 brijeshk Created
  1382. //
  1383. //--------------------------------------------------------------------------
  1384. DWORD
  1385. CDataStoreMgr::TriggerFreezeOrFifo()
  1386. {
  1387. TENTER("CDataStoreMgr::TriggerFreezeOrFifo");
  1388. SDriveTableEnumContext dtec = {NULL, 0};
  1389. DWORD dwRc = ERROR_SUCCESS;
  1390. CDataStore *pds = _dt.FindFirstDrive (dtec);
  1391. // update datastore capacities
  1392. // and get free space on each drive
  1393. dwRc = UpdateDiskFree(NULL);
  1394. if (dwRc != ERROR_SUCCESS)
  1395. {
  1396. trace(0, "! UpdateDiskFree : %ld", dwRc);
  1397. goto done;
  1398. }
  1399. // check the free space and datastore usage
  1400. while (pds != NULL && dwRc == ERROR_SUCCESS)
  1401. {
  1402. // we care only if the drive is not already frozen
  1403. // and if it is monitored
  1404. if (!(pds->GetFlags() & SR_DRIVE_FROZEN) &&
  1405. (pds->GetFlags() & SR_DRIVE_MONITORED))
  1406. {
  1407. //
  1408. // if there is no rp on this drive,
  1409. // then we don't really care
  1410. //
  1411. CRestorePointEnum rpe((LPWSTR) pds->GetDrive(), FALSE, FALSE); // backward, include current
  1412. CRestorePoint rp;
  1413. int nUsagePercent = 0;
  1414. DWORD dwErr = rpe.FindFirstRestorePoint(rp) ;
  1415. if (dwErr == ERROR_SUCCESS || dwErr == ERROR_FILE_NOT_FOUND)
  1416. {
  1417. if (pds->GetDiskFree() <= THRESHOLD_FREEZE_DISKSPACE * MEGABYTE)
  1418. {
  1419. dwRc = FreezeDrive(pds->GetGuid());
  1420. }
  1421. else if (pds->GetDiskFree() <= THRESHOLD_FIFO_DISKSPACE * MEGABYTE)
  1422. {
  1423. dwRc = Fifo(pds->GetGuid(), 0, TARGET_FIFO_PERCENT, TRUE, TRUE);
  1424. }
  1425. else if (ERROR_SUCCESS == pds->GetUsagePercent(&nUsagePercent)
  1426. && nUsagePercent >= THRESHOLD_FIFO_PERCENT)
  1427. {
  1428. dwRc = Fifo(pds->GetGuid(), 0, TARGET_FIFO_PERCENT, TRUE, FALSE);
  1429. }
  1430. }
  1431. rpe.FindClose();
  1432. }
  1433. pds = _dt.FindNextDrive (dtec);
  1434. }
  1435. done:
  1436. TLEAVE();
  1437. return dwRc;
  1438. }
  1439. //+-------------------------------------------------------------------------
  1440. //
  1441. // Function: CDataStoreMgr::FindFrozenDrive
  1442. //
  1443. // Synopsis: returns ERROR_SUCCESS if any drives are frozen
  1444. // ERROR_NO_MORE_ITEMS otherwise
  1445. // Arguments:
  1446. //
  1447. // Returns:
  1448. //
  1449. // History: 27-Apr-2000 brijeshk Created
  1450. //
  1451. //--------------------------------------------------------------------------
  1452. DWORD
  1453. CDataStoreMgr::FindFrozenDrive()
  1454. {
  1455. CDataStore * pds = NULL;
  1456. SDriveTableEnumContext dtec = {NULL, 0};
  1457. pds = _dt.FindFirstDrive (dtec);
  1458. while (pds != NULL)
  1459. {
  1460. if ((pds->GetFlags() & SR_DRIVE_MONITORED) &&
  1461. (pds->GetFlags() & SR_DRIVE_FROZEN))
  1462. return ERROR_SUCCESS;
  1463. pds = _dt.FindNextDrive (dtec);
  1464. }
  1465. return ERROR_NO_MORE_ITEMS;
  1466. }
  1467. //+-------------------------------------------------------------------------
  1468. //
  1469. // Function: CDataStoreMgr::FifoOldRps
  1470. //
  1471. // Synopsis: fifoes out restore points older than a given time period
  1472. //
  1473. // Arguments: [llTimeInSeconds] -- FIFO interval time
  1474. //
  1475. // Returns:
  1476. //
  1477. // History: 14-Jul-2000 brijeshk Created
  1478. //
  1479. //--------------------------------------------------------------------------
  1480. DWORD
  1481. CDataStoreMgr::FifoOldRps(
  1482. INT64 llTimeInSeconds)
  1483. {
  1484. TENTER("CDataStoreMgr::FifoOldRps");
  1485. CDataStore *pds = _dt.FindSystemDrive();
  1486. DWORD dwRc = ERROR_SUCCESS;
  1487. CRestorePointEnum *prpe = NULL;
  1488. CRestorePoint *prp = NULL;
  1489. if (pds)
  1490. {
  1491. DWORD dwRpFifo = 0;
  1492. LARGE_INTEGER *pllRp = NULL, *pllNow = NULL;
  1493. FILETIME ftNow, *pftRp = NULL;
  1494. // enumerate RPs forward on the system drive
  1495. // skip the current one
  1496. // even if the current rp is older than a month, we won't fifo it
  1497. prpe = new CRestorePointEnum(pds->GetDrive(), TRUE, TRUE);
  1498. prp = new CRestorePoint;
  1499. if (!prpe || !prp)
  1500. {
  1501. trace(0, "Cannot allocate memory for restore point enum");
  1502. dwRc = ERROR_OUTOFMEMORY;
  1503. goto done;
  1504. }
  1505. // get the current time
  1506. GetSystemTimeAsFileTime(&ftNow);
  1507. pllNow = (LARGE_INTEGER *) &ftNow;
  1508. dwRc = prpe->FindFirstRestorePoint(*prp);
  1509. while (dwRc == ERROR_SUCCESS || dwRc == ERROR_FILE_NOT_FOUND)
  1510. {
  1511. // first check if this is not a cancelled restore point
  1512. if (dwRc != ERROR_FILE_NOT_FOUND && ! prp->IsDefunct())
  1513. {
  1514. // get the restore point creation time
  1515. pftRp = prp->GetTime();
  1516. pllRp = (LARGE_INTEGER *) pftRp;
  1517. if (!pllRp || !pllNow)
  1518. {
  1519. trace(0, "! pulRp or pulNow = NULL");
  1520. dwRc = ERROR_INTERNAL_ERROR;
  1521. goto done;
  1522. }
  1523. // check if it is newer than a month
  1524. // if so, stop looking
  1525. // else, try the next restore point
  1526. if (pllNow->QuadPart - pllRp->QuadPart < llTimeInSeconds * 10 * 1000 * 1000)
  1527. {
  1528. trace(0, "%S newer than a month", prp->GetDir());
  1529. break;
  1530. }
  1531. else
  1532. {
  1533. dwRpFifo = prp->GetNum();
  1534. }
  1535. }
  1536. dwRc = prpe->FindNextRestorePoint(*prp);
  1537. }
  1538. // at this point, if dwRpFifo != 0,
  1539. // it contains the latest RP that's older than a month
  1540. // call fifo on this to fifo out all previous RPs including this one
  1541. if (dwRpFifo != 0)
  1542. dwRc = Fifo(pds->GetGuid(), dwRpFifo, 0, FALSE, FALSE);
  1543. else
  1544. dwRc = ERROR_SUCCESS;
  1545. }
  1546. else
  1547. {
  1548. trace(0, "! FindSystemDrive");
  1549. dwRc = ERROR_INVALID_DRIVE;
  1550. }
  1551. done:
  1552. if (prpe)
  1553. delete prpe;
  1554. if (prp)
  1555. delete prp;
  1556. TLEAVE();
  1557. return dwRc;
  1558. }
  1559. //+-------------------------------------------------------------------------
  1560. //
  1561. // Function: CDataStoreMgr::UpdateDataStoreUsage
  1562. //
  1563. // Synopsis: update the size of a datastore
  1564. //
  1565. // Arguments:
  1566. //
  1567. // Returns:
  1568. //
  1569. // History: 27-Apr-2000 brijeshk Created
  1570. //
  1571. //--------------------------------------------------------------------------
  1572. DWORD
  1573. CDataStoreMgr::UpdateDataStoreUsage(WCHAR *pwszDrive, INT64 llDelta)
  1574. {
  1575. TENTER ("CDataStoreMgr::UpdateDataStoreUsage");
  1576. DWORD dwErr = ERROR_SUCCESS;
  1577. CDataStore *pds = _dt.FindDriveInTable(pwszDrive);
  1578. if (pds)
  1579. {
  1580. if ((pds->GetFlags() & SR_DRIVE_FROZEN) ||
  1581. ! (pds->GetFlags() & SR_DRIVE_MONITORED))
  1582. {
  1583. TRACE(0, "Size update on frozen/unmonitored drive!");
  1584. }
  1585. else dwErr = pds->UpdateDataStoreUsage(llDelta, TRUE);
  1586. }
  1587. else
  1588. dwErr = ERROR_INVALID_DRIVE;
  1589. TLEAVE();
  1590. return dwErr;
  1591. }
  1592. //+-------------------------------------------------------------------------
  1593. //
  1594. // Function: CDataStoreMgr::GetFlags
  1595. //
  1596. // Synopsis: get the participation bit from a drive
  1597. //
  1598. // Arguments: [pwszDrive] -- drive letter
  1599. //
  1600. // Returns:
  1601. //
  1602. // History: 13-Apr-2000 HenryLee Created
  1603. //
  1604. //--------------------------------------------------------------------------
  1605. DWORD CDataStoreMgr::GetFlags(WCHAR *pwszDrive, PDWORD pdwFlags)
  1606. {
  1607. CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
  1608. DWORD dwErr = ERROR_SUCCESS;
  1609. if (NULL != pds)
  1610. {
  1611. *pdwFlags = pds->GetFlags();
  1612. }
  1613. else dwErr = ERROR_INVALID_DRIVE;
  1614. return dwErr;
  1615. }
  1616. //+-------------------------------------------------------------------------
  1617. //
  1618. // Function: CDataStoreMgr::GetUsagePercent
  1619. //
  1620. // Synopsis: get the datastore usage for a drive
  1621. //
  1622. // Arguments: [pwszDrive] -- drive letter
  1623. //
  1624. // Returns:
  1625. //
  1626. // History: 13-Apr-2000 HenryLee Created
  1627. //
  1628. //--------------------------------------------------------------------------
  1629. DWORD CDataStoreMgr::GetUsagePercent(WCHAR *pwszDrive, int *pnPercent)
  1630. {
  1631. CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
  1632. DWORD dwErr = ERROR_SUCCESS;
  1633. if (NULL != pds)
  1634. {
  1635. dwErr = pds->GetUsagePercent(pnPercent);
  1636. }
  1637. else dwErr = ERROR_INVALID_DRIVE;
  1638. return dwErr;
  1639. }
  1640. //+-------------------------------------------------------------------------
  1641. //
  1642. // Function: CDataStoreMgr::SwitchRestorePoint
  1643. //
  1644. // Synopsis: change the drive table when switching restore points
  1645. //
  1646. // Arguments: [prp] -- old restore point
  1647. //
  1648. // Returns:
  1649. //
  1650. // History: 13-Apr-2000 HenryLee Created
  1651. //
  1652. //--------------------------------------------------------------------------
  1653. DWORD CDataStoreMgr::SwitchRestorePoint (CRestorePoint *prp)
  1654. {
  1655. DWORD dwErr = ERROR_SUCCESS;
  1656. dwErr = _dt.ForAllDrives (&CDataStore::CountChangeLogs, (LONG_PTR) prp);
  1657. if (dwErr != ERROR_SUCCESS)
  1658. goto Err;
  1659. // persist old restore point dt
  1660. if (prp)
  1661. {
  1662. dwErr = _dt.SaveDriveTable (prp);
  1663. if (dwErr != ERROR_SUCCESS)
  1664. goto Err;
  1665. }
  1666. // remove old volumes
  1667. dwErr = _dt.RemoveDrivesFromTable ();
  1668. if (dwErr != ERROR_SUCCESS)
  1669. goto Err;
  1670. // reset per-rp flags
  1671. dwErr = _dt.ForAllDrives (&CDataStore::ResetFlags, NULL);
  1672. if (dwErr != ERROR_SUCCESS)
  1673. goto Err;
  1674. // persist current restore point dt
  1675. dwErr = _dt.SaveDriveTable((CRestorePoint *) NULL);
  1676. Err:
  1677. return dwErr;
  1678. }
  1679. //+-------------------------------------------------------------------------
  1680. //
  1681. // Function: CDataStoreMgr::FreezeDrive
  1682. //
  1683. // Synopsis: freeze a drive
  1684. //
  1685. // Arguments: [pwszDrive] -- drive
  1686. //
  1687. // Returns:
  1688. //
  1689. // History: 13-Apr-2000 HenryLee Created
  1690. //
  1691. //--------------------------------------------------------------------------
  1692. DWORD CDataStoreMgr::FreezeDrive(WCHAR *pwszDrive)
  1693. {
  1694. DWORD dwErr = ERROR_SUCCESS;
  1695. WCHAR szThawSize[GUID_STRLEN], szSystemDrive[MAX_SYS_DRIVE] = L" ";
  1696. TENTER("CDataStoreMgr::FreezeDrive");
  1697. if (pwszDrive != NULL)
  1698. {
  1699. CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
  1700. if (! pds)
  1701. {
  1702. dwErr = ERROR_INVALID_DRIVE;
  1703. TRACE (0, "FindDriveInTable failed in CDataStoreMgr::FreezeDrive %ld\n", dwErr);
  1704. goto Err;
  1705. }
  1706. //
  1707. // freeze all drives
  1708. //
  1709. }
  1710. dwErr = _dt.ForAllDrives (CDataStore::FreezeDrive, NULL);
  1711. if (dwErr == ERROR_SUCCESS)
  1712. {
  1713. //
  1714. // rebuild _filelst.cfg and pass to filter
  1715. //
  1716. ASSERT(g_pEventHandler);
  1717. dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
  1718. if (g_pSRService != NULL)
  1719. {
  1720. if (g_pSRConfig && g_pSRConfig->m_dwFreezeThawLogCount < MAX_FREEZETHAW_LOG_MESSAGES)
  1721. {
  1722. TRACE (0, "Freezing the SR service due to low disk space.");
  1723. wsprintf(szThawSize, L"%d",THRESHOLD_THAW_DISKSPACE);
  1724. if (pwszDrive == NULL)
  1725. {
  1726. if(GetSystemDrive(szSystemDrive) == FALSE)
  1727. TRACE (0, "GetSystemDrive failed in CDataStoreMgr::FreezeDrive.");
  1728. pwszDrive = szSystemDrive;
  1729. }
  1730. g_pSRService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_FROZEN, NULL, 0, szThawSize, pwszDrive);
  1731. g_pSRConfig->m_dwFreezeThawLogCount++;
  1732. }
  1733. }
  1734. }
  1735. //
  1736. // request for idle time
  1737. // so that we can thaw later
  1738. //
  1739. ASSERT(g_pSRConfig);
  1740. SetEvent(g_pSRConfig->m_hIdleRequestEvent);
  1741. if (g_pEventHandler)
  1742. g_pEventHandler->RefreshCurrentRp(FALSE);
  1743. if (g_pSRConfig->m_dwTestBroadcast)
  1744. PostTestMessage(g_pSRConfig->m_uiTMFreeze, NULL, NULL);
  1745. Err:
  1746. TLEAVE();
  1747. return dwErr;
  1748. }
  1749. //+-------------------------------------------------------------------------
  1750. //
  1751. // Function: CDataStoreMgr::IsDriveFrozen
  1752. //
  1753. // Synopsis: check if given drive is frozen
  1754. // if NULL, check if any drive is frozen
  1755. //
  1756. // Arguments:
  1757. //
  1758. // Returns:
  1759. //
  1760. // History: 21-Jul-2000 Brijeshk Created
  1761. //
  1762. //--------------------------------------------------------------------------
  1763. BOOL CDataStoreMgr::IsDriveFrozen(LPWSTR pszDrive)
  1764. {
  1765. CDataStore *pds = NULL;
  1766. SDriveTableEnumContext dtec = {NULL, 0};
  1767. if (!pszDrive)
  1768. {
  1769. pds = _dt.FindFirstDrive(dtec);
  1770. while (pds)
  1771. {
  1772. if (pds->GetFlags() & SR_DRIVE_FROZEN)
  1773. return TRUE;
  1774. pds = _dt.FindNextDrive(dtec);
  1775. }
  1776. }
  1777. else
  1778. {
  1779. CDataStore *pds = _dt.FindDriveInTable(pszDrive);
  1780. if (pds)
  1781. {
  1782. if (pds->GetFlags() & SR_DRIVE_FROZEN)
  1783. return TRUE;
  1784. }
  1785. }
  1786. return FALSE;
  1787. }
  1788. //+-------------------------------------------------------------------------
  1789. //
  1790. // Function: CDataStoreMgr::ThawDrives
  1791. //
  1792. // Synopsis: thaw one or more drives
  1793. //
  1794. // Arguments: [fCheckOnly] -- if TRUE do not actually thaw
  1795. //
  1796. // Returns: if any drive is thawed, returns ERROR_SUCCESS
  1797. // else returns ERROR_NO_MORE_ITEMS
  1798. //
  1799. // History: 13-Apr-2000 HenryLee Created
  1800. //
  1801. //--------------------------------------------------------------------------
  1802. DWORD
  1803. CDataStoreMgr::ThawDrives(BOOL fCheckOnly)
  1804. {
  1805. TENTER("CDataStoreMgr::ThawDrives");
  1806. CDataStore *pds = NULL, *pdsSys = _dt.FindSystemDrive();
  1807. DWORD dwRc = ERROR_NO_MORE_ITEMS;
  1808. SDriveTableEnumContext dtec;
  1809. DWORD dwTemp;
  1810. if (! pdsSys)
  1811. {
  1812. dwRc = ERROR_INVALID_DRIVE;
  1813. TRACE (0, "Cannot find system drive %ld\n", dwRc);
  1814. goto done;
  1815. }
  1816. // if system drive is frozen, then check if 200mb is free
  1817. // if yes, then thaw all drives
  1818. // if no, thaw none
  1819. ASSERT(pdsSys->GetFlags() & SR_DRIVE_MONITORED);
  1820. if ((pdsSys->GetFlags() & SR_DRIVE_FROZEN))
  1821. {
  1822. dwRc = pdsSys->UpdateDiskFree(NULL);
  1823. if (dwRc != ERROR_SUCCESS)
  1824. {
  1825. trace(0, "! UpdateDiskFree : %ld", dwRc);
  1826. goto done;
  1827. }
  1828. if (pdsSys->GetDiskFree() >= THRESHOLD_THAW_DISKSPACE * MEGABYTE)
  1829. {
  1830. if (fCheckOnly)
  1831. {
  1832. dwRc = ERROR_SUCCESS;
  1833. goto done;
  1834. }
  1835. pds = _dt.FindFirstDrive (dtec);
  1836. while (pds != NULL)
  1837. {
  1838. dwTemp = pds->ThawDrive(NULL);
  1839. if (dwTemp != ERROR_SUCCESS) // remember the error and
  1840. {
  1841. dwRc = dwTemp; // keep on going
  1842. TRACE (0, "ThawDrive failed with %ld\n", dwRc);
  1843. }
  1844. pds = _dt.FindNextDrive (dtec);
  1845. }
  1846. }
  1847. else // cannot thaw now
  1848. {
  1849. dwRc = ERROR_NO_MORE_ITEMS;
  1850. TRACE (0, "No drives to thaw %ld\n", dwRc);
  1851. }
  1852. }
  1853. else // make sure all the other drives are thawed too for consistency
  1854. {
  1855. pds = _dt.FindFirstDrive (dtec);
  1856. while (pds != NULL)
  1857. {
  1858. if (pds->GetFlags() & SR_DRIVE_FROZEN)
  1859. pds->ThawDrive(NULL);
  1860. pds = _dt.FindNextDrive (dtec);
  1861. }
  1862. dwRc = ERROR_SUCCESS;
  1863. }
  1864. if (_dt.GetDirty())
  1865. {
  1866. dwRc = _dt.SaveDriveTable ((CRestorePoint *) NULL);
  1867. if (dwRc != ERROR_SUCCESS)
  1868. TRACE (0, "SaveDriveTable failed with %ld\n", dwRc);
  1869. }
  1870. if (g_pSRService != NULL && ERROR_SUCCESS == dwRc && FALSE == fCheckOnly)
  1871. {
  1872. if (g_pSRConfig && g_pSRConfig->m_dwFreezeThawLogCount <= MAX_FREEZETHAW_LOG_MESSAGES)
  1873. {
  1874. g_pSRService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_THAWED);
  1875. g_pSRConfig->m_dwFreezeThawLogCount++;
  1876. }
  1877. }
  1878. done:
  1879. TLEAVE();
  1880. return dwRc;
  1881. }
  1882. //+-------------------------------------------------------------------------
  1883. //
  1884. // Function: CDataStoreMgr::MonitorDrive
  1885. //
  1886. // Synopsis: enable/disable a drive
  1887. //
  1888. // Arguments: [pwszDrive] -- drive, [fSet] -- enable/disable
  1889. //
  1890. // Returns:
  1891. //
  1892. // History: 13-Apr-2000 HenryLee Created
  1893. //
  1894. //--------------------------------------------------------------------------
  1895. DWORD CDataStoreMgr::MonitorDrive(WCHAR *pwszDrive, BOOL fSet)
  1896. {
  1897. CDataStore *pds = pwszDrive ? _dt.FindDriveInTable(pwszDrive) : NULL;
  1898. DWORD dwErr = ERROR_SUCCESS;
  1899. BOOL fTellFilter = TRUE;
  1900. if (! pwszDrive || ! pds || pds == _dt.FindSystemDrive()) // system drive
  1901. {
  1902. // something wrong
  1903. // cannot enable/disable whole of SR this way
  1904. dwErr = ERROR_INVALID_DRIVE;
  1905. }
  1906. else
  1907. {
  1908. // enable/disable only this drive
  1909. dwErr = pds->MonitorDrive(fSet);
  1910. if (ERROR_SUCCESS == dwErr && (pds->GetFlags() & SR_DRIVE_FROZEN))
  1911. fTellFilter = FALSE;
  1912. }
  1913. if (dwErr == ERROR_SUCCESS)
  1914. {
  1915. // update drivetable on disk
  1916. if (_dt.GetDirty())
  1917. {
  1918. dwErr = _dt.SaveDriveTable ((CRestorePoint *) NULL);
  1919. // rebuild _filelst.cfg and pass to filter
  1920. if (fTellFilter)
  1921. {
  1922. ASSERT(g_pEventHandler);
  1923. dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
  1924. }
  1925. }
  1926. }
  1927. return dwErr;
  1928. }
  1929. //+-------------------------------------------------------------------------
  1930. //
  1931. // Function: CDataStoreMgr::WriteMachineGuid
  1932. //
  1933. // Synopsis: write machine guid for disk cleanup utility
  1934. //
  1935. // Arguments:
  1936. //
  1937. // Returns:
  1938. //
  1939. // History: 13-Apr-2000 HenryLee Created
  1940. //
  1941. //--------------------------------------------------------------------------
  1942. DWORD CDataStoreMgr::WriteMachineGuid ()
  1943. {
  1944. DWORD dwErr = ERROR_SUCCESS;
  1945. WCHAR wcsPath [MAX_PATH];
  1946. if (0 == GetSystemDirectoryW (wcsPath, MAX_PATH))
  1947. {
  1948. dwErr = GetLastError();
  1949. }
  1950. else
  1951. {
  1952. lstrcatW (wcsPath, L"\\Restore\\MachineGuid.txt");
  1953. HANDLE hFile = CreateFileW ( wcsPath, // file name
  1954. GENERIC_WRITE, // file access
  1955. 0, // share mode
  1956. NULL, // SD
  1957. CREATE_ALWAYS, // how to create
  1958. 0, // file attributes
  1959. NULL); // handle to template file
  1960. if (INVALID_HANDLE_VALUE == hFile)
  1961. {
  1962. dwErr = GetLastError();
  1963. }
  1964. else
  1965. {
  1966. WCHAR *pwszGuid = GetMachineGuid();
  1967. ULONG cbWritten;
  1968. if (FALSE == WriteFile (hFile, (BYTE *) pwszGuid,
  1969. (lstrlenW(pwszGuid)+1) * sizeof(WCHAR),
  1970. &cbWritten, NULL))
  1971. {
  1972. dwErr = GetLastError();
  1973. }
  1974. CloseHandle (hFile);
  1975. }
  1976. }
  1977. return dwErr;
  1978. }
  1979. //+-------------------------------------------------------------------------
  1980. //
  1981. // Function: CDataStoreMgr::DeleteMachineGuidFile
  1982. //
  1983. // Synopsis: write machine guid for disk cleanup utility
  1984. //
  1985. // Arguments:
  1986. //
  1987. // Returns:
  1988. //
  1989. // History: 13-Apr-2000 HenryLee Created
  1990. //
  1991. //--------------------------------------------------------------------------
  1992. DWORD CDataStoreMgr::DeleteMachineGuidFile ()
  1993. {
  1994. DWORD dwErr = ERROR_SUCCESS;
  1995. WCHAR wcsPath [MAX_PATH];
  1996. if (0 == GetSystemDirectoryW (wcsPath, MAX_PATH))
  1997. {
  1998. dwErr = GetLastError();
  1999. }
  2000. else
  2001. {
  2002. lstrcatW (wcsPath, L"\\Restore\\MachineGuid.txt");
  2003. if (FALSE == DeleteFileW (wcsPath))
  2004. dwErr = GetLastError();
  2005. }
  2006. return dwErr;
  2007. }
  2008. //+-------------------------------------------------------------------------
  2009. //
  2010. // Function: CDataStoreMgr::Compress
  2011. //
  2012. // Synopsis: compress files in each datastore
  2013. //
  2014. // Arguments: lDuration - duration to compress
  2015. //
  2016. // Returns:
  2017. //
  2018. // History: 26-Feb-01 Brijeshk Created
  2019. //
  2020. //--------------------------------------------------------------------------
  2021. DWORD CDataStoreMgr::Compress (
  2022. LPWSTR pszDrive,
  2023. LONG lDuration)
  2024. {
  2025. TENTER("CDataStoreMgr::Compress");
  2026. DWORD dwErr = ERROR_SUCCESS;
  2027. CDataStore *pds = NULL, *pdsSys = NULL;
  2028. INT64 llAllocated = 0, llUsed = 0;
  2029. SDriveTableEnumContext dtec = {NULL, 0};
  2030. BOOL fFirstTime;
  2031. llAllocated = lDuration * 1000 * 1000 * 10; // 100's of nanoseconds
  2032. //
  2033. // if drive specified, compress only that
  2034. //
  2035. if (pszDrive)
  2036. {
  2037. pds = _dt.FindDriveInTable(pszDrive);
  2038. if (pds)
  2039. {
  2040. dwErr = pds->Compress(llAllocated, &llUsed);
  2041. }
  2042. else
  2043. {
  2044. dwErr = ERROR_INVALID_DRIVE;
  2045. }
  2046. goto Err;
  2047. }
  2048. //
  2049. // else, compress all drives if time permits
  2050. // starting with system drive
  2051. //
  2052. pdsSys = _dt.FindSystemDrive();
  2053. pds = pdsSys;
  2054. fFirstTime = TRUE;
  2055. while (pds)
  2056. {
  2057. if (fFirstTime || pds != pdsSys)
  2058. {
  2059. trace(0, "Allocated time for %S is %I64d", pds->GetDrive(), llAllocated);
  2060. llUsed = 0;
  2061. dwErr = pds->Compress(llAllocated, &llUsed);
  2062. if (dwErr != ERROR_SUCCESS && dwErr != ERROR_OPERATION_ABORTED)
  2063. {
  2064. trace(0, "! Compress : %ld", dwErr);
  2065. goto Err;
  2066. }
  2067. llAllocated -= llUsed;
  2068. if (llAllocated <= 0)
  2069. {
  2070. //
  2071. // used up all time
  2072. //
  2073. dwErr = ERROR_OPERATION_ABORTED;
  2074. break;
  2075. }
  2076. }
  2077. //
  2078. // go to next drive
  2079. //
  2080. if (fFirstTime)
  2081. {
  2082. pds = _dt.FindFirstDrive(dtec);
  2083. }
  2084. else
  2085. {
  2086. pds = _dt.FindNextDrive(dtec);
  2087. }
  2088. fFirstTime = FALSE;
  2089. }
  2090. Err:
  2091. TLEAVE();
  2092. return dwErr;
  2093. }