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
2496 lines
67 KiB
/*****************************************************************************
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*
|
|
* Module Name:
|
|
* datastormgr.cpp
|
|
*
|
|
* Abstract:
|
|
* CDataStoreMgr class functions
|
|
*
|
|
* Revision History:
|
|
* Brijesh Krishnaswami (brijeshk) 03/28/2000
|
|
* created
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "datastormgr.h"
|
|
#include "srapi.h"
|
|
#include "srconfig.h"
|
|
#include "evthandler.h"
|
|
#include "ntservice.h"
|
|
#include "ntservmsg.h"
|
|
|
|
#include <coguid.h>
|
|
#include <rpc.h>
|
|
#include <stdio.h>
|
|
#include <shlwapi.h>
|
|
|
|
#ifdef THIS_FILE
|
|
#undef THIS_FILE
|
|
#endif
|
|
static char __szTraceSourceFile[] = __FILE__;
|
|
#define THIS_FILE __szTraceSourceFile
|
|
|
|
CDataStoreMgr * g_pDataStoreMgr = NULL; // the global instance
|
|
|
|
//
|
|
// we can't use %s for the volume label because it can contain spaces
|
|
// so we look for all characters until the end-of-line
|
|
//
|
|
static WCHAR gs_wcsScanFormat[] = L"%[^/]/%s %x %i %i %[^\r]\n";
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::CDriveTable ()
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDriveTable::CDriveTable ()
|
|
{
|
|
_pdtNext = NULL;
|
|
_nLastDrive = 0;
|
|
_fDirty = FALSE;
|
|
_fLockInit = FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::~CDriveTable
|
|
//
|
|
// Synopsis: delete all drive table entries
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDriveTable::~CDriveTable ()
|
|
{
|
|
for (int i = 0; i < _nLastDrive; i++)
|
|
{
|
|
if (_rgDriveTable[i] != NULL)
|
|
{
|
|
delete _rgDriveTable[i];
|
|
_rgDriveTable[i] = NULL;
|
|
}
|
|
}
|
|
_nLastDrive = 0;
|
|
|
|
if (_pdtNext != NULL)
|
|
{
|
|
delete _pdtNext;
|
|
_pdtNext = NULL;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::CreateNewEntry
|
|
//
|
|
// Synopsis: populate the table with this datastore object
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::CreateNewEntry (CDataStore *pds)
|
|
{
|
|
if (_nLastDrive < DRIVE_TABLE_SIZE)
|
|
{
|
|
_rgDriveTable[_nLastDrive] = pds;
|
|
_nLastDrive++;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// this table is full, allocate a new one if needed
|
|
if (_pdtNext == NULL)
|
|
{
|
|
_pdtNext = new CDriveTable();
|
|
if (_pdtNext == NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
// Now add the entry to the new table
|
|
return _pdtNext->CreateNewEntry (pds);
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::FindDriveInTable
|
|
//
|
|
// Synopsis: return datastore object matching this drive
|
|
//
|
|
// Arguments: can pass in dos drive letter, mount point path, or volume guid
|
|
//
|
|
// Returns: pointer to corresponding datastore object
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStore * CDriveTable::FindDriveInTable (WCHAR *pwszDrive) const
|
|
{
|
|
if (NULL == pwszDrive) // not a valid drive
|
|
return NULL;
|
|
|
|
if (0 == wcsncmp(pwszDrive, L"\\\\?\\Volume", 10))
|
|
return FindGuidInTable(pwszDrive);
|
|
|
|
for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
|
|
{
|
|
for (int i = 0; i < pdt->_nLastDrive; i++)
|
|
{
|
|
if ((pdt->_rgDriveTable[i] != NULL) &&
|
|
lstrcmpi (pwszDrive, pdt->_rgDriveTable[i]->GetDrive()) == 0)
|
|
{
|
|
return pdt->_rgDriveTable[i];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::RemoveDrivesFromTable
|
|
//
|
|
// Synopsis: remove inactive drive table entries
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::RemoveDrivesFromTable ()
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
tenter("removedrivesfromtable");
|
|
|
|
for (CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
|
|
{
|
|
for (int i = 0; i < pdt->_nLastDrive; i++)
|
|
{
|
|
if (pdt->_rgDriveTable[i] != NULL &&
|
|
pdt->_rgDriveTable[i]->IsVolumeDeleted())
|
|
{
|
|
trace(0, "removing %S from drivetable", pdt->_rgDriveTable[i]->GetDrive());
|
|
|
|
delete pdt->_rgDriveTable[i];
|
|
pdt->_rgDriveTable[i] = NULL;
|
|
|
|
if (i == pdt->_nLastDrive - 1)
|
|
--(pdt->_nLastDrive);
|
|
|
|
_fDirty = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
tleave();
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::FindGuidInTable
|
|
//
|
|
// Synopsis: get the drive table entry matching the volume GUID
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStore * CDriveTable::FindGuidInTable (WCHAR *pwszGuid) const
|
|
{
|
|
if (NULL == pwszGuid) // not a valid string
|
|
return NULL;
|
|
|
|
for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
|
|
{
|
|
for (int i = 0; i < pdt->_nLastDrive; i++)
|
|
{
|
|
if (pdt->_rgDriveTable[i] != NULL &&
|
|
lstrcmp (pwszGuid, pdt->_rgDriveTable[i]->GetGuid()) == 0)
|
|
{
|
|
return pdt->_rgDriveTable[i];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::FindSystemDrive
|
|
//
|
|
// Synopsis: get the drive table entry for the system drive
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStore * CDriveTable::FindSystemDrive () const
|
|
{
|
|
for (const CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
|
|
{
|
|
for (int i = 0; i < pdt->_nLastDrive; i++)
|
|
{
|
|
if (pdt->_rgDriveTable[i] != NULL &&
|
|
pdt->_rgDriveTable[i]->GetFlags() & SR_DRIVE_SYSTEM)
|
|
{
|
|
return pdt->_rgDriveTable[i];
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::ForAllDrives
|
|
//
|
|
// Synopsis: Execute this CDataStore method for all drives
|
|
//
|
|
// Arguments: [pMethod] -- CDataStore method to call
|
|
// [lParam] -- parameter to that method
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::ForAllDrives (PDATASTOREMETHOD pMethod, LONG_PTR lParam)
|
|
{
|
|
TENTER ("ForAllDrives");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
for (CDriveTable *pdt = this; pdt != NULL; pdt = pdt->_pdtNext)
|
|
{
|
|
for (int i = 0; i < pdt->_nLastDrive; i++)
|
|
{
|
|
if (pdt->_rgDriveTable[i] != NULL)
|
|
{
|
|
dwErr = (pdt->_rgDriveTable[i]->*pMethod) (lParam);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
TRACE(0, "%S ForAllDrives failed %x", pdt->_rgDriveTable[i]->GetDrive(), dwErr);
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS && _fDirty)
|
|
dwErr = SaveDriveTable ((CRestorePoint *) NULL);
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::ForOneOrAllDrives
|
|
//
|
|
// Synopsis: Execute this CDataStore method for one or all drives
|
|
//
|
|
// Arguments: [pwszDrive] -- drive to execute method
|
|
// [pMethod] -- CDataStore method to call
|
|
// [lParam] -- parameter to that method
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::ForOneOrAllDrives (WCHAR *pwszDrive,
|
|
PDATASTOREMETHOD pMethod,
|
|
LONG_PTR lParam)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (pwszDrive == NULL)
|
|
{
|
|
dwErr = ForAllDrives (pMethod, lParam);
|
|
}
|
|
else
|
|
{
|
|
CDataStore *pds = FindDriveInTable (pwszDrive);
|
|
dwErr = (pds != NULL) ? (pds->*pMethod)(lParam) : ERROR_INVALID_DRIVE;
|
|
|
|
if (dwErr == ERROR_SUCCESS && _fDirty)
|
|
dwErr = SaveDriveTable ((CRestorePoint *) NULL);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::FindMountPoint
|
|
//
|
|
// Synopsis: Given a volume GUID, find a mount point that points to it
|
|
//
|
|
// Arguments: [pwszGuid] -- input volume GUID
|
|
// [pwszPath] -- output path to mount point
|
|
//
|
|
// Returns: Win32 error
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::FindMountPoint (WCHAR *pwszGuid, WCHAR *pwszPath) const
|
|
{
|
|
TENTER ("CDriveTable::FindMountPoint");
|
|
|
|
DWORD dwErr = ERROR_MORE_DATA; // initialize for loop
|
|
WCHAR * pwszMount = NULL; // MultiSz string
|
|
DWORD dwMountLen = MAX_PATH; // initial buffer size
|
|
DWORD dwChars = 0;
|
|
|
|
pwszPath[0] = L'\0';
|
|
|
|
while (dwErr == ERROR_MORE_DATA)
|
|
{
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
pwszMount = new WCHAR [dwMountLen];
|
|
if (pwszMount == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Err;
|
|
}
|
|
|
|
if (FALSE == GetVolumePathNamesForVolumeNameW (pwszGuid,
|
|
pwszMount,
|
|
dwMountLen,
|
|
&dwChars ))
|
|
{
|
|
dwErr = GetLastError();
|
|
delete [] pwszMount; // free the existing buffer
|
|
pwszMount = NULL;
|
|
dwMountLen *= 2; // double the length
|
|
}
|
|
}
|
|
|
|
if (ERROR_SUCCESS == dwErr && pwszMount != NULL)
|
|
{
|
|
if (L'\0' == pwszMount[0]) // empty string
|
|
{
|
|
dwErr = ERROR_NOT_DOS_DISK; // no drive letter or mount point
|
|
}
|
|
else if (lstrlenW (pwszMount) < MAX_MOUNTPOINT_PATH)
|
|
{
|
|
lstrcpyW (pwszPath, pwszMount); // copy the first string
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_BAD_PATHNAME; // 1st path too long
|
|
}
|
|
}
|
|
|
|
Err:
|
|
if (pwszMount != NULL)
|
|
delete [] pwszMount;
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::AddDriveToTable
|
|
//
|
|
// Synopsis: add the volume to the drive table
|
|
//
|
|
// Arguments: [pwszGuid] -- the volume GUID
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::AddDriveToTable(WCHAR *pwszDrive, WCHAR *pwszGuid)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (NULL == pwszDrive)
|
|
return ERROR_INVALID_DRIVE;
|
|
|
|
// Eventually, this routine will require pwszGuid to be non-NULL
|
|
CDataStore *pds = pwszGuid != NULL ? FindGuidInTable (pwszGuid) :
|
|
FindDriveInTable (pwszDrive);
|
|
|
|
if (pds != NULL) // found the drive already
|
|
{
|
|
if (lstrcmpiW (pwszDrive, pds->GetDrive()) != 0) // drive rename
|
|
pds->SetDrive (pwszDrive);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
pds = new CDataStore(this);
|
|
if (pds == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
return dwErr;
|
|
}
|
|
|
|
dwErr = pds->Initialize (pwszDrive, pwszGuid);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = CreateNewEntry (pds);
|
|
_fDirty = TRUE;
|
|
}
|
|
|
|
if (dwErr != ERROR_SUCCESS) // clean up on error
|
|
{
|
|
delete pds;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::FindFirstDrive
|
|
// CDriveTable::FindNextDrive
|
|
//
|
|
// Synopsis: loop through drive table entries
|
|
//
|
|
// Arguments: [dtec] -- enumeration context
|
|
//
|
|
// Returns: CDataStore object pointer
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStore * CDriveTable::FindFirstDrive (SDriveTableEnumContext & dtec) const
|
|
{
|
|
for (dtec._pdt = this; dtec._pdt != NULL; dtec._pdt = dtec._pdt->_pdtNext)
|
|
{
|
|
for (dtec._iIndex = 0; dtec._iIndex < dtec._pdt->_nLastDrive; dtec._iIndex++)
|
|
{
|
|
CDataStore *pds = dtec._pdt->_rgDriveTable[dtec._iIndex];
|
|
if (pds != NULL)
|
|
{
|
|
return pds;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CDataStore * CDriveTable::FindNextDrive (SDriveTableEnumContext & dtec) const
|
|
{
|
|
for (; dtec._pdt != NULL; dtec._pdt = dtec._pdt->_pdtNext)
|
|
{
|
|
dtec._iIndex++;
|
|
for (; dtec._iIndex < dtec._pdt->_nLastDrive; dtec._iIndex++)
|
|
{
|
|
CDataStore *pds = dtec._pdt->_rgDriveTable[dtec._iIndex];
|
|
|
|
if (pds != NULL)
|
|
{
|
|
return pds;
|
|
}
|
|
}
|
|
dtec._iIndex = 0;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::Merge
|
|
//
|
|
// Synopsis: loop through drive table entries and merge
|
|
//
|
|
// Arguments: [dt] -- drive table read from disk
|
|
//
|
|
// Returns: Win32 error
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::Merge (CDriveTable &dt)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fApplyDefaults = FALSE;
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
HKEY hKeyGP = NULL;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
s_cszGroupPolicy,
|
|
0,
|
|
KEY_READ,
|
|
&hKeyGP))
|
|
{
|
|
DWORD dwRet = 0;
|
|
if (ERROR_SUCCESS == RegReadDWORD(hKeyGP, s_cszDisableConfig, &dwRet))
|
|
{
|
|
if (dwRet == 0)
|
|
fApplyDefaults = TRUE;
|
|
}
|
|
RegCloseKey (hKeyGP);
|
|
}
|
|
|
|
CDataStore *pds = dt.FindFirstDrive (dtec);
|
|
while (pds != NULL)
|
|
{
|
|
CDataStore *pdsFound = FindGuidInTable (pds->GetGuid());
|
|
if (pdsFound != NULL)
|
|
{
|
|
pds->GetVolumeInfo(); // refresh the volume flags
|
|
|
|
if (fApplyDefaults)
|
|
{
|
|
pds->MonitorDrive(TRUE); // make sure drive is monitored
|
|
pds->SetSizeLimit(0); // set max datastore size to default
|
|
}
|
|
|
|
// don't overwrite the newer drive letter and label
|
|
dwErr = pdsFound->LoadDataStore (NULL, pds->GetGuid(), NULL,
|
|
pds->GetFlags() | SR_DRIVE_ACTIVE, pds->GetNumChangeLogs(), pds->GetSizeLimit());
|
|
}
|
|
else
|
|
{
|
|
CDataStore *pdsNew = new CDataStore ( this);
|
|
if (pdsNew == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
return dwErr;
|
|
}
|
|
|
|
dwErr = pdsNew->LoadDataStore (pds->GetDrive(), pds->GetGuid(),
|
|
pds->GetLabel(),
|
|
pds->GetFlags() & ~SR_DRIVE_ACTIVE,
|
|
pds->GetNumChangeLogs(), pds->GetSizeLimit());
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
delete pdsNew;
|
|
pdsNew = NULL;
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = CreateNewEntry (pdsNew);
|
|
}
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
|
|
pds = dt.FindNextDrive (dtec);
|
|
}
|
|
|
|
if (fApplyDefaults && g_pEventHandler != NULL)
|
|
{
|
|
dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
|
|
}
|
|
Err:
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::IsAdvancedRp()
|
|
//
|
|
// Synopsis: method to determine if a given restore point is an
|
|
// advanced restore point
|
|
//
|
|
// Arguments: restore point, pointer to flags
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDriveTable::IsAdvancedRp(CRestorePoint *prp, PDWORD pdwFlags)
|
|
{
|
|
TraceFunctEnter("CDriveTable::IsAdvancedRp");
|
|
|
|
WCHAR szPath[MAX_PATH];
|
|
WCHAR szSysDrive[MAX_PATH];
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CDataStore *pds = NULL;
|
|
CRestorePoint rp;
|
|
CDriveTable dt;
|
|
|
|
//
|
|
// read the drivetable file for this restore point
|
|
//
|
|
|
|
if (FALSE == GetSystemDrive(szSysDrive))
|
|
{
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
trace(0, "! GetSystemDrive : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
dwErr = GetCurrentRestorePoint(rp);
|
|
if ( dwErr != ERROR_SUCCESS )
|
|
goto Err;
|
|
|
|
//
|
|
// if no restore point specified, assume current
|
|
//
|
|
|
|
if (! prp)
|
|
prp = &rp;
|
|
if (prp->GetNum() == rp.GetNum())
|
|
{
|
|
MakeRestorePath(szPath, szSysDrive, s_cszDriveTable);
|
|
}
|
|
else
|
|
{
|
|
MakeRestorePath(szPath, szSysDrive, prp->GetDir());
|
|
PathAppend(szPath, s_cszDriveTable);
|
|
}
|
|
|
|
dwErr = dt.LoadDriveTable(szPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
//
|
|
// check if the rp directory exists on all drives
|
|
// if it does not, then it is an advanced restore point
|
|
//
|
|
|
|
*pdwFlags = RP_NORMAL;
|
|
pds = dt.FindFirstDrive(dtec);
|
|
while (pds)
|
|
{
|
|
//
|
|
// is the rp dir supposed to exist?
|
|
//
|
|
|
|
if ((pds->GetFlags() & SR_DRIVE_ACTIVE) &&
|
|
(pds->GetFlags() & SR_DRIVE_MONITORED) &&
|
|
(pds->GetFlags() & SR_DRIVE_PARTICIPATE) &&
|
|
!(pds->GetFlags() & SR_DRIVE_FROZEN))
|
|
{
|
|
MakeRestorePath(szPath, pds->GetDrive(), rp.GetDir());
|
|
if (0xFFFFFFFF == GetFileAttributes(szPath))
|
|
{
|
|
*pdwFlags = RP_ADVANCED;
|
|
break;
|
|
}
|
|
}
|
|
pds = dt.FindNextDrive(dtec);
|
|
}
|
|
|
|
Err:
|
|
TraceFunctLeave();
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::AnyMountedDrives()
|
|
//
|
|
// Synopsis: check if there are any mounted drives
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 25-Oct-2000 Brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
BOOL CDriveTable::AnyMountedDrives()
|
|
{
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
CDataStore *pds = FindFirstDrive(dtec);
|
|
while (pds)
|
|
{
|
|
//
|
|
// get the first '\' in the drive path
|
|
// if this is not the last character in the path
|
|
// then this is a mount point
|
|
//
|
|
|
|
LPWSTR pszfirst = wcschr(pds->GetDrive(), L'\\');
|
|
if (pszfirst &&
|
|
pszfirst != pds->GetDrive() + (lstrlen(pds->GetDrive()) - 1))
|
|
{
|
|
return TRUE;
|
|
}
|
|
pds = FindNextDrive(dtec);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::CDataStoreMgr()
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStoreMgr::CDataStoreMgr()
|
|
{
|
|
_fStop = FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::~CDataStoreMgr()
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CDataStoreMgr::~CDataStoreMgr()
|
|
{
|
|
}
|
|
|
|
|
|
// helper functions for Fifo
|
|
|
|
BOOL
|
|
IsCurrentRp(CRestorePoint& rp, CRestorePoint& rpCur)
|
|
{
|
|
return rp.GetNum() == rpCur.GetNum();
|
|
}
|
|
|
|
BOOL
|
|
IsTargetPercentMet(int nUsagePercent, int nTargetPercent)
|
|
{
|
|
return nUsagePercent <= nTargetPercent;
|
|
}
|
|
|
|
BOOL
|
|
IsTargetRpMet(DWORD dwRPNum, DWORD dwTargetRPNum)
|
|
{
|
|
return dwRPNum > dwTargetRPNum;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::Fifo
|
|
//
|
|
// Synopsis: fifo restore points upto a given percentage
|
|
//
|
|
// Arguments: drive to fifo, target RP dir, target percentage to stop fifo
|
|
// specify only one of both (dwTargetRPNum or nTargetPercent)
|
|
// fIncludeCurrentRp = TRUE : fifo current rp if necessary (i.e. freeze)
|
|
// fIncludeCurrentRp = FALSE : don't fifo current rp
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
// History: 27-Apr-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::Fifo(
|
|
WCHAR *pwszDrive,
|
|
DWORD dwTargetRPNum,
|
|
int nTargetPercent,
|
|
BOOL fIncludeCurrentRp,
|
|
BOOL fFifoAtLeastOneRp
|
|
)
|
|
{
|
|
TENTER("CDataStoreMgr::Fifo");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CDataStore *pds = _dt.FindDriveInTable(pwszDrive);
|
|
BOOL fFifoed = FALSE;
|
|
DWORD dwLastFifoedRp;
|
|
CDataStore *pdsLead = NULL;
|
|
BOOL fFirstIteration;
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
CRestorePointEnum *prpe = NULL;
|
|
CRestorePoint *prp = new CRestorePoint;
|
|
|
|
// can't specify many target criteria
|
|
|
|
if (dwTargetRPNum != 0 && nTargetPercent != 0)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Err;
|
|
}
|
|
|
|
// can't specify no target criteria
|
|
|
|
if (fIncludeCurrentRp == TRUE && dwTargetRPNum == 0 && nTargetPercent == 0)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Err;
|
|
}
|
|
|
|
|
|
// can't specify bad target criteria
|
|
|
|
if (dwTargetRPNum > g_pEventHandler->m_CurRp.GetNum() ||
|
|
nTargetPercent < 0 ||
|
|
nTargetPercent > 100)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Err;
|
|
}
|
|
|
|
if (!prp)
|
|
{
|
|
trace(0, "cannot allocate memory for restore point");
|
|
dwErr = ERROR_OUTOFMEMORY;
|
|
goto Err;
|
|
}
|
|
|
|
if (! pds)
|
|
{
|
|
TRACE(0, "! Drive %S not in drivetable", pwszDrive);
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
goto Err;
|
|
}
|
|
|
|
if (! (pds->GetFlags() & SR_DRIVE_MONITORED) ||
|
|
(pds->GetFlags() & SR_DRIVE_FROZEN) )
|
|
{
|
|
trace(0, "Drive %S already frozen/disabled", pwszDrive);
|
|
goto Err;
|
|
}
|
|
|
|
if (g_pSRConfig->m_dwTestBroadcast)
|
|
PostTestMessage(g_pSRConfig->m_uiTMFifoStart, (WPARAM) NULL, (LPARAM) NULL);
|
|
|
|
|
|
pdsLead = NULL;
|
|
fFirstIteration = TRUE;
|
|
while (pds)
|
|
{
|
|
fFifoed = FALSE;
|
|
|
|
//
|
|
// skip the drive we fifoed first
|
|
//
|
|
|
|
if (pds != pdsLead)
|
|
{
|
|
//
|
|
// enum forward, don't skip last
|
|
//
|
|
|
|
prpe = new CRestorePointEnum( pds->GetDrive(), TRUE, FALSE );
|
|
|
|
if (!prpe)
|
|
{
|
|
trace(0, "cannot allocate memory for restore point enum");
|
|
dwErr = ERROR_OUTOFMEMORY;
|
|
goto Err;
|
|
}
|
|
|
|
|
|
{
|
|
WCHAR szFifoedRpPath[MAX_PATH];
|
|
|
|
//
|
|
// blow away any obsolete "Fifoed" directories
|
|
//
|
|
|
|
MakeRestorePath(szFifoedRpPath, pwszDrive, s_cszFifoedRpDir);
|
|
|
|
CHECKERR(Delnode_Recurse(szFifoedRpPath, TRUE, &_fStop),
|
|
"Denode_Recurse Fifoed");
|
|
|
|
//
|
|
// blow away any obsolete "RP0" directories
|
|
//
|
|
|
|
MakeRestorePath(szFifoedRpPath, pwszDrive, L"RP0");
|
|
dwErr = Delnode_Recurse(szFifoedRpPath, TRUE, &_fStop);
|
|
|
|
if (ERROR_SUCCESS != dwErr)
|
|
{
|
|
trace (0, "Cannot FIFO RP0 error %d, ignoring", dwErr);
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// loop through restore points on this drive
|
|
//
|
|
|
|
dwErr = prpe->FindFirstRestorePoint (*prp);
|
|
|
|
//
|
|
// enumeration can return ERROR_FILE_NOT_FOUND for restorepoints
|
|
// that are missing rp.log
|
|
// we will just continue in this case
|
|
//
|
|
|
|
while (dwErr == ERROR_SUCCESS || dwErr == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
//
|
|
// check for the stop event
|
|
//
|
|
|
|
ASSERT(g_pSRConfig);
|
|
if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
|
|
{
|
|
TRACE(0, "Stop signalled - aborting fifo");
|
|
dwErr = ERROR_OPERATION_ABORTED;
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// check if fifo is disabled from this restore point
|
|
//
|
|
|
|
if (g_pSRConfig->GetFifoDisabledNum() != 0 &&
|
|
prp->GetNum() >= g_pSRConfig->GetFifoDisabledNum())
|
|
{
|
|
TRACE(0, "Fifo disabled from %S", prp->GetDir());
|
|
break;
|
|
}
|
|
|
|
//
|
|
// check if we've reached target restore point or percentage
|
|
//
|
|
|
|
if (dwTargetRPNum)
|
|
{
|
|
if (IsTargetRpMet(prp->GetNum(), dwTargetRPNum))
|
|
{
|
|
TRACE(0, "Target restore point reached");
|
|
break;
|
|
}
|
|
}
|
|
else if (nTargetPercent && FALSE == fFifoAtLeastOneRp)
|
|
{
|
|
int nUsagePercent = 0;
|
|
|
|
if (ERROR_SUCCESS == pds->GetUsagePercent(&nUsagePercent) &&
|
|
IsTargetPercentMet(nUsagePercent, nTargetPercent))
|
|
{
|
|
TRACE(0, "Target percentage reached");
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check if we've reached the current rp
|
|
//
|
|
|
|
if (IsCurrentRp(*prp, g_pEventHandler->m_CurRp))
|
|
{
|
|
if (fIncludeCurrentRp)
|
|
{
|
|
//
|
|
// need to fifo this one too
|
|
// this is same as freezing the drive
|
|
// so freeze
|
|
//
|
|
|
|
dwErr = FreezeDrive(pwszDrive);
|
|
goto Err;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// don't fifo current rp
|
|
// (usually called from Disk Cleanup)
|
|
//
|
|
|
|
trace(0, "No more rps to fifo");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// throw away this restore point on this drive
|
|
//
|
|
|
|
dwErr = pds->FifoRestorePoint (*prp);
|
|
if ( ERROR_SUCCESS != dwErr )
|
|
{
|
|
TRACE(0, "! FifoRestorePoint on %S on drive %S : %ld",
|
|
prp->GetDir(), pwszDrive, dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// record in the fifo log
|
|
//
|
|
|
|
WriteFifoLog (prp->GetDir(), pds->GetDrive());
|
|
dwLastFifoedRp = prp->GetNum();
|
|
fFifoed = TRUE;
|
|
fFifoAtLeastOneRp = FALSE;
|
|
|
|
dwErr = prpe->FindNextRestorePoint(*prp);
|
|
}
|
|
|
|
if (prpe)
|
|
{
|
|
delete prpe;
|
|
prpe = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// go to next drive
|
|
//
|
|
|
|
if (fFirstIteration)
|
|
{
|
|
if (! fFifoed) // we did not fifo anything
|
|
{
|
|
break;
|
|
}
|
|
|
|
pdsLead = pds;
|
|
pds = _dt.FindFirstDrive(dtec);
|
|
fFirstIteration = FALSE;
|
|
dwTargetRPNum = dwLastFifoedRp; // fifo till what we fifoed just now
|
|
nTargetPercent = 0;
|
|
fIncludeCurrentRp = TRUE;
|
|
fFifoAtLeastOneRp = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pds = _dt.FindNextDrive(dtec);
|
|
}
|
|
}
|
|
|
|
|
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
if (g_pSRConfig->m_dwTestBroadcast)
|
|
PostTestMessage(g_pSRConfig->m_uiTMFifoStop, (WPARAM) dwLastFifoedRp, (LPARAM) NULL);
|
|
|
|
Err:
|
|
if (prpe)
|
|
delete prpe;
|
|
if (prp)
|
|
delete prp;
|
|
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::WriteFifoLog
|
|
//
|
|
// Synopsis: appends to the fifo log
|
|
//
|
|
// Arguments: dir name of restore point fifoed, drive
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 27-Apr-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDataStoreMgr::WriteFifoLog(LPWSTR pwszDir, LPWSTR pwszDrive)
|
|
{
|
|
FILE *f = NULL;
|
|
WCHAR szLog[MAX_PATH];
|
|
DWORD dwRc = ERROR_INTERNAL_ERROR;
|
|
WCHAR wszTime[MAX_PATH] = L"";
|
|
WCHAR wszDate[MAX_PATH] = L"";
|
|
CDataStore *pds = NULL;
|
|
|
|
TENTER("CDataStoreMgr::WriteFifoLog");
|
|
|
|
TRACE(0, "Fifoed %S on drive %S", pwszDir, pwszDrive);
|
|
|
|
if (pds = _dt.FindSystemDrive())
|
|
{
|
|
MakeRestorePath(szLog, pds->GetDrive(), s_cszFifoLog);
|
|
|
|
f = (FILE *) _wfopen(szLog, L"a");
|
|
if (f)
|
|
{
|
|
_wstrdate(wszDate);
|
|
_wstrtime(wszTime);
|
|
fwprintf(f, L"%s-%s : Fifoed %s on drive %s\n", wszDate, wszTime, pwszDir, pwszDrive);
|
|
fclose(f);
|
|
dwRc = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
TRACE(0, "_wfopen failed on %s", szLog);
|
|
}
|
|
}
|
|
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::EnumAllVolumes
|
|
//
|
|
// Synopsis: enumerates all local volumes and updates the drive table
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Win32 error code
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::EnumAllVolumes ()
|
|
{
|
|
TENTER("CDriveTable::EnumAllVolumes");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wcsVolumeName[MAX_PATH];
|
|
WCHAR wcsDosName[MAX_PATH];
|
|
|
|
//
|
|
// Let's first get all the local volumes
|
|
//
|
|
HANDLE hVolume = FindFirstVolume (wcsVolumeName, MAX_PATH);
|
|
|
|
// If we can't even find one volume, return an error
|
|
if (hVolume == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = GetLastError();
|
|
return dwErr;
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// We have to find a mount point that points to this volume
|
|
// If there is no such mount point, then the volume is not
|
|
// accessible, and we ignore it
|
|
//
|
|
dwErr = FindMountPoint (wcsVolumeName, wcsDosName);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = AddDriveToTable (wcsDosName, wcsVolumeName);
|
|
|
|
if (dwErr == ERROR_BAD_DEV_TYPE || //add only fixed drives
|
|
dwErr == ERROR_UNRECOGNIZED_VOLUME) //unformatted
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
goto Err;
|
|
}
|
|
}
|
|
}
|
|
while (FindNextVolume (hVolume, wcsVolumeName, MAX_PATH));
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
Err:
|
|
FindVolumeClose (hVolume);
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::LoadDriveTable
|
|
//
|
|
// Synopsis: loads a drive table from a restore point directory
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::LoadDriveTable (WCHAR *pwszPath)
|
|
{
|
|
TENTER ("CDriveTable::LoadDriveTable");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (FALSE == _fLockInit)
|
|
{
|
|
dwErr = _lock.Init();
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
_fLockInit = TRUE;
|
|
}
|
|
BOOL fLocked = _lock.Lock(CLock::TIMEOUT);
|
|
if (!fLocked)
|
|
{
|
|
return WAIT_TIMEOUT;
|
|
}
|
|
|
|
CDataStore *pds = NULL;
|
|
WCHAR *pwcBuffer = NULL;
|
|
WCHAR *pwszLine = NULL;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
DWORD dwFlags = 0;
|
|
DWORD dwFileSize = 0;
|
|
DWORD cbRead = 0;
|
|
int iChangeLogs = 0;
|
|
WCHAR wcsDrive[MAX_PATH] = L"";
|
|
WCHAR wcsGuid[GUID_STRLEN] = L"";
|
|
WCHAR wcsLabel[CDataStore::LABEL_STRLEN];
|
|
DWORD dwSizeLimit = 0;
|
|
|
|
hFile = CreateFileW ( pwszPath, // file name
|
|
GENERIC_READ, // file access
|
|
FILE_SHARE_READ, // share mode
|
|
NULL, // SD
|
|
OPEN_EXISTING, // how to create
|
|
0, // file attributes
|
|
NULL); // handle to template file
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
dwErr = GetLastError();
|
|
goto Err;
|
|
}
|
|
|
|
dwFileSize = GetFileSize (hFile, NULL);
|
|
if (dwFileSize > SR_DEFAULT_DSMAX * MEGABYTE)
|
|
{
|
|
dwErr = ERROR_FILE_CORRUPT;
|
|
goto Err;
|
|
}
|
|
|
|
pwcBuffer = (WCHAR *) SRMemAlloc (dwFileSize);
|
|
if (pwcBuffer == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto Err;
|
|
}
|
|
|
|
if (FALSE == ReadFile (hFile, (BYTE*)pwcBuffer, dwFileSize, &cbRead, NULL))
|
|
{
|
|
dwErr = GetLastError();
|
|
goto Err;
|
|
}
|
|
|
|
pwszLine = pwcBuffer;
|
|
for (UINT i = 0; i < dwFileSize / sizeof(WCHAR); i++)
|
|
{
|
|
if (pwcBuffer[i] == L'\n')
|
|
{
|
|
pwcBuffer[i] = L'\0'; // convert all newlines to terminators
|
|
wcsLabel[0] = L'\0'; // initialize in case scanf terminates early
|
|
|
|
if (EOF != swscanf(pwszLine, gs_wcsScanFormat, wcsDrive,
|
|
wcsGuid, &dwFlags, &iChangeLogs,
|
|
&dwSizeLimit, wcsLabel))
|
|
{
|
|
pds = new CDataStore ( this);
|
|
if (pds == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
return dwErr;
|
|
}
|
|
|
|
dwErr = pds->LoadDataStore (wcsDrive, wcsGuid,
|
|
wcsLabel, dwFlags, iChangeLogs,
|
|
(INT64) dwSizeLimit * MEGABYTE);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
dwErr = CreateNewEntry (pds);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
}
|
|
pwszLine = &pwcBuffer[i+1]; // skip to next line
|
|
}
|
|
}
|
|
|
|
Err:
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle (hFile);
|
|
|
|
if (pwcBuffer != NULL)
|
|
SRMemFree (pwcBuffer);
|
|
|
|
if (fLocked)
|
|
_lock.Unlock();
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDriveTable::SaveDriveTable
|
|
//
|
|
// Synopsis: saves a drive table into a restore point directory
|
|
//
|
|
// Arguments: [prp] -- restore point to save into
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDriveTable::SaveDriveTable (CRestorePoint *prp)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wcsPath[MAX_PATH];
|
|
CDataStore *pds = FindSystemDrive();
|
|
|
|
if (NULL == pds)
|
|
{
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
goto Err;
|
|
}
|
|
|
|
if (prp == NULL) // no restore point, so save to the datastore directory
|
|
{
|
|
MakeRestorePath(wcsPath, pds->GetDrive(), L"");
|
|
}
|
|
else
|
|
{
|
|
MakeRestorePath(wcsPath, pds->GetDrive(), prp->GetDir());
|
|
}
|
|
|
|
lstrcatW (wcsPath, L"\\");
|
|
lstrcatW (wcsPath, s_cszDriveTable);
|
|
|
|
dwErr = SaveDriveTable (wcsPath);
|
|
|
|
Err:
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD CDriveTable::SaveDriveTable (WCHAR *pwszPath)
|
|
{
|
|
TENTER ("CDriveTable::SaveDriveTable");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (FALSE == _fLockInit)
|
|
{
|
|
dwErr = _lock.Init();
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
_fLockInit = TRUE;
|
|
}
|
|
BOOL fLocked = _lock.Lock(CLock::TIMEOUT);
|
|
if (!fLocked)
|
|
{
|
|
return WAIT_TIMEOUT;
|
|
}
|
|
|
|
BOOL fDirtySave = _fDirty; // save the dirty bit
|
|
|
|
HANDLE hFile = CreateFileW ( pwszPath, // file name
|
|
GENERIC_WRITE, // file access
|
|
0, // share mode
|
|
NULL, // SD
|
|
CREATE_ALWAYS, // how to create
|
|
FILE_FLAG_WRITE_THROUGH, // file attributes
|
|
NULL); // handle to template file
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
dwErr = GetLastError();
|
|
goto Err;
|
|
}
|
|
|
|
_fDirty = FALSE; // avoid calling back into SaveDriveTable again
|
|
|
|
dwErr = ForAllDrives (CDataStore::SaveDataStore, (LONG_PTR) hFile);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
if (lstrcmp (pwszPath, L"CONOUT$") != 0)
|
|
{
|
|
if (FALSE == FlushFileBuffers (hFile)) // make sure it's on disk
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
Err:
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle (hFile);
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
_fDirty = FALSE;
|
|
else
|
|
_fDirty = fDirtySave;
|
|
|
|
if (fLocked)
|
|
_lock.Unlock();
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::Initialize
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments: fFirstRun -- true if run on first boot
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::Initialize (BOOL fFirstRun)
|
|
{
|
|
TENTER("CDataStoreMgr::Initialize");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
dwErr = _dt.EnumAllVolumes();
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
CDataStore *pds = _dt.FindSystemDrive();
|
|
|
|
// now create system datastore on firstrun
|
|
|
|
if (pds != NULL)
|
|
{
|
|
WCHAR wcsPath[MAX_PATH];
|
|
|
|
if (fFirstRun)
|
|
{
|
|
// destroy datastores on all drives and
|
|
// create new on system drive
|
|
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
|
|
CDataStore *pdsDel = _dt.FindFirstDrive (dtec);
|
|
while (pdsDel != NULL)
|
|
{
|
|
if (pdsDel->GetFlags() & (SR_DRIVE_ACTIVE))
|
|
{
|
|
dwErr = pdsDel->DestroyDataStore (TRUE);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! DestroyDataStore : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
}
|
|
pdsDel = _dt.FindNextDrive (dtec);
|
|
}
|
|
|
|
dwErr = pds->CreateDataStore (NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! CreateDataStore : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
(void) WriteMachineGuid();
|
|
}
|
|
else // verify that the system datastore exists
|
|
{
|
|
CDriveTable dt;
|
|
|
|
MakeRestorePath (wcsPath, pds->GetDrive(), L"");
|
|
|
|
DWORD dwAttr = GetFileAttributes (wcsPath);
|
|
if (0xFFFFFFFF==dwAttr || !(FILE_ATTRIBUTE_DIRECTORY & dwAttr))
|
|
{
|
|
dwErr = pds->CreateDataStore( NULL );
|
|
}
|
|
|
|
MakeRestorePath(wcsPath, pds->GetDrive(), s_cszDriveTable);
|
|
if (ERROR_SUCCESS == dt.LoadDriveTable (wcsPath))
|
|
{
|
|
dwErr = _dt.Merge(dt);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! CDriveTable::Merge : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
}
|
|
}
|
|
|
|
// update the disk free space variable and
|
|
// set datastore size for each datastore if not already done
|
|
|
|
dwErr = UpdateDiskFree(NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! UpdateDiskFree : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
// freeze system drive if this is firstrun and disk free is < 200MB
|
|
|
|
if (fFirstRun && g_pSRConfig)
|
|
{
|
|
if (pds->GetDiskFree() < (g_pSRConfig->m_dwDSMin * MEGABYTE))
|
|
{
|
|
dwErr = FreezeDrive(pds->GetGuid());
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! FreezeDrive : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
}
|
|
}
|
|
|
|
MakeRestorePath(wcsPath, pds->GetDrive(), s_cszDriveTable);
|
|
dwErr = _dt.SaveDriveTable (wcsPath);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! SaveDriveTable : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
}
|
|
else dwErr = ERROR_INVALID_DRIVE;
|
|
}
|
|
Err:
|
|
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::TriggerFreezeOrFifo
|
|
//
|
|
// Synopsis: checks freedisk space & datastore size,
|
|
// triggering freeze or fifo as required
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 27-Apr-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDataStoreMgr::TriggerFreezeOrFifo()
|
|
{
|
|
TENTER("CDataStoreMgr::TriggerFreezeOrFifo");
|
|
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
DWORD dwRc = ERROR_SUCCESS;
|
|
CDataStore *pds = _dt.FindFirstDrive (dtec);
|
|
|
|
// update datastore capacities
|
|
// and get free space on each drive
|
|
|
|
dwRc = UpdateDiskFree(NULL);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! UpdateDiskFree : %ld", dwRc);
|
|
goto done;
|
|
}
|
|
|
|
// check the free space and datastore usage
|
|
|
|
while (pds != NULL && dwRc == ERROR_SUCCESS)
|
|
{
|
|
// we care only if the drive is not already frozen
|
|
// and if it is monitored
|
|
|
|
if (!(pds->GetFlags() & SR_DRIVE_FROZEN) &&
|
|
(pds->GetFlags() & SR_DRIVE_MONITORED))
|
|
{
|
|
//
|
|
// if there is no rp on this drive,
|
|
// then we don't really care
|
|
//
|
|
|
|
CRestorePointEnum rpe((LPWSTR) pds->GetDrive(), FALSE, FALSE); // backward, include current
|
|
CRestorePoint rp;
|
|
int nUsagePercent = 0;
|
|
|
|
DWORD dwErr = rpe.FindFirstRestorePoint(rp) ;
|
|
if (dwErr == ERROR_SUCCESS || dwErr == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
if (pds->GetDiskFree() <= THRESHOLD_FREEZE_DISKSPACE * MEGABYTE)
|
|
{
|
|
dwRc = FreezeDrive(pds->GetGuid());
|
|
}
|
|
else if (pds->GetDiskFree() <= THRESHOLD_FIFO_DISKSPACE * MEGABYTE)
|
|
{
|
|
dwRc = Fifo(pds->GetGuid(), 0, TARGET_FIFO_PERCENT, TRUE, TRUE);
|
|
}
|
|
else if (ERROR_SUCCESS == pds->GetUsagePercent(&nUsagePercent)
|
|
&& nUsagePercent >= THRESHOLD_FIFO_PERCENT)
|
|
{
|
|
dwRc = Fifo(pds->GetGuid(), 0, TARGET_FIFO_PERCENT, TRUE, FALSE);
|
|
}
|
|
}
|
|
|
|
rpe.FindClose();
|
|
}
|
|
|
|
pds = _dt.FindNextDrive (dtec);
|
|
}
|
|
|
|
done:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::FindFrozenDrive
|
|
//
|
|
// Synopsis: returns ERROR_SUCCESS if any drives are frozen
|
|
// ERROR_NO_MORE_ITEMS otherwise
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 27-Apr-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDataStoreMgr::FindFrozenDrive()
|
|
{
|
|
CDataStore * pds = NULL;
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
|
|
pds = _dt.FindFirstDrive (dtec);
|
|
|
|
while (pds != NULL)
|
|
{
|
|
if ((pds->GetFlags() & SR_DRIVE_MONITORED) &&
|
|
(pds->GetFlags() & SR_DRIVE_FROZEN))
|
|
return ERROR_SUCCESS;
|
|
|
|
pds = _dt.FindNextDrive (dtec);
|
|
}
|
|
|
|
return ERROR_NO_MORE_ITEMS;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::FifoOldRps
|
|
//
|
|
// Synopsis: fifoes out restore points older than a given time period
|
|
//
|
|
// Arguments: [llTimeInSeconds] -- FIFO interval time
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 14-Jul-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD
|
|
CDataStoreMgr::FifoOldRps(
|
|
INT64 llTimeInSeconds)
|
|
{
|
|
TENTER("CDataStoreMgr::FifoOldRps");
|
|
|
|
CDataStore *pds = _dt.FindSystemDrive();
|
|
DWORD dwRc = ERROR_SUCCESS;
|
|
CRestorePointEnum *prpe = NULL;
|
|
CRestorePoint *prp = NULL;
|
|
|
|
if (pds)
|
|
{
|
|
DWORD dwRpFifo = 0;
|
|
LARGE_INTEGER *pllRp = NULL, *pllNow = NULL;
|
|
FILETIME ftNow, *pftRp = NULL;
|
|
|
|
// enumerate RPs forward on the system drive
|
|
// skip the current one
|
|
// even if the current rp is older than a month, we won't fifo it
|
|
|
|
prpe = new CRestorePointEnum(pds->GetDrive(), TRUE, TRUE);
|
|
prp = new CRestorePoint;
|
|
|
|
if (!prpe || !prp)
|
|
{
|
|
trace(0, "Cannot allocate memory for restore point enum");
|
|
dwRc = ERROR_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
// get the current time
|
|
|
|
GetSystemTimeAsFileTime(&ftNow);
|
|
pllNow = (LARGE_INTEGER *) &ftNow;
|
|
|
|
dwRc = prpe->FindFirstRestorePoint(*prp);
|
|
|
|
while (dwRc == ERROR_SUCCESS || dwRc == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
// first check if this is not a cancelled restore point
|
|
|
|
if (dwRc != ERROR_FILE_NOT_FOUND && ! prp->IsDefunct())
|
|
{
|
|
// get the restore point creation time
|
|
|
|
pftRp = prp->GetTime();
|
|
pllRp = (LARGE_INTEGER *) pftRp;
|
|
|
|
if (!pllRp || !pllNow)
|
|
{
|
|
trace(0, "! pulRp or pulNow = NULL");
|
|
dwRc = ERROR_INTERNAL_ERROR;
|
|
goto done;
|
|
}
|
|
|
|
// check if it is newer than a month
|
|
// if so, stop looking
|
|
// else, try the next restore point
|
|
|
|
if (pllNow->QuadPart - pllRp->QuadPart < llTimeInSeconds * 10 * 1000 * 1000)
|
|
{
|
|
trace(0, "%S newer than a month", prp->GetDir());
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
dwRpFifo = prp->GetNum();
|
|
}
|
|
}
|
|
|
|
dwRc = prpe->FindNextRestorePoint(*prp);
|
|
}
|
|
|
|
// at this point, if dwRpFifo != 0,
|
|
// it contains the latest RP that's older than a month
|
|
// call fifo on this to fifo out all previous RPs including this one
|
|
|
|
if (dwRpFifo != 0)
|
|
dwRc = Fifo(pds->GetGuid(), dwRpFifo, 0, FALSE, FALSE);
|
|
else
|
|
dwRc = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
trace(0, "! FindSystemDrive");
|
|
dwRc = ERROR_INVALID_DRIVE;
|
|
}
|
|
|
|
done:
|
|
if (prpe)
|
|
delete prpe;
|
|
if (prp)
|
|
delete prp;
|
|
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::UpdateDataStoreUsage
|
|
//
|
|
// Synopsis: update the size of a datastore
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 27-Apr-2000 brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDataStoreMgr::UpdateDataStoreUsage(WCHAR *pwszDrive, INT64 llDelta)
|
|
{
|
|
TENTER ("CDataStoreMgr::UpdateDataStoreUsage");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CDataStore *pds = _dt.FindDriveInTable(pwszDrive);
|
|
|
|
if (pds)
|
|
{
|
|
if ((pds->GetFlags() & SR_DRIVE_FROZEN) ||
|
|
! (pds->GetFlags() & SR_DRIVE_MONITORED))
|
|
{
|
|
TRACE(0, "Size update on frozen/unmonitored drive!");
|
|
}
|
|
else dwErr = pds->UpdateDataStoreUsage(llDelta, TRUE);
|
|
}
|
|
else
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
|
|
TLEAVE();
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::GetFlags
|
|
//
|
|
// Synopsis: get the participation bit from a drive
|
|
//
|
|
// Arguments: [pwszDrive] -- drive letter
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::GetFlags(WCHAR *pwszDrive, PDWORD pdwFlags)
|
|
{
|
|
CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (NULL != pds)
|
|
{
|
|
*pdwFlags = pds->GetFlags();
|
|
}
|
|
else dwErr = ERROR_INVALID_DRIVE;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::GetUsagePercent
|
|
//
|
|
// Synopsis: get the datastore usage for a drive
|
|
//
|
|
// Arguments: [pwszDrive] -- drive letter
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::GetUsagePercent(WCHAR *pwszDrive, int *pnPercent)
|
|
{
|
|
CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (NULL != pds)
|
|
{
|
|
dwErr = pds->GetUsagePercent(pnPercent);
|
|
}
|
|
else dwErr = ERROR_INVALID_DRIVE;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::SwitchRestorePoint
|
|
//
|
|
// Synopsis: change the drive table when switching restore points
|
|
//
|
|
// Arguments: [prp] -- old restore point
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::SwitchRestorePoint (CRestorePoint *prp)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
dwErr = _dt.ForAllDrives (&CDataStore::CountChangeLogs, (LONG_PTR) prp);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
// persist old restore point dt
|
|
|
|
if (prp)
|
|
{
|
|
dwErr = _dt.SaveDriveTable (prp);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
}
|
|
|
|
// remove old volumes
|
|
|
|
dwErr = _dt.RemoveDrivesFromTable ();
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
// reset per-rp flags
|
|
|
|
dwErr = _dt.ForAllDrives (&CDataStore::ResetFlags, NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto Err;
|
|
|
|
// persist current restore point dt
|
|
|
|
dwErr = _dt.SaveDriveTable((CRestorePoint *) NULL);
|
|
|
|
Err:
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::FreezeDrive
|
|
//
|
|
// Synopsis: freeze a drive
|
|
//
|
|
// Arguments: [pwszDrive] -- drive
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::FreezeDrive(WCHAR *pwszDrive)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR szThawSize[GUID_STRLEN], szSystemDrive[MAX_SYS_DRIVE] = L" ";
|
|
|
|
|
|
TENTER("CDataStoreMgr::FreezeDrive");
|
|
|
|
if (pwszDrive != NULL)
|
|
{
|
|
CDataStore *pds = _dt.FindDriveInTable (pwszDrive);
|
|
|
|
if (! pds)
|
|
{
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
TRACE (0, "FindDriveInTable failed in CDataStoreMgr::FreezeDrive %ld\n", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
//
|
|
// freeze all drives
|
|
//
|
|
}
|
|
|
|
dwErr = _dt.ForAllDrives (CDataStore::FreezeDrive, NULL);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// rebuild _filelst.cfg and pass to filter
|
|
//
|
|
|
|
ASSERT(g_pEventHandler);
|
|
dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
|
|
|
|
if (g_pSRService != NULL)
|
|
{
|
|
if (g_pSRConfig && g_pSRConfig->m_dwFreezeThawLogCount < MAX_FREEZETHAW_LOG_MESSAGES)
|
|
{
|
|
TRACE (0, "Freezing the SR service due to low disk space.");
|
|
wsprintf(szThawSize, L"%d",THRESHOLD_THAW_DISKSPACE);
|
|
if (pwszDrive == NULL)
|
|
{
|
|
if(GetSystemDrive(szSystemDrive) == FALSE)
|
|
TRACE (0, "GetSystemDrive failed in CDataStoreMgr::FreezeDrive.");
|
|
pwszDrive = szSystemDrive;
|
|
}
|
|
g_pSRService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_FROZEN, NULL, 0, szThawSize, pwszDrive);
|
|
g_pSRConfig->m_dwFreezeThawLogCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// request for idle time
|
|
// so that we can thaw later
|
|
//
|
|
|
|
ASSERT(g_pSRConfig);
|
|
SetEvent(g_pSRConfig->m_hIdleRequestEvent);
|
|
|
|
if (g_pEventHandler)
|
|
g_pEventHandler->RefreshCurrentRp(FALSE);
|
|
|
|
if (g_pSRConfig->m_dwTestBroadcast)
|
|
PostTestMessage(g_pSRConfig->m_uiTMFreeze, NULL, NULL);
|
|
|
|
Err:
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::IsDriveFrozen
|
|
//
|
|
// Synopsis: check if given drive is frozen
|
|
// if NULL, check if any drive is frozen
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 21-Jul-2000 Brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOL CDataStoreMgr::IsDriveFrozen(LPWSTR pszDrive)
|
|
{
|
|
CDataStore *pds = NULL;
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
|
|
if (!pszDrive)
|
|
{
|
|
pds = _dt.FindFirstDrive(dtec);
|
|
while (pds)
|
|
{
|
|
if (pds->GetFlags() & SR_DRIVE_FROZEN)
|
|
return TRUE;
|
|
pds = _dt.FindNextDrive(dtec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CDataStore *pds = _dt.FindDriveInTable(pszDrive);
|
|
if (pds)
|
|
{
|
|
if (pds->GetFlags() & SR_DRIVE_FROZEN)
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::ThawDrives
|
|
//
|
|
// Synopsis: thaw one or more drives
|
|
//
|
|
// Arguments: [fCheckOnly] -- if TRUE do not actually thaw
|
|
//
|
|
// Returns: if any drive is thawed, returns ERROR_SUCCESS
|
|
// else returns ERROR_NO_MORE_ITEMS
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
CDataStoreMgr::ThawDrives(BOOL fCheckOnly)
|
|
{
|
|
TENTER("CDataStoreMgr::ThawDrives");
|
|
|
|
CDataStore *pds = NULL, *pdsSys = _dt.FindSystemDrive();
|
|
DWORD dwRc = ERROR_NO_MORE_ITEMS;
|
|
SDriveTableEnumContext dtec;
|
|
DWORD dwTemp;
|
|
|
|
if (! pdsSys)
|
|
{
|
|
dwRc = ERROR_INVALID_DRIVE;
|
|
TRACE (0, "Cannot find system drive %ld\n", dwRc);
|
|
goto done;
|
|
}
|
|
|
|
// if system drive is frozen, then check if 200mb is free
|
|
// if yes, then thaw all drives
|
|
// if no, thaw none
|
|
|
|
ASSERT(pdsSys->GetFlags() & SR_DRIVE_MONITORED);
|
|
|
|
if ((pdsSys->GetFlags() & SR_DRIVE_FROZEN))
|
|
{
|
|
dwRc = pdsSys->UpdateDiskFree(NULL);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
{
|
|
trace(0, "! UpdateDiskFree : %ld", dwRc);
|
|
goto done;
|
|
}
|
|
|
|
if (pdsSys->GetDiskFree() >= THRESHOLD_THAW_DISKSPACE * MEGABYTE)
|
|
{
|
|
if (fCheckOnly)
|
|
{
|
|
dwRc = ERROR_SUCCESS;
|
|
goto done;
|
|
}
|
|
|
|
pds = _dt.FindFirstDrive (dtec);
|
|
while (pds != NULL)
|
|
{
|
|
dwTemp = pds->ThawDrive(NULL);
|
|
if (dwTemp != ERROR_SUCCESS) // remember the error and
|
|
{
|
|
dwRc = dwTemp; // keep on going
|
|
TRACE (0, "ThawDrive failed with %ld\n", dwRc);
|
|
}
|
|
pds = _dt.FindNextDrive (dtec);
|
|
}
|
|
}
|
|
else // cannot thaw now
|
|
{
|
|
dwRc = ERROR_NO_MORE_ITEMS;
|
|
TRACE (0, "No drives to thaw %ld\n", dwRc);
|
|
}
|
|
}
|
|
else // make sure all the other drives are thawed too for consistency
|
|
{
|
|
pds = _dt.FindFirstDrive (dtec);
|
|
while (pds != NULL)
|
|
{
|
|
if (pds->GetFlags() & SR_DRIVE_FROZEN)
|
|
pds->ThawDrive(NULL);
|
|
|
|
pds = _dt.FindNextDrive (dtec);
|
|
}
|
|
dwRc = ERROR_SUCCESS;
|
|
}
|
|
|
|
if (_dt.GetDirty())
|
|
{
|
|
dwRc = _dt.SaveDriveTable ((CRestorePoint *) NULL);
|
|
if (dwRc != ERROR_SUCCESS)
|
|
TRACE (0, "SaveDriveTable failed with %ld\n", dwRc);
|
|
}
|
|
|
|
if (g_pSRService != NULL && ERROR_SUCCESS == dwRc && FALSE == fCheckOnly)
|
|
{
|
|
if (g_pSRConfig && g_pSRConfig->m_dwFreezeThawLogCount <= MAX_FREEZETHAW_LOG_MESSAGES)
|
|
{
|
|
g_pSRService->LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_THAWED);
|
|
g_pSRConfig->m_dwFreezeThawLogCount++;
|
|
}
|
|
}
|
|
|
|
done:
|
|
TLEAVE();
|
|
return dwRc;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::MonitorDrive
|
|
//
|
|
// Synopsis: enable/disable a drive
|
|
//
|
|
// Arguments: [pwszDrive] -- drive, [fSet] -- enable/disable
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
DWORD CDataStoreMgr::MonitorDrive(WCHAR *pwszDrive, BOOL fSet)
|
|
{
|
|
CDataStore *pds = pwszDrive ? _dt.FindDriveInTable(pwszDrive) : NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL fTellFilter = TRUE;
|
|
|
|
if (! pwszDrive || ! pds || pds == _dt.FindSystemDrive()) // system drive
|
|
{
|
|
// something wrong
|
|
// cannot enable/disable whole of SR this way
|
|
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
}
|
|
else
|
|
{
|
|
// enable/disable only this drive
|
|
|
|
dwErr = pds->MonitorDrive(fSet);
|
|
if (ERROR_SUCCESS == dwErr && (pds->GetFlags() & SR_DRIVE_FROZEN))
|
|
fTellFilter = FALSE;
|
|
}
|
|
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// update drivetable on disk
|
|
|
|
if (_dt.GetDirty())
|
|
{
|
|
dwErr = _dt.SaveDriveTable ((CRestorePoint *) NULL);
|
|
|
|
// rebuild _filelst.cfg and pass to filter
|
|
if (fTellFilter)
|
|
{
|
|
ASSERT(g_pEventHandler);
|
|
dwErr = g_pEventHandler->SRUpdateMonitoredListS(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::WriteMachineGuid
|
|
//
|
|
// Synopsis: write machine guid for disk cleanup utility
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::WriteMachineGuid ()
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wcsPath [MAX_PATH];
|
|
|
|
if (0 == GetSystemDirectoryW (wcsPath, MAX_PATH))
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
lstrcatW (wcsPath, L"\\Restore\\MachineGuid.txt");
|
|
|
|
HANDLE hFile = CreateFileW ( wcsPath, // file name
|
|
GENERIC_WRITE, // file access
|
|
0, // share mode
|
|
NULL, // SD
|
|
CREATE_ALWAYS, // how to create
|
|
0, // file attributes
|
|
NULL); // handle to template file
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile)
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
WCHAR *pwszGuid = GetMachineGuid();
|
|
ULONG cbWritten;
|
|
|
|
if (FALSE == WriteFile (hFile, (BYTE *) pwszGuid,
|
|
(lstrlenW(pwszGuid)+1) * sizeof(WCHAR),
|
|
&cbWritten, NULL))
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
CloseHandle (hFile);
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::DeleteMachineGuidFile
|
|
//
|
|
// Synopsis: write machine guid for disk cleanup utility
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 13-Apr-2000 HenryLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::DeleteMachineGuidFile ()
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR wcsPath [MAX_PATH];
|
|
|
|
if (0 == GetSystemDirectoryW (wcsPath, MAX_PATH))
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
lstrcatW (wcsPath, L"\\Restore\\MachineGuid.txt");
|
|
if (FALSE == DeleteFileW (wcsPath))
|
|
dwErr = GetLastError();
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: CDataStoreMgr::Compress
|
|
//
|
|
// Synopsis: compress files in each datastore
|
|
//
|
|
// Arguments: lDuration - duration to compress
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 26-Feb-01 Brijeshk Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
DWORD CDataStoreMgr::Compress (
|
|
LPWSTR pszDrive,
|
|
LONG lDuration)
|
|
{
|
|
TENTER("CDataStoreMgr::Compress");
|
|
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CDataStore *pds = NULL, *pdsSys = NULL;
|
|
INT64 llAllocated = 0, llUsed = 0;
|
|
SDriveTableEnumContext dtec = {NULL, 0};
|
|
BOOL fFirstTime;
|
|
|
|
llAllocated = lDuration * 1000 * 1000 * 10; // 100's of nanoseconds
|
|
|
|
//
|
|
// if drive specified, compress only that
|
|
//
|
|
|
|
if (pszDrive)
|
|
{
|
|
pds = _dt.FindDriveInTable(pszDrive);
|
|
if (pds)
|
|
{
|
|
dwErr = pds->Compress(llAllocated, &llUsed);
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_INVALID_DRIVE;
|
|
}
|
|
goto Err;
|
|
}
|
|
|
|
|
|
//
|
|
// else, compress all drives if time permits
|
|
// starting with system drive
|
|
//
|
|
|
|
pdsSys = _dt.FindSystemDrive();
|
|
pds = pdsSys;
|
|
fFirstTime = TRUE;
|
|
while (pds)
|
|
{
|
|
if (fFirstTime || pds != pdsSys)
|
|
{
|
|
trace(0, "Allocated time for %S is %I64d", pds->GetDrive(), llAllocated);
|
|
|
|
llUsed = 0;
|
|
dwErr = pds->Compress(llAllocated, &llUsed);
|
|
if (dwErr != ERROR_SUCCESS && dwErr != ERROR_OPERATION_ABORTED)
|
|
{
|
|
trace(0, "! Compress : %ld", dwErr);
|
|
goto Err;
|
|
}
|
|
|
|
llAllocated -= llUsed;
|
|
|
|
if (llAllocated <= 0)
|
|
{
|
|
//
|
|
// used up all time
|
|
//
|
|
dwErr = ERROR_OPERATION_ABORTED;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// go to next drive
|
|
//
|
|
if (fFirstTime)
|
|
{
|
|
pds = _dt.FindFirstDrive(dtec);
|
|
}
|
|
else
|
|
{
|
|
pds = _dt.FindNextDrive(dtec);
|
|
}
|
|
fFirstTime = FALSE;
|
|
}
|
|
|
|
Err:
|
|
TLEAVE();
|
|
return dwErr;
|
|
}
|