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.

1829 lines
50 KiB

  1. /******************************************************************************
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. * datastor.cpp
  7. *
  8. * Abstract:
  9. * CDataStore class functions
  10. *
  11. * Revision History:
  12. * Brijesh Krishnaswami (brijeshk) 03/17/2000
  13. * created
  14. *
  15. *****************************************************************************/
  16. #include "datastor.h"
  17. #include "datastormgr.h"
  18. #include "enumlogs.h"
  19. #include "srconfig.h"
  20. #include "srapi.h"
  21. #include "evthandler.h"
  22. #include "..\snapshot\snappatch.h"
  23. #include "NTServMsg.h" // generated from the MC message compiler
  24. #ifdef THIS_FILE
  25. #undef THIS_FILE
  26. #endif
  27. static char __szTraceSourceFile[] = __FILE__;
  28. #define THIS_FILE __szTraceSourceFile
  29. //
  30. // The format for each line of the drive table
  31. //
  32. static WCHAR gs_wcsPrintFormat[] = L"%s/%s %x %i %i %s\r\n";
  33. //+---------------------------------------------------------------------------
  34. //
  35. // Function: CDataStore::CDataStore
  36. //
  37. // Synopsis: Initialize an empty datastore object
  38. //
  39. // Arguments:
  40. //
  41. // History: 12-Apr-2000 HenryLee Created
  42. //
  43. //----------------------------------------------------------------------------
  44. CDataStore::CDataStore (CDriveTable *pdt)
  45. {
  46. _pwszDrive[0] = L'\0';
  47. _pwszGuid[0] = L'\0';
  48. _pwszLabel[0] = L'\0';
  49. _dwFlags = 0;
  50. _llDataStoreUsageBytes = -1;
  51. _llCurrentRpUsageBytes = 0;
  52. _llDataStoreSizeBytes = 0;
  53. _llDiskFreeBytes = 0;
  54. _prp = NULL;
  55. _prpe = NULL;
  56. _iChangeLogs = -1;
  57. _pdt = pdt;
  58. }
  59. CDataStore::~CDataStore()
  60. {
  61. if (_prp != NULL)
  62. delete _prp;
  63. if (_prpe != NULL)
  64. delete _prpe;
  65. // we leave _pdt as a dangling reference,
  66. // since deleting _pdt will delete all child datastores
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Function: CDataStore::LoadDataStore
  71. //
  72. // Synopsis: Initialize a datastore object from a file
  73. //
  74. // Arguments: [pwszDrive] -- optional drive letter
  75. // [pwszGuid] -- mount manager GUID
  76. // [pwszLabel] -- optional volume label
  77. // [dwFlags] -- SR volume flags
  78. // [iChangeLogs] -- number of change logs
  79. // [llSizeLimit] -- datastore size limit
  80. //
  81. // History: 12-Apr-2000 HenryLee Created
  82. //
  83. //----------------------------------------------------------------------------
  84. DWORD CDataStore::LoadDataStore (WCHAR *pwszDrive,
  85. WCHAR *pwszGuid,
  86. WCHAR *pwszLabel,
  87. DWORD dwFlags,
  88. int iChangeLogs,
  89. INT64 llSizeLimit)
  90. {
  91. if (pwszDrive != NULL)
  92. {
  93. if (lstrlen(pwszDrive) >= MAX_PATH)
  94. return ERROR_INVALID_PARAMETER;
  95. else
  96. lstrcpy (_pwszDrive, pwszDrive);
  97. }
  98. if (pwszGuid != NULL)
  99. {
  100. if (lstrlen(pwszGuid) >= GUID_STRLEN)
  101. return ERROR_INVALID_PARAMETER;
  102. else
  103. lstrcpy (_pwszGuid, pwszGuid);
  104. }
  105. if (pwszLabel != NULL)
  106. {
  107. if (lstrlen(pwszLabel) >= LABEL_STRLEN)
  108. return ERROR_INVALID_PARAMETER;
  109. else
  110. lstrcpy (_pwszLabel, pwszLabel);
  111. }
  112. _dwFlags = dwFlags;
  113. _prpe = NULL;
  114. _prp = NULL;
  115. _iChangeLogs = iChangeLogs;
  116. _llDataStoreSizeBytes = llSizeLimit;
  117. return ERROR_SUCCESS;
  118. }
  119. //+---------------------------------------------------------------------------
  120. //
  121. // Function: CDataStore::GetVolumeInfo
  122. //
  123. // Synopsis: retrieves volume information
  124. //
  125. // Arguments:
  126. //
  127. // History: 12-Apr-2000 HenryLee Created
  128. //
  129. //----------------------------------------------------------------------------
  130. DWORD CDataStore::GetVolumeInfo ()
  131. {
  132. DWORD dwErr = ERROR_SUCCESS;
  133. WCHAR wcsLabel [LABEL_STRLEN];
  134. DWORD dwSerial;
  135. DWORD dwFsFlags;
  136. TENTER ("CDataStore::GetVolumeInfo");
  137. // Get the volume label and flags
  138. if (TRUE == GetVolumeInformationW (_pwszGuid,
  139. wcsLabel, LABEL_STRLEN,
  140. &dwSerial, NULL, &dwFsFlags, NULL, 0))
  141. {
  142. lstrcpy (_pwszLabel, wcsLabel);
  143. if (dwFsFlags & FS_VOL_IS_COMPRESSED)
  144. _dwFlags |= SR_DRIVE_COMPRESSED;
  145. if (dwFsFlags & FS_PERSISTENT_ACLS)
  146. _dwFlags |= SR_DRIVE_NTFS;
  147. if (dwFsFlags & FILE_READ_ONLY_VOLUME)
  148. _dwFlags |= SR_DRIVE_READONLY;
  149. }
  150. else
  151. {
  152. dwErr = GetLastError();
  153. TRACE(0, "! CDataStore::GetVolumeInfo : %ld", dwErr);
  154. }
  155. TLEAVE();
  156. return dwErr;
  157. }
  158. //+---------------------------------------------------------------------------
  159. //
  160. // Function: CDataStore::Initialize
  161. //
  162. // Synopsis: Initialize a datastore object
  163. //
  164. // Arguments: [pwszDrive] -- drive letter or mount point
  165. // [pwszGuid] -- volume GUID
  166. //
  167. // Returns: Win32 error code
  168. //
  169. // History: 12-Apr-2000 HenryLee Created
  170. //
  171. //----------------------------------------------------------------------------
  172. DWORD CDataStore::Initialize(WCHAR *pwszDrive, WCHAR *pwszGuid)
  173. {
  174. TENTER("CDataStore::Initialize");
  175. ULARGE_INTEGER ulTotalFreeBytes;
  176. DWORD dwErr = ERROR_SUCCESS;
  177. NTSTATUS nts;
  178. HANDLE h = INVALID_HANDLE_VALUE;
  179. WCHAR wcsBuffer[MAX_PATH];
  180. if (pwszDrive == NULL)
  181. return ERROR_INVALID_PARAMETER;
  182. if (pwszGuid == NULL)
  183. {
  184. if (!GetVolumeNameForVolumeMountPoint (pwszDrive, wcsBuffer, MAX_PATH))
  185. {
  186. dwErr = GetLastError();
  187. TRACE(0, "! CDataStore::Initialize GetVolumeNameForVolumeMountPoint"
  188. " : %ld", dwErr);
  189. return dwErr;
  190. }
  191. pwszGuid = wcsBuffer;
  192. }
  193. if (lstrlen (pwszDrive) >= MAX_PATH ||
  194. lstrlen (pwszGuid) >= GUID_STRLEN)
  195. {
  196. dwErr = ERROR_INVALID_PARAMETER;
  197. goto Err;
  198. }
  199. if (DRIVE_FIXED != GetDriveType (pwszDrive))
  200. return ERROR_BAD_DEV_TYPE;
  201. lstrcpy (_pwszDrive, pwszDrive);
  202. lstrcpy (_pwszGuid, pwszGuid);
  203. // Open a handle to the volume
  204. h = CreateFileW ( pwszGuid,
  205. GENERIC_READ,
  206. FILE_SHARE_READ | FILE_SHARE_WRITE,
  207. NULL,
  208. OPEN_EXISTING,
  209. FILE_FLAG_BACKUP_SEMANTICS,
  210. NULL );
  211. if (h == INVALID_HANDLE_VALUE) // The volume could be unformatted or locked
  212. {
  213. dwErr = GetLastError();
  214. TRACE(0, "! CDataStore::Initialize CreateFileW : %ld", dwErr);
  215. dwErr = ERROR_UNRECOGNIZED_VOLUME;
  216. goto Err;
  217. }
  218. dwErr = GetVolumeInfo ();
  219. if (dwErr != ERROR_SUCCESS)
  220. goto Err;
  221. if (IsSystemDrive (_pwszDrive))
  222. {
  223. _dwFlags |= SR_DRIVE_SYSTEM;
  224. }
  225. _dwFlags |= SR_DRIVE_ACTIVE;
  226. _dwFlags |= SR_DRIVE_MONITORED;
  227. Err:
  228. if (h != INVALID_HANDLE_VALUE)
  229. CloseHandle (h);
  230. TLEAVE();
  231. return dwErr;
  232. }
  233. //+-------------------------------------------------------------------------
  234. //
  235. // Function: CDataStore::UpdateDiskFree
  236. //
  237. // Synopsis: calculates disk free and sets initial datastore size
  238. //
  239. // Arguments:
  240. //
  241. //
  242. // Returns:
  243. //
  244. // History: 13-Apr-2000 HenryLee Created
  245. //
  246. //--------------------------------------------------------------------------
  247. DWORD
  248. CDataStore::UpdateDiskFree(LONG_PTR lReserved)
  249. {
  250. ULARGE_INTEGER ulTotalFreeBytes, ulTotalBytes;
  251. DWORD dwErr = ERROR_SUCCESS;
  252. const BOOL fSystem = _dwFlags & SR_DRIVE_SYSTEM;
  253. if (FALSE == GetDiskFreeSpaceEx (_pwszGuid, NULL, &ulTotalBytes, &ulTotalFreeBytes))
  254. {
  255. dwErr = GetLastError();
  256. goto Err;
  257. }
  258. if (g_pSRConfig != NULL)
  259. {
  260. if (_llDataStoreSizeBytes == 0)
  261. {
  262. // datastore size calculation
  263. // minimum = 50mb (non-system) or 200mb (system)
  264. // maximum = min (disksize, max(12%, 400mb))
  265. // actual ds size = calculated maximum
  266. INT64 llDSQuota = g_pSRConfig->m_dwDiskPercent * ulTotalBytes.QuadPart / 100;
  267. INT64 llDSMin = (INT64) (g_pSRConfig->GetDSMin(fSystem));
  268. INT64 llDSMax = min( ulTotalBytes.QuadPart,
  269. max( llDSQuota, (INT64) g_pSRConfig->m_dwDSMax * MEGABYTE ) );
  270. if (llDSMax < llDSMin)
  271. llDSMax = llDSMin;
  272. //
  273. // take floor of this value
  274. //
  275. _llDataStoreSizeBytes = ((INT64) (llDSMax / (INT64) MEGABYTE)) * (INT64) MEGABYTE;
  276. }
  277. }
  278. else
  279. {
  280. _llDataStoreSizeBytes = SR_DEFAULT_DSMAX * MEGABYTE;
  281. }
  282. _llDiskFreeBytes = (INT64) ulTotalFreeBytes.QuadPart;
  283. Err:
  284. return dwErr;
  285. }
  286. //+---------------------------------------------------------------------------
  287. //
  288. // Function: CDataStore::UpdateParticipate
  289. //
  290. // Synopsis: updates participate bit
  291. //
  292. // Arguments:
  293. //
  294. // Returns: boolean
  295. //
  296. // History: 27-Apr-2000 brijeshk Created
  297. //
  298. //----------------------------------------------------------------------------
  299. DWORD
  300. CDataStore::UpdateParticipate(LONG_PTR pwszDir)
  301. {
  302. DWORD dwRc = ERROR_SUCCESS;
  303. if (! (_dwFlags & SR_DRIVE_PARTICIPATE))
  304. {
  305. WCHAR szPath[MAX_PATH];
  306. MakeRestorePath(szPath, _pwszDrive, (LPWSTR) pwszDir);
  307. if (-1 != GetFileAttributes(szPath))
  308. {
  309. dwRc = SetParticipate(TRUE);
  310. }
  311. }
  312. return dwRc;
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // Function: CDataStore::GetUsagePercent
  317. //
  318. // Synopsis: returns datastore usage in percentage
  319. //
  320. // Arguments:
  321. //
  322. // Returns: error code
  323. //
  324. // History: 27-Apr-2000 brijeshk Created
  325. //
  326. //----------------------------------------------------------------------------
  327. DWORD CDataStore::GetUsagePercent(int * pnPercent)
  328. {
  329. TENTER("CDataStore::GetUsagePercent");
  330. DWORD dwErr = ERROR_SUCCESS;
  331. INT64 llAdjustedSize;
  332. if (_llDataStoreUsageBytes == -1) // not initialized yet
  333. {
  334. dwErr = CalculateDataStoreUsage (NULL);
  335. if (dwErr != ERROR_SUCCESS)
  336. goto done;
  337. }
  338. if (_llDiskFreeBytes + _llDataStoreUsageBytes + _llCurrentRpUsageBytes < _llDataStoreSizeBytes)
  339. {
  340. llAdjustedSize = _llDiskFreeBytes + _llDataStoreUsageBytes + _llCurrentRpUsageBytes;
  341. }
  342. else
  343. {
  344. llAdjustedSize = _llDataStoreSizeBytes;
  345. }
  346. if (llAdjustedSize)
  347. {
  348. *pnPercent = (int) ((_llDataStoreUsageBytes + _llCurrentRpUsageBytes) * 100/ llAdjustedSize);
  349. }
  350. else
  351. {
  352. *pnPercent = 0;
  353. }
  354. TRACE(0, "Datastore %S: Usage=%I64d, Size=%I64d, AdjustedSize=%I64d, Percentage=%d",
  355. _pwszDrive,
  356. _llDataStoreUsageBytes + _llCurrentRpUsageBytes,
  357. _llDataStoreSizeBytes,
  358. llAdjustedSize,
  359. *pnPercent);
  360. done:
  361. TLEAVE();
  362. return dwErr;
  363. }
  364. DWORD CompressDir_Recurse (WCHAR *pwszPath,
  365. INT64 *pllDiff,
  366. INT64 llAllocatedTime,
  367. ULARGE_INTEGER ulft1,
  368. ULARGE_INTEGER& ulft2)
  369. {
  370. TENTER ("CompressDir_Recurse");
  371. DWORD dwErr = ERROR_SUCCESS;
  372. WIN32_FIND_DATAW wfd;
  373. WCHAR wcsPath [MAX_PATH];
  374. WCHAR wcsSrch [MAX_PATH];
  375. lstrcpy(wcsSrch, pwszPath);
  376. lstrcat(wcsSrch, L"\\*.*");
  377. HANDLE hFind = FindFirstFile (wcsSrch, &wfd);
  378. if (hFind != INVALID_HANDLE_VALUE)
  379. {
  380. do
  381. {
  382. BOOL fDir = wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
  383. if (!lstrcmp(wfd.cFileName, L".") ||
  384. !lstrcmp(wfd.cFileName, L"..") ||
  385. (wfd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ||
  386. (wfd.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
  387. {
  388. continue;
  389. }
  390. lstrcpyW (wcsPath, pwszPath);
  391. lstrcatW (wcsPath, L"\\");
  392. lstrcatW (wcsPath, wfd.cFileName);
  393. if (fDir)
  394. {
  395. dwErr = CompressDir_Recurse (wcsPath, pllDiff, llAllocatedTime, ulft1, ulft2);
  396. if (dwErr != ERROR_SUCCESS)
  397. break;
  398. }
  399. dwErr = CompressFile (wcsPath, TRUE, fDir);
  400. if (ERROR_SUCCESS != dwErr)
  401. break;
  402. if (!fDir)
  403. {
  404. LARGE_INTEGER ulBefore;
  405. ULARGE_INTEGER ulAfter;
  406. ulBefore.HighPart = wfd.nFileSizeHigh;
  407. ulBefore.LowPart = wfd.nFileSizeLow;
  408. ulAfter.LowPart = GetCompressedFileSize (wcsPath,
  409. &ulAfter.HighPart);
  410. if (ulAfter.LowPart == 0xFFFFFFFF)
  411. {
  412. dwErr = GetLastError();
  413. TRACE(0, "! GetCompressedFileSize : %ld", dwErr);
  414. break;
  415. }
  416. *pllDiff += ulAfter.QuadPart - ulBefore.QuadPart;
  417. }
  418. FILETIME ft2;
  419. GetSystemTimeAsFileTime (&ft2);
  420. ulft2.LowPart = ft2.dwLowDateTime;
  421. ulft2.HighPart = ft2.dwHighDateTime;
  422. // check to see if we need to exit
  423. if (llAllocatedTime < ulft2.QuadPart - ulft1.QuadPart)
  424. {
  425. TRACE(0, "Timed out - aborting compression");
  426. dwErr = ERROR_OPERATION_ABORTED;
  427. break;
  428. }
  429. ASSERT(g_pSRConfig);
  430. if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
  431. {
  432. TRACE(0, "Stop signalled - aborting compression");
  433. dwErr = ERROR_OPERATION_ABORTED;
  434. break;
  435. }
  436. }
  437. while (FindNextFile (hFind, &wfd));
  438. FindClose (hFind);
  439. }
  440. TLEAVE();
  441. return dwErr;
  442. }
  443. //+---------------------------------------------------------------------------
  444. //
  445. // Function: CDataStore::Compress
  446. //
  447. // Synopsis: compress a file in this datastore
  448. //
  449. // Arguments:
  450. //
  451. // Returns: Win32 error code
  452. //
  453. // History: 12-Apr-2000 HenryLee Created
  454. //
  455. //----------------------------------------------------------------------------
  456. DWORD CDataStore::Compress (INT64 llAllocatedTime, INT64 *pllUsed)
  457. {
  458. TENTER ("CDataStore::Compress");
  459. if (g_pSRConfig != NULL &&
  460. TRUE == g_pSRConfig->GetSafeMode()) // do not compress in SafeMode
  461. {
  462. return ERROR_BAD_ENVIRONMENT;
  463. }
  464. if (_dwFlags & SR_DRIVE_READONLY) // cannot compress read-only volumes
  465. return ERROR_SUCCESS;
  466. ULARGE_INTEGER ulft1, ulft2;
  467. FILETIME ft1, ft2;
  468. DWORD dwErr = ERROR_SUCCESS;
  469. WCHAR wcsPath[MAX_PATH];
  470. GetSystemTimeAsFileTime (&ft1);
  471. ulft1.LowPart = ft1.dwLowDateTime;
  472. ulft1.HighPart = ft1.dwHighDateTime;
  473. ulft2.LowPart = ft1.dwLowDateTime;
  474. ulft2.HighPart = ft1.dwHighDateTime;
  475. if (_prp == NULL)
  476. {
  477. _prp = new CRestorePoint;
  478. if (_prp == NULL)
  479. return ERROR_NOT_ENOUGH_MEMORY;
  480. _prpe = new CRestorePointEnum (_pwszDrive, TRUE, TRUE);
  481. if (_prpe == NULL)
  482. {
  483. delete _prp;
  484. _prp = NULL;
  485. return ERROR_NOT_ENOUGH_MEMORY;
  486. }
  487. dwErr = _prpe->FindFirstRestorePoint( * _prp );
  488. if (dwErr != ERROR_SUCCESS)
  489. {
  490. dwErr = ERROR_SUCCESS; // no restore points to compress
  491. goto Err;
  492. }
  493. }
  494. if (g_pSRConfig->m_dwTestBroadcast)
  495. PostTestMessage(g_pSRConfig->m_uiTMCompressStart, (WPARAM) _pwszDrive[0], NULL);
  496. do
  497. {
  498. MakeRestorePath(wcsPath, _pwszDrive, _prp->GetDir());
  499. //
  500. // patch the snapshot directory on system drive
  501. //
  502. // BUGBUG - add a time restriction to this
  503. // and factor this into the compression time allocated
  504. if (_dwFlags & SR_DRIVE_SYSTEM)
  505. {
  506. WCHAR wcsSnapshot[MAX_PATH];
  507. lstrcpy(wcsSnapshot, wcsPath);
  508. lstrcat(wcsSnapshot, L"\\snapshot");
  509. dwErr = PatchComputePatch(wcsSnapshot);
  510. if (dwErr != ERROR_SUCCESS)
  511. {
  512. trace(0, "! PatchComputePatch : %ld", dwErr);
  513. goto Err;
  514. }
  515. }
  516. if (_dwFlags & SR_DRIVE_NTFS) // use NTFS compression
  517. {
  518. INT64 llDiff = 0;
  519. dwErr = CompressDir_Recurse (wcsPath, &llDiff, llAllocatedTime, ulft1, ulft2);
  520. if (llDiff != 0)
  521. {
  522. INT64 llSize = 0;
  523. if (ERROR_SUCCESS == _prp->ReadSize (_pwszDrive, &llSize ))
  524. _prp->WriteSize (_pwszDrive, llSize + llDiff);
  525. if (_llDataStoreUsageBytes != -1) // counter initialized
  526. _llDataStoreUsageBytes += llDiff;
  527. }
  528. // check to see if we need to exit
  529. if (ERROR_SUCCESS != dwErr && ERROR_OPERATION_ABORTED != dwErr)
  530. break;
  531. }
  532. }
  533. while (dwErr != ERROR_OPERATION_ABORTED && ERROR_SUCCESS == _prpe->FindNextRestorePoint ( * _prp ));
  534. *pllUsed = ulft2.QuadPart - ulft1.QuadPart;
  535. trace(0, "Compression on drive %S used up %I64d", _pwszDrive, *pllUsed);
  536. if (g_pSRConfig->m_dwTestBroadcast)
  537. PostTestMessage(g_pSRConfig->m_uiTMCompressStop, (WPARAM) _pwszDrive[0], NULL);
  538. Err:
  539. if (ERROR_SUCCESS == dwErr) // if we finished everything
  540. {
  541. delete _prpe;
  542. _prpe = NULL;
  543. delete _prp;
  544. _prp = NULL;
  545. }
  546. TLEAVE();
  547. return dwErr;
  548. }
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Function: CDataStore::UpdateDataStoreUsage
  552. //
  553. // Synopsis: incremental update of usage byte count
  554. //
  555. // Arguments: [llDelta] -- add this amount to the total
  556. // [fCurrent] -- update current restore point's size
  557. //
  558. // Returns: Win32 error code
  559. //
  560. // History: 12-Apr-2000 HenryLee Created
  561. //
  562. //----------------------------------------------------------------------------
  563. DWORD CDataStore::UpdateDataStoreUsage(INT64 llDelta, BOOL fCurrent)
  564. {
  565. TENTER ("CDataStore::UpdateDataStoreUsage");
  566. DWORD dwErr = ERROR_SUCCESS;
  567. if (_llDataStoreUsageBytes != -1) // counter is initialized
  568. {
  569. if (fCurrent)
  570. {
  571. CRestorePoint rpCur;
  572. _llCurrentRpUsageBytes += llDelta;
  573. if (_llCurrentRpUsageBytes < 0)
  574. _llCurrentRpUsageBytes = 0;
  575. CHECKERR(GetCurrentRestorePoint(rpCur),
  576. "GetCurrentRestorePoint");
  577. CHECKERR(rpCur.WriteSize(_pwszDrive, _llCurrentRpUsageBytes),
  578. "WriteSize");
  579. }
  580. else
  581. {
  582. _llDataStoreUsageBytes += llDelta;
  583. if (_llDataStoreUsageBytes < 0)
  584. _llDataStoreUsageBytes = 0;
  585. }
  586. }
  587. Err:
  588. TLEAVE();
  589. return dwErr;
  590. }
  591. //+---------------------------------------------------------------------------
  592. //
  593. // Function: CDataStore::CalculateRpUsage
  594. //
  595. // Synopsis: get disk space used by restore point on this volume
  596. //
  597. // Arguments: prp - pointer to restore point object
  598. // pllTemp - pointer to variable that stores calculated size
  599. // fForce - ignore existing restorepointsize file
  600. // fSnapshotOnly - calculate size of snapshot only
  601. //
  602. // Returns: Win32 error code
  603. //
  604. // History: 12-Apr-2000 HenryLee Created
  605. //
  606. //----------------------------------------------------------------------------
  607. DWORD CDataStore::CalculateRpUsage(
  608. CRestorePoint *prp,
  609. INT64* pllTemp,
  610. BOOL fForce,
  611. BOOL fSnapshotOnly)
  612. {
  613. TENTER("CDataStore::CalculateRpUsage");
  614. WCHAR wcsPath[MAX_PATH];
  615. DWORD dwErr = ERROR_SUCCESS;
  616. if (! fForce)
  617. {
  618. dwErr = prp->ReadSize(_pwszDrive, pllTemp);
  619. }
  620. if (fForce || dwErr != ERROR_SUCCESS)
  621. {
  622. //
  623. // recalculate size
  624. // when a new restore point is created, only calculate
  625. // the snapshot size
  626. // filter will notify us at 25mb intervals
  627. // and we will accurately calculate the size when the restore
  628. // point is closed
  629. //
  630. MakeRestorePath(wcsPath, _pwszDrive, prp->GetDir());
  631. if (fSnapshotOnly)
  632. {
  633. lstrcat(wcsPath, L"\\snapshot");
  634. }
  635. *pllTemp = 0;
  636. dwErr = GetFileSize_Recurse (wcsPath, pllTemp,
  637. g_pDataStoreMgr->GetStopFlag());
  638. if (dwErr == ERROR_PATH_NOT_FOUND)
  639. {
  640. dwErr = ERROR_SUCCESS;
  641. }
  642. else
  643. {
  644. dwErr = prp->WriteSize(_pwszDrive, *pllTemp);
  645. }
  646. }
  647. return dwErr;
  648. }
  649. //+---------------------------------------------------------------------------
  650. //
  651. // Function: CDataStore::CalculateDataStoreUsage
  652. //
  653. // Synopsis: get disk space used by data store and volume
  654. //
  655. // Arguments:
  656. //
  657. // Returns: Win32 error code
  658. //
  659. // History: 12-Apr-2000 HenryLee Created
  660. //
  661. //----------------------------------------------------------------------------
  662. DWORD CDataStore::CalculateDataStoreUsage(LONG_PTR lReserved)
  663. {
  664. TENTER ("CDataStore::CalculateDataStoreUsage");
  665. DWORD dwErr = ERROR_SUCCESS;
  666. CRestorePointEnum rpe (_pwszDrive, TRUE, TRUE); // enum forward, skipping current
  667. CRestorePoint rp;
  668. _llDataStoreUsageBytes = 0;
  669. dwErr = rpe.FindFirstRestorePoint(rp);
  670. while (ERROR_SUCCESS == dwErr || dwErr == ERROR_FILE_NOT_FOUND)
  671. {
  672. INT64 llTemp = 0;
  673. CHECKERR(
  674. CalculateRpUsage(
  675. &rp,
  676. &llTemp,
  677. FALSE, // don't force
  678. FALSE), // everything
  679. "CalculateRpUsage");
  680. _llDataStoreUsageBytes += llTemp;
  681. dwErr = rpe.FindNextRestorePoint (rp);
  682. }
  683. rpe.FindClose ();
  684. if (dwErr == ERROR_NO_MORE_ITEMS)
  685. dwErr = ERROR_SUCCESS;
  686. //
  687. // get the size of the current restore point
  688. //
  689. CHECKERR(GetCurrentRestorePoint(rp),
  690. "GetCurrentRestorePoint");
  691. CHECKERR(CalculateRpUsage(&rp,
  692. &_llCurrentRpUsageBytes,
  693. FALSE,
  694. FALSE),
  695. "CalculateRpUsage");
  696. Err:
  697. TLEAVE();
  698. return dwErr;
  699. }
  700. //+---------------------------------------------------------------------------
  701. //
  702. // Function: CDataStore::CreateDataStore
  703. //
  704. // Synopsis: create the _restore directory and pertinent files
  705. //
  706. // Arguments:
  707. //
  708. // Returns: Win32 error code
  709. //
  710. // History: 12-Apr-2000 HenryLee Created
  711. //
  712. //----------------------------------------------------------------------------
  713. DWORD CDataStore::CreateDataStore (LONG_PTR lReserved)
  714. {
  715. TENTER("CDataStore::CreateDataStore");
  716. ULARGE_INTEGER ulTotalFreeBytes;
  717. SECURITY_ATTRIBUTES *psa = NULL;
  718. SECURITY_ATTRIBUTES *psa2 = NULL;
  719. DWORD dwErr = ERROR_SUCCESS;
  720. DWORD dwAttrs = 0;
  721. WCHAR wcsPath[MAX_PATH];
  722. SECURITY_ATTRIBUTES sa;
  723. SECURITY_ATTRIBUTES sa2;
  724. SECURITY_DESCRIPTOR sd;
  725. SECURITY_DESCRIPTOR sd2;
  726. SID *pSid = NULL;
  727. if (_dwFlags & SR_DRIVE_NTFS)
  728. {
  729. struct
  730. {
  731. ACL acl; // the ACL header
  732. BYTE rgb[ 128 - sizeof(ACL) ]; // buffer to hold 2 ACEs
  733. } DaclBuffer;
  734. struct
  735. {
  736. ACL acl; // the ACL header
  737. BYTE rgb[ 128 - sizeof(ACL) ]; // buffer to hold 2 ACEs
  738. } DaclBuffer2;
  739. SID_IDENTIFIER_AUTHORITY SaNT = SECURITY_NT_AUTHORITY;
  740. SID_IDENTIFIER_AUTHORITY SaWorld = SECURITY_WORLD_SID_AUTHORITY;
  741. if (!InitializeAcl(&DaclBuffer.acl, sizeof(DaclBuffer), ACL_REVISION))
  742. {
  743. dwErr = GetLastError();
  744. goto Err;
  745. }
  746. // Create the SID. We'll give the local system full access
  747. if( !AllocateAndInitializeSid( &SaNT, // Top-level authority
  748. 1, SECURITY_LOCAL_SYSTEM_RID,
  749. 0, 0, 0, 0, 0, 0, 0,
  750. (void **) &pSid ))
  751. {
  752. dwErr = GetLastError();
  753. TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
  754. goto Err;
  755. }
  756. if (!AddAccessAllowedAce( &DaclBuffer.acl,
  757. ACL_REVISION,
  758. STANDARD_RIGHTS_ALL | GENERIC_ALL,
  759. pSid ))
  760. {
  761. dwErr = GetLastError();
  762. TRACE(0, "! AddAccessAllowedAce : %ld", dwErr);
  763. goto Err;
  764. }
  765. if (!InitializeAcl(&DaclBuffer2.acl, sizeof(DaclBuffer2), ACL_REVISION))
  766. {
  767. dwErr = GetLastError();
  768. goto Err;
  769. }
  770. FreeSid (pSid);
  771. if( !AllocateAndInitializeSid( &SaWorld, // Top-level authority
  772. 1, SECURITY_WORLD_RID,
  773. 0, 0, 0, 0, 0, 0, 0,
  774. (void **) &pSid ))
  775. {
  776. dwErr = GetLastError();
  777. TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
  778. goto Err;
  779. }
  780. if (!AddAccessAllowedAceEx ( &DaclBuffer2.acl,
  781. ACL_REVISION,
  782. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
  783. STANDARD_RIGHTS_ALL | GENERIC_ALL,
  784. pSid ))
  785. {
  786. dwErr = GetLastError();
  787. TRACE(0, "! AddAccessAllowedAce : %ld", dwErr);
  788. goto Err;
  789. }
  790. // Set up the security descriptor with that DACL in it.
  791. if (!InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ))
  792. {
  793. dwErr = GetLastError();
  794. TRACE(0, "! InitializeSecurityDescriptor : %ld", dwErr);
  795. goto Err;
  796. }
  797. if( !SetSecurityDescriptorDacl( &sd, TRUE, &DaclBuffer.acl, FALSE ))
  798. {
  799. dwErr = GetLastError();
  800. TRACE(0, "! SetSecurityDescriptorDacl : %ld", dwErr);
  801. goto Err;
  802. }
  803. if (!InitializeSecurityDescriptor( &sd2, SECURITY_DESCRIPTOR_REVISION ))
  804. {
  805. dwErr = GetLastError();
  806. TRACE(0, "! InitializeSecurityDescriptor : %ld", dwErr);
  807. goto Err;
  808. }
  809. if( !SetSecurityDescriptorDacl( &sd2, TRUE, &DaclBuffer2.acl, FALSE ))
  810. {
  811. dwErr = GetLastError();
  812. TRACE(0, "! SetSecurityDescriptorDacl : %ld", dwErr);
  813. goto Err;
  814. }
  815. if( !SetSecurityDescriptorControl( &sd2,
  816. SE_DACL_PROTECTED,
  817. SE_DACL_PROTECTED ))
  818. {
  819. dwErr = GetLastError();
  820. TRACE(0, "! SetSecurityDescriptorControl : %ld", dwErr);
  821. goto Err;
  822. }
  823. // Put the security descriptor into the security attributes.
  824. ZeroMemory (&sa, sizeof(sa));
  825. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  826. sa.lpSecurityDescriptor = &sd;
  827. sa.bInheritHandle = TRUE;
  828. psa = &sa;
  829. ZeroMemory (&sa2, sizeof(sa2));
  830. sa2.nLength = sizeof(SECURITY_ATTRIBUTES);
  831. sa2.lpSecurityDescriptor = &sd2;
  832. sa2.bInheritHandle = TRUE;
  833. psa2 = &sa2;
  834. }
  835. // create "System Volume Information" if it does not exist
  836. // set "system only" dacl on this directory
  837. // make this S+H+non-CI
  838. wsprintf(wcsPath, L"%s%s", _pwszDrive, s_cszSysVolInfo);
  839. if (-1 == GetFileAttributes(wcsPath))
  840. {
  841. if (FALSE == CreateDirectoryW(wcsPath, psa))
  842. {
  843. dwErr = GetLastError();
  844. TRACE(0, "! CreateDirectoryW for %s : %ld", wcsPath, dwErr);
  845. goto Err;
  846. }
  847. if (FALSE == SetFileAttributesW (wcsPath,
  848. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
  849. FILE_ATTRIBUTE_HIDDEN |
  850. FILE_ATTRIBUTE_SYSTEM))
  851. {
  852. dwErr = GetLastError();
  853. TRACE(0, "! SetFileAttributes for %s : %ld", wcsPath, dwErr);
  854. goto Err;
  855. }
  856. }
  857. // now create our _Restore directory
  858. // don't put any dacl on it
  859. MakeRestorePath (wcsPath, _pwszDrive, L"");
  860. dwAttrs = GetFileAttributes(wcsPath);
  861. if (-1 != dwAttrs && !(FILE_ATTRIBUTE_DIRECTORY & dwAttrs))
  862. {
  863. DeleteFileW (wcsPath); // try deleting the file
  864. }
  865. if (FALSE == CreateDirectoryW (wcsPath, psa2))
  866. {
  867. dwErr = GetLastError();
  868. if (ERROR_ALREADY_EXISTS == dwErr)
  869. {
  870. if (psa2 != NULL && FALSE == SetFileSecurity (wcsPath,
  871. DACL_SECURITY_INFORMATION,
  872. &sd2))
  873. {
  874. dwErr = GetLastError();
  875. TRACE(0, "! SetFileSecurity for %s : %ld", wcsPath, dwErr);
  876. }
  877. else
  878. dwErr = ERROR_SUCCESS;
  879. }
  880. if (dwErr != ERROR_SUCCESS)
  881. {
  882. TRACE(0, "! CreateDataStore CreateDirectoryW : %ld", dwErr);
  883. goto Err;
  884. }
  885. }
  886. //
  887. // let's keep the datastore uncompressed
  888. // so that filter can make quicker unbuffered copies
  889. //
  890. #if 0
  891. // If the datastore is marked uncompressed, mark it compressed
  892. //
  893. if (_dwFlags & SR_DRIVE_NTFS)
  894. {
  895. dwAttrs = GetFileAttributesW (wcsPath);
  896. if (dwAttrs != INVALID_FILE_SIZE &&
  897. 0 == (FILE_ATTRIBUTE_COMPRESSED & dwAttrs))
  898. {
  899. dwErr = CompressFile ( wcsPath, TRUE, TRUE );
  900. if (dwErr != ERROR_SUCCESS)
  901. {
  902. TRACE(0, "! CreateDataStore CompressFile : %ld", dwErr);
  903. goto Err;
  904. }
  905. }
  906. }
  907. #endif
  908. if (FALSE == SetFileAttributesW (wcsPath,
  909. FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
  910. FILE_ATTRIBUTE_HIDDEN |
  911. FILE_ATTRIBUTE_SYSTEM))
  912. {
  913. dwErr = GetLastError();
  914. TRACE(0, "! CreateDataStore SetFileAttributesW : %ld", dwErr);
  915. }
  916. Err:
  917. if (pSid != NULL)
  918. FreeSid (pSid);
  919. TLEAVE();
  920. return dwErr;
  921. }
  922. //+---------------------------------------------------------------------------
  923. //
  924. // Function: CDataStore::DestroyDataStore
  925. //
  926. // Synopsis: remove the _restore directory and pertinent files
  927. //
  928. // Arguments: [fDeleteDir] -- TRUE if deleting parent directory
  929. //
  930. // Returns: Win32 error code
  931. //
  932. // History: 12-Apr-2000 HenryLee Created
  933. //
  934. //----------------------------------------------------------------------------
  935. DWORD CDataStore::DestroyDataStore (LONG_PTR fDeleteDir)
  936. {
  937. TENTER("CDataStore::DestroyDataStore");
  938. DWORD dwErr = ERROR_SUCCESS;
  939. WCHAR wcsPath[MAX_PATH];
  940. MakeRestorePath (wcsPath, _pwszDrive, L"");
  941. // delete the restore directory
  942. dwErr = Delnode_Recurse (wcsPath, (BOOL) fDeleteDir,
  943. g_pDataStoreMgr->GetStopFlag());
  944. if (_dwFlags & SR_DRIVE_SYSTEM)
  945. {
  946. g_pDataStoreMgr->DeleteMachineGuidFile();
  947. }
  948. if (ERROR_SUCCESS == dwErr)
  949. {
  950. _llDataStoreUsageBytes = 0;
  951. _llCurrentRpUsageBytes = 0;
  952. }
  953. TLEAVE();
  954. return dwErr;
  955. }
  956. //+---------------------------------------------------------------------------
  957. //
  958. // Function: CDataStore::MonitorDrive
  959. //
  960. // Synopsis: tell the filter to start/stop monitoring this drive
  961. //
  962. // Arguments: [fStart] -- TRUE start monitoring, FALSE stop monitoring
  963. //
  964. // Returns: Win32 error code
  965. //
  966. // History: 12-Apr-2000 HenryLee Created
  967. //
  968. //----------------------------------------------------------------------------
  969. DWORD CDataStore::MonitorDrive (LONG_PTR fSet)
  970. {
  971. DWORD dwRc = ERROR_SUCCESS;
  972. HANDLE hEventSource = NULL;
  973. TENTER("CDataStore::MonitorDrive");
  974. if (!fSet)
  975. {
  976. // if the drive is already disabled, then no op
  977. if (! (_dwFlags & SR_DRIVE_MONITORED))
  978. goto done;
  979. dwRc = SrDisableVolume(g_pSRConfig->GetFilter(), GetNTName());
  980. if (dwRc != ERROR_SUCCESS)
  981. goto done;
  982. _dwFlags &= ~SR_DRIVE_MONITORED;
  983. // reset any per-rp flags as well
  984. ResetFlags(NULL);
  985. dwRc = DestroyDataStore(TRUE);
  986. }
  987. else
  988. {
  989. // if the drive is already enabled, then no op
  990. if (_dwFlags & SR_DRIVE_MONITORED)
  991. {
  992. dwRc = ERROR_SERVICE_ALREADY_RUNNING;
  993. goto done;
  994. }
  995. _dwFlags |= SR_DRIVE_MONITORED;
  996. // reset any per-rp flags as well
  997. ResetFlags(NULL);
  998. }
  999. DirtyDriveTable();
  1000. trace(0, "****%S drive %S****", fSet ? L"Enabled" : L"Disabled", _pwszDrive);
  1001. hEventSource = RegisterEventSource(NULL, s_cszServiceName);
  1002. if (hEventSource != NULL)
  1003. {
  1004. SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, fSet ? EVMSG_DRIVE_ENABLED : EVMSG_DRIVE_DISABLED,
  1005. NULL, 0, _pwszDrive, NULL, NULL);
  1006. DeregisterEventSource(hEventSource);
  1007. }
  1008. if (g_pSRConfig->m_dwTestBroadcast)
  1009. PostTestMessage( fSet ? g_pSRConfig->m_uiTMEnable : g_pSRConfig->m_uiTMDisable,
  1010. (WPARAM) _pwszDrive[0],
  1011. NULL);
  1012. done:
  1013. TLEAVE();
  1014. return dwRc;
  1015. }
  1016. //+---------------------------------------------------------------------------
  1017. //
  1018. // Function: CDataStore::FreezeDrive
  1019. //
  1020. // Synopsis: tell the filter to freeze this drive
  1021. //
  1022. // Arguments:
  1023. //
  1024. // Returns: Win32 error code
  1025. //
  1026. // History: 04-Jun-2000 brijeshk Created
  1027. //
  1028. //----------------------------------------------------------------------------
  1029. DWORD CDataStore::FreezeDrive (LONG_PTR lReserved)
  1030. {
  1031. DWORD dwErr = ERROR_SUCCESS;
  1032. TENTER("CDataStore::FreezeDrive");
  1033. _dwFlags |= SR_DRIVE_FROZEN; // freeze in spite of open file handles
  1034. // if the drive is disabled, no op
  1035. if (! (_dwFlags & SR_DRIVE_MONITORED))
  1036. goto Err;
  1037. //
  1038. // check if the drive exists before calling the driver
  1039. //
  1040. if (0xFFFFFFFF == GetFileAttributes(_pwszGuid))
  1041. {
  1042. trace(0, "Drive %s does not exist", _pwszDrive);
  1043. goto Err;
  1044. }
  1045. CHECKERR(SrDisableVolume(g_pSRConfig->GetFilter(), GetNTName()),
  1046. "SrDisableVolume");
  1047. DestroyDataStore(FALSE);
  1048. DirtyDriveTable();
  1049. trace(0, "****Froze drive %S****", _pwszDrive);
  1050. Err:
  1051. TLEAVE();
  1052. return dwErr;
  1053. }
  1054. //+---------------------------------------------------------------------------
  1055. //
  1056. // Function: CDataStore::ThawDrive
  1057. //
  1058. // Synopsis: check and thaw this drive
  1059. //
  1060. // Arguments:
  1061. //
  1062. // Returns: Win32 error code
  1063. //
  1064. // History: 04-Jun-2000 brijeshk Created
  1065. //
  1066. //----------------------------------------------------------------------------
  1067. DWORD CDataStore::ThawDrive(LONG_PTR fCheckOnly)
  1068. {
  1069. DWORD dwRc = ERROR_SUCCESS;
  1070. TENTER("CDataStore::ThawDrive");
  1071. if (_dwFlags & SR_DRIVE_FROZEN)
  1072. {
  1073. //Actually we want to clean up everything except for the
  1074. //current restore point
  1075. //dwRc = DestroyDataStore(FALSE);
  1076. if (ERROR_SUCCESS == dwRc)
  1077. {
  1078. _dwFlags &= ~SR_DRIVE_FROZEN;
  1079. DirtyDriveTable();
  1080. trace(0, "****Thawed drive %S****", _pwszDrive);
  1081. }
  1082. else trace(0, "Cannot thaw %S error %d", _pwszDrive, dwRc);
  1083. }
  1084. TLEAVE();
  1085. return dwRc;
  1086. }
  1087. //+---------------------------------------------------------------------------
  1088. //
  1089. // Functiion CDataStore::FifoRestorePoint
  1090. //
  1091. // Synopsis: fifo one restore point in this datastore
  1092. //
  1093. // Arguments:
  1094. //
  1095. // Returns: Win32 error code
  1096. //
  1097. // History: 12-Apr-2000 BrijeshK Created
  1098. //
  1099. //----------------------------------------------------------------------------
  1100. DWORD
  1101. CDataStore::FifoRestorePoint(
  1102. CRestorePoint& rp)
  1103. {
  1104. TENTER("CDataStore::FifoRestorePoint");
  1105. WCHAR szRpPath[MAX_PATH], szFifoedPath[MAX_PATH];
  1106. INT64 llSize = 0;
  1107. DWORD dwRc;
  1108. //
  1109. // if patching is on, and this is a reference directory
  1110. // for later snapshots, then don't fifo the snapshot folder
  1111. // rename it to RefRPx, and keep it around
  1112. // BUGBUG - how do we update size correctly ?
  1113. //
  1114. if (PatchGetPatchWindow() != 0)
  1115. {
  1116. // if Reference(RPx) == x, then x is a reference rp
  1117. if (PatchGetReferenceRpNum(rp.GetNum()) == rp.GetNum())
  1118. {
  1119. WCHAR szRp[MAX_RP_PATH + sizeof(s_cszReferenceDir)/sizeof(WCHAR)];
  1120. MakeRestorePath(szRpPath, _pwszDrive, rp.GetDir());
  1121. lstrcat(szRpPath, SNAPSHOT_DIR_NAME);
  1122. wsprintf(szRp, L"%s%ld", s_cszReferenceDir, rp.GetNum());
  1123. MakeRestorePath(szFifoedPath, _pwszDrive, szRp);
  1124. CreateDirectory(szFifoedPath, NULL);
  1125. lstrcat(szFifoedPath, SNAPSHOT_DIR_NAME);
  1126. MoveFile(szRpPath, szFifoedPath);
  1127. }
  1128. }
  1129. // read the size of this restore point
  1130. // but don't update the datastore size yet
  1131. dwRc = rp.ReadSize(_pwszDrive, &llSize);
  1132. // move the rp dir to a temp dir "Fifoed"
  1133. // this is to make the fifo of a single rp atomic
  1134. // to take care of unclean shutdowns
  1135. MakeRestorePath(szRpPath, _pwszDrive, rp.GetDir());
  1136. MakeRestorePath(szFifoedPath, _pwszDrive, s_cszFifoedRpDir);
  1137. if (! MoveFile(szRpPath, szFifoedPath))
  1138. {
  1139. dwRc = GetLastError();
  1140. TRACE(0, "! MoveFile from %S to %S : %ld", szRpPath, szFifoedPath, dwRc);
  1141. goto done;
  1142. }
  1143. // now examine the result of rp.ReadSize
  1144. // and update the datastore usage variable
  1145. if (ERROR_SUCCESS == dwRc)
  1146. {
  1147. UpdateDataStoreUsage (-llSize, FALSE);
  1148. }
  1149. else
  1150. {
  1151. // ignore this error and continue
  1152. TRACE(0, "! rp.ReadSize : %ld", dwRc);
  1153. }
  1154. // blow away the temp fifoed directory again
  1155. dwRc = Delnode_Recurse(szFifoedPath, TRUE,
  1156. g_pDataStoreMgr->GetStopFlag());
  1157. if (ERROR_SUCCESS != dwRc)
  1158. {
  1159. TRACE(0, "! Delnode_Recurse : %ld", dwRc);
  1160. goto done;
  1161. }
  1162. done:
  1163. TLEAVE();
  1164. return dwRc;
  1165. }
  1166. DWORD
  1167. CDataStore::Print(LONG_PTR lptr)
  1168. {
  1169. TENTER("CDataStore::Print");
  1170. DWORD dwErr = ERROR_SUCCESS;
  1171. DWORD cbWritten;
  1172. HANDLE h = (HANDLE) lptr;
  1173. WCHAR w[1024];
  1174. wsprintf(w, L"Drive: %s, Guid: %s\r\n", _pwszDrive, _pwszGuid);
  1175. WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
  1176. trace(0, "Drive: %S, Guid: %S", _pwszDrive, _pwszGuid);
  1177. wsprintf(w, L"\t%s %s %s %s %s %s %s %s\r\n",
  1178. _dwFlags & SR_DRIVE_ACTIVE ? L"Active, " : L"",
  1179. _dwFlags & SR_DRIVE_COMPRESSED ? L"Compressed, " : L"",
  1180. _dwFlags & SR_DRIVE_MONITORED ? L"Monitored, " : L"",
  1181. _dwFlags & SR_DRIVE_NTFS ? L"NTFS, " : L"",
  1182. _dwFlags & SR_DRIVE_PARTICIPATE ? L"Participate, " : L"",
  1183. _dwFlags & SR_DRIVE_FROZEN ? L"Frozen, " : L"",
  1184. _dwFlags & SR_DRIVE_READONLY ? L"ReadOnly, " : L"",
  1185. _dwFlags & SR_DRIVE_ERROR ? L"Error" : L"");
  1186. WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
  1187. trace(0, "%S %S %S %S", _dwFlags & SR_DRIVE_ACTIVE ? L"Active, " : L"",
  1188. _dwFlags & SR_DRIVE_COMPRESSED ? L"Compressed, " : L"",
  1189. _dwFlags & SR_DRIVE_MONITORED ? L"Monitored, " : L"",
  1190. _dwFlags & SR_DRIVE_NTFS ? L"NTFS, " : L"");
  1191. trace(0, "%S %S %S %S", _dwFlags & SR_DRIVE_PARTICIPATE ? L"Participate, " : L"",
  1192. _dwFlags & SR_DRIVE_FROZEN ? L"Frozen, " : L"",
  1193. _dwFlags & SR_DRIVE_READONLY ? L"ReadOnly, " : L"",
  1194. _dwFlags & SR_DRIVE_ERROR ? L"Error" : L"");
  1195. wsprintf(w, L"\tSize: %I64d, Usage: %I64d, Diskfree: %I64d\r\n\r\n",
  1196. _llDataStoreSizeBytes,
  1197. _llDataStoreUsageBytes + _llCurrentRpUsageBytes,
  1198. _llDiskFreeBytes);
  1199. WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
  1200. trace(0, "Size: %I64d, Usage: %I64d, Diskfree: %I64d",
  1201. _llDataStoreSizeBytes,
  1202. _llDataStoreUsageBytes + _llCurrentRpUsageBytes,
  1203. _llDiskFreeBytes);
  1204. TLEAVE();
  1205. return dwErr;
  1206. }
  1207. //+---------------------------------------------------------------------------
  1208. //
  1209. // Functiion CDataStore::SaveDataStore
  1210. //
  1211. // Synopsis: save datastore info as a line in the drive table
  1212. //
  1213. // Arguments:
  1214. //
  1215. // Returns: Win32 error code
  1216. //
  1217. // History: 12-Apr-2000 HenryLee Created
  1218. //
  1219. //----------------------------------------------------------------------------
  1220. DWORD CDataStore::SaveDataStore (LONG_PTR hFile)
  1221. {
  1222. HANDLE h = (HANDLE) hFile;
  1223. DWORD dwErr = ERROR_SUCCESS;
  1224. WCHAR wcsBuffer[MAX_PATH * 2];
  1225. DWORD cbWritten = 0;
  1226. wsprintf (wcsBuffer, gs_wcsPrintFormat,
  1227. GetDrive(), GetGuid(), _dwFlags,
  1228. GetNumChangeLogs(), (DWORD) (GetSizeLimit() / (INT64) MEGABYTE),
  1229. GetLabel());
  1230. if (FALSE == WriteFile (h, (BYTE *) wcsBuffer,
  1231. lstrlen(wcsBuffer) * sizeof(WCHAR), &cbWritten, NULL))
  1232. {
  1233. dwErr = GetLastError();
  1234. }
  1235. return dwErr;
  1236. }
  1237. //+---------------------------------------------------------------------------
  1238. //
  1239. // Functiion CDataStore::DirtyDriveTable
  1240. //
  1241. // Synopsis: set the dirty bit in the drive table
  1242. //
  1243. // Arguments:
  1244. //
  1245. // Returns: Win32 error code
  1246. //
  1247. // History: 12-Apr-2000 HenryLee Created
  1248. //
  1249. //----------------------------------------------------------------------------
  1250. DWORD CDataStore::DirtyDriveTable ()
  1251. {
  1252. if (_pdt != NULL)
  1253. _pdt->SetDirty ();
  1254. return ERROR_SUCCESS;
  1255. }
  1256. //+---------------------------------------------------------------------------
  1257. //
  1258. // Functiion CDataStore::SwitchRestorePoint
  1259. //
  1260. // Synopsis: change the drive table when switching restore points
  1261. //
  1262. // Arguments: pointer to restore point object
  1263. //
  1264. // Returns: Win32 error code
  1265. //
  1266. // History: 14-Jun-2000 BrijeshK Created
  1267. //
  1268. //----------------------------------------------------------------------------
  1269. DWORD CDataStore::SwitchRestorePoint(LONG_PTR pRestorePoint)
  1270. {
  1271. TENTER("CDataStore::SwitchRestorePoint");
  1272. CRestorePoint *prp = (CRestorePoint *) pRestorePoint;
  1273. DWORD dwErr = ERROR_SUCCESS;
  1274. INT64 llTemp;
  1275. if (prp)
  1276. {
  1277. //
  1278. // get the last restore point size - accurate
  1279. //
  1280. if (_llDataStoreUsageBytes != -1) // initialized
  1281. {
  1282. CHECKERR(CalculateRpUsage(prp,
  1283. &_llCurrentRpUsageBytes,
  1284. TRUE, // force calculation
  1285. FALSE), // everything
  1286. "CalculateRpUsage");
  1287. _llDataStoreUsageBytes += _llCurrentRpUsageBytes;
  1288. _llCurrentRpUsageBytes = 0;
  1289. }
  1290. }
  1291. //
  1292. // get the size of the current snapshot
  1293. //
  1294. if (_dwFlags & SR_DRIVE_SYSTEM)
  1295. {
  1296. CRestorePoint rpCur;
  1297. CHECKERR(GetCurrentRestorePoint(rpCur),
  1298. "GetCurrentRestorePoint");
  1299. CHECKERR(CalculateRpUsage(&rpCur,
  1300. &_llCurrentRpUsageBytes,
  1301. TRUE,
  1302. TRUE),
  1303. "CalculateRpUsage");
  1304. }
  1305. Err:
  1306. TLEAVE();
  1307. return dwErr;
  1308. }
  1309. //+---------------------------------------------------------------------------
  1310. //
  1311. // Functiion CDataStore::CountChangeLogs
  1312. //
  1313. // Synopsis: counts the number of change logs & saves the drive table
  1314. //
  1315. // Arguments:
  1316. //
  1317. // Returns: Win32 error code
  1318. //
  1319. // History: 12-Apr-2000 HenryLee Created
  1320. //
  1321. //----------------------------------------------------------------------------
  1322. DWORD CDataStore::CountChangeLogs (LONG_PTR pRestorePoint)
  1323. {
  1324. CRestorePoint *prp = (CRestorePoint *) pRestorePoint;
  1325. CFindFile ff;
  1326. WIN32_FIND_DATA *pwfd = new WIN32_FIND_DATA;
  1327. DWORD dwErr = ERROR_SUCCESS;
  1328. int iCount = -1;
  1329. CRestorePoint *pCurRp = NULL;
  1330. if (! pwfd)
  1331. {
  1332. dwErr = ERROR_OUTOFMEMORY;
  1333. goto Err;
  1334. }
  1335. if (prp == NULL)
  1336. {
  1337. pCurRp = new CRestorePoint;
  1338. if (! pCurRp)
  1339. {
  1340. dwErr = ERROR_OUTOFMEMORY;
  1341. goto Err;
  1342. }
  1343. dwErr = GetCurrentRestorePoint (*pCurRp);
  1344. if (dwErr != ERROR_SUCCESS)
  1345. {
  1346. if (_dwFlags & SR_DRIVE_SYSTEM)
  1347. goto Err;
  1348. // This drive has no current restore point
  1349. // It could have been re-formatted or placed in read-only mode
  1350. // So assume no change logs are available
  1351. dwErr = ERROR_SUCCESS;
  1352. }
  1353. else prp = pCurRp;
  1354. }
  1355. if (prp != NULL)
  1356. {
  1357. LPWSTR pwcsPath = new WCHAR[MAX_PATH];
  1358. if (! pwcsPath)
  1359. {
  1360. dwErr = ERROR_OUTOFMEMORY;
  1361. goto Err;
  1362. }
  1363. iCount = 0;
  1364. MakeRestorePath (pwcsPath, _pwszDrive, prp->GetDir());
  1365. lstrcatW (pwcsPath, L"\\");
  1366. lstrcatW (pwcsPath, s_cszChangeLogPrefix);
  1367. if (TRUE == ff._FindFirstFile (pwcsPath, s_cszChangeLogSuffix, pwfd,
  1368. FALSE, FALSE))
  1369. do
  1370. {
  1371. iCount++;
  1372. }
  1373. while (ff._FindNextFile (pwcsPath, s_cszChangeLogSuffix, pwfd));
  1374. delete [] pwcsPath;
  1375. }
  1376. dwErr = SetNumChangeLogs (iCount);
  1377. Err:
  1378. if (pCurRp)
  1379. delete pCurRp;
  1380. if (pwfd)
  1381. delete pwfd;
  1382. return dwErr;
  1383. }
  1384. //+---------------------------------------------------------------------------
  1385. //
  1386. // Functiion CDataStore::IsVolumeDeleted
  1387. //
  1388. // Synopsis: determines if this volume is no longer accessible
  1389. //
  1390. // Arguments:
  1391. //
  1392. // Returns: TRUE if can be removed
  1393. //
  1394. // History: 12-Apr-2000 HenryLee Created
  1395. //
  1396. //----------------------------------------------------------------------------
  1397. BOOL CDataStore::IsVolumeDeleted ()
  1398. {
  1399. WCHAR wszMount[MAX_PATH];
  1400. DWORD dwChars = 0;
  1401. DWORD dwFsFlags = 0;
  1402. tenter("CDataStore::IsVolumeDeleted");
  1403. // don't open the volume, since it could be locked for chkdsk
  1404. if (FALSE == GetVolumePathNamesForVolumeNameW (_pwszGuid,
  1405. wszMount,
  1406. MAX_PATH,
  1407. &dwChars ))
  1408. {
  1409. if (GetLastError() != ERROR_MORE_DATA)
  1410. {
  1411. _dwFlags &= ~SR_DRIVE_ACTIVE;
  1412. trace(0, "! GetVolumePathNamesForVolumeNameW : %ld", GetLastError());
  1413. return TRUE;
  1414. }
  1415. }
  1416. if (L'\0' == wszMount[0]) // empty string, no mount point
  1417. {
  1418. _dwFlags &= ~SR_DRIVE_ACTIVE;
  1419. trace(0, "! Empty mountpoint");
  1420. return TRUE;
  1421. }
  1422. wszMount[MAX_PATH-1] = L'\0';
  1423. if (lstrlenW (wszMount) > MAX_MOUNTPOINT_PATH) // mountpoint too long
  1424. {
  1425. _dwFlags &= ~SR_DRIVE_ACTIVE;
  1426. trace(0, "! Mountpoint too long");
  1427. return TRUE;
  1428. }
  1429. // update the drive letter
  1430. lstrcpyW (_pwszDrive, wszMount); // copy the first string
  1431. if (GetVolumeNameForVolumeMountPoint (_pwszDrive, wszMount, MAX_PATH))
  1432. {
  1433. if (lstrcmpW (wszMount, _pwszGuid) != 0)
  1434. {
  1435. _dwFlags &= ~SR_DRIVE_ACTIVE;
  1436. trace(0, "! volume GUID changed");
  1437. return TRUE;
  1438. }
  1439. }
  1440. GetVolumeInfo (); // get the latest volume flags if possible
  1441. trace(0, "volume %S is active", wszMount);
  1442. tleave();
  1443. return FALSE; // volume is still active
  1444. }
  1445. //+---------------------------------------------------------------------------
  1446. //
  1447. // Functiion CDataStore::GetNTName
  1448. //
  1449. // Synopsis: constructs the NT object name into a static buffer
  1450. //
  1451. // Arguments: (none) caller must take the datastore lock
  1452. //
  1453. // Returns: pointer to string
  1454. //
  1455. // History: 12-Apr-2000 HenryLee Created
  1456. //
  1457. //----------------------------------------------------------------------------
  1458. WCHAR * CDataStore::GetNTName ()
  1459. {
  1460. NTSTATUS nts;
  1461. static WCHAR wcsBuffer [MAX_PATH];
  1462. wcsBuffer[0] = L'\0';
  1463. // Open a handle to the volume
  1464. HANDLE h = CreateFileW ( _pwszGuid,
  1465. GENERIC_READ,
  1466. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1467. NULL,
  1468. OPEN_EXISTING,
  1469. FILE_FLAG_BACKUP_SEMANTICS,
  1470. NULL );
  1471. if (h != INVALID_HANDLE_VALUE)
  1472. {
  1473. OBJECT_NAME_INFORMATION * poni;
  1474. poni = (OBJECT_NAME_INFORMATION *) wcsBuffer;
  1475. // Get name from NT namespace
  1476. nts = NtQueryObject (h, ObjectNameInformation, poni, MAX_PATH, NULL);
  1477. if (NT_SUCCESS(nts))
  1478. {
  1479. if (poni->Name.Length < MAX_PATH * sizeof(WCHAR))
  1480. poni->Name.Buffer [poni->Name.Length / sizeof(WCHAR) - 1] = TEXT('\0');
  1481. }
  1482. CloseHandle (h);
  1483. return poni->Name.Buffer;
  1484. }
  1485. else
  1486. {
  1487. return wcsBuffer;
  1488. }
  1489. }