|
|
/******************************************************************************
* * Copyright (c) 2000 Microsoft Corporation * * Module Name: * respoint.cpp * * Abstract: * CRestorePoint, CRestorePointEnum class functions * * Revision History: * Brijesh Krishnaswami (brijeshk) 03/17/2000 * created * *****************************************************************************/
#include "precomp.h"
#include "srapi.h"
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile
// constructors
// use this constructor to read in an existing rp
// then need to call Read() to initialize rp members
CRestorePoint::CRestorePoint() { m_pRPInfo = NULL; lstrcpy(m_szRPDir, L""); m_itCurChgLogEntry = m_ChgLogList.end(); m_fForward = TRUE; m_fDefunct = FALSE; }
// initialize
BOOL CRestorePoint::Load(RESTOREPOINTINFOW *prpinfo) { if (prpinfo) { if (! m_pRPInfo) { m_pRPInfo = (RESTOREPOINTINFOW *) SRMemAlloc(sizeof(RESTOREPOINTINFOW)); if (! m_pRPInfo) return FALSE; } CopyMemory(m_pRPInfo, prpinfo, sizeof(RESTOREPOINTINFOW)); } return TRUE; }
// destructor
// call FindClose here
// if no enumeration was done, this is a no-op
CRestorePoint::~CRestorePoint() { if (m_pRPInfo) SRMemFree(m_pRPInfo); FindClose(); }
// return first/last change log entry in this restore point
// assumes Read() has already been called
DWORD CRestorePoint::FindFirstChangeLogEntry( LPWSTR pszDrive, BOOL fForward, CChangeLogEntry& cle) { DWORD dwRc = ERROR_SUCCESS; WCHAR szChgLogPrefix[MAX_PATH]; WIN32_FIND_DATA FindData; INT64 llSeqNum; WCHAR szPath[MAX_PATH];
TENTER("CRestorePoint::FindFirstChangeLogEntry"); m_fForward = fForward; lstrcpy(m_szDrive, pszDrive);
// read the first/last change log in this restore point
// all entries inside a change log will always be read in forward order
MakeRestorePath(szPath, m_szDrive, m_szRPDir); wsprintf(szChgLogPrefix, L"%s\\%s", szPath, s_cszChangeLogPrefix); if (! m_FindFile._FindFirstFile(szChgLogPrefix, s_cszChangeLogSuffix, &FindData, m_fForward, FALSE)) { TRACE(0, "No changelog in %S", szPath); dwRc = ERROR_NO_MORE_ITEMS; goto done; }
lstrcat(szPath, L"\\"); lstrcat(szPath, FindData.cFileName);
// build list of entries in increasing order of sequence number
dwRc = BuildList(szPath); if (ERROR_SUCCESS != dwRc) { TRACE(0, "! BuildList : %ld", dwRc); goto done; }
TRACE(0, "Enumerating %S in %S", FindData.cFileName, m_szRPDir);
// if there was no entry in this change log, go to the next
if (m_ChgLogList.empty()) { dwRc = FindNextChangeLogEntry(cle); goto done; }
// get the first/last entry
if (m_fForward) { m_itCurChgLogEntry = m_ChgLogList.begin(); } else { m_itCurChgLogEntry = m_ChgLogList.end(); m_itCurChgLogEntry--; }
// read in the change log entry into the object
cle.Load(*m_itCurChgLogEntry, m_szRPDir);
done: TLEAVE(); return dwRc; }
// return next/prev change log entry in this restore point
// assumes Read() has already been called
DWORD CRestorePoint::FindNextChangeLogEntry( CChangeLogEntry& cle) { DWORD dwRc = ERROR_SUCCESS; WCHAR szPath[MAX_PATH]; WCHAR szChgLogPrefix[MAX_PATH]; WIN32_FIND_DATA FindData; INT64 llSeqNum;
TENTER("CRestorePoint::FindNextChangeLogEntry"); // go to the next entry in the list
m_fForward ? m_itCurChgLogEntry++ : m_itCurChgLogEntry--;
// check if we've reached the end of this change log
// end is the same for both forward and reverse enumeration
if (m_itCurChgLogEntry == m_ChgLogList.end()) { // if so, read the next change log into memory
// nuke the current list
FindClose();
MakeRestorePath(szPath, m_szDrive, m_szRPDir); wsprintf(szChgLogPrefix, L"%s\\%s", szPath, s_cszChangeLogPrefix);
if (FALSE == m_FindFile._FindNextFile(szChgLogPrefix, s_cszChangeLogSuffix, &FindData)) { dwRc = ERROR_NO_MORE_ITEMS; TRACE(0, "No more change logs"); goto done; }
lstrcat(szPath, L"\\"); lstrcat(szPath, FindData.cFileName);
dwRc = BuildList(szPath); if (ERROR_SUCCESS != dwRc) { TRACE(0, "BuildList : error=%ld", dwRc); goto done; }
TRACE(0, "Enumerating %S in %S", FindData.cFileName, m_szRPDir);
if (m_ChgLogList.empty()) { dwRc = FindNextChangeLogEntry(cle); goto done; }
// get the first/last entry
if (m_fForward) { m_itCurChgLogEntry = m_ChgLogList.begin(); } else { m_itCurChgLogEntry = m_ChgLogList.end(); m_itCurChgLogEntry--; } }
// read in the change log entry fields into the object
cle.Load(*m_itCurChgLogEntry, m_szRPDir); done: TLEAVE(); return dwRc; }
DWORD CRestorePoint::BuildList( LPWSTR pszChgLog) { DWORD dwRc = ERROR_INTERNAL_ERROR; HANDLE hChgLog = INVALID_HANDLE_VALUE; DWORD dwRead; DWORD dwEntrySize; PVOID pBlob = NULL; SR_LOG_ENTRY* pEntry = NULL; PSR_LOG_HEADER pLogHeader = NULL; DWORD cbSize;
TENTER("CChangeLogEntry::BuildList");
hChgLog = CreateFile(pszChgLog, // file name
GENERIC_READ, // access mode
FILE_SHARE_READ, // share mode
NULL, // SD
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); if (INVALID_HANDLE_VALUE == hChgLog) { dwRc = GetLastError(); TRACE(0, "! CreateFile on %S : %ld", pszChgLog, dwRc); goto done; }
// read header size
if (FALSE == ReadFile(hChgLog, &cbSize, sizeof(DWORD), &dwRead, NULL) || dwRead == 0 || cbSize == 0) { // if the file could not be read,
// assume that it is a 0-sized log, and go to the next log
dwRc = GetLastError(); TRACE(0, "Zero sized log : %ld", pszChgLog, dwRc); dwRc = ERROR_SUCCESS; goto done; }
pLogHeader = (SR_LOG_HEADER *) SRMemAlloc(cbSize); if (! pLogHeader) { TRACE(0, "Out of memory"); goto done; }
// read header
pLogHeader->Header.RecordSize = cbSize; if (FALSE == ReadFile(hChgLog, (PVOID) ( ((BYTE *) pLogHeader) + sizeof(DWORD)), cbSize - sizeof(DWORD), &dwRead, NULL)) { dwRc = GetLastError(); TRACE(0, "! ReadFile on %S : %ld", pszChgLog, dwRc); goto done; }
// check log's integrity
if( pLogHeader->LogVersion != SR_LOG_VERSION || pLogHeader->MagicNum != SR_LOG_MAGIC_NUMBER ) { TRACE(0, "! LogHeader for %S : invalid or corrupt", pszChgLog); goto done; }
// now read the entries
do { // get the size of the entry
if (FALSE == ReadFile(hChgLog, &dwEntrySize, sizeof(DWORD), &dwRead, NULL)) { TRACE(0, "ReadFile failed, error=%ld", GetLastError()); break; }
if (0 == dwRead) // end of file
{ TRACE(0, "End of file"); dwRc = ERROR_NO_MORE_ITEMS; break; }
if (dwRead != sizeof(DWORD)) // error reading entry
{ TRACE(0, "Readfile could not read a DWORD"); break; }
if (0 == dwEntrySize) // reached the last entry
{ TRACE(0, "No more entries"); dwRc = ERROR_NO_MORE_ITEMS; break; }
// get the entry itself
pEntry = (SR_LOG_ENTRY *) SRMemAlloc(dwEntrySize); if (! pEntry) { TRACE(0, "Out of memory"); break; }
pEntry->Header.RecordSize = dwEntrySize;
// skip the size field
pBlob = (PVOID) ((PBYTE) pEntry + sizeof(dwEntrySize));
if (FALSE == ReadFile(hChgLog, pBlob, dwEntrySize - sizeof(dwEntrySize), &dwRead, NULL)) { TRACE(0, "! ReadFile on %S : %ld", pszChgLog, GetLastError()); break; }
if (dwRead != dwEntrySize - sizeof(dwEntrySize)) // error reading entry
{ TRACE(0, "! Readfile: ToRead=%ld, Read=%ld bytes", dwEntrySize - sizeof(dwEntrySize), dwRead); break; }
// insert entry into list
dwRc = InsertEntryIntoList(pEntry);
} while (ERROR_SUCCESS == dwRc);
if (ERROR_NO_MORE_ITEMS == dwRc) { dwRc = ERROR_SUCCESS; }
done: if (INVALID_HANDLE_VALUE != hChgLog) CloseHandle(hChgLog);
SRMemFree(pLogHeader);
TLEAVE(); return dwRc; }
// release memory and empty the list
DWORD CRestorePoint::FindClose() { // nuke the list
for (m_itCurChgLogEntry = m_ChgLogList.begin(); m_itCurChgLogEntry != m_ChgLogList.end(); m_itCurChgLogEntry++) { SRMemFree(*m_itCurChgLogEntry); }
m_ChgLogList.clear(); return ERROR_SUCCESS; }
// insert change log entry into list
DWORD CRestorePoint::InsertEntryIntoList( SR_LOG_ENTRY* pEntry) { TENTER("CRestorePoint::InsertEntryIntoList"); m_ChgLogList.push_back(pEntry);
TLEAVE(); return ERROR_SUCCESS; }
// populate members
DWORD CRestorePoint::ReadLog() { DWORD dwRc = ERROR_SUCCESS; WCHAR szLog[MAX_PATH]; WCHAR szSystemDrive[MAX_PATH]; DWORD dwRead;
TENTER("CRestorePoint::ReadLog");
// construct path of rp.log
GetSystemDrive(szSystemDrive); MakeRestorePath(szLog, szSystemDrive, m_szRPDir); lstrcat(szLog, L"\\"); lstrcat(szLog, s_cszRestorePointLogName);
HANDLE hFile = CreateFile (szLog, // 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) { dwRc = GetLastError(); trace(0, "! CreateFile on %S : %ld", szLog, dwRc); goto done; }
// read the restore point info
if (! m_pRPInfo) { m_pRPInfo = (RESTOREPOINTINFOW *) SRMemAlloc(sizeof(RESTOREPOINTINFOW)); if (! m_pRPInfo) { dwRc = ERROR_OUTOFMEMORY; trace(0, "SRMemAlloc failed"); goto done; } } if (FALSE == ReadFile(hFile, m_pRPInfo, sizeof(RESTOREPOINTINFOW), &dwRead, NULL) || dwRead != sizeof(RESTOREPOINTINFOW)) { dwRc = GetLastError(); trace(0, "! ReadFile on %S : %ld", szLog, dwRc); goto done; }
m_fDefunct = (m_pRPInfo->dwRestorePtType == CANCELLED_OPERATION); // read the creation time
if (FALSE == ReadFile(hFile, &m_Time, sizeof(m_Time), &dwRead, NULL) || dwRead != sizeof(m_Time)) { dwRc = GetLastError(); trace(0, "! ReadFile on %S : %ld", szLog, dwRc); goto done; }
done: if (INVALID_HANDLE_VALUE != hFile) CloseHandle(hFile);
TLEAVE(); return dwRc; }
DWORD CRestorePoint::WriteLog() { DWORD dwRc = ERROR_SUCCESS; WCHAR szLog[MAX_PATH]; WCHAR szSystemDrive[MAX_PATH]; DWORD dwWritten; HANDLE hFile = INVALID_HANDLE_VALUE; TENTER("CRestorePoint::WriteLog");
if (! m_pRPInfo) { ASSERT(0); dwRc = ERROR_INTERNAL_ERROR; goto done; } // set the creation time to the current time
GetSystemTimeAsFileTime(&m_Time);
// construct path of rp.log
GetSystemDrive(szSystemDrive); MakeRestorePath(szLog, szSystemDrive, m_szRPDir); lstrcat(szLog, L"\\"); lstrcat(szLog, s_cszRestorePointLogName);
hFile = CreateFile (szLog, // 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) { dwRc = GetLastError(); trace(0, "! CreateFile on %S : %ld", szLog, dwRc); goto done; }
// write the restore point info
if (FALSE == WriteFile(hFile, m_pRPInfo, sizeof(RESTOREPOINTINFOW), &dwWritten, NULL)) { dwRc = GetLastError(); trace(0, "! WriteFile on %S : %ld", szLog, dwRc); goto done; }
// write the creation time
if (FALSE == WriteFile(hFile, &m_Time, sizeof(m_Time), &dwWritten, NULL)) { dwRc = GetLastError(); trace(0, "! WriteFile on %S : %ld", szLog, dwRc); goto done; }
done: if (INVALID_HANDLE_VALUE != hFile) CloseHandle(hFile);
TLEAVE(); return dwRc; }
BOOL CRestorePoint::DeleteLog() { WCHAR szLog[MAX_PATH]; WCHAR szSystemDrive[MAX_PATH];
GetSystemDrive(szSystemDrive); MakeRestorePath(szLog, szSystemDrive, m_szRPDir); lstrcat(szLog, L"\\"); lstrcat(szLog, s_cszRestorePointLogName);
return DeleteFile(szLog); }
DWORD CRestorePoint::Cancel() { if (m_pRPInfo) { m_pRPInfo->dwRestorePtType = CANCELLED_OPERATION; return WriteLog(); } else { ASSERT(0); return ERROR_INTERNAL_ERROR; } }
DWORD CRestorePoint::GetNum() { return GetID(m_szRPDir); }
// read the size of the restore point folder from file
DWORD CRestorePoint::ReadSize (const WCHAR *pwszDrive, INT64 *pllSize) { DWORD dwErr = ERROR_SUCCESS; DWORD cbRead = 0; WCHAR wcsPath[MAX_PATH];
MakeRestorePath(wcsPath, pwszDrive, m_szRPDir); lstrcat(wcsPath, L"\\"); lstrcat (wcsPath, s_cszRestorePointSize);
HANDLE hFile = CreateFileW ( wcsPath, // 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(); return dwErr; }
if (FALSE == ReadFile (hFile, (BYTE *) pllSize, sizeof(*pllSize), &cbRead, NULL)) { dwErr = GetLastError(); }
CloseHandle (hFile); return dwErr; }
// write the size of the restore point folder to file
DWORD CRestorePoint::WriteSize (const WCHAR *pwszDrive, INT64 llSize) { DWORD dwErr = ERROR_SUCCESS; DWORD cbWritten = 0; WCHAR wcsPath[MAX_PATH];
MakeRestorePath(wcsPath, pwszDrive, m_szRPDir); lstrcat(wcsPath, L"\\"); lstrcat (wcsPath, s_cszRestorePointSize);
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(); return dwErr; }
if (FALSE == WriteFile (hFile, (BYTE *) &llSize, sizeof(llSize), &cbWritten, NULL)) { dwErr = GetLastError(); }
CloseHandle (hFile); return dwErr; }
// populate a changelogentry object
void CChangeLogEntry::Load(SR_LOG_ENTRY *pentry, LPWSTR pszRPDir) { PSR_LOG_DEBUG_INFO pDebugRec = NULL; _pentry = pentry;
_pszPath1 = _pszPath2 = _pszTemp = _pszProcess = _pszShortName = NULL; _pbAcl = NULL; _cbAcl = 0; _fAclInline = FALSE; lstrcpy(_pszRPDir, pszRPDir); BYTE *pRec = (PBYTE) & _pentry->SubRecords;
//
// get source path
//
_pszPath1 = (LPWSTR) (pRec + sizeof(RECORD_HEADER));
//
// get temp path if exists
//
if (_pentry->EntryFlags & ENTRYFLAGS_TEMPPATH) { pRec += RECORD_SIZE(pRec); _pszTemp = (LPWSTR) (pRec + sizeof(RECORD_HEADER)); }
//
// get second path if exists
//
if (_pentry->EntryFlags & ENTRYFLAGS_SECONDPATH) { pRec += RECORD_SIZE(pRec); _pszPath2 = (LPWSTR) (pRec + sizeof(RECORD_HEADER)); }
//
// get acl info if exists
//
if (_pentry->EntryFlags & ENTRYFLAGS_ACLINFO) { pRec += RECORD_SIZE(pRec); if (RECORD_TYPE(pRec) == RecordTypeAclInline) { _fAclInline = TRUE; }
_pbAcl = (BYTE *) (pRec + sizeof(RECORD_HEADER)); _cbAcl = RECORD_SIZE(pRec) - sizeof(RECORD_HEADER); }
//
// get debug info if exists
//
if (_pentry->EntryFlags & ENTRYFLAGS_DEBUGINFO) { pRec += RECORD_SIZE(pRec); pDebugRec = (PSR_LOG_DEBUG_INFO) pRec; _pszProcess = (LPWSTR) (pDebugRec->ProcessName); }
//
// get shortname if exists
//
if (_pentry->EntryFlags & ENTRYFLAGS_SHORTNAME) { pRec += RECORD_SIZE(pRec); _pszShortName = (LPWSTR) (pRec + sizeof(RECORD_HEADER)); }
return; }
// this function will check if any filepath length exceeds
// the max length that restore supports
// if so, it will return FALSE
BOOL CChangeLogEntry::CheckPathLengths() { if (_pszPath1 && lstrlen(_pszPath1) > SR_MAX_FILENAME_PATH-1) return FALSE; if (_pszPath2 && lstrlen(_pszPath2) > SR_MAX_FILENAME_PATH-1) return FALSE; if (_pszTemp && lstrlen(_pszTemp) > SR_MAX_FILENAME_PATH-1) return FALSE;
return TRUE; }
|