|
|
/*++
Copyright (c) 2002 Microsoft Corporation
Module Name:
backup.cpp
Abstract:
This module contains routines that handle the COM+ VSS writer object for backup and restore of the catalogs, the catalog databases, and for WFP-protected system files.
Author:
Patrick Masse (patmasse) 04-02-2002
--*/
#include <windows.h>
#include <stdio.h>
#include <dbgdef.h>
#include <assert.h>
#include <sfc.h>
#include <vss.h>
#include <vswriter.h>
#include <vsbackup.h>
#include "service.h"
#include "errlog.h"
#include "cryptmsg.h"
//***************************************************************************************
//
// _CatDB prototypes
//
//***************************************************************************************
LPWSTR _CatDBGetCatrootDirW( BOOL fCatroot2);
LPWSTR _CatDBCreatePath( IN LPCWSTR pwsz1, IN LPCWSTR pwsz2);
BOOL _CatDBFreeze();
VOID _CatDBThaw();
//***************************************************************************************
//
// CSystemWriter object declaration
//
//***************************************************************************************
class CSystemWriter : public CVssWriter { private: static CSystemWriter *sm_pWriter; STDMETHODCALLTYPE CSystemWriter() {}
public: virtual STDMETHODCALLTYPE ~CSystemWriter() {}
// CSystemWriter object Startup and Shutdown functions
static bool Startup(); static void Shutdown();
// CSystemWriter object exported VSS member functions
virtual bool STDMETHODCALLTYPE OnIdentify( IN IVssCreateWriterMetadata *pMetadata); virtual bool STDMETHODCALLTYPE OnPrepareBackup( IN IVssWriterComponents *pWriterComponents); virtual bool STDMETHODCALLTYPE OnPrepareSnapshot(); virtual bool STDMETHODCALLTYPE OnFreeze(); virtual bool STDMETHODCALLTYPE OnThaw(); virtual bool STDMETHODCALLTYPE OnAbort();
private:
// CSystemWriter object VSS helper functions
bool AddCatalogFiles( IN IVssCreateWriterMetadata *pMetadata, IN bool fCatroot2); bool AddSystemFiles( IN IVssCreateWriterMetadata *pMetadata);
// CSystemWriter object private initialization functions
static BOOL IsSystemSetupInProgress(); static BOOL WaitForServiceRunning( IN PWSTR wszServiceName); static DWORD WINAPI InitializeThreadFunc( IN PVOID pvResult); bool STDMETHODCALLTYPE Initialize(); bool STDMETHODCALLTYPE Uninitialize();
// Error handling functions
static HRESULT SqlErrorToWriterError( IN HRESULT hSqlError); static HRESULT WinErrorToWriterError( IN DWORD dwWinError); static void LogSystemErrorEvent( IN DWORD dwMsgId, IN PWSTR pwszDetails, IN DWORD dwSysErrCode); };
//***************************************************************************************
//
// Globals
//
//***************************************************************************************
// The writer COM+ object guid
CONST GUID g_guidWriterId = { 0xe8132975, 0x6f93, 0x4464, { 0xa5, 0x3e, 0x10, 0x50, 0x25, 0x3a, 0xe2, 0x20 } };
// The writer display name
LPCWSTR g_wszWriterName = L"System Writer";
// The component name
LPCWSTR g_wszComponentName = L"System Files";
// Handle to the initialization thread
HANDLE g_hInitializeThread = NULL;
// Static class member variables
CSystemWriter *CSystemWriter::sm_pWriter = NULL;
// Global from catdbsvc.cpp
extern BOOL g_fShuttingDown;
//***************************************************************************************
//
// CSystemWriter object Startup and Shutdown functions
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// CSystemWriter::Startup()
//
//---------------------------------------------------------------------------------------
bool CSystemWriter::Startup() { bool fRet = true; DWORD dwThreadId; //
// Writer object already created?
//
if (sm_pWriter != NULL) { goto CommonReturn; }
//
// Is a system setup currently in progress?
// If so... don't initialize, but return ok.
//
// Notes: Added because any attempt to initialize VSS during GUI-mode setup
// really screws things up.
//
if (IsSystemSetupInProgress()) { goto CommonReturn; }
//
// Create the CSystemWriter object
//
sm_pWriter = new CSystemWriter;
if (sm_pWriter == NULL) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Allocation of CSystemWriter object failed.", ERROR_OUTOFMEMORY); goto ErrorReturn; }
//
// Spin up a thread to do the subscription in.
//
// Notes: We must use a thread to do this, since the rest of this service is
// required early in the boot sequence, and this thread may take quite
// a while to initialize, since it will wait for needed services before
// attempting initialization.
//
g_hInitializeThread = ::CreateThread( NULL, 0, InitializeThreadFunc, NULL, 0, &dwThreadId);
if (g_hInitializeThread == NULL) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Creation of CSystemWriter initialization thread failed.", GetLastError()); goto ErrorReturn; }
CommonReturn:
return fRet;
ErrorReturn:
fRet = false;
if (sm_pWriter) { delete sm_pWriter; sm_pWriter = NULL; }
goto CommonReturn; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::Shutdown()
//
//---------------------------------------------------------------------------------------
void CSystemWriter::Shutdown() { HANDLE hInitializeThread = InterlockedExchangePointer(&g_hInitializeThread, NULL);
if (hInitializeThread != NULL) { WaitForSingleObject(hInitializeThread, INFINITE); CloseHandle(hInitializeThread); } if (sm_pWriter) { sm_pWriter->Uninitialize();
delete sm_pWriter; sm_pWriter = NULL; } }
//***************************************************************************************
//
// CSystemWriter object exported VSS member functions
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnIdentify()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnIdentify( IN IVssCreateWriterMetadata *pMetadata) { bool fRet = true; HRESULT hResult;
//
// Set the restore method for the writer
//
hResult = pMetadata->SetRestoreMethod( VSS_RME_RESTORE_AT_REBOOT, NULL, NULL, VSS_WRE_NEVER, true);
if (hResult != S_OK) { SetWriterFailure(SqlErrorToWriterError(hResult)); goto ErrorReturn; }
//
// Add one file group component
//
hResult = pMetadata->AddComponent( VSS_CT_FILEGROUP, NULL, g_wszComponentName, g_wszComponentName, NULL, 0, false, false, false);
if (hResult != S_OK) { SetWriterFailure(SqlErrorToWriterError(hResult)); goto ErrorReturn; }
//
// Add catalog files group to component
//
if (!AddCatalogFiles(pMetadata,false)) { // Writer failure already set by AddCatalogFiles function
goto ErrorReturn; }
//
// Add catalog database files to component
//
if (!AddCatalogFiles(pMetadata,true)) { // Writer failure already set by AddCatalogFiles function
goto ErrorReturn; }
//
// Add system files group to component
//
if (!AddSystemFiles(pMetadata)) { // Writer failure already set by AddSystemFiles function
goto ErrorReturn; }
CommonReturn:
return fRet;
ErrorReturn:
fRet = false; goto CommonReturn; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnPrepareBackup()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnPrepareBackup( IN IVssWriterComponents *pWriterComponents) { //
// Nothing...
//
// Notes: But at a later time, we may want to make sure all of the files are
// in the snapshot here.
//
return true; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnPrepareSnapshot()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnPrepareSnapshot() { //
// Nothing...
//
return true; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnFreeze()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnFreeze() { if(!_CatDBFreeze()) { //
// The backup should not continue!
//
SetWriterFailure(VSS_E_WRITERERROR_NONRETRYABLE); return false; }
return true; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnThaw()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnThaw() { _CatDBThaw();
return true; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::OnAbort()
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::OnAbort() { _CatDBThaw();
return true; }
//***************************************************************************************
//
// CSystemWriter object VSS helper functions
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// CSystemWriter::AddCatalogFiles()
//
//---------------------------------------------------------------------------------------
bool CSystemWriter::AddCatalogFiles( IN IVssCreateWriterMetadata *pMetadata, IN bool fCatroot2) { bool fRet = true; LPWSTR pwszCatroot = NULL; LPWSTR pwszSearch = NULL; LPWSTR pwszPathName = NULL; HANDLE hFindHandle = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW FindData; DWORD dwErr; HRESULT hResult;
//
// Get the directory where the catalog files live
//
pwszCatroot = _CatDBGetCatrootDirW(fCatroot2);
if (pwszCatroot == NULL) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Build a search string for the catalog directories
//
pwszSearch = _CatDBCreatePath(pwszCatroot, L"{????????????????????????????????????}");
if (pwszSearch == NULL) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Do the initial find
//
hFindHandle = FindFirstFileW(pwszSearch, &FindData); if (hFindHandle == INVALID_HANDLE_VALUE) { //
// See if a real error occurred, or just no directories
//
dwErr = GetLastError(); if ((dwErr == ERROR_NO_MORE_FILES) || (dwErr == ERROR_PATH_NOT_FOUND) || (dwErr == ERROR_FILE_NOT_FOUND)) { //
// There are no directories of this form
//
goto CommonReturn; } else { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; } }
while (TRUE) { //
// Only care about directories
//
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { pwszPathName = _CatDBCreatePath(pwszCatroot, FindData.cFileName);
if (pwszPathName == NULL) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Add this catalog directory to component files group
//
hResult = pMetadata->AddFilesToFileGroup( NULL, g_wszComponentName, pwszPathName, L"*", true, NULL);
free(pwszPathName); pwszPathName = NULL; if (hResult != S_OK) { SetWriterFailure(SqlErrorToWriterError(hResult)); goto ErrorReturn; } }
//
// Get next file
//
if (!FindNextFileW(hFindHandle, &FindData)) { //
// Check to make sure the enumeration loop terminated normally
//
if (GetLastError() == ERROR_NO_MORE_FILES) { break; } else { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; } } }
CommonReturn:
if (pwszCatroot != NULL) { free(pwszCatroot); }
if (pwszSearch != NULL) { free(pwszSearch); }
if (pwszPathName != NULL) { free(pwszPathName); }
return (fRet);
ErrorReturn:
fRet = false; goto CommonReturn; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::AddSystemFiles()
//
//---------------------------------------------------------------------------------------
bool CSystemWriter::AddSystemFiles( IN IVssCreateWriterMetadata *pMetadata) { bool fRet = true; PROTECTED_FILE_DATA FileData; DWORD dwAttributes; PWSTR pwszPathName; PWSTR pwszFileSpec; bool bRecursive; HRESULT hResult;
FileData.FileNumber = 0;
//
// Enumerate all of the files and directories protected by WFP
//
while (SfcGetNextProtectedFile(NULL, &FileData)) { //
// Make sure this file or directory is currently on this system
//
dwAttributes = GetFileAttributes(FileData.FileName); if (dwAttributes != INVALID_FILE_ATTRIBUTES) { //
// Is this a directory?
//
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) { pwszPathName = FileData.FileName; pwszFileSpec = L"*";
bRecursive = true; } else { //
// Extract path and filename
//
if (pwszFileSpec = wcsrchr(FileData.FileName, L'\\')) { pwszPathName = FileData.FileName; *(pwszFileSpec++) = 0; } else { // Should never get here!
assert(FALSE); }
bRecursive = false; }
//
// Add this file or directory to component files group
//
hResult = pMetadata->AddFilesToFileGroup( NULL, g_wszComponentName, pwszPathName, pwszFileSpec, bRecursive, NULL);
if (hResult != S_OK) { SetWriterFailure(SqlErrorToWriterError(hResult)); goto ErrorReturn; } } }
//
// Check to make sure the enumeration loop terminated normally
//
if (GetLastError() != ERROR_NO_MORE_FILES) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Kludge to add the WinSxS directory for backup and restore, since
// the SfcGetNextProtectedFile() API does not report files under this
// directory.
//
WCHAR wszWindowsDir[MAX_PATH+1];
//
// Get Windows directory
//
if (!GetWindowsDirectory(wszWindowsDir, MAX_PATH+1)) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Create %WINDIR%\WinSxs directory string
//
pwszPathName = _CatDBCreatePath(wszWindowsDir, L"WinSxS"); if (pwszPathName == NULL) { SetWriterFailure(WinErrorToWriterError(GetLastError())); goto ErrorReturn; }
//
// Make sure the %WINDIR%\WinSxs directory exists
// and that it is a directory
//
dwAttributes = GetFileAttributes(pwszPathName); if ((dwAttributes != INVALID_FILE_ATTRIBUTES) && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) { //
// Add this directory to component files group
//
hResult = pMetadata->AddFilesToFileGroup( NULL, g_wszComponentName, pwszPathName, L"*", true, NULL);
free(pwszPathName); pwszPathName = NULL;
if (hResult != S_OK) { SetWriterFailure(SqlErrorToWriterError(hResult)); goto ErrorReturn; } } else { free(pwszPathName); pwszPathName = NULL; } //
// End kludge
//
CommonReturn:
return fRet;
ErrorReturn:
fRet = false; goto CommonReturn; }
//***************************************************************************************
//
// CSystemWriter object private initialization functions
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// CSystemWriter::IsSystemSetupInProgress()
//
// Queries the registry to determine if a system setup is in progress.
//
//---------------------------------------------------------------------------------------
BOOL CSystemWriter::IsSystemSetupInProgress() { HKEY hKey; LONG lResult; DWORD dwSystemSetupInProgress = FALSE; DWORD dwSize = sizeof(dwSystemSetupInProgress);
//
// Open the System Setup key
//
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\Setup", 0, KEY_QUERY_VALUE, &hKey);
if (lResult == ERROR_SUCCESS) { //
// Query SystemSetupInProgress value (assume 0 if value doesn't exist)
//
RegQueryValueEx(hKey, L"SystemSetupInProgress", NULL, NULL, (LPBYTE)&dwSystemSetupInProgress, &dwSize); //
// Close the System Setup key
//
RegCloseKey(hKey); }
return (BOOL)dwSystemSetupInProgress; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::WaitForServiceRunning()
//
// Blocks until the service specified by wszServiceName enters the SERVICE_RUNNING
// state.
//
// Notes: Uses a QueryServiceStatusEx()/Sleep() loop bevause no sync-object
// mechanism is currently available. Should be changed to use sync-object
// mechanism when available.
//
// Returns: TRUE Service specified is in SERVICE_RUNNING state.
// FALSE An error has occured preventing us from determining the
// state of the service specified.
//
//---------------------------------------------------------------------------------------
BOOL CSystemWriter::WaitForServiceRunning( IN PWSTR wszServiceName) { BOOL fRet = TRUE; SC_HANDLE hScm = NULL; SC_HANDLE hService = NULL; LPSERVICE_STATUS_PROCESS pInfo = NULL; DWORD cbInfo = 0; DWORD cbNeeded = 0; BOOL fReady = FALSE; DWORD dwError;
//
// Open the service control manager
//
hScm = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_ENUMERATE_SERVICE);
if (!hScm) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Could not open the Service Control Manager.", GetLastError()); goto ErrorReturn; }
//
// Open the service
//
// Notes: This should fail only if the service is not installed.
//
hService = OpenService(hScm, wszServiceName, SERVICE_QUERY_STATUS);
if (!hService) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Could not open the EventSystem service for query.", GetLastError()); goto ErrorReturn; }
//
// This query loop should only execute twixe. First to determine the size of the data, and second to
// retrieve the data. Only if the data size changes in between the first and second loops, will the
// loop execute a third time
//
while(!fReady) { if (QueryServiceStatusEx( hService, SC_STATUS_PROCESS_INFO, (LPBYTE)pInfo, cbInfo, &cbNeeded)) { //
// Check that the state of the service is SERVICE_RUNNING.
//
if (pInfo->dwCurrentState == SERVICE_RUNNING) { fReady = TRUE; } else { //
// If not, sleep for awhile
//
Sleep(500);
//
// Check for service shutdown condition
//
if (g_fShuttingDown) { goto ErrorReturn; } } } else { if ((dwError = GetLastError()) != ERROR_INSUFFICIENT_BUFFER) { //
// For all other errors
//
LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Could not query the status of the EventSystem service.", dwError); goto ErrorReturn; }
//
// Just in case we already allocated a buffer on a previous loop
//
if (pInfo) { LocalFree((HLOCAL)pInfo); }
//
// Allocate buffer for the status data
//
pInfo = (LPSERVICE_STATUS_PROCESS) LocalAlloc(LMEM_FIXED, cbNeeded);
if (!pInfo) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"Could not query the status of the EventSystem service.", GetLastError()); goto ErrorReturn; }
// Update parameters passed to QueryServiceStatusEx for next loop
cbInfo = cbNeeded; cbNeeded = 0; } }
CommonReturn:
if (pInfo) { LocalFree((HLOCAL)pInfo); }
if (hService) { CloseServiceHandle(hService); }
if (hScm) { CloseServiceHandle(hScm); }
return fRet;
ErrorReturn:
fRet = FALSE; goto CommonReturn; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::InitializeThreadFunc()
//
// This thread initializes the VSS base class. If an error during initialization,
// it is responsible for cleaning-up the object before exiting.
//
// Notes: Waits for the EventSystem, COM+, and VSS services to initialize before
// intializing the VSS base class.
//
//---------------------------------------------------------------------------------------
DWORD CSystemWriter::InitializeThreadFunc( IN PVOID pvDummy) { UNREFERENCED_PARAMETER(pvDummy);
HRESULT hResult; bool fCoInitialized = false; bool fInitialized = false;
//
// Wait for EventSystem service to initialize here...
//
// Notes: The call to Initialize() below requires that the EventSystem be up
// and running or it will hang. We can't add a service-level dependency
// on the EventSystem service, because the EventSystem service fails
// to initialize during GUI-mode system setup, and the rest of our
// service must absolutely be available to the setup process.
//
if (!WaitForServiceRunning(L"EventSystem")) { //
// We either couldn't determine the state of the EventSystem service or this
// service is being shutdown, so we should just exit here and not initialize.
//
goto Done; }
//
// Intialize MTA thread
//
hResult = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); if (hResult != S_OK) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"CoInitializeEx failed.", hResult); goto Done; } fCoInitialized = true;
//
// Note: CoInitializeSecurity() is called by the service host, so we don't have to do it here.
//
//
// Initialize the base class and subscribe
//
// Notes: This call will wait for the COM+ and VSS services to initialize!
//
fInitialized = sm_pWriter->Initialize();
Done: //
// Detach this thread from COM+ now, since we're about to exit.
//
if (fCoInitialized) { CoUninitialize(); }
//
// If something prevented us from initializing, cleanup the object
//
if (!fInitialized) { delete sm_pWriter; sm_pWriter = NULL; }
//
// NULL-out and close global handle to this thread.
//
HANDLE hInitializeThread = InterlockedExchangePointer(&g_hInitializeThread, NULL);
if (hInitializeThread != NULL) { ::CloseHandle(hInitializeThread); }
return 0; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::Initialize()
//
// Initializes and subscribes to the VSS base class.
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::Initialize() { bool fRet = true; HRESULT hResult;
//
// Initialize the VSS base class
//
hResult = CVssWriter::Initialize( g_guidWriterId, g_wszWriterName, VSS_UT_BOOTABLESYSTEMSTATE, VSS_ST_OTHER, VSS_APP_SYSTEM, 60000);
if (hResult != S_OK) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"System Writer object failed to initialize VSS.", hResult); goto ErrorReturn; }
//
// Subscribe to the VSS base class
//
hResult = Subscribe();
if (hResult != S_OK) { LogSystemErrorEvent(MSG_SYSTEMWRITER_INIT_FAILURE, L"System Writer object failed to subscribe to VSS.", hResult); goto ErrorReturn; }
CommonReturn:
return fRet;
ErrorReturn:
fRet = false; goto CommonReturn; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::Uninitialize()
//
// Unsubscribes from the VSS base class.
//
//---------------------------------------------------------------------------------------
bool STDMETHODCALLTYPE CSystemWriter::Uninitialize() { //
// Unsubscribe from the VSS base class
//
return (Unsubscribe() == S_OK); }
//***************************************************************************************
//
// Error handling helper functions
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// CSystemWriter::SqlErrorToWriterError()
//
// Translate a SQL writer error code into a VSS writer error.
//
//---------------------------------------------------------------------------------------
HRESULT CSystemWriter::SqlErrorToWriterError( IN HRESULT hSqlError) { switch(hSqlError) { case E_OUTOFMEMORY: case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY): case HRESULT_FROM_WIN32(ERROR_DISK_FULL): case HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES): case HRESULT_FROM_WIN32(ERROR_NO_MORE_USER_HANDLES): return VSS_E_WRITERERROR_OUTOFRESOURCES; } return VSS_E_WRITERERROR_NONRETRYABLE; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::WinErrorToWriterError()
//
// Translate WinError to a writer error
//
//---------------------------------------------------------------------------------------
HRESULT CSystemWriter::WinErrorToWriterError( IN DWORD dwWinError) { switch(dwWinError) { case ERROR_OUTOFMEMORY: case ERROR_NOT_ENOUGH_MEMORY: case ERROR_DISK_FULL: case ERROR_TOO_MANY_OPEN_FILES: case ERROR_NO_MORE_USER_HANDLES: return VSS_E_WRITERERROR_OUTOFRESOURCES; } return VSS_E_WRITERERROR_NONRETRYABLE; }
//---------------------------------------------------------------------------------------
//
// CSystemWriter::LogSystemErrorEvent()
//
// Logs a SYSTEM error event based on the dwMsgId and additional optional info.
//
//---------------------------------------------------------------------------------------
void CSystemWriter::LogSystemErrorEvent( IN DWORD dwMsgId, IN PWSTR pwszDetails, IN DWORD dwSysErrCode) { HANDLE hEventLog = NULL; LPWSTR wszDetailsHdr = L"\n\nDetails:\n"; LPWSTR wszErrorHdr = L"\n\nSystem Error:\n"; LPWSTR pwszError = NULL; LPWSTR pwszExtra = NULL; DWORD dwExtraLength = 0; LPCWSTR rgpwszStrings[1] = {L""};
if (pwszDetails) { dwExtraLength += wcslen(wszDetailsHdr); dwExtraLength += wcslen(pwszDetails); }
if (dwSysErrCode) { dwExtraLength += wcslen(wszErrorHdr);
//
// Try to get error message from system
//
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwSysErrCode, 0, (LPWSTR) &pwszError, 0, NULL);
//
// If we couldn't get an error message from the system, we'll just
// print out the error code.
//
if (!pwszError) { pwszError = (LPWSTR) LocalAlloc(LMEM_FIXED, 26*sizeof(WCHAR));
if (pwszError) { swprintf(pwszError, L"0x%08X (unresolvable)", dwSysErrCode); } }
if (pwszError) { dwExtraLength += wcslen(pwszError); } }
if (dwExtraLength) { //
// Allocate extra string
//
pwszExtra = (LPWSTR) LocalAlloc(LMEM_FIXED, (dwExtraLength+1)*sizeof(WCHAR));
if (pwszExtra) { pwszExtra[0] = 0;
if (pwszDetails) { wcscat(pwszExtra, wszDetailsHdr); wcscat(pwszExtra, pwszDetails); }
if (pwszError) { wcscat(pwszExtra, wszErrorHdr); wcscat(pwszExtra, pwszError); } } }
if (pwszExtra) { rgpwszStrings[0] = pwszExtra; }
hEventLog = RegisterEventSourceW(NULL, SZSERVICENAME); if (hEventLog != NULL) { ReportEventW( hEventLog, EVENTLOG_ERROR_TYPE, 0, dwMsgId, NULL, 1, 0, rgpwszStrings, NULL);
DeregisterEventSource(hEventLog); }
if (pwszError) { LocalFree((HLOCAL)pwszError); }
if (pwszExtra) { LocalFree((HLOCAL)pwszExtra); } }
//***************************************************************************************
//
// Exported wrapper for CSystemWriter object Startup/Shutdown
//
//***************************************************************************************
//---------------------------------------------------------------------------------------
//
// _SystemWriterInit()
//
//---------------------------------------------------------------------------------------
VOID _SystemWriterInit( BOOL fUnInit) { if (!fUnInit) { CSystemWriter::Startup(); } else { CSystemWriter::Shutdown(); } }
|