windows-nt/Source/XPSP1/NT/admin/pchealth/sr/shell/logfile.cpp
2020-09-26 16:20:57 +08:00

430 lines
10 KiB
C++

/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
logfile.cpp
Abstract:
This file contains the implementation of the ValidateLogFile() function,
which reads and validate restore operations log file.
Revision History:
Seong Kook Khang (SKKhang) 08/20/99
created
******************************************************************************/
#include "stdwin.h"
#include "rstrpriv.h"
#include "srui_htm.h"
#include "rstrmgr.h"
#include "srapi.h"
static LPCWSTR s_cszLogPath = L"%SystemRoot%\\system32\\restore\\rstrlog.dat";
static LPCWSTR s_cszWinInitErr = L"%SystemRoot%\\wininit.err";
/******************************************************************************/
BOOL ReadStrAlign4( HANDLE hFile, LPWSTR pszStr )
{
BOOL fRet = FALSE;
DWORD dwLen;
DWORD dwRead;
if ( !::ReadFile( hFile, &dwLen, sizeof(DWORD), &dwRead, NULL ) || dwRead != sizeof(DWORD) )
{
goto Exit;
}
if ( dwRead > MAX_PATH+4 )
{
// Broken log file...
goto Exit;
}
if ( dwLen > 0 )
{
if ( !::ReadFile( hFile, pszStr, dwLen, &dwRead, NULL ) || dwRead != dwLen )
{
goto Exit;
}
}
fRet = TRUE;
Exit:
return( fRet );
}
/////////////////////////////////////////////////////////////////////////////
//
// CMappedFileRead class
//
/////////////////////////////////////////////////////////////////////////////
class CMappedFileRead
{
public:
CMappedFileRead();
~CMappedFileRead();
// Operations
public:
void Close();
BOOL Open( LPCWSTR cszPath );
BOOL Read( LPVOID pBuf, DWORD cbBuf );
BOOL Read( DWORD *pdw );
BOOL ReadDynStr( LPWSTR szBuf, DWORD cchMax );
protected:
// Attributes
public:
DWORD GetAvail() { return( m_dwAvail ); }
protected:
WCHAR m_szPath[MAX_PATH];
DWORD m_dwSize;
HANDLE m_hFile;
HANDLE m_hMap;
LPBYTE m_pBuf;
LPBYTE m_pCur;
DWORD m_dwAvail;
};
/////////////////////////////////////////////////////////////////////////////
// CMappedFileRead construction / destruction
CMappedFileRead::CMappedFileRead()
{
m_szPath[0] = L'\0';
m_dwSize = 0;
m_hFile = INVALID_HANDLE_VALUE;
m_hMap = INVALID_HANDLE_VALUE;
m_pBuf = NULL;
}
CMappedFileRead::~CMappedFileRead()
{
Close();
}
/////////////////////////////////////////////////////////////////////////////
// CMappedFileRead operations
void CMappedFileRead::Close()
{
TraceFunctEnter("CMappedFileRead::Close");
if ( m_pBuf != NULL )
{
::UnmapViewOfFile( m_pBuf );
m_pBuf = NULL;
}
if ( m_hMap != INVALID_HANDLE_VALUE )
{
::CloseHandle( m_hMap );
m_hMap = INVALID_HANDLE_VALUE;
}
if ( m_hFile != INVALID_HANDLE_VALUE )
{
::CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
TraceFunctLeave();
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMappedFileRead::Open( LPCWSTR cszPath )
{
TraceFunctEnter("CMappedFileRead::Open");
BOOL fRet = FALSE;
LPCWSTR cszErr;
Close();
m_hFile = ::CreateFile( cszPath, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL );
if ( m_hFile == INVALID_HANDLE_VALUE )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::CreateFile failed - %ls", cszErr);
goto Exit;
}
m_dwSize = ::GetFileSize( m_hFile, NULL );
if ( m_dwSize == 0xFFFFFFFF )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::GetFileSize failed - %ls", cszErr);
goto Exit;
}
m_hMap = ::CreateFileMapping( m_hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if ( m_hFile == INVALID_HANDLE_VALUE )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::CreateFileMapping failed - %ls", cszErr);
goto Exit;
}
m_pBuf = (LPBYTE)::MapViewOfFile( m_hMap, FILE_MAP_READ, 0, 0, 0 );
if ( m_pBuf == NULL )
{
cszErr = ::GetSysErrStr();
ErrorTrace(0, "::MapViewOfFile failed - %ls", cszErr);
goto Exit;
}
::lstrcpy( m_szPath, cszPath );
m_pCur = m_pBuf;
m_dwAvail = m_dwSize;
fRet = TRUE;
Exit:
if ( !fRet )
Close();
TraceFunctLeave();
return( fRet );
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMappedFileRead::Read( LPVOID pBuf, DWORD cbBuf )
{
TraceFunctEnter("CMappedFileRead::Read(LPVOID,DWORD)");
BOOL fRet = FALSE;
if ( cbBuf > m_dwAvail )
{
ErrorTrace(0, "Insufficient data - %d bytes (need=%d bytes)\n", m_dwAvail, cbBuf);
goto Exit;
}
::CopyMemory( pBuf, m_pCur, cbBuf );
m_pCur += cbBuf;
m_dwAvail -= cbBuf;
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMappedFileRead::Read( DWORD *pdw )
{
TraceFunctEnter("CMappedFileRead::Read(DWORD*)");
BOOL fRet = FALSE;
if ( sizeof(DWORD) > m_dwAvail )
{
ErrorTrace(0, "Insufficient data - %d bytes (need=%d bytes)\n", m_dwAvail, sizeof(DWORD));
goto Exit;
}
*pdw = *((LPDWORD)m_pCur);
m_pCur += sizeof(DWORD);
m_dwAvail -= sizeof(DWORD);
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/////////////////////////////////////////////////////////////////////////////
BOOL CMappedFileRead::ReadDynStr( LPWSTR szBuf, DWORD cchMax )
{
TraceFunctEnter("CMappedFileRead::Read(LPWSTR,DWORD)");
BOOL fRet = FALSE;
DWORD dwLen;
// note, this "length" is in bytes, not chars.
if ( !Read( &dwLen ) )
goto Exit;
if ( dwLen == 0 )
{
szBuf[0] = L'\0';
goto Done;
}
if ( dwLen > cchMax*sizeof(WCHAR) )
{
ErrorTrace(0, "Invalid string length - %d (max=%d)\n", dwLen, cchMax);
goto Exit;
}
if ( !Read( szBuf, dwLen ) )
goto Exit;
Done:
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
/////////////////////////////////////////////////////////////////////////////
//
// ValidateLogFile function
//
/////////////////////////////////////////////////////////////////////////////
struct SRFINode
{
PSRFI pRFI;
SRFINode *pNext;
};
BOOL ValidateLogFile( BOOL *pfSilent, BOOL *pfUndo )
{
TraceFunctEnter("ValidateLogFile");
BOOL fRet = FALSE;
WCHAR szLogPath[MAX_PATH];
CMappedFileRead cMFR;
SRstrLogHdrBase sHdr1;
SRstrLogHdrV3 sHdr2;
SRstrLogHdrV3Ex sHdr3;
SRstrEntryHdr sEntHdr;
DWORD i;
DWORD dwFlags;
WCHAR szBuf1[SR_MAX_FILENAME_LENGTH];
WCHAR szBuf2[SR_MAX_FILENAME_LENGTH];
WCHAR szBuf3[SR_MAX_FILENAME_LENGTH];
PSRFI pRFI;
::ExpandEnvironmentStrings( s_cszLogPath, szLogPath, MAX_PATH );
if ( !cMFR.Open( szLogPath ) )
goto Exit;
if ( !cMFR.Read( &sHdr1, sizeof(sHdr1) ) )
goto Exit;
if ( ( sHdr1.dwSig1 != RSTRLOG_SIGNATURE1 ) ||
( sHdr1.dwSig2 != RSTRLOG_SIGNATURE2 ) )
{
ErrorTrace(0, "Invalid restore log file signature...");
goto Exit;
}
if ( HIWORD(sHdr1.dwVer) != RSTRLOG_VER_MAJOR )
{
ErrorTrace(0, "Unknown restore log file version - %d (0x%08X)\n", HIWORD(sHdr1.dwVer), sHdr1.dwVer);
goto Exit;
}
if ( !cMFR.Read( &sHdr2, sizeof(sHdr2) ) )
goto Exit;
if ( pfSilent != NULL )
*pfSilent = ( ( sHdr2.dwFlags & RLHF_SILENT ) != 0 );
if ( pfUndo != NULL )
*pfUndo = ( ( sHdr2.dwFlags & RLHF_UNDO ) != 0 );
g_pRstrMgr->SetRPsUsed( sHdr2.dwRPNum, sHdr2.dwRPNew );
DebugTrace(0, "RP ID = %d, # of Drives = %d, New RP=%d", sHdr2.dwRPNum, sHdr2.dwDrives, sHdr2.dwRPNew);
for ( i = 0; i < sHdr2.dwDrives; i++ )
{
if ( !cMFR.Read( &dwFlags ) )
goto Exit;
if ( !cMFR.ReadDynStr( szBuf1, MAX_PATH ) )
goto Exit;
if ( !cMFR.ReadDynStr( szBuf2, MAX_PATH ) )
goto Exit;
if ( !cMFR.ReadDynStr( szBuf3, MAX_PATH ) )
goto Exit;
DebugTrace(0, "Drv#%d - %08X, %ls, %ls, %ls", i, dwFlags, szBuf1, szBuf2, szBuf3);
// Just ignore drive table...
}
//if ( !cMFR.Read( &sHdr3, sizeof(sHdr3) ) )
// goto Exit;
//DebugTrace(0, "New RP ID = %d, # of Entries = %d", sHdr3.dwRPNew, sHdr3.dwCount);
for ( i = 0; cMFR.GetAvail() > 0; i++ )
{
if ( !cMFR.Read( &sEntHdr, sizeof(sEntHdr) ) )
goto Exit;
if ( sEntHdr.dwRes == RSTRRES_FAIL )
goto Exit;
if ( ( sEntHdr.dwID == RSTRLOGID_STARTUNDO ) ||
( sEntHdr.dwID == RSTRLOGID_ENDOFUNDO ) )
continue;
if ( sEntHdr.dwID == RSTRLOGID_ENDOFMAP )
{
if ( cMFR.GetAvail() > 0 )
{
ErrorTrace(0, "Unknown trailing data after the EndOfMap marker...");
// but ignore and continue...
}
break;
}
if ( !cMFR.ReadDynStr( szBuf1, SR_MAX_FILENAME_LENGTH ) )
goto Exit;
if ( !cMFR.ReadDynStr( szBuf2, SR_MAX_FILENAME_LENGTH ) )
goto Exit;
if ( !cMFR.ReadDynStr( szBuf3, SR_MAX_FILENAME_LENGTH ) )
goto Exit;
if ( sEntHdr.dwID == RSTRLOGID_COLLISION )
{
pRFI = new SRenamedFolderInfo;
if ( pRFI == NULL )
{
FatalTrace(0, "Insufficient memory...");
goto Exit;
}
pRFI->strOld = ::PathFindFileName( szBuf1 );
pRFI->strNew = ::PathFindFileName( szBuf2 );
::PathRemoveFileSpec( szBuf2 );
pRFI->strLoc = szBuf2;
if ( !g_pRstrMgr->AddRenamedFolder( pRFI ) )
goto Exit;
}
}
fRet = TRUE;
Exit:
cMFR.Close();
TraceFunctLeave();
return( fRet );
}
/******************************************************************************/
BOOL CheckWininitErr()
{
TraceFunctEnter("CheckWininitErr");
BOOL fRet = FALSE;
WCHAR szWinInitErr[MAX_PATH+1];
::ExpandEnvironmentStrings( s_cszWinInitErr, szWinInitErr, MAX_PATH );
if ( ::GetFileAttributes( szWinInitErr ) != 0xFFFFFFFF )
{
DebugTrace(TRACE_ID, "WININIT.ERR file exists");
goto Exit;
}
fRet = TRUE;
Exit:
TraceFunctLeave();
return( fRet );
}
// end of file