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.
 
 
 
 
 
 

519 lines
13 KiB

f/*++
Copyright (c) 2001 Microsoft Corporation
Abstract:
@doc
@module evtlogwriter.cxx | Implementation of the Event Log Writer
@end
Author:
Stefan Steiner [SSteiner] 07/26/2001
TBD:
Revision History:
Name Date Comments
ssteiner 07/26/2001 created
--*/
#include "stdafx.h"
#include "vs_idl.hxx"
#include "vs_hash.hxx"
#include <vswriter.h>
#include <Sddl.h>
#include "vs_seh.hxx"
#include "vs_trace.hxx"
#include "vs_debug.hxx"
#include "vs_reg.hxx"
#include "evtlogwriter.hxx"
#include "allerror.h"
////////////////////////////////////////////////////////////////////////
// Standard foo for file name aliasing. This code block must be after
// all includes of VSS header files.
//
#ifdef VSS_FILE_ALIAS
#undef VSS_FILE_ALIAS
#endif
#define VSS_FILE_ALIAS "WRTEVTRC"
//
////////////////////////////////////////////////////////////////////////
static GUID s_writerId =
{
0xeee8c692, 0x67ed, 0x4250, 0x8d, 0x86, 0x39, 0x6, 0x3, 0x7, 0xd, 0x00
};
// The display name of the Event Log writer.
static LPCWSTR s_wszWriterName = L"Event Log Writer";
// The file group component name for the Event Log
static LPCWSTR s_wszComponentName = L"Event Logs";
// The Registry key that contains event-log information
static LPCWSTR s_wszLogKey = L"SYSTEM\\CurrentControlSet\\Services\\Eventlog";
// The value field that contains the the event-log file
static LPCWSTR s_wszLogFile = L"File";
// The location of where the Event Log will be copied.
static CBsString s_cwsEventLogsTargetDir = ROOT_BACKUP_DIR SERVICE_STATE_SUBDIR L"\\EventLogs";
// The location of the Event Log
static CBsString s_cwsSystemEventLogDir = L"%SystemRoot%\\system32\\config";
// The mask specifying which files to exclude from backup
static CBsString s_cwsSystemEventLogFiles = L"*.evt";
// Class wide member variables
CEventLogWriter *CEventLogWriter::sm_pWriter;
HRESULT CEventLogWriter::sm_hrInitialize;
HRESULT STDMETHODCALLTYPE CEventLogWriter::Initialize()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::Initialize");
try
{
ft.hr = CVssWriter::Initialize
(
s_writerId,
s_wszWriterName,
VSS_UT_SYSTEMSERVICE,
VSS_ST_OTHER,
VSS_APP_SYSTEM,
60000
);
if (ft.HrFailed())
ft.Throw
(
VSSDBG_WRITER,
E_UNEXPECTED,
L"Failed to initialize the Event Log writer. hr = 0x%08lx",
ft.hr
);
ft.hr = Subscribe();
if (ft.HrFailed())
ft.Throw
(
VSSDBG_WRITER,
E_UNEXPECTED,
L"Subscribing the Event Log server writer failed. hr = %0x08lx",
ft.hr
);
}
VSS_STANDARD_CATCH(ft)
return ft.hr;
}
HRESULT STDMETHODCALLTYPE CEventLogWriter::Uninitialize()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::Uninitialize");
return Unsubscribe();
}
// handle request for WRITER_METADATA
// implements CVssWriter::OnIdentify
bool STDMETHODCALLTYPE CEventLogWriter::OnIdentify(IVssCreateWriterMetadata *pMetadata)
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::OnIdentify");
try
{
//
// Set the restore method for the writer
//
ft.hr = pMetadata->SetRestoreMethod
(
VSS_RME_RESTORE_AT_REBOOT,
NULL,
NULL,
VSS_WRE_NEVER,
true
);
ft.CheckForErrorInternal(VSSDBG_WRITER, L"IVssCreateWriterMetadata::SetRestoreMethod");
//
// Add the one file component
//
ft.hr = pMetadata->AddComponent
(
VSS_CT_FILEGROUP,
NULL,
s_wszComponentName,
s_wszComponentName,
NULL, // icon
0,
false,
false,
true
);
ft.CheckForErrorInternal(VSSDBG_WRITER, L"IVssCreateWriterMetadata::AddComponent");
AddExcludes(pMetadata);
ScanLogs();
AddLogs(pMetadata);
}
VSS_STANDARD_CATCH(ft)
TranslateWriterError(ft.hr);
return ft.HrSucceeded();
}
bool STDMETHODCALLTYPE CEventLogWriter::OnPrepareSnapshot()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::OnPrepareSnapshot");
try
{
CBsString cwsExpanded;
if (!cwsExpanded.ExpandEnvironmentStrings(s_cwsEventLogsTargetDir))
{
ft.TranslateError(VSSDBG_WRITER, HRESULT_FROM_WIN32(::GetLastError()),
L"CBsString::ExpandEnvironmentStrings");
}
// make sure that we don't backup up old stuff in the event log backup dir
ft.hr = ::RemoveDirectoryTree(cwsExpanded);
ft.CheckForErrorInternal(VSSDBG_WRITER, L"::RemoveDirectoryTree");
ft.hr = ::CreateTargetPath(cwsExpanded);
ft.CheckForError(VSSDBG_WRITER, L"::CreateTargetPath");
if (IsPathAffected(s_cwsSystemEventLogDir))
BackupLogs();
}
VSS_STANDARD_CATCH( ft );
TranslateWriterError(ft.hr);
ft.Trace(VSSDBG_WRITER, L"CEventLogWriter returning with hresult 0x%08lx", ft.hr);
return ft.HrSucceeded();
}
bool STDMETHODCALLTYPE CEventLogWriter::OnFreeze()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::OnFreeze");
return ft.HrSucceeded();
}
bool STDMETHODCALLTYPE CEventLogWriter::OnThaw()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::OnThaw");
return ft.HrSucceeded();
}
bool STDMETHODCALLTYPE CEventLogWriter::OnAbort()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::OnAbort");
return ft.HrSucceeded();
}
bool CEventLogWriter::IsPathInSnapshot(const WCHAR *wszPath) throw()
{
return IsPathAffected(wszPath);
}
// translate a sql writer error code into a writer error
void CEventLogWriter::TranslateWriterError( HRESULT hr )
{
switch(hr)
{
default:
SetWriterFailure(VSS_E_WRITERERROR_NONRETRYABLE);
break;
case S_OK:
break;
case E_OUTOFMEMORY:
case HRESULT_FROM_WIN32(ERROR_DISK_FULL):
case HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES):
case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
case HRESULT_FROM_WIN32(ERROR_NO_MORE_USER_HANDLES):
SetWriterFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
break;
}
}
// Creates one instance of the Event Log writer class. If one already exists, it simple returns.
// static
HRESULT CEventLogWriter::CreateWriter()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::CreateWriter");
if ( sm_pWriter != NULL )
return S_OK;
//
// OK, spin up a thread to do the subscription in.
//
try
{
sm_pWriter = new CEventLogWriter;
if (sm_pWriter == NULL)
ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Allocation of CEventLogWriter object failed.");
DWORD tid;
HANDLE hThread = ::CreateThread
(
NULL,
256* 1024,
InitializeThreadFunc,
NULL,
0,
&tid
);
if (hThread == NULL)
ft.Throw
(
VSSDBG_WRITER,
E_UNEXPECTED,
L"CreateThread failed with error %d",
::GetLastError()
);
// wait for thread to complete
::WaitForSingleObject( hThread, INFINITE );
::CloseHandle( hThread );
ft.hr = sm_hrInitialize;
}
VSS_STANDARD_CATCH(ft)
if (ft.HrFailed() && sm_pWriter)
{
delete sm_pWriter;
sm_pWriter = NULL;
}
return ft.hr;
}
void CEventLogWriter::FreeLogs()
{
// free event-log information
for (int x = 0; x < m_eventLogs.GetSize(); x++)
{
::VssFreeString(m_eventLogs[x].m_pwszName);
::VssFreeString(m_eventLogs[x].m_pwszFileName);
}
m_eventLogs.RemoveAll();
}
void CEventLogWriter::ScanLogs()
{
CVssFunctionTracer ft (VSSDBG_WRITER, L"CEventLogWriter::ScanLogs");
FreeLogs();
// open the main registry key
CVssRegistryKey hkeyEventLogList (KEY_READ);
if (!hkeyEventLogList.Open(HKEY_LOCAL_MACHINE, s_wszLogKey))
{
ft.Trace (VSSDBG_WRITER, L"Failed to open registry key: %s", s_wszLogKey);
return;
}
CVssRegistryKeyIterator iterator;
iterator.Attach (hkeyEventLogList);
// for each subkey corresponding to a log
while (!iterator.IsEOF())
{
EventLog currentLog;
// --- get the file entry
CVssRegistryKey hkeyEventLog(KEY_QUERY_VALUE);
if (!hkeyEventLog.Open(hkeyEventLogList.GetHandle(), iterator.GetCurrentKeyName()))
{
ft.Throw(VSSDBG_WRITER, E_UNEXPECTED,
L"Failed to open registry entry for event log %s", iterator.GetCurrentKeyName());
}
CVssAutoPWSZ pwszFileName;
hkeyEventLog.GetValue(s_wszLogFile, pwszFileName.GetRef(), false);
if (pwszFileName.GetRef() == NULL)
{
ft.Trace(VSSDBG_WRITER,
L"Error reading File value for event log %s", iterator.GetCurrentKeyName());
iterator.MoveNext();
continue;
}
// ensure that the name has at least a single \ in it
if (wcschr(pwszFileName, DIR_SEP_CHAR) == NULL)
{
ft.Trace(VSSDBG_WRITER,
L"Error in the File value for event log %s", iterator.GetCurrentKeyName());
iterator.MoveNext();
continue;
}
// --- get the name of the log
CVssAutoPWSZ pwszName;
if (!pwszName.CopyFrom(iterator.GetCurrentKeyName()))
ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Failed to allocate memory for event log name");
// -- add the information to the list
currentLog.m_pwszFileName = pwszFileName;
currentLog.m_pwszName = pwszName;
if (!m_eventLogs.Add(currentLog))
ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Failed to add entry to list");
pwszFileName.Detach();
pwszName.Detach();
iterator.MoveNext();
}
}
void CEventLogWriter::AddExcludes(IVssCreateWriterMetadata* pMetadata)
{
CVssFunctionTracer ft (VSSDBG_WRITER, L"CEventLogWriter::AddExcludes");
pMetadata->AddExcludeFiles(s_cwsSystemEventLogDir, s_cwsSystemEventLogFiles,
false);
}
void CEventLogWriter::AddLogs(IVssCreateWriterMetadata* pMetadata)
{
CVssFunctionTracer ft (VSSDBG_WRITER, L"CEventLogWriter::AddLogs");
// add each log file to the component
for (int x = 0; x < m_eventLogs.GetSize(); x++)
{
CVssAutoPWSZ pwszEventPath;
if (!pwszEventPath.CopyFrom(m_eventLogs[x].m_pwszFileName))
ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Failed to allocate memory for event log name");
// --- seperate out the path, and add to the component
VSS_PWSZ pwszEventFile = wcsrchr(pwszEventPath, DIR_SEP_CHAR);
BS_ASSERT(pwszEventFile != NULL);
*pwszEventFile = L'\0';
++pwszEventFile;
ft.hr = pMetadata->AddFilesToFileGroup
(NULL,
s_wszComponentName,
pwszEventPath,
pwszEventFile,
false,
s_cwsEventLogsTargetDir
);
ft.CheckForErrorInternal(VSSDBG_WRITER, L"IVssCreateWriterMetadata::AddFilesToFileGroup");
}
}
void CEventLogWriter::BackupLogs()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::BackupLogs");
// back up each event log
for (int x = 0; x < m_eventLogs.GetSize(); x++)
{
BS_ASSERT(m_eventLogs[x].m_pwszName != NULL);
BS_ASSERT(m_eventLogs[x].m_pwszName != NULL);
CVssAutoWin32EventLogHandle hLog =
::OpenEventLog(NULL, m_eventLogs[x].m_pwszName);
if (hLog == NULL)
{
ft.Throw(VSSDBG_WRITER, E_UNEXPECTED,
L"Failed to open event log %s. [0x%08lx]", m_eventLogs[x].m_pwszName, ::GetLastError());
}
// --- build up the path that we will back up to
VSS_PWSZ pwszBackupFile = ::wcsrchr(m_eventLogs[x].m_pwszFileName, DIR_SEP_CHAR);
BS_ASSERT(pwszBackupFile != NULL);
CBsString cwsBackupPath;
cwsBackupPath.ExpandEnvironmentStrings(s_cwsEventLogsTargetDir);
cwsBackupPath += pwszBackupFile;
// --- NOTE: There's a potential failure scenario here. If two different event logs have the same filename
// --- in different directories, they will overwrite each other in the spit directory. This will be fixed when the
// --- writer is altered to be an in-place writer
if (::BackupEventLog(hLog, cwsBackupPath) == FALSE)
{
ft.Throw(VSSDBG_WRITER, E_UNEXPECTED,
L"Failed to backup event log %s to %s. [0x%08lx]", m_eventLogs[x].m_pwszName,
cwsBackupPath, ::GetLastError());
}
}
}
// static
DWORD CEventLogWriter::InitializeThreadFunc(VOID *pv)
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::InitializeThreadFunc");
BOOL fCoinitializeSucceeded = false;
try
{
// intialize MTA thread
ft.hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (ft.HrFailed())
ft.Throw
(
VSSDBG_WRITER,
E_UNEXPECTED,
L"CoInitializeEx failed 0x%08lx", ft.hr
);
fCoinitializeSucceeded = true;
// Now initialize the base class and subscribe
ft.hr = sm_pWriter->Initialize();
}
VSS_STANDARD_CATCH(ft)
if (fCoinitializeSucceeded)
CoUninitialize();
sm_hrInitialize = ft.hr;
return 0;
UNREFERENCED_PARAMETER( pv );
}
// static
void CEventLogWriter::DestroyWriter()
{
CVssFunctionTracer ft(VSSDBG_WRITER, L"CEventLogWriter::DestroyWriter");
if (sm_pWriter)
{
sm_pWriter->Uninitialize();
delete sm_pWriter;
sm_pWriter = NULL;
}
}