Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2496 lines
67 KiB

/*****************************************************************************
*
* 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;
}