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.

1208 lines
34 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. drvtable.cpp
  5. Abstract:
  6. This file contains CRstrDriveInfo class and CreateDriveList function.
  7. Revision History:
  8. Seong Kook Khang (SKKhang) 07/20/00
  9. created
  10. ******************************************************************************/
  11. #include "stdwin.h"
  12. #include "rstrcore.h"
  13. #include "resource.h"
  14. #include "..\shell\resource.h"
  15. static LPCWSTR s_cszEmpty = L"";
  16. WCHAR s_szSysDrv[MAX_PATH];
  17. /////////////////////////////////////////////////////////////////////////////
  18. //
  19. // CRstrDriveInfo class
  20. //
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. // NOTE - 7/26/00 - skkhang
  24. // CSRStr has one issue -- NULL return in case of memory failure. Even though
  25. // the behavior is just same with regular C language pointer, many codes are
  26. // blindly passing it to some external functions (e.g. strcmp) which does not
  27. // gracefully handle NULL pointer. Ideally and eventually all of code should
  28. // prevent any possible NULL pointers from getting passed to such functions,
  29. // but for now, I'm using an alternative workaround -- GetID, GetMount, and
  30. // GetLabel returns a static empty string instead of NULL pointer.
  31. //
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CRstrDriveInfo construction / destruction
  34. CRstrDriveInfo::CRstrDriveInfo()
  35. {
  36. m_dwFlags = 0;
  37. m_hIcon[0] = NULL;
  38. m_hIcon[1] = NULL;
  39. m_llDSMin = SR_DEFAULT_DSMIN * MEGABYTE;
  40. m_llDSMax = SR_DEFAULT_DSMAX * MEGABYTE;
  41. m_uDSUsage = 0;
  42. m_fCfgExcluded = FALSE;
  43. m_uCfgDSUsage = 0;
  44. m_ulTotalBytes.QuadPart = 0;
  45. }
  46. CRstrDriveInfo::~CRstrDriveInfo()
  47. {
  48. if ( m_hIcon[0] != NULL )
  49. ::DestroyIcon( m_hIcon[0] );
  50. if ( m_hIcon[1] != NULL )
  51. ::DestroyIcon( m_hIcon[1] );
  52. }
  53. BOOL CRstrDriveInfo::InitUsage (LPCWSTR cszID, INT64 llDSUsage)
  54. {
  55. TraceFunctEnter("CRstrDriveInfo::InitUsage");
  56. //
  57. // calculate max datastore size - max (12% of disk, 400mb)
  58. //
  59. // read % from registry
  60. HKEY hKey = NULL;
  61. DWORD dwPercent = SR_DEFAULT_DISK_PERCENT;
  62. DWORD dwDSMax = SR_DEFAULT_DSMAX;
  63. DWORD dwDSMin = IsSystem() ? SR_DEFAULT_DSMIN : SR_DEFAULT_DSMIN_NONSYSTEM;
  64. ULARGE_INTEGER ulDummy;
  65. DWORD dwRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  66. s_cszSRRegKey, 0, KEY_READ, &hKey);
  67. if (ERROR_SUCCESS == dwRes)
  68. {
  69. RegReadDWORD(hKey, s_cszDiskPercent, &dwPercent);
  70. RegReadDWORD(hKey, s_cszDSMax, &dwDSMax);
  71. if (IsSystem())
  72. RegReadDWORD(hKey, s_cszDSMin, &dwDSMin);
  73. RegCloseKey(hKey);
  74. }
  75. else
  76. {
  77. ErrorTrace(0, "! RegOpenKeyEx : %ld", dwRes);
  78. }
  79. // BUGBUG - this call may not always give total disk space (per-user quota)
  80. ulDummy.QuadPart = 0;
  81. if (FALSE == GetDiskFreeSpaceEx (cszID, &ulDummy, &m_ulTotalBytes, NULL))
  82. {
  83. ErrorTrace(0, "! GetDiskFreeSpaceEx : %ld", GetLastError());
  84. goto done;
  85. }
  86. m_llDSMin = min(m_ulTotalBytes.QuadPart, (INT64) dwDSMin * MEGABYTE);
  87. m_llDSMax = min(m_ulTotalBytes.QuadPart,
  88. max( (INT64) dwDSMax * MEGABYTE,
  89. (INT64) dwPercent * m_ulTotalBytes.QuadPart / 100 ));
  90. if (m_llDSMax < m_llDSMin)
  91. m_llDSMax = m_llDSMin;
  92. //
  93. // take floor of this value
  94. //
  95. m_llDSMax = ((INT64) (m_llDSMax / (INT64) MEGABYTE)) * (INT64) MEGABYTE;
  96. DebugTrace(0, "m_llDSMax: %I64d, Size: %I64d", m_llDSMax, llDSUsage);
  97. if ( ( llDSUsage == 0) || (llDSUsage > m_llDSMax) )
  98. // not initialized, assume maximum
  99. {
  100. llDSUsage = m_llDSMax;
  101. }
  102. if ( ( llDSUsage - m_llDSMin > 0) && ( m_llDSMax - m_llDSMin > 0))
  103. {
  104. // + ((llDSUsage - m_llDSMin)/2) is to ensure that correct
  105. // rounding off happens here
  106. m_uDSUsage =( ((llDSUsage - m_llDSMin) * DSUSAGE_SLIDER_FREQ)
  107. + ((m_llDSMax - m_llDSMin)/2))/( m_llDSMax - m_llDSMin);
  108. }
  109. else
  110. m_uDSUsage = 0;
  111. m_uCfgDSUsage = m_uDSUsage;
  112. done:
  113. TraceFunctLeave();
  114. return TRUE;
  115. }
  116. /////////////////////////////////////////////////////////////////////////////
  117. // CRstrDriveInfo operations
  118. BOOL
  119. CRstrDriveInfo::Init( LPCWSTR cszID, DWORD dwFlags, INT64 llDSUsage, LPCWSTR cszMount, LPCWSTR cszLabel )
  120. {
  121. TraceFunctEnter("CRstrDriveInfo::Init");
  122. BOOL fRet = FALSE;
  123. LPCWSTR cszErr;
  124. DWORD dwRes;
  125. WCHAR szMount[MAX_PATH];
  126. WCHAR szLabel[MAX_PATH];
  127. m_dwFlags = dwFlags;
  128. m_strID = cszID;
  129. if ( !IsOffline() )
  130. {
  131. // Get Mount Point (drive letter or root directory path) from Unique Volume ID
  132. //
  133. if ( !::GetVolumePathNamesForVolumeName( cszID, szMount, MAX_PATH, &dwRes ) && GetLastError() != ERROR_MORE_DATA)
  134. {
  135. cszErr = ::GetSysErrStr();
  136. ErrorTrace(0, "::GetVolumePathNamesForVolumeName failed - %ls", cszErr);
  137. // Instead of fail, use cszMount even if it may not accurate
  138. ::lstrcpy( szMount, cszMount );
  139. }
  140. else
  141. {
  142. szMount[MAX_PATH-1] = L'\0';
  143. if (lstrlenW (szMount) > MAX_MOUNTPOINT_PATH)
  144. {
  145. // Instead of fail, use cszMount even if it may not accurate
  146. ::lstrcpy( szMount, cszMount );
  147. }
  148. }
  149. // Get Volume Label from Mount Point
  150. //
  151. if ( !::GetVolumeInformation( cszID, szLabel, MAX_PATH, NULL, NULL, NULL, NULL, 0 ) )
  152. {
  153. cszErr = ::GetSysErrStr();
  154. ErrorTrace(0, "::GetVolumeInformation failed - %ls", cszErr);
  155. // Instead of fail, use cszLabel even if it may not accurate
  156. ::lstrcpy( szLabel, cszLabel );
  157. }
  158. }
  159. if ( ( szMount[1] == L':' ) && ( szMount[2] == L'\\' ) && ( szMount[3] == L'\0' ) )
  160. szMount[2] = L'\0';
  161. m_strMount = szMount;
  162. m_strLabel = szLabel;
  163. InitUsage (cszID, llDSUsage);
  164. m_fCfgExcluded = IsExcluded();
  165. fRet = TRUE;
  166. TraceFunctLeave();
  167. return( fRet );
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. BOOL
  171. CRstrDriveInfo::Init( LPCWSTR cszID, CDataStore *pDS, BOOL fOffline )
  172. {
  173. TraceFunctEnter("CRstrDriveInfo::Init");
  174. BOOL fRet = FALSE;
  175. LPCWSTR cszErr;
  176. DWORD dwRes;
  177. WCHAR szMount[MAX_PATH];
  178. WCHAR szLabel[MAX_PATH];
  179. m_strID = cszID;
  180. UpdateStatus( pDS->GetFlags(), fOffline );
  181. if ( !fOffline )
  182. {
  183. // Get Mount Point (drive letter or root directory path) from Unique Volume ID
  184. //
  185. if ( !::GetVolumePathNamesForVolumeName( cszID, szMount, MAX_PATH, &dwRes ) && GetLastError() != ERROR_MORE_DATA )
  186. {
  187. cszErr = ::GetSysErrStr();
  188. ErrorTrace(0, "::GetVolumePathNamesForVolumeName failed - %ls", cszErr);
  189. goto Exit;
  190. }
  191. else
  192. {
  193. szMount[MAX_PATH-1] = L'\0';
  194. if (lstrlenW (szMount) > MAX_MOUNTPOINT_PATH)
  195. {
  196. cszErr = ::GetSysErrStr();
  197. ErrorTrace(0, "mount point too long %ls", cszErr);
  198. goto Exit;
  199. }
  200. }
  201. // Get Volume Label from Mount Point
  202. //
  203. if ( !::GetVolumeInformation( cszID, szLabel, MAX_PATH, NULL, NULL, NULL, NULL, 0 ) )
  204. {
  205. cszErr = ::GetSysErrStr();
  206. ErrorTrace(0, "::GetVolumeInformation failed - %ls", cszErr);
  207. // this is not a fatal error - this can happen if the
  208. // volume is being formatted for example. assume that the
  209. // label is empty
  210. szLabel[0]= L'\0';
  211. }
  212. }
  213. else
  214. {
  215. ::lstrcpyW (szMount, pDS->GetDrive());
  216. ::lstrcpyW (szLabel, pDS->GetLabel());
  217. }
  218. if ( ( szMount[1] == L':' ) && ( szMount[2] == L'\\' ) && ( szMount[3] == L'\0' ) )
  219. szMount[2] = L'\0';
  220. m_strMount = szMount;
  221. m_strLabel = szLabel;
  222. InitUsage (cszID, pDS->GetSizeLimit());
  223. m_fCfgExcluded = IsExcluded();
  224. fRet = TRUE;
  225. Exit:
  226. TraceFunctLeave();
  227. return( fRet );
  228. }
  229. /////////////////////////////////////////////////////////////////////////////
  230. BOOL
  231. CRstrDriveInfo::LoadFromLog( HANDLE hfLog )
  232. {
  233. TraceFunctEnter("CRstrDriveInfo::LoadFromLog");
  234. BOOL fRet = FALSE;
  235. DWORD dwRes;
  236. WCHAR szBuf[MAX_PATH];
  237. // Read m_dwFlags
  238. READFILE_AND_VALIDATE( hfLog, &m_dwFlags, sizeof(DWORD), dwRes, Exit );
  239. // Read m_strID
  240. if ( !::ReadStrAlign4( hfLog, szBuf ) )
  241. {
  242. ErrorTrace(0, "Cannot read drive ID...");
  243. goto Exit;
  244. }
  245. if ( szBuf[0] == L'\0' )
  246. {
  247. ErrorTrace(0, "Drive Guid is empty...");
  248. goto Exit;
  249. }
  250. m_strID = szBuf;
  251. // Read m_strMount
  252. if ( !::ReadStrAlign4( hfLog, szBuf ) )
  253. {
  254. ErrorTrace(0, "Cannot read drive mount point...");
  255. goto Exit;
  256. }
  257. m_strMount = szBuf;
  258. // Read m_strLabel
  259. if ( !::ReadStrAlign4( hfLog, szBuf ) )
  260. {
  261. ErrorTrace(0, "Cannot read drive mount point...");
  262. goto Exit;
  263. }
  264. m_strLabel = szBuf;
  265. m_fCfgExcluded = IsExcluded();
  266. // m_nCfgMaxSize = ...
  267. fRet = TRUE;
  268. Exit:
  269. TraceFunctLeave();
  270. return( fRet );
  271. }
  272. /////////////////////////////////////////////////////////////////////////////
  273. void
  274. CRstrDriveInfo::UpdateStatus( DWORD dwFlags, BOOL fOffline )
  275. {
  276. TraceFunctEnter("CRstrDriveInfo::UpdateStatus");
  277. m_dwFlags = 0;
  278. if ( fOffline )
  279. {
  280. m_dwFlags |= RDIF_OFFLINE;
  281. }
  282. else
  283. {
  284. // check if frozen
  285. if ( ( dwFlags & SR_DRIVE_FROZEN ) != 0 )
  286. m_dwFlags |= RDIF_FROZEN;
  287. // check if system drive
  288. if ( ( dwFlags & SR_DRIVE_SYSTEM ) != 0 )
  289. {
  290. m_dwFlags |= RDIF_SYSTEM;
  291. }
  292. else
  293. {
  294. // if not system drive, simply use MONITORED flag of drive table
  295. if ( ( dwFlags & SR_DRIVE_MONITORED ) == 0 )
  296. m_dwFlags |= RDIF_EXCLUDED;
  297. }
  298. }
  299. DebugTrace(0, "Status has been updated, m_dwFlags=%08X", m_dwFlags);
  300. TraceFunctLeave();
  301. }
  302. /////////////////////////////////////////////////////////////////////////////
  303. // CRstrDriveInfo - methods
  304. DWORD
  305. CRstrDriveInfo::GetFlags()
  306. {
  307. return( m_dwFlags );
  308. }
  309. /////////////////////////////////////////////////////////////////////////////
  310. BOOL
  311. CRstrDriveInfo::IsExcluded()
  312. {
  313. return( ( m_dwFlags & RDIF_EXCLUDED ) != 0 );
  314. }
  315. /////////////////////////////////////////////////////////////////////////////
  316. BOOL
  317. CRstrDriveInfo::IsFrozen()
  318. {
  319. return( ( m_dwFlags & RDIF_FROZEN ) != 0 );
  320. }
  321. /////////////////////////////////////////////////////////////////////////////
  322. BOOL
  323. CRstrDriveInfo::IsOffline()
  324. {
  325. return( ( m_dwFlags & RDIF_OFFLINE ) != 0 );
  326. }
  327. /////////////////////////////////////////////////////////////////////////////
  328. BOOL
  329. CRstrDriveInfo::IsSystem()
  330. {
  331. return( ( m_dwFlags & RDIF_SYSTEM ) != 0 );
  332. }
  333. /////////////////////////////////////////////////////////////////////////////
  334. BOOL
  335. CRstrDriveInfo::RefreshStatus()
  336. {
  337. TraceFunctEnter("CRstrDriveInfo::RefreshStatus");
  338. BOOL fRet = FALSE;
  339. LPCWSTR cszErr;
  340. WCHAR szDTFile[MAX_PATH];
  341. DWORD dwRes;
  342. CDriveTable cDrvTable;
  343. CDataStore *pDS;
  344. ::MakeRestorePath( szDTFile, s_szSysDrv, NULL );
  345. ::PathAppend( szDTFile, s_cszDriveTable );
  346. DebugTrace(0, "Loading drive table - %ls", szDTFile);
  347. dwRes = cDrvTable.LoadDriveTable( szDTFile );
  348. if ( dwRes != ERROR_SUCCESS )
  349. {
  350. cszErr = ::GetSysErrStr( dwRes );
  351. ErrorTrace(0, "Cannot load a drive table - %ls", cszErr);
  352. ErrorTrace(0, " szDTFile: '%ls'", szDTFile);
  353. goto Exit;
  354. }
  355. dwRes = cDrvTable.RemoveDrivesFromTable();
  356. if ( dwRes != ERROR_SUCCESS )
  357. {
  358. cszErr = ::GetSysErrStr( dwRes );
  359. ErrorTrace(0, "CDriveTable::RemoveDrivesFromTable failed - %ls", cszErr);
  360. // ignore error
  361. }
  362. pDS = cDrvTable.FindGuidInTable( (LPWSTR)GetID() );
  363. if ( pDS == NULL )
  364. UpdateStatus( 0, TRUE );
  365. else
  366. UpdateStatus( pDS->GetFlags(), FALSE );
  367. fRet = TRUE;
  368. Exit:
  369. TraceFunctLeave();
  370. return( fRet );
  371. }
  372. /////////////////////////////////////////////////////////////////////////////
  373. LPCWSTR
  374. CRstrDriveInfo::GetID()
  375. {
  376. return( ( m_strID.Length() > 0 ) ? m_strID : s_cszEmpty );
  377. }
  378. /////////////////////////////////////////////////////////////////////////////
  379. LPCWSTR
  380. CRstrDriveInfo::GetMount()
  381. {
  382. return( ( m_strMount.Length() > 0 ) ? m_strMount : s_cszEmpty );
  383. }
  384. /////////////////////////////////////////////////////////////////////////////
  385. LPCWSTR
  386. CRstrDriveInfo::GetLabel()
  387. {
  388. return( ( m_strLabel.Length() > 0 ) ? m_strLabel : s_cszEmpty );
  389. }
  390. /////////////////////////////////////////////////////////////////////////////
  391. void
  392. CRstrDriveInfo::SetMountAndLabel( LPCWSTR cszMount, LPCWSTR cszLabel )
  393. {
  394. TraceFunctEnter("CRstrDriveInfo::SetMountAndLabel");
  395. m_strMount = cszMount;
  396. m_strLabel = cszLabel;
  397. TraceFunctLeave();
  398. }
  399. /////////////////////////////////////////////////////////////////////////////
  400. HICON
  401. CRstrDriveInfo::GetIcon( BOOL fSmall )
  402. {
  403. TraceFunctEnter("CRstrDriveInfo::GetIcon");
  404. LPCWSTR cszErr;
  405. int nIdx = fSmall ? 0 : 1;
  406. int cxIcon, cyIcon;
  407. HICON hIcon;
  408. if ( m_hIcon[nIdx] != NULL )
  409. goto Exit;
  410. cxIcon = ::GetSystemMetrics( fSmall ? SM_CXSMICON : SM_CXICON );
  411. cyIcon = ::GetSystemMetrics( fSmall ? SM_CYSMICON : SM_CYICON );
  412. hIcon = (HICON)::LoadImage( g_hInst, MAKEINTRESOURCE(IDI_DRIVE_FIXED),
  413. IMAGE_ICON, cxIcon, cyIcon, LR_DEFAULTCOLOR );
  414. if ( hIcon == NULL )
  415. {
  416. cszErr = ::GetSysErrStr();
  417. ErrorTrace(0, "::LoadImage failed - %ls", cszErr);
  418. goto Exit;
  419. }
  420. m_hIcon[nIdx] = hIcon;
  421. Exit:
  422. TraceFunctLeave();
  423. return( m_hIcon[nIdx] );
  424. }
  425. /////////////////////////////////////////////////////////////////////////////
  426. BOOL
  427. CRstrDriveInfo::SaveToLog( HANDLE hfLog )
  428. {
  429. TraceFunctEnter("CRstrDriveInfo::SaveToLog");
  430. BOOL fRet = FALSE;
  431. BYTE pbBuf[7*MAX_PATH];
  432. DWORD dwSize = 0;
  433. DWORD dwRes;
  434. *((DWORD*)pbBuf) = m_dwFlags;
  435. dwSize += sizeof(DWORD);
  436. dwSize += ::StrCpyAlign4( pbBuf+dwSize, m_strID );
  437. dwSize += ::StrCpyAlign4( pbBuf+dwSize, m_strMount );
  438. dwSize += ::StrCpyAlign4( pbBuf+dwSize, m_strLabel );
  439. WRITEFILE_AND_VALIDATE( hfLog, pbBuf, dwSize, dwRes, Exit );
  440. fRet = TRUE;
  441. Exit:
  442. TraceFunctLeave();
  443. return( fRet );
  444. }
  445. /////////////////////////////////////////////////////////////////////////////
  446. UINT
  447. CRstrDriveInfo::GetDSUsage()
  448. {
  449. TraceFunctEnter("CRstrDriveInfo::GetDSUsage");
  450. TraceFunctLeave();
  451. return( m_uDSUsage );
  452. }
  453. /////////////////////////////////////////////////////////////////////////////
  454. BOOL
  455. CRstrDriveInfo::GetUsageText( LPWSTR szUsage )
  456. {
  457. TraceFunctEnter("CRstrDriveInfo::GetUsageText");
  458. INT64 llUsage;
  459. int nPercent;
  460. int nUsage;
  461. if (m_llDSMax - m_llDSMin > 0)
  462. llUsage = m_llDSMin + ( m_llDSMax - m_llDSMin ) * m_uCfgDSUsage / DSUSAGE_SLIDER_FREQ;
  463. else
  464. llUsage = m_llDSMin;
  465. if (m_ulTotalBytes.QuadPart != 0)
  466. {
  467. // the m_ulTotalBytes.QuadPart/200 addition is to ensure that
  468. // the correct round off happens
  469. nPercent = (llUsage + (m_ulTotalBytes.QuadPart/200)) * 100/
  470. m_ulTotalBytes.QuadPart;
  471. }
  472. else nPercent = 0;
  473. nUsage = llUsage / ( 1024 * 1024 );
  474. ::wsprintf( szUsage, L"%d%% (%d MB)", nPercent, nUsage );
  475. TraceFunctLeave();
  476. return( TRUE );
  477. }
  478. /////////////////////////////////////////////////////////////////////////////
  479. BOOL
  480. CRstrDriveInfo::GetCfgExcluded( BOOL *pfExcluded )
  481. {
  482. TraceFunctEnter("CRstrDriveInfo::GetCfgExcluded");
  483. BOOL fRet = FALSE;
  484. if ( m_fCfgExcluded != IsExcluded() )
  485. {
  486. *pfExcluded = m_fCfgExcluded;
  487. fRet = TRUE;
  488. }
  489. TraceFunctLeave();
  490. return( fRet );
  491. }
  492. /////////////////////////////////////////////////////////////////////////////
  493. void
  494. CRstrDriveInfo::SetCfgExcluded( BOOL fExcluded )
  495. {
  496. TraceFunctEnter("CRstrDriveInfo::SetCfgExcluded");
  497. m_fCfgExcluded = fExcluded;
  498. TraceFunctLeave();
  499. }
  500. /////////////////////////////////////////////////////////////////////////////
  501. BOOL
  502. CRstrDriveInfo::GetCfgDSUsage( UINT *puPos )
  503. {
  504. TraceFunctEnter("CRstrDriveInfo::GetCfgDSUsage");
  505. BOOL fRet = FALSE;
  506. if ( m_uCfgDSUsage != m_uDSUsage )
  507. {
  508. *puPos = m_uCfgDSUsage;
  509. fRet = TRUE;
  510. }
  511. TraceFunctLeave();
  512. return( fRet );
  513. }
  514. /////////////////////////////////////////////////////////////////////////////
  515. void
  516. CRstrDriveInfo::SetCfgDSUsage( UINT uPos )
  517. {
  518. TraceFunctEnter("CRstrDriveInfo::SetCfgDSUsage");
  519. m_uCfgDSUsage = uPos;
  520. TraceFunctLeave();
  521. }
  522. /////////////////////////////////////////////////////////////////////////////
  523. void
  524. CloseRestoreUI()
  525. {
  526. WCHAR szPath[MAX_PATH], szTitle[MAX_PATH] = L"";
  527. if (ExpandEnvironmentStrings(L"%windir%\\system32\\restore\\rstrui.exe", szPath, MAX_PATH))
  528. {
  529. if (ERROR_SUCCESS == SRLoadString(szPath, IDS_RESTOREUI_TITLE, szTitle, MAX_PATH))
  530. {
  531. HWND hWnd = FindWindow(CLSNAME_RSTRSHELL, szTitle);
  532. if (hWnd != NULL)
  533. PostMessage(hWnd, WM_CLOSE, 0, 0);
  534. }
  535. }
  536. }
  537. /////////////////////////////////////////////////////////////////////////////
  538. BOOL
  539. CRstrDriveInfo::ApplyConfig( HWND hWnd )
  540. {
  541. TraceFunctEnter("CRstrDriveInfo::ApplyConfig");
  542. BOOL fRet = FALSE;
  543. LPCWSTR cszErr;
  544. INT64 llUsage;
  545. DWORD dwRes;
  546. if ( m_fCfgExcluded != IsExcluded() )
  547. {
  548. if ( m_fCfgExcluded )
  549. {
  550. WCHAR szTitle[MAX_STR];
  551. WCHAR szMsg[MAX_STR+2*MAX_PATH];
  552. // Confirm if it's ok to turn drive or SR off.
  553. ::LoadString( g_hInst, IDS_SYSTEMRESTORE, szTitle,
  554. sizeof(szTitle)/sizeof(WCHAR) );
  555. if ( IsSystem() )
  556. ::LoadString( g_hInst, IDS_CONFIRM_TURN_SR_OFF, szMsg,
  557. sizeof(szMsg)/sizeof(WCHAR) );
  558. else
  559. {
  560. ::SRFormatMessage( szMsg, IDS_CONFIRM_TURN_DRV_OFF, GetLabel() ? GetLabel() : L"", GetMount() );
  561. }
  562. if ( ::MessageBox( hWnd, szMsg, szTitle, MB_YESNO ) == IDNO )
  563. {
  564. m_fCfgExcluded = IsExcluded();
  565. goto Exit;
  566. }
  567. //
  568. // if disabling all of SR, close the wizard if open
  569. //
  570. if (IsSystem())
  571. {
  572. CloseRestoreUI();
  573. }
  574. dwRes = ::DisableSR( m_strID );
  575. if ( dwRes != ERROR_SUCCESS )
  576. {
  577. ShowSRErrDlg (IDS_ERR_SR_ON_OFF);
  578. cszErr = ::GetSysErrStr( dwRes );
  579. ErrorTrace(0, "::DisableSR failed - %ls", cszErr);
  580. goto Exit;
  581. }
  582. m_dwFlags |= RDIF_EXCLUDED;
  583. }
  584. else
  585. {
  586. //
  587. // make a synchronous call to enable sr
  588. // this will block till the firstrun checkpoint is created
  589. // and the service is fully initialized
  590. //
  591. dwRes = ::EnableSREx( m_strID, TRUE );
  592. if ( dwRes != ERROR_SUCCESS )
  593. {
  594. ShowSRErrDlg (IDS_ERR_SR_ON_OFF);
  595. cszErr = ::GetSysErrStr( dwRes );
  596. ErrorTrace(0, "::EnableSR failed - %ls", cszErr);
  597. goto Exit;
  598. }
  599. m_dwFlags &= ~RDIF_EXCLUDED;
  600. }
  601. }
  602. if ( m_uCfgDSUsage != m_uDSUsage )
  603. {
  604. if (m_llDSMax - m_llDSMin > 0)
  605. llUsage = m_llDSMin + (m_llDSMax - m_llDSMin)* m_uCfgDSUsage /DSUSAGE_SLIDER_FREQ;
  606. else
  607. llUsage = m_llDSMin;
  608. dwRes = ::SRUpdateDSSize( m_strID, llUsage );
  609. if ( dwRes != ERROR_SUCCESS )
  610. {
  611. LPCWSTR cszErr = ::GetSysErrStr( dwRes );
  612. ErrorTrace(0, "::SRUpdateDriveTable failed - %ls", cszErr);
  613. goto Exit;
  614. }
  615. m_uDSUsage = m_uCfgDSUsage;
  616. }
  617. fRet = TRUE;
  618. Exit:
  619. TraceFunctLeave();
  620. return( fRet );
  621. }
  622. /////////////////////////////////////////////////////////////////////////////
  623. BOOL
  624. CRstrDriveInfo::Release()
  625. {
  626. TraceFunctEnter("CRstrDriveInfo::Release");
  627. delete this;
  628. TraceFunctLeave();
  629. return( TRUE );
  630. }
  631. /////////////////////////////////////////////////////////////////////////////
  632. //
  633. // Helper Function
  634. //
  635. /////////////////////////////////////////////////////////////////////////////
  636. //
  637. // Enumerate Volumes without Drive Table if SR is disabled and DS not exists.
  638. //
  639. BOOL
  640. EnumVolumes( CRDIArray &aryDrv )
  641. {
  642. TraceFunctEnter("EnumVolumes");
  643. BOOL fRet = FALSE;
  644. LPCWSTR cszErr;
  645. HANDLE hEnumVol = INVALID_HANDLE_VALUE;
  646. WCHAR szVolume[MAX_PATH];
  647. WCHAR szMount[MAX_PATH];
  648. DWORD cbMount;
  649. CRstrDriveInfo *pDrv = NULL;
  650. DWORD dwFlags;
  651. hEnumVol = ::FindFirstVolume( szVolume, MAX_PATH );
  652. if ( hEnumVol == INVALID_HANDLE_VALUE )
  653. {
  654. cszErr = ::GetSysErrStr();
  655. ErrorTrace(0, "::FindFirstVolume failed - %ls", cszErr);
  656. goto Exit;
  657. }
  658. // dummy space for system drive
  659. if ( !aryDrv.AddItem( NULL ) )
  660. goto Exit;
  661. do
  662. {
  663. HANDLE hfDrv;
  664. DebugTrace(0, "Guid=%ls", szVolume);
  665. if ( !::GetVolumePathNamesForVolumeName( szVolume, szMount, MAX_PATH, &cbMount ) && GetLastError() != ERROR_MORE_DATA)
  666. {
  667. cszErr = ::GetSysErrStr();
  668. ErrorTrace(0, "::GetVolumePathNamesForVolumeName failed - %ls", cszErr);
  669. continue;
  670. }
  671. else
  672. {
  673. szMount[MAX_PATH-1] = L'\0';
  674. if (lstrlenW (szMount) > MAX_MOUNTPOINT_PATH)
  675. continue;
  676. }
  677. DebugTrace(0, " Mount=%ls", szMount);
  678. if ( ::GetDriveType( szMount ) != DRIVE_FIXED )
  679. {
  680. DebugTrace(0, "Non-fixed drive");
  681. // includes only the fixed drives.
  682. continue;
  683. }
  684. hfDrv = ::CreateFile( szVolume, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  685. NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL );
  686. if ( hfDrv == INVALID_HANDLE_VALUE )
  687. {
  688. cszErr = ::GetSysErrStr();
  689. ErrorTrace(0, "::CreateFile(volume) failed - %ls", cszErr);
  690. // probably an unformatted drive.
  691. continue;
  692. }
  693. ::CloseHandle( hfDrv );
  694. pDrv = new CRstrDriveInfo;
  695. if ( pDrv == NULL )
  696. {
  697. FatalTrace(0, "Insufficient memory...");
  698. goto Exit;
  699. }
  700. dwFlags = RDIF_EXCLUDED;
  701. if ( ::IsSystemDrive( szVolume ) )
  702. {
  703. dwFlags |= RDIF_SYSTEM;
  704. if ( !aryDrv.SetItem( 0, pDrv ) )
  705. goto Exit;
  706. }
  707. else
  708. {
  709. if ( !aryDrv.AddItem( pDrv ) )
  710. goto Exit;
  711. }
  712. if ( !pDrv->Init( szVolume, dwFlags, 0, szMount, NULL ) )
  713. goto Exit;
  714. pDrv = NULL;
  715. }
  716. while ( ::FindNextVolume( hEnumVol, szVolume, MAX_PATH ) );
  717. fRet = TRUE;
  718. Exit:
  719. if ( pDrv != NULL )
  720. if ( hEnumVol != INVALID_HANDLE_VALUE )
  721. ::FindVolumeClose( hEnumVol );
  722. TraceFunctLeave();
  723. return( fRet );
  724. }
  725. /////////////////////////////////////////////////////////////////////////////
  726. BOOL
  727. LoadDriveTable( LPCWSTR cszRPDir, CRDIArray &aryDrv, BOOL fRemoveDrives)
  728. {
  729. TraceFunctEnter("LoadDriveTable");
  730. BOOL fRet = FALSE;
  731. LPCWSTR cszErr;
  732. WCHAR szDTFile[MAX_PATH];
  733. DWORD dwRes;
  734. CDriveTable cDrvTable;
  735. SDriveTableEnumContext sDTEnum = { NULL, 0 };
  736. CDataStore *pDS;
  737. CRstrDriveInfo *pDrv = NULL;
  738. BOOL fOffline;
  739. ::MakeRestorePath( szDTFile, s_szSysDrv, cszRPDir );
  740. ::PathAppend( szDTFile, s_cszDriveTable );
  741. DebugTrace(0, "Loading drive table - %ls", szDTFile);
  742. dwRes = cDrvTable.LoadDriveTable( szDTFile );
  743. if ( dwRes != ERROR_SUCCESS )
  744. {
  745. cszErr = ::GetSysErrStr( dwRes );
  746. ErrorTrace(0, "Cannot load a drive table - %ls", cszErr);
  747. ErrorTrace(0, " szDTFile: '%ls'", szDTFile);
  748. goto Exit;
  749. }
  750. // If this is for the current drive table, try to update information
  751. // about removed volumes.
  752. if ( cszRPDir == NULL )
  753. {
  754. if (fRemoveDrives)
  755. cDrvTable.RemoveDrivesFromTable();
  756. else
  757. {
  758. sDTEnum.Reset();
  759. pDS = cDrvTable.FindFirstDrive (sDTEnum);
  760. while (pDS != NULL)
  761. {
  762. pDS->IsVolumeDeleted(); // mark deleted volumes as inactive
  763. pDS = cDrvTable.FindNextDrive( sDTEnum );
  764. }
  765. }
  766. }
  767. sDTEnum.Reset();
  768. pDS = cDrvTable.FindFirstDrive( sDTEnum );
  769. while ( pDS != NULL )
  770. {
  771. int i;
  772. LPCWSTR cszGuid = pDS->GetGuid();
  773. DebugTrace(0, "Drive: %ls %ls", pDS->GetDrive(), cszGuid);
  774. if ( cszRPDir != NULL ) // not the current restore point
  775. {
  776. for ( i = aryDrv.GetUpperBound(); i >= 0; i-- )
  777. {
  778. CRstrDriveInfo *pExist = aryDrv.GetItem( i );
  779. if ( ::lstrcmpi( cszGuid, pExist->GetID() ) == 0 )
  780. {
  781. // Match has been found. Check if it's offline, in which
  782. // case mount point and volume label should be updated to the
  783. // latest ones.
  784. if ( pExist->IsOffline() )
  785. pExist->SetMountAndLabel( pDS->GetDrive(), pDS->GetLabel() );
  786. break;
  787. }
  788. pDrv = NULL;
  789. }
  790. if ( i >= 0 )
  791. goto NextDrv;
  792. }
  793. pDrv = new CRstrDriveInfo;
  794. if ( pDrv == NULL )
  795. {
  796. FatalTrace(0, "Insufficient memory...");
  797. goto Exit;
  798. }
  799. //
  800. // mark a drive as offline if it's not in the current restore point
  801. // or it's inactive in the current restore point
  802. //
  803. fOffline = (cszRPDir != NULL) || !(pDS->GetFlags() & SR_DRIVE_ACTIVE);
  804. if ( !pDrv->Init( cszGuid, pDS, fOffline ) )
  805. goto Exit;
  806. if (( pDrv->GetMount() == NULL ) || ( (pDrv->GetMount())[0] == L'\0' ))
  807. {
  808. pDrv->Release();
  809. goto NextDrv;
  810. }
  811. if ( pDrv->IsSystem() )
  812. {
  813. if ( !aryDrv.SetItem( 0, pDrv ) )
  814. goto Exit;
  815. }
  816. else
  817. {
  818. if ( !aryDrv.AddItem( pDrv ) )
  819. goto Exit;
  820. }
  821. pDrv = NULL;
  822. NextDrv:
  823. pDS = cDrvTable.FindNextDrive( sDTEnum );
  824. }
  825. fRet = TRUE;
  826. Exit:
  827. if ( !fRet )
  828. SAFE_RELEASE(pDrv);
  829. TraceFunctLeave();
  830. return( fRet );
  831. }
  832. /////////////////////////////////////////////////////////////////////////////
  833. BOOL
  834. UpdateDriveList( CRDIArray &aryDrv )
  835. {
  836. TraceFunctEnter("UpdateDriveTable");
  837. BOOL fRet = FALSE;
  838. LPCWSTR cszErr;
  839. DWORD dwDisable = 0;
  840. WCHAR szDTFile[MAX_PATH];
  841. DWORD dwRes;
  842. CDriveTable cDrvTable;
  843. CDataStore *pDS;
  844. CRstrDriveInfo *pDrv;
  845. int i;
  846. // Check if SR is disabled
  847. if ( ::SRGetRegDword( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszDisableSR, &dwDisable ) )
  848. if ( dwDisable != 0 )
  849. {
  850. for ( i = aryDrv.GetUpperBound(); i >= 0; i-- )
  851. {
  852. pDrv = (CRstrDriveInfo*)aryDrv[i];
  853. pDrv->UpdateStatus( SR_DRIVE_FROZEN, FALSE );
  854. }
  855. goto Done;
  856. }
  857. ::MakeRestorePath( szDTFile, s_szSysDrv, NULL );
  858. ::PathAppend( szDTFile, s_cszDriveTable );
  859. DebugTrace(0, "Loading drive table - %ls", szDTFile);
  860. dwRes = cDrvTable.LoadDriveTable( szDTFile );
  861. if ( dwRes != ERROR_SUCCESS )
  862. {
  863. cszErr = ::GetSysErrStr( dwRes );
  864. ErrorTrace(0, "Cannot load a drive table - %ls", cszErr);
  865. ErrorTrace(0, " szDTFile: '%ls'", szDTFile);
  866. goto Exit;
  867. }
  868. dwRes = cDrvTable.RemoveDrivesFromTable();
  869. if ( dwRes != ERROR_SUCCESS )
  870. {
  871. cszErr = ::GetSysErrStr( dwRes );
  872. ErrorTrace(0, "CDriveTable::RemoveDrivesFromTable failed - %ls", cszErr);
  873. // ignore error
  874. }
  875. for ( i = aryDrv.GetUpperBound(); i >= 0; i-- )
  876. {
  877. pDrv = (CRstrDriveInfo*)aryDrv[i];
  878. pDS = cDrvTable.FindGuidInTable( (LPWSTR)pDrv->GetID() );
  879. if ( ( pDS == NULL ) || ( pDS->GetDrive() == NULL ) || ( (pDS->GetDrive())[0] == L'\0' ) )
  880. pDrv->UpdateStatus( 0, TRUE );
  881. else
  882. pDrv->UpdateStatus( pDS->GetFlags(), FALSE );
  883. }
  884. Done:
  885. fRet = TRUE;
  886. Exit:
  887. TraceFunctLeave();
  888. return( fRet );
  889. }
  890. /////////////////////////////////////////////////////////////////////////////
  891. //
  892. // CreateAndLoadDriveInfoInstance
  893. //
  894. // This routine creates a CRstrDriveInfo class instance and load the content
  895. // from a log file.
  896. //
  897. /////////////////////////////////////////////////////////////////////////////
  898. BOOL
  899. CreateAndLoadDriveInfoInstance( HANDLE hfLog, CRstrDriveInfo **ppRDI )
  900. {
  901. TraceFunctEnter("CreateAndLoadDriveInfoInstance");
  902. BOOL fRet = FALSE;
  903. CRstrDriveInfo *pRDI=NULL;
  904. if ( ppRDI == NULL )
  905. {
  906. ErrorTrace(0, "Invalid parameter, ppRDI is NULL.");
  907. goto Exit;
  908. }
  909. *ppRDI = NULL;
  910. pRDI = new CRstrDriveInfo;
  911. if ( pRDI == NULL )
  912. {
  913. ErrorTrace(0, "Insufficient memory...");
  914. goto Exit;
  915. }
  916. if ( !pRDI->LoadFromLog( hfLog ) )
  917. goto Exit;
  918. *ppRDI = pRDI;
  919. fRet = TRUE;
  920. Exit:
  921. if ( !fRet )
  922. SAFE_RELEASE(pRDI);
  923. TraceFunctLeave();
  924. return( fRet );
  925. }
  926. /////////////////////////////////////////////////////////////////////////////
  927. //
  928. // CreateDriveList
  929. //
  930. // This routine creates a drive list consists of CDriveInfo class instances.
  931. //
  932. /////////////////////////////////////////////////////////////////////////////
  933. BOOL
  934. CreateDriveList( int nRP, CRDIArray &aryDrv, BOOL fRemoveDrives )
  935. {
  936. TraceFunctEnter("CreateDriveList");
  937. BOOL fRet = FALSE;
  938. LPCWSTR cszErr;
  939. DWORD fDisable;
  940. if ( !::GetSystemDrive( s_szSysDrv ) )
  941. {
  942. cszErr = ::GetSysErrStr();
  943. ErrorTrace(0, "Cannot get system drive - %ls", cszErr);
  944. goto Exit;
  945. }
  946. DebugTrace(0, "SystemDrive=%ls", s_szSysDrv);
  947. // Check if SR is disabled
  948. if ( !::SRGetRegDword( HKEY_LOCAL_MACHINE, s_cszSRRegKey, s_cszDisableSR, &fDisable ) )
  949. {
  950. DebugTrace(0, "Cannot get disable reg key");
  951. goto Exit;
  952. }
  953. if ( fDisable )
  954. {
  955. DebugTrace(0, "SR is DISABLED!!!");
  956. // Enumerate instead of reading drive table...
  957. if ( !EnumVolumes( aryDrv ) )
  958. goto Exit;
  959. }
  960. else
  961. {
  962. // dummy space for system drive
  963. if ( !aryDrv.AddItem( NULL ) )
  964. goto Exit;
  965. // process the current drive table...
  966. if ( !LoadDriveTable( NULL, aryDrv, fRemoveDrives ) )
  967. {
  968. DebugTrace(0, "Loading current drive table failed");
  969. goto Exit;
  970. }
  971. if ( nRP > 0 )
  972. {
  973. CRestorePointEnum cEnum( s_szSysDrv, FALSE, FALSE );
  974. CRestorePoint cRP;
  975. DWORD dwRes;
  976. dwRes = cEnum.FindFirstRestorePoint( cRP );
  977. if ( dwRes != ERROR_SUCCESS && dwRes != ERROR_FILE_NOT_FOUND )
  978. {
  979. cszErr = ::GetSysErrStr(dwRes);
  980. ErrorTrace(0, "CRestorePointEnum::FindFirstRestorePoint failed - %ls", cszErr);
  981. goto Exit;
  982. }
  983. while ( (dwRes == ERROR_SUCCESS || dwRes == ERROR_FILE_NOT_FOUND) && ( cRP.GetNum() >= nRP ))
  984. {
  985. dwRes = cEnum.FindNextRestorePoint( cRP );
  986. if ( dwRes == ERROR_NO_MORE_ITEMS )
  987. break;
  988. if ( dwRes != ERROR_SUCCESS && dwRes != ERROR_FILE_NOT_FOUND )
  989. {
  990. cszErr = ::GetSysErrStr(dwRes);
  991. ErrorTrace(0, "CRestorePointEnum::FindNextRestorePoint failed - %ls", cszErr);
  992. goto Exit;
  993. }
  994. DebugTrace(0, "RPNum=%d", cRP.GetNum());
  995. if ( cRP.GetNum() >= nRP )
  996. {
  997. // process drive table of each RP...
  998. if ( !LoadDriveTable( cRP.GetDir(), aryDrv, fRemoveDrives))
  999. {
  1000. // The last restore point does not have drive table...
  1001. // simply ignore it.
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. fRet = TRUE;
  1008. Exit:
  1009. TraceFunctLeave();
  1010. return( fRet );
  1011. }
  1012. // end of file