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.
 
 
 
 
 
 

1334 lines
34 KiB

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