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

1829 lines
50 KiB

/******************************************************************************
*
* Copyright (c) 2000 Microsoft Corporation
*
* Module Name:
* datastor.cpp
*
* Abstract:
* CDataStore class functions
*
* Revision History:
* Brijesh Krishnaswami (brijeshk) 03/17/2000
* created
*
*****************************************************************************/
#include "datastor.h"
#include "datastormgr.h"
#include "enumlogs.h"
#include "srconfig.h"
#include "srapi.h"
#include "evthandler.h"
#include "..\snapshot\snappatch.h"
#include "NTServMsg.h" // generated from the MC message compiler
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
//
// The format for each line of the drive table
//
static WCHAR gs_wcsPrintFormat[] = L"%s/%s %x %i %i %s\r\n";
//+---------------------------------------------------------------------------
//
// Function: CDataStore::CDataStore
//
// Synopsis: Initialize an empty datastore object
//
// Arguments:
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
CDataStore::CDataStore (CDriveTable *pdt)
{
_pwszDrive[0] = L'\0';
_pwszGuid[0] = L'\0';
_pwszLabel[0] = L'\0';
_dwFlags = 0;
_llDataStoreUsageBytes = -1;
_llCurrentRpUsageBytes = 0;
_llDataStoreSizeBytes = 0;
_llDiskFreeBytes = 0;
_prp = NULL;
_prpe = NULL;
_iChangeLogs = -1;
_pdt = pdt;
}
CDataStore::~CDataStore()
{
if (_prp != NULL)
delete _prp;
if (_prpe != NULL)
delete _prpe;
// we leave _pdt as a dangling reference,
// since deleting _pdt will delete all child datastores
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::LoadDataStore
//
// Synopsis: Initialize a datastore object from a file
//
// Arguments: [pwszDrive] -- optional drive letter
// [pwszGuid] -- mount manager GUID
// [pwszLabel] -- optional volume label
// [dwFlags] -- SR volume flags
// [iChangeLogs] -- number of change logs
// [llSizeLimit] -- datastore size limit
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::LoadDataStore (WCHAR *pwszDrive,
WCHAR *pwszGuid,
WCHAR *pwszLabel,
DWORD dwFlags,
int iChangeLogs,
INT64 llSizeLimit)
{
if (pwszDrive != NULL)
{
if (lstrlen(pwszDrive) >= MAX_PATH)
return ERROR_INVALID_PARAMETER;
else
lstrcpy (_pwszDrive, pwszDrive);
}
if (pwszGuid != NULL)
{
if (lstrlen(pwszGuid) >= GUID_STRLEN)
return ERROR_INVALID_PARAMETER;
else
lstrcpy (_pwszGuid, pwszGuid);
}
if (pwszLabel != NULL)
{
if (lstrlen(pwszLabel) >= LABEL_STRLEN)
return ERROR_INVALID_PARAMETER;
else
lstrcpy (_pwszLabel, pwszLabel);
}
_dwFlags = dwFlags;
_prpe = NULL;
_prp = NULL;
_iChangeLogs = iChangeLogs;
_llDataStoreSizeBytes = llSizeLimit;
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::GetVolumeInfo
//
// Synopsis: retrieves volume information
//
// Arguments:
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::GetVolumeInfo ()
{
DWORD dwErr = ERROR_SUCCESS;
WCHAR wcsLabel [LABEL_STRLEN];
DWORD dwSerial;
DWORD dwFsFlags;
TENTER ("CDataStore::GetVolumeInfo");
// Get the volume label and flags
if (TRUE == GetVolumeInformationW (_pwszGuid,
wcsLabel, LABEL_STRLEN,
&dwSerial, NULL, &dwFsFlags, NULL, 0))
{
lstrcpy (_pwszLabel, wcsLabel);
if (dwFsFlags & FS_VOL_IS_COMPRESSED)
_dwFlags |= SR_DRIVE_COMPRESSED;
if (dwFsFlags & FS_PERSISTENT_ACLS)
_dwFlags |= SR_DRIVE_NTFS;
if (dwFsFlags & FILE_READ_ONLY_VOLUME)
_dwFlags |= SR_DRIVE_READONLY;
}
else
{
dwErr = GetLastError();
TRACE(0, "! CDataStore::GetVolumeInfo : %ld", dwErr);
}
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::Initialize
//
// Synopsis: Initialize a datastore object
//
// Arguments: [pwszDrive] -- drive letter or mount point
// [pwszGuid] -- volume GUID
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::Initialize(WCHAR *pwszDrive, WCHAR *pwszGuid)
{
TENTER("CDataStore::Initialize");
ULARGE_INTEGER ulTotalFreeBytes;
DWORD dwErr = ERROR_SUCCESS;
NTSTATUS nts;
HANDLE h = INVALID_HANDLE_VALUE;
WCHAR wcsBuffer[MAX_PATH];
if (pwszDrive == NULL)
return ERROR_INVALID_PARAMETER;
if (pwszGuid == NULL)
{
if (!GetVolumeNameForVolumeMountPoint (pwszDrive, wcsBuffer, MAX_PATH))
{
dwErr = GetLastError();
TRACE(0, "! CDataStore::Initialize GetVolumeNameForVolumeMountPoint"
" : %ld", dwErr);
return dwErr;
}
pwszGuid = wcsBuffer;
}
if (lstrlen (pwszDrive) >= MAX_PATH ||
lstrlen (pwszGuid) >= GUID_STRLEN)
{
dwErr = ERROR_INVALID_PARAMETER;
goto Err;
}
if (DRIVE_FIXED != GetDriveType (pwszDrive))
return ERROR_BAD_DEV_TYPE;
lstrcpy (_pwszDrive, pwszDrive);
lstrcpy (_pwszGuid, pwszGuid);
// Open a handle to the volume
h = CreateFileW ( pwszGuid,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL );
if (h == INVALID_HANDLE_VALUE) // The volume could be unformatted or locked
{
dwErr = GetLastError();
TRACE(0, "! CDataStore::Initialize CreateFileW : %ld", dwErr);
dwErr = ERROR_UNRECOGNIZED_VOLUME;
goto Err;
}
dwErr = GetVolumeInfo ();
if (dwErr != ERROR_SUCCESS)
goto Err;
if (IsSystemDrive (_pwszDrive))
{
_dwFlags |= SR_DRIVE_SYSTEM;
}
_dwFlags |= SR_DRIVE_ACTIVE;
_dwFlags |= SR_DRIVE_MONITORED;
Err:
if (h != INVALID_HANDLE_VALUE)
CloseHandle (h);
TLEAVE();
return dwErr;
}
//+-------------------------------------------------------------------------
//
// Function: CDataStore::UpdateDiskFree
//
// Synopsis: calculates disk free and sets initial datastore size
//
// Arguments:
//
//
// Returns:
//
// History: 13-Apr-2000 HenryLee Created
//
//--------------------------------------------------------------------------
DWORD
CDataStore::UpdateDiskFree(LONG_PTR lReserved)
{
ULARGE_INTEGER ulTotalFreeBytes, ulTotalBytes;
DWORD dwErr = ERROR_SUCCESS;
const BOOL fSystem = _dwFlags & SR_DRIVE_SYSTEM;
if (FALSE == GetDiskFreeSpaceEx (_pwszGuid, NULL, &ulTotalBytes, &ulTotalFreeBytes))
{
dwErr = GetLastError();
goto Err;
}
if (g_pSRConfig != NULL)
{
if (_llDataStoreSizeBytes == 0)
{
// datastore size calculation
// minimum = 50mb (non-system) or 200mb (system)
// maximum = min (disksize, max(12%, 400mb))
// actual ds size = calculated maximum
INT64 llDSQuota = g_pSRConfig->m_dwDiskPercent * ulTotalBytes.QuadPart / 100;
INT64 llDSMin = (INT64) (g_pSRConfig->GetDSMin(fSystem));
INT64 llDSMax = min( ulTotalBytes.QuadPart,
max( llDSQuota, (INT64) g_pSRConfig->m_dwDSMax * MEGABYTE ) );
if (llDSMax < llDSMin)
llDSMax = llDSMin;
//
// take floor of this value
//
_llDataStoreSizeBytes = ((INT64) (llDSMax / (INT64) MEGABYTE)) * (INT64) MEGABYTE;
}
}
else
{
_llDataStoreSizeBytes = SR_DEFAULT_DSMAX * MEGABYTE;
}
_llDiskFreeBytes = (INT64) ulTotalFreeBytes.QuadPart;
Err:
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::UpdateParticipate
//
// Synopsis: updates participate bit
//
// Arguments:
//
// Returns: boolean
//
// History: 27-Apr-2000 brijeshk Created
//
//----------------------------------------------------------------------------
DWORD
CDataStore::UpdateParticipate(LONG_PTR pwszDir)
{
DWORD dwRc = ERROR_SUCCESS;
if (! (_dwFlags & SR_DRIVE_PARTICIPATE))
{
WCHAR szPath[MAX_PATH];
MakeRestorePath(szPath, _pwszDrive, (LPWSTR) pwszDir);
if (-1 != GetFileAttributes(szPath))
{
dwRc = SetParticipate(TRUE);
}
}
return dwRc;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::GetUsagePercent
//
// Synopsis: returns datastore usage in percentage
//
// Arguments:
//
// Returns: error code
//
// History: 27-Apr-2000 brijeshk Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::GetUsagePercent(int * pnPercent)
{
TENTER("CDataStore::GetUsagePercent");
DWORD dwErr = ERROR_SUCCESS;
INT64 llAdjustedSize;
if (_llDataStoreUsageBytes == -1) // not initialized yet
{
dwErr = CalculateDataStoreUsage (NULL);
if (dwErr != ERROR_SUCCESS)
goto done;
}
if (_llDiskFreeBytes + _llDataStoreUsageBytes + _llCurrentRpUsageBytes < _llDataStoreSizeBytes)
{
llAdjustedSize = _llDiskFreeBytes + _llDataStoreUsageBytes + _llCurrentRpUsageBytes;
}
else
{
llAdjustedSize = _llDataStoreSizeBytes;
}
if (llAdjustedSize)
{
*pnPercent = (int) ((_llDataStoreUsageBytes + _llCurrentRpUsageBytes) * 100/ llAdjustedSize);
}
else
{
*pnPercent = 0;
}
TRACE(0, "Datastore %S: Usage=%I64d, Size=%I64d, AdjustedSize=%I64d, Percentage=%d",
_pwszDrive,
_llDataStoreUsageBytes + _llCurrentRpUsageBytes,
_llDataStoreSizeBytes,
llAdjustedSize,
*pnPercent);
done:
TLEAVE();
return dwErr;
}
DWORD CompressDir_Recurse (WCHAR *pwszPath,
INT64 *pllDiff,
INT64 llAllocatedTime,
ULARGE_INTEGER ulft1,
ULARGE_INTEGER& ulft2)
{
TENTER ("CompressDir_Recurse");
DWORD dwErr = ERROR_SUCCESS;
WIN32_FIND_DATAW wfd;
WCHAR wcsPath [MAX_PATH];
WCHAR wcsSrch [MAX_PATH];
lstrcpy(wcsSrch, pwszPath);
lstrcat(wcsSrch, L"\\*.*");
HANDLE hFind = FindFirstFile (wcsSrch, &wfd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
BOOL fDir = wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
if (!lstrcmp(wfd.cFileName, L".") ||
!lstrcmp(wfd.cFileName, L"..") ||
(wfd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ||
(wfd.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
{
continue;
}
lstrcpyW (wcsPath, pwszPath);
lstrcatW (wcsPath, L"\\");
lstrcatW (wcsPath, wfd.cFileName);
if (fDir)
{
dwErr = CompressDir_Recurse (wcsPath, pllDiff, llAllocatedTime, ulft1, ulft2);
if (dwErr != ERROR_SUCCESS)
break;
}
dwErr = CompressFile (wcsPath, TRUE, fDir);
if (ERROR_SUCCESS != dwErr)
break;
if (!fDir)
{
LARGE_INTEGER ulBefore;
ULARGE_INTEGER ulAfter;
ulBefore.HighPart = wfd.nFileSizeHigh;
ulBefore.LowPart = wfd.nFileSizeLow;
ulAfter.LowPart = GetCompressedFileSize (wcsPath,
&ulAfter.HighPart);
if (ulAfter.LowPart == 0xFFFFFFFF)
{
dwErr = GetLastError();
TRACE(0, "! GetCompressedFileSize : %ld", dwErr);
break;
}
*pllDiff += ulAfter.QuadPart - ulBefore.QuadPart;
}
FILETIME ft2;
GetSystemTimeAsFileTime (&ft2);
ulft2.LowPart = ft2.dwLowDateTime;
ulft2.HighPart = ft2.dwHighDateTime;
// check to see if we need to exit
if (llAllocatedTime < ulft2.QuadPart - ulft1.QuadPart)
{
TRACE(0, "Timed out - aborting compression");
dwErr = ERROR_OPERATION_ABORTED;
break;
}
ASSERT(g_pSRConfig);
if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent))
{
TRACE(0, "Stop signalled - aborting compression");
dwErr = ERROR_OPERATION_ABORTED;
break;
}
}
while (FindNextFile (hFind, &wfd));
FindClose (hFind);
}
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::Compress
//
// Synopsis: compress a file in this datastore
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::Compress (INT64 llAllocatedTime, INT64 *pllUsed)
{
TENTER ("CDataStore::Compress");
if (g_pSRConfig != NULL &&
TRUE == g_pSRConfig->GetSafeMode()) // do not compress in SafeMode
{
return ERROR_BAD_ENVIRONMENT;
}
if (_dwFlags & SR_DRIVE_READONLY) // cannot compress read-only volumes
return ERROR_SUCCESS;
ULARGE_INTEGER ulft1, ulft2;
FILETIME ft1, ft2;
DWORD dwErr = ERROR_SUCCESS;
WCHAR wcsPath[MAX_PATH];
GetSystemTimeAsFileTime (&ft1);
ulft1.LowPart = ft1.dwLowDateTime;
ulft1.HighPart = ft1.dwHighDateTime;
ulft2.LowPart = ft1.dwLowDateTime;
ulft2.HighPart = ft1.dwHighDateTime;
if (_prp == NULL)
{
_prp = new CRestorePoint;
if (_prp == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
_prpe = new CRestorePointEnum (_pwszDrive, TRUE, TRUE);
if (_prpe == NULL)
{
delete _prp;
_prp = NULL;
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = _prpe->FindFirstRestorePoint( * _prp );
if (dwErr != ERROR_SUCCESS)
{
dwErr = ERROR_SUCCESS; // no restore points to compress
goto Err;
}
}
if (g_pSRConfig->m_dwTestBroadcast)
PostTestMessage(g_pSRConfig->m_uiTMCompressStart, (WPARAM) _pwszDrive[0], NULL);
do
{
MakeRestorePath(wcsPath, _pwszDrive, _prp->GetDir());
//
// patch the snapshot directory on system drive
//
// BUGBUG - add a time restriction to this
// and factor this into the compression time allocated
if (_dwFlags & SR_DRIVE_SYSTEM)
{
WCHAR wcsSnapshot[MAX_PATH];
lstrcpy(wcsSnapshot, wcsPath);
lstrcat(wcsSnapshot, L"\\snapshot");
dwErr = PatchComputePatch(wcsSnapshot);
if (dwErr != ERROR_SUCCESS)
{
trace(0, "! PatchComputePatch : %ld", dwErr);
goto Err;
}
}
if (_dwFlags & SR_DRIVE_NTFS) // use NTFS compression
{
INT64 llDiff = 0;
dwErr = CompressDir_Recurse (wcsPath, &llDiff, llAllocatedTime, ulft1, ulft2);
if (llDiff != 0)
{
INT64 llSize = 0;
if (ERROR_SUCCESS == _prp->ReadSize (_pwszDrive, &llSize ))
_prp->WriteSize (_pwszDrive, llSize + llDiff);
if (_llDataStoreUsageBytes != -1) // counter initialized
_llDataStoreUsageBytes += llDiff;
}
// check to see if we need to exit
if (ERROR_SUCCESS != dwErr && ERROR_OPERATION_ABORTED != dwErr)
break;
}
}
while (dwErr != ERROR_OPERATION_ABORTED && ERROR_SUCCESS == _prpe->FindNextRestorePoint ( * _prp ));
*pllUsed = ulft2.QuadPart - ulft1.QuadPart;
trace(0, "Compression on drive %S used up %I64d", _pwszDrive, *pllUsed);
if (g_pSRConfig->m_dwTestBroadcast)
PostTestMessage(g_pSRConfig->m_uiTMCompressStop, (WPARAM) _pwszDrive[0], NULL);
Err:
if (ERROR_SUCCESS == dwErr) // if we finished everything
{
delete _prpe;
_prpe = NULL;
delete _prp;
_prp = NULL;
}
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::UpdateDataStoreUsage
//
// Synopsis: incremental update of usage byte count
//
// Arguments: [llDelta] -- add this amount to the total
// [fCurrent] -- update current restore point's size
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::UpdateDataStoreUsage(INT64 llDelta, BOOL fCurrent)
{
TENTER ("CDataStore::UpdateDataStoreUsage");
DWORD dwErr = ERROR_SUCCESS;
if (_llDataStoreUsageBytes != -1) // counter is initialized
{
if (fCurrent)
{
CRestorePoint rpCur;
_llCurrentRpUsageBytes += llDelta;
if (_llCurrentRpUsageBytes < 0)
_llCurrentRpUsageBytes = 0;
CHECKERR(GetCurrentRestorePoint(rpCur),
"GetCurrentRestorePoint");
CHECKERR(rpCur.WriteSize(_pwszDrive, _llCurrentRpUsageBytes),
"WriteSize");
}
else
{
_llDataStoreUsageBytes += llDelta;
if (_llDataStoreUsageBytes < 0)
_llDataStoreUsageBytes = 0;
}
}
Err:
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::CalculateRpUsage
//
// Synopsis: get disk space used by restore point on this volume
//
// Arguments: prp - pointer to restore point object
// pllTemp - pointer to variable that stores calculated size
// fForce - ignore existing restorepointsize file
// fSnapshotOnly - calculate size of snapshot only
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::CalculateRpUsage(
CRestorePoint *prp,
INT64* pllTemp,
BOOL fForce,
BOOL fSnapshotOnly)
{
TENTER("CDataStore::CalculateRpUsage");
WCHAR wcsPath[MAX_PATH];
DWORD dwErr = ERROR_SUCCESS;
if (! fForce)
{
dwErr = prp->ReadSize(_pwszDrive, pllTemp);
}
if (fForce || dwErr != ERROR_SUCCESS)
{
//
// recalculate size
// when a new restore point is created, only calculate
// the snapshot size
// filter will notify us at 25mb intervals
// and we will accurately calculate the size when the restore
// point is closed
//
MakeRestorePath(wcsPath, _pwszDrive, prp->GetDir());
if (fSnapshotOnly)
{
lstrcat(wcsPath, L"\\snapshot");
}
*pllTemp = 0;
dwErr = GetFileSize_Recurse (wcsPath, pllTemp,
g_pDataStoreMgr->GetStopFlag());
if (dwErr == ERROR_PATH_NOT_FOUND)
{
dwErr = ERROR_SUCCESS;
}
else
{
dwErr = prp->WriteSize(_pwszDrive, *pllTemp);
}
}
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::CalculateDataStoreUsage
//
// Synopsis: get disk space used by data store and volume
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::CalculateDataStoreUsage(LONG_PTR lReserved)
{
TENTER ("CDataStore::CalculateDataStoreUsage");
DWORD dwErr = ERROR_SUCCESS;
CRestorePointEnum rpe (_pwszDrive, TRUE, TRUE); // enum forward, skipping current
CRestorePoint rp;
_llDataStoreUsageBytes = 0;
dwErr = rpe.FindFirstRestorePoint(rp);
while (ERROR_SUCCESS == dwErr || dwErr == ERROR_FILE_NOT_FOUND)
{
INT64 llTemp = 0;
CHECKERR(
CalculateRpUsage(
&rp,
&llTemp,
FALSE, // don't force
FALSE), // everything
"CalculateRpUsage");
_llDataStoreUsageBytes += llTemp;
dwErr = rpe.FindNextRestorePoint (rp);
}
rpe.FindClose ();
if (dwErr == ERROR_NO_MORE_ITEMS)
dwErr = ERROR_SUCCESS;
//
// get the size of the current restore point
//
CHECKERR(GetCurrentRestorePoint(rp),
"GetCurrentRestorePoint");
CHECKERR(CalculateRpUsage(&rp,
&_llCurrentRpUsageBytes,
FALSE,
FALSE),
"CalculateRpUsage");
Err:
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::CreateDataStore
//
// Synopsis: create the _restore directory and pertinent files
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::CreateDataStore (LONG_PTR lReserved)
{
TENTER("CDataStore::CreateDataStore");
ULARGE_INTEGER ulTotalFreeBytes;
SECURITY_ATTRIBUTES *psa = NULL;
SECURITY_ATTRIBUTES *psa2 = NULL;
DWORD dwErr = ERROR_SUCCESS;
DWORD dwAttrs = 0;
WCHAR wcsPath[MAX_PATH];
SECURITY_ATTRIBUTES sa;
SECURITY_ATTRIBUTES sa2;
SECURITY_DESCRIPTOR sd;
SECURITY_DESCRIPTOR sd2;
SID *pSid = NULL;
if (_dwFlags & SR_DRIVE_NTFS)
{
struct
{
ACL acl; // the ACL header
BYTE rgb[ 128 - sizeof(ACL) ]; // buffer to hold 2 ACEs
} DaclBuffer;
struct
{
ACL acl; // the ACL header
BYTE rgb[ 128 - sizeof(ACL) ]; // buffer to hold 2 ACEs
} DaclBuffer2;
SID_IDENTIFIER_AUTHORITY SaNT = SECURITY_NT_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SaWorld = SECURITY_WORLD_SID_AUTHORITY;
if (!InitializeAcl(&DaclBuffer.acl, sizeof(DaclBuffer), ACL_REVISION))
{
dwErr = GetLastError();
goto Err;
}
// Create the SID. We'll give the local system full access
if( !AllocateAndInitializeSid( &SaNT, // Top-level authority
1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0,
(void **) &pSid ))
{
dwErr = GetLastError();
TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
goto Err;
}
if (!AddAccessAllowedAce( &DaclBuffer.acl,
ACL_REVISION,
STANDARD_RIGHTS_ALL | GENERIC_ALL,
pSid ))
{
dwErr = GetLastError();
TRACE(0, "! AddAccessAllowedAce : %ld", dwErr);
goto Err;
}
if (!InitializeAcl(&DaclBuffer2.acl, sizeof(DaclBuffer2), ACL_REVISION))
{
dwErr = GetLastError();
goto Err;
}
FreeSid (pSid);
if( !AllocateAndInitializeSid( &SaWorld, // Top-level authority
1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
(void **) &pSid ))
{
dwErr = GetLastError();
TRACE(0, "! AllocateAndInitializeSid : %ld", dwErr);
goto Err;
}
if (!AddAccessAllowedAceEx ( &DaclBuffer2.acl,
ACL_REVISION,
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
STANDARD_RIGHTS_ALL | GENERIC_ALL,
pSid ))
{
dwErr = GetLastError();
TRACE(0, "! AddAccessAllowedAce : %ld", dwErr);
goto Err;
}
// Set up the security descriptor with that DACL in it.
if (!InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ))
{
dwErr = GetLastError();
TRACE(0, "! InitializeSecurityDescriptor : %ld", dwErr);
goto Err;
}
if( !SetSecurityDescriptorDacl( &sd, TRUE, &DaclBuffer.acl, FALSE ))
{
dwErr = GetLastError();
TRACE(0, "! SetSecurityDescriptorDacl : %ld", dwErr);
goto Err;
}
if (!InitializeSecurityDescriptor( &sd2, SECURITY_DESCRIPTOR_REVISION ))
{
dwErr = GetLastError();
TRACE(0, "! InitializeSecurityDescriptor : %ld", dwErr);
goto Err;
}
if( !SetSecurityDescriptorDacl( &sd2, TRUE, &DaclBuffer2.acl, FALSE ))
{
dwErr = GetLastError();
TRACE(0, "! SetSecurityDescriptorDacl : %ld", dwErr);
goto Err;
}
if( !SetSecurityDescriptorControl( &sd2,
SE_DACL_PROTECTED,
SE_DACL_PROTECTED ))
{
dwErr = GetLastError();
TRACE(0, "! SetSecurityDescriptorControl : %ld", dwErr);
goto Err;
}
// Put the security descriptor into the security attributes.
ZeroMemory (&sa, sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = TRUE;
psa = &sa;
ZeroMemory (&sa2, sizeof(sa2));
sa2.nLength = sizeof(SECURITY_ATTRIBUTES);
sa2.lpSecurityDescriptor = &sd2;
sa2.bInheritHandle = TRUE;
psa2 = &sa2;
}
// create "System Volume Information" if it does not exist
// set "system only" dacl on this directory
// make this S+H+non-CI
wsprintf(wcsPath, L"%s%s", _pwszDrive, s_cszSysVolInfo);
if (-1 == GetFileAttributes(wcsPath))
{
if (FALSE == CreateDirectoryW(wcsPath, psa))
{
dwErr = GetLastError();
TRACE(0, "! CreateDirectoryW for %s : %ld", wcsPath, dwErr);
goto Err;
}
if (FALSE == SetFileAttributesW (wcsPath,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM))
{
dwErr = GetLastError();
TRACE(0, "! SetFileAttributes for %s : %ld", wcsPath, dwErr);
goto Err;
}
}
// now create our _Restore directory
// don't put any dacl on it
MakeRestorePath (wcsPath, _pwszDrive, L"");
dwAttrs = GetFileAttributes(wcsPath);
if (-1 != dwAttrs && !(FILE_ATTRIBUTE_DIRECTORY & dwAttrs))
{
DeleteFileW (wcsPath); // try deleting the file
}
if (FALSE == CreateDirectoryW (wcsPath, psa2))
{
dwErr = GetLastError();
if (ERROR_ALREADY_EXISTS == dwErr)
{
if (psa2 != NULL && FALSE == SetFileSecurity (wcsPath,
DACL_SECURITY_INFORMATION,
&sd2))
{
dwErr = GetLastError();
TRACE(0, "! SetFileSecurity for %s : %ld", wcsPath, dwErr);
}
else
dwErr = ERROR_SUCCESS;
}
if (dwErr != ERROR_SUCCESS)
{
TRACE(0, "! CreateDataStore CreateDirectoryW : %ld", dwErr);
goto Err;
}
}
//
// let's keep the datastore uncompressed
// so that filter can make quicker unbuffered copies
//
#if 0
// If the datastore is marked uncompressed, mark it compressed
//
if (_dwFlags & SR_DRIVE_NTFS)
{
dwAttrs = GetFileAttributesW (wcsPath);
if (dwAttrs != INVALID_FILE_SIZE &&
0 == (FILE_ATTRIBUTE_COMPRESSED & dwAttrs))
{
dwErr = CompressFile ( wcsPath, TRUE, TRUE );
if (dwErr != ERROR_SUCCESS)
{
TRACE(0, "! CreateDataStore CompressFile : %ld", dwErr);
goto Err;
}
}
}
#endif
if (FALSE == SetFileAttributesW (wcsPath,
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM))
{
dwErr = GetLastError();
TRACE(0, "! CreateDataStore SetFileAttributesW : %ld", dwErr);
}
Err:
if (pSid != NULL)
FreeSid (pSid);
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::DestroyDataStore
//
// Synopsis: remove the _restore directory and pertinent files
//
// Arguments: [fDeleteDir] -- TRUE if deleting parent directory
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::DestroyDataStore (LONG_PTR fDeleteDir)
{
TENTER("CDataStore::DestroyDataStore");
DWORD dwErr = ERROR_SUCCESS;
WCHAR wcsPath[MAX_PATH];
MakeRestorePath (wcsPath, _pwszDrive, L"");
// delete the restore directory
dwErr = Delnode_Recurse (wcsPath, (BOOL) fDeleteDir,
g_pDataStoreMgr->GetStopFlag());
if (_dwFlags & SR_DRIVE_SYSTEM)
{
g_pDataStoreMgr->DeleteMachineGuidFile();
}
if (ERROR_SUCCESS == dwErr)
{
_llDataStoreUsageBytes = 0;
_llCurrentRpUsageBytes = 0;
}
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::MonitorDrive
//
// Synopsis: tell the filter to start/stop monitoring this drive
//
// Arguments: [fStart] -- TRUE start monitoring, FALSE stop monitoring
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::MonitorDrive (LONG_PTR fSet)
{
DWORD dwRc = ERROR_SUCCESS;
HANDLE hEventSource = NULL;
TENTER("CDataStore::MonitorDrive");
if (!fSet)
{
// if the drive is already disabled, then no op
if (! (_dwFlags & SR_DRIVE_MONITORED))
goto done;
dwRc = SrDisableVolume(g_pSRConfig->GetFilter(), GetNTName());
if (dwRc != ERROR_SUCCESS)
goto done;
_dwFlags &= ~SR_DRIVE_MONITORED;
// reset any per-rp flags as well
ResetFlags(NULL);
dwRc = DestroyDataStore(TRUE);
}
else
{
// if the drive is already enabled, then no op
if (_dwFlags & SR_DRIVE_MONITORED)
{
dwRc = ERROR_SERVICE_ALREADY_RUNNING;
goto done;
}
_dwFlags |= SR_DRIVE_MONITORED;
// reset any per-rp flags as well
ResetFlags(NULL);
}
DirtyDriveTable();
trace(0, "****%S drive %S****", fSet ? L"Enabled" : L"Disabled", _pwszDrive);
hEventSource = RegisterEventSource(NULL, s_cszServiceName);
if (hEventSource != NULL)
{
SRLogEvent (hEventSource, EVENTLOG_INFORMATION_TYPE, fSet ? EVMSG_DRIVE_ENABLED : EVMSG_DRIVE_DISABLED,
NULL, 0, _pwszDrive, NULL, NULL);
DeregisterEventSource(hEventSource);
}
if (g_pSRConfig->m_dwTestBroadcast)
PostTestMessage( fSet ? g_pSRConfig->m_uiTMEnable : g_pSRConfig->m_uiTMDisable,
(WPARAM) _pwszDrive[0],
NULL);
done:
TLEAVE();
return dwRc;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::FreezeDrive
//
// Synopsis: tell the filter to freeze this drive
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 04-Jun-2000 brijeshk Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::FreezeDrive (LONG_PTR lReserved)
{
DWORD dwErr = ERROR_SUCCESS;
TENTER("CDataStore::FreezeDrive");
_dwFlags |= SR_DRIVE_FROZEN; // freeze in spite of open file handles
// if the drive is disabled, no op
if (! (_dwFlags & SR_DRIVE_MONITORED))
goto Err;
//
// check if the drive exists before calling the driver
//
if (0xFFFFFFFF == GetFileAttributes(_pwszGuid))
{
trace(0, "Drive %s does not exist", _pwszDrive);
goto Err;
}
CHECKERR(SrDisableVolume(g_pSRConfig->GetFilter(), GetNTName()),
"SrDisableVolume");
DestroyDataStore(FALSE);
DirtyDriveTable();
trace(0, "****Froze drive %S****", _pwszDrive);
Err:
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Function: CDataStore::ThawDrive
//
// Synopsis: check and thaw this drive
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 04-Jun-2000 brijeshk Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::ThawDrive(LONG_PTR fCheckOnly)
{
DWORD dwRc = ERROR_SUCCESS;
TENTER("CDataStore::ThawDrive");
if (_dwFlags & SR_DRIVE_FROZEN)
{
//Actually we want to clean up everything except for the
//current restore point
//dwRc = DestroyDataStore(FALSE);
if (ERROR_SUCCESS == dwRc)
{
_dwFlags &= ~SR_DRIVE_FROZEN;
DirtyDriveTable();
trace(0, "****Thawed drive %S****", _pwszDrive);
}
else trace(0, "Cannot thaw %S error %d", _pwszDrive, dwRc);
}
TLEAVE();
return dwRc;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::FifoRestorePoint
//
// Synopsis: fifo one restore point in this datastore
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 BrijeshK Created
//
//----------------------------------------------------------------------------
DWORD
CDataStore::FifoRestorePoint(
CRestorePoint& rp)
{
TENTER("CDataStore::FifoRestorePoint");
WCHAR szRpPath[MAX_PATH], szFifoedPath[MAX_PATH];
INT64 llSize = 0;
DWORD dwRc;
//
// if patching is on, and this is a reference directory
// for later snapshots, then don't fifo the snapshot folder
// rename it to RefRPx, and keep it around
// BUGBUG - how do we update size correctly ?
//
if (PatchGetPatchWindow() != 0)
{
// if Reference(RPx) == x, then x is a reference rp
if (PatchGetReferenceRpNum(rp.GetNum()) == rp.GetNum())
{
WCHAR szRp[MAX_RP_PATH + sizeof(s_cszReferenceDir)/sizeof(WCHAR)];
MakeRestorePath(szRpPath, _pwszDrive, rp.GetDir());
lstrcat(szRpPath, SNAPSHOT_DIR_NAME);
wsprintf(szRp, L"%s%ld", s_cszReferenceDir, rp.GetNum());
MakeRestorePath(szFifoedPath, _pwszDrive, szRp);
CreateDirectory(szFifoedPath, NULL);
lstrcat(szFifoedPath, SNAPSHOT_DIR_NAME);
MoveFile(szRpPath, szFifoedPath);
}
}
// read the size of this restore point
// but don't update the datastore size yet
dwRc = rp.ReadSize(_pwszDrive, &llSize);
// move the rp dir to a temp dir "Fifoed"
// this is to make the fifo of a single rp atomic
// to take care of unclean shutdowns
MakeRestorePath(szRpPath, _pwszDrive, rp.GetDir());
MakeRestorePath(szFifoedPath, _pwszDrive, s_cszFifoedRpDir);
if (! MoveFile(szRpPath, szFifoedPath))
{
dwRc = GetLastError();
TRACE(0, "! MoveFile from %S to %S : %ld", szRpPath, szFifoedPath, dwRc);
goto done;
}
// now examine the result of rp.ReadSize
// and update the datastore usage variable
if (ERROR_SUCCESS == dwRc)
{
UpdateDataStoreUsage (-llSize, FALSE);
}
else
{
// ignore this error and continue
TRACE(0, "! rp.ReadSize : %ld", dwRc);
}
// blow away the temp fifoed directory again
dwRc = Delnode_Recurse(szFifoedPath, TRUE,
g_pDataStoreMgr->GetStopFlag());
if (ERROR_SUCCESS != dwRc)
{
TRACE(0, "! Delnode_Recurse : %ld", dwRc);
goto done;
}
done:
TLEAVE();
return dwRc;
}
DWORD
CDataStore::Print(LONG_PTR lptr)
{
TENTER("CDataStore::Print");
DWORD dwErr = ERROR_SUCCESS;
DWORD cbWritten;
HANDLE h = (HANDLE) lptr;
WCHAR w[1024];
wsprintf(w, L"Drive: %s, Guid: %s\r\n", _pwszDrive, _pwszGuid);
WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
trace(0, "Drive: %S, Guid: %S", _pwszDrive, _pwszGuid);
wsprintf(w, L"\t%s %s %s %s %s %s %s %s\r\n",
_dwFlags & SR_DRIVE_ACTIVE ? L"Active, " : L"",
_dwFlags & SR_DRIVE_COMPRESSED ? L"Compressed, " : L"",
_dwFlags & SR_DRIVE_MONITORED ? L"Monitored, " : L"",
_dwFlags & SR_DRIVE_NTFS ? L"NTFS, " : L"",
_dwFlags & SR_DRIVE_PARTICIPATE ? L"Participate, " : L"",
_dwFlags & SR_DRIVE_FROZEN ? L"Frozen, " : L"",
_dwFlags & SR_DRIVE_READONLY ? L"ReadOnly, " : L"",
_dwFlags & SR_DRIVE_ERROR ? L"Error" : L"");
WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
trace(0, "%S %S %S %S", _dwFlags & SR_DRIVE_ACTIVE ? L"Active, " : L"",
_dwFlags & SR_DRIVE_COMPRESSED ? L"Compressed, " : L"",
_dwFlags & SR_DRIVE_MONITORED ? L"Monitored, " : L"",
_dwFlags & SR_DRIVE_NTFS ? L"NTFS, " : L"");
trace(0, "%S %S %S %S", _dwFlags & SR_DRIVE_PARTICIPATE ? L"Participate, " : L"",
_dwFlags & SR_DRIVE_FROZEN ? L"Frozen, " : L"",
_dwFlags & SR_DRIVE_READONLY ? L"ReadOnly, " : L"",
_dwFlags & SR_DRIVE_ERROR ? L"Error" : L"");
wsprintf(w, L"\tSize: %I64d, Usage: %I64d, Diskfree: %I64d\r\n\r\n",
_llDataStoreSizeBytes,
_llDataStoreUsageBytes + _llCurrentRpUsageBytes,
_llDiskFreeBytes);
WriteFile (h, (BYTE *) w, lstrlen(w) * sizeof(WCHAR), &cbWritten, NULL);
trace(0, "Size: %I64d, Usage: %I64d, Diskfree: %I64d",
_llDataStoreSizeBytes,
_llDataStoreUsageBytes + _llCurrentRpUsageBytes,
_llDiskFreeBytes);
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::SaveDataStore
//
// Synopsis: save datastore info as a line in the drive table
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::SaveDataStore (LONG_PTR hFile)
{
HANDLE h = (HANDLE) hFile;
DWORD dwErr = ERROR_SUCCESS;
WCHAR wcsBuffer[MAX_PATH * 2];
DWORD cbWritten = 0;
wsprintf (wcsBuffer, gs_wcsPrintFormat,
GetDrive(), GetGuid(), _dwFlags,
GetNumChangeLogs(), (DWORD) (GetSizeLimit() / (INT64) MEGABYTE),
GetLabel());
if (FALSE == WriteFile (h, (BYTE *) wcsBuffer,
lstrlen(wcsBuffer) * sizeof(WCHAR), &cbWritten, NULL))
{
dwErr = GetLastError();
}
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::DirtyDriveTable
//
// Synopsis: set the dirty bit in the drive table
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::DirtyDriveTable ()
{
if (_pdt != NULL)
_pdt->SetDirty ();
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::SwitchRestorePoint
//
// Synopsis: change the drive table when switching restore points
//
// Arguments: pointer to restore point object
//
// Returns: Win32 error code
//
// History: 14-Jun-2000 BrijeshK Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::SwitchRestorePoint(LONG_PTR pRestorePoint)
{
TENTER("CDataStore::SwitchRestorePoint");
CRestorePoint *prp = (CRestorePoint *) pRestorePoint;
DWORD dwErr = ERROR_SUCCESS;
INT64 llTemp;
if (prp)
{
//
// get the last restore point size - accurate
//
if (_llDataStoreUsageBytes != -1) // initialized
{
CHECKERR(CalculateRpUsage(prp,
&_llCurrentRpUsageBytes,
TRUE, // force calculation
FALSE), // everything
"CalculateRpUsage");
_llDataStoreUsageBytes += _llCurrentRpUsageBytes;
_llCurrentRpUsageBytes = 0;
}
}
//
// get the size of the current snapshot
//
if (_dwFlags & SR_DRIVE_SYSTEM)
{
CRestorePoint rpCur;
CHECKERR(GetCurrentRestorePoint(rpCur),
"GetCurrentRestorePoint");
CHECKERR(CalculateRpUsage(&rpCur,
&_llCurrentRpUsageBytes,
TRUE,
TRUE),
"CalculateRpUsage");
}
Err:
TLEAVE();
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::CountChangeLogs
//
// Synopsis: counts the number of change logs & saves the drive table
//
// Arguments:
//
// Returns: Win32 error code
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
DWORD CDataStore::CountChangeLogs (LONG_PTR pRestorePoint)
{
CRestorePoint *prp = (CRestorePoint *) pRestorePoint;
CFindFile ff;
WIN32_FIND_DATA *pwfd = new WIN32_FIND_DATA;
DWORD dwErr = ERROR_SUCCESS;
int iCount = -1;
CRestorePoint *pCurRp = NULL;
if (! pwfd)
{
dwErr = ERROR_OUTOFMEMORY;
goto Err;
}
if (prp == NULL)
{
pCurRp = new CRestorePoint;
if (! pCurRp)
{
dwErr = ERROR_OUTOFMEMORY;
goto Err;
}
dwErr = GetCurrentRestorePoint (*pCurRp);
if (dwErr != ERROR_SUCCESS)
{
if (_dwFlags & SR_DRIVE_SYSTEM)
goto Err;
// This drive has no current restore point
// It could have been re-formatted or placed in read-only mode
// So assume no change logs are available
dwErr = ERROR_SUCCESS;
}
else prp = pCurRp;
}
if (prp != NULL)
{
LPWSTR pwcsPath = new WCHAR[MAX_PATH];
if (! pwcsPath)
{
dwErr = ERROR_OUTOFMEMORY;
goto Err;
}
iCount = 0;
MakeRestorePath (pwcsPath, _pwszDrive, prp->GetDir());
lstrcatW (pwcsPath, L"\\");
lstrcatW (pwcsPath, s_cszChangeLogPrefix);
if (TRUE == ff._FindFirstFile (pwcsPath, s_cszChangeLogSuffix, pwfd,
FALSE, FALSE))
do
{
iCount++;
}
while (ff._FindNextFile (pwcsPath, s_cszChangeLogSuffix, pwfd));
delete [] pwcsPath;
}
dwErr = SetNumChangeLogs (iCount);
Err:
if (pCurRp)
delete pCurRp;
if (pwfd)
delete pwfd;
return dwErr;
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::IsVolumeDeleted
//
// Synopsis: determines if this volume is no longer accessible
//
// Arguments:
//
// Returns: TRUE if can be removed
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
BOOL CDataStore::IsVolumeDeleted ()
{
WCHAR wszMount[MAX_PATH];
DWORD dwChars = 0;
DWORD dwFsFlags = 0;
tenter("CDataStore::IsVolumeDeleted");
// don't open the volume, since it could be locked for chkdsk
if (FALSE == GetVolumePathNamesForVolumeNameW (_pwszGuid,
wszMount,
MAX_PATH,
&dwChars ))
{
if (GetLastError() != ERROR_MORE_DATA)
{
_dwFlags &= ~SR_DRIVE_ACTIVE;
trace(0, "! GetVolumePathNamesForVolumeNameW : %ld", GetLastError());
return TRUE;
}
}
if (L'\0' == wszMount[0]) // empty string, no mount point
{
_dwFlags &= ~SR_DRIVE_ACTIVE;
trace(0, "! Empty mountpoint");
return TRUE;
}
wszMount[MAX_PATH-1] = L'\0';
if (lstrlenW (wszMount) > MAX_MOUNTPOINT_PATH) // mountpoint too long
{
_dwFlags &= ~SR_DRIVE_ACTIVE;
trace(0, "! Mountpoint too long");
return TRUE;
}
// update the drive letter
lstrcpyW (_pwszDrive, wszMount); // copy the first string
if (GetVolumeNameForVolumeMountPoint (_pwszDrive, wszMount, MAX_PATH))
{
if (lstrcmpW (wszMount, _pwszGuid) != 0)
{
_dwFlags &= ~SR_DRIVE_ACTIVE;
trace(0, "! volume GUID changed");
return TRUE;
}
}
GetVolumeInfo (); // get the latest volume flags if possible
trace(0, "volume %S is active", wszMount);
tleave();
return FALSE; // volume is still active
}
//+---------------------------------------------------------------------------
//
// Functiion CDataStore::GetNTName
//
// Synopsis: constructs the NT object name into a static buffer
//
// Arguments: (none) caller must take the datastore lock
//
// Returns: pointer to string
//
// History: 12-Apr-2000 HenryLee Created
//
//----------------------------------------------------------------------------
WCHAR * CDataStore::GetNTName ()
{
NTSTATUS nts;
static WCHAR wcsBuffer [MAX_PATH];
wcsBuffer[0] = L'\0';
// Open a handle to the volume
HANDLE h = CreateFileW ( _pwszGuid,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL );
if (h != INVALID_HANDLE_VALUE)
{
OBJECT_NAME_INFORMATION * poni;
poni = (OBJECT_NAME_INFORMATION *) wcsBuffer;
// Get name from NT namespace
nts = NtQueryObject (h, ObjectNameInformation, poni, MAX_PATH, NULL);
if (NT_SUCCESS(nts))
{
if (poni->Name.Length < MAX_PATH * sizeof(WCHAR))
poni->Name.Buffer [poni->Name.Length / sizeof(WCHAR) - 1] = TEXT('\0');
}
CloseHandle (h);
return poni->Name.Buffer;
}
else
{
return wcsBuffer;
}
}