windows-nt/Source/XPSP1/NT/base/subsys/sm/sfc/dll/eventlog.c

380 lines
10 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
eventlog.c
Abstract:
Implementation of event logging.
Author:
Wesley Witt (wesw) 18-Dec-1998
Revision History:
Andrew Ritz (andrewr) 7-Jul-1999
--*/
#include "sfcp.h"
#pragma hdrstop
typedef BOOL (WINAPI *PPSETUPLOGSFCERROR)(PCWSTR,DWORD);
//
// global handle to eventlog
//
HANDLE hEventSrc;
//
// pointer to gui-setup eventlog function
//
PPSETUPLOGSFCERROR pSetuplogSfcError;
BOOL
pSfcGetSetuplogSfcError(
VOID
)
/*++
Routine Description:
Routine retreives a function pointer to the error logging entrypoint in
syssetup.dll
Arguments:
None.
Return Value:
TRUE for success, FALSE for failure.
--*/
{
HMODULE hMod;
if (NULL == pSetuplogSfcError) {
hMod = GetModuleHandle( L"syssetup.dll" );
if (hMod) {
pSetuplogSfcError = (PPSETUPLOGSFCERROR)SfcGetProcAddress( hMod, "pSetuplogSfcError" );
} else {
DebugPrint1(LVL_MINIMAL, L"GetModuleHandle on syssetup.dll failed, ec=0x%08x",GetLastError());
}
}
return pSetuplogSfcError != NULL;
}
BOOL
SfcReportEvent(
IN ULONG EventId,
IN PCWSTR FileName,
IN PCOMPLETE_VALIDATION_DATA ImageValData,
IN DWORD LastError OPTIONAL
)
/*++
Routine Description:
Routine logs an event into the eventlog. Also contains a hack for logging
data into the GUI-setup error log as well. we typically log unsigned files
or the user tht cancelled the replacement of the signed files.
Arguments:
EventId - id of the eventlog error
FileName - null terminated unicode string indicating the file that was
unsigned, etc.
ImageValData - pointer to file data for unsigned file
LastError - contains an optional last error code for logging
Return Value:
TRUE for success, FALSE for failure.
--*/
{
PFILE_VERSION_INFO FileVer;
WCHAR SysVer[64];
WCHAR BadVer[64];
PCWSTR s[3];
WORD Count = 0;
WCHAR LastErrorText[MAX_PATH];
PVOID ErrText = NULL;
WORD wEventType;
//
// if we're in gui-mode setup, we take a special path to log into
// gui-setup's logfile instead of the eventlog
//
if (SFCDisable == SFC_DISABLE_SETUP) {
if(!pSfcGetSetuplogSfcError()) {
return FALSE;
}
switch (EventId){
case MSG_DLL_CHANGE: //fall through
case MSG_SCAN_FOUND_BAD_FILE:
pSetuplogSfcError( FileName,0 );
break;
case MSG_COPY_CANCEL_NOUI:
case MSG_RESTORE_FAILURE:
pSetuplogSfcError( FileName, 1 );
break;
case MSG_CACHE_COPY_ERROR:
pSetuplogSfcError( FileName, 2 );
break;
default:
DebugPrint1(
LVL_MINIMAL,
L"unexpected EventId 0x%08x in GUI Setup, ",
EventId);
return FALSE;
//ASSERT( FALSE && L"Unexpected EventId in SfcReportEvent");
}
return(TRUE);
}
//
// we're outside of GUI-setup so we really want to log to the eventlog
//
if (EventId == 0) {
ASSERT( FALSE && L"Unexpected EventId in SfcReportEvent");
return(FALSE);
}
//
// if we don't have a handle to the eventlog, create one.
//
if (hEventSrc == NULL) {
hEventSrc = RegisterEventSource( NULL, L"Windows File Protection" );
if (hEventSrc == NULL) {
DebugPrint1(LVL_MINIMAL, L"RegisterEventSource failed, ec=0x%08x",GetLastError());
return(FALSE);
}
}
ASSERT(hEventSrc != NULL);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
LastError,
0,
(PWSTR) &ErrText,
0,
NULL
);
if (ErrText) {
wsprintf(LastErrorText,L"0x%08x [%ws]",LastError,ErrText);
LocalFree( ErrText );
} else {
wsprintf(LastErrorText,L"0x%08x",LastError);
}
//
// pick out the appropriate message to log
// the default event type is "information"
//
wEventType = EVENTLOG_INFORMATION_TYPE;
switch (EventId) {
case MSG_DLL_CHANGE:
ASSERT(FileName != NULL);
s[0] = FileName;
//
// we prefer a message that is most informative message with
// version information for both dlls to the least informative
// message with no version information
//
//
if (ImageValData->New.DllVersion && ImageValData->Original.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->New.DllVersion;
swprintf( SysVer, L"%d.%d.%d.%d", FileVer->VersionHigh, FileVer->VersionLow, FileVer->BuildNumber, FileVer->Revision );
FileVer = (PFILE_VERSION_INFO)&ImageValData->Original.DllVersion;
swprintf( BadVer, L"%d.%d.%d.%d", FileVer->VersionHigh, FileVer->VersionLow, FileVer->BuildNumber, FileVer->Revision );
s[1] = BadVer;
s[2] = SysVer;
Count = 3;
EventId = MSG_DLL_CHANGE2;
} else if (ImageValData->New.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->New.DllVersion;
swprintf( SysVer, L"%d.%d.%d.%d", FileVer->VersionHigh, FileVer->VersionLow, FileVer->BuildNumber, FileVer->Revision );
s[1] = SysVer;
Count = 2;
EventId = MSG_DLL_CHANGE3;
} else if (ImageValData->Original.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->Original.DllVersion;
swprintf( BadVer, L"%d.%d.%d.%d", FileVer->VersionHigh, FileVer->VersionLow, FileVer->BuildNumber, FileVer->Revision );
s[1] = BadVer;
Count = 2;
EventId = MSG_DLL_CHANGE;
} else {
//
// we have to protect some things without version information,
// so we just log an error that doesn't mention version
// information. If we stop protecting files like this, this
// should be an assert in prerelease versions of the code
//
Count = 1;
EventId = MSG_DLL_CHANGE_NOVERSION;
DebugPrint1( LVL_MINIMAL, L"TskTsk...the protected OS file %ws does not have any version information", FileName);
}
break;
case MSG_SCAN_FOUND_BAD_FILE:
ASSERT(FileName != NULL);
s[0] = FileName;
//
// if we found a bad file, we only want the version of the restored file
//
if (ImageValData->New.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->New.DllVersion;
swprintf( SysVer, L"%d.%d.%d.%d", FileVer->VersionHigh, FileVer->VersionLow, FileVer->BuildNumber, FileVer->Revision );
s[1] = SysVer;
Count = 2;
} else {
DebugPrint1( LVL_MINIMAL, L"TskTsk...the protected OS file %ws does not have any version information", FileName);
EventId = MSG_SCAN_FOUND_BAD_FILE_NOVERSION;
Count = 1;
break;
}
break;
case MSG_RESTORE_FAILURE:
Count = 3;
s[0] = FileName;
s[1] = BadVer;
s[2] = (PCWSTR)LastErrorText;
if (ImageValData->Original.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->Original.DllVersion;
swprintf( BadVer,
L"%d.%d.%d.%d",
FileVer->VersionHigh,
FileVer->VersionLow,
FileVer->BuildNumber,
FileVer->Revision );
} else {
LoadString( SfcInstanceHandle,IDS_UNKNOWN,BadVer,UnicodeChars(BadVer));
}
break;
case MSG_CACHE_COPY_ERROR:
Count = 2;
s[0] = FileName;
s[1] = (PCWSTR)LastErrorText;
break;
case MSG_COPY_CANCEL_NOUI:
//fall through
case MSG_COPY_CANCEL:
Count = 3;
s[0] = FileName;
s[1] = LoggedOnUserName;
s[2] = BadVer;
if (ImageValData->Original.DllVersion) {
FileVer = (PFILE_VERSION_INFO)&ImageValData->Original.DllVersion;
swprintf( BadVer,
L"%d.%d.%d.%d",
FileVer->VersionHigh,
FileVer->VersionLow,
FileVer->BuildNumber,
FileVer->Revision );
} else {
LoadString( SfcInstanceHandle,IDS_UNKNOWN,BadVer,UnicodeChars(BadVer));
}
break;
case MSG_DLL_NOVALIDATION_TERMINATION:
wEventType = EVENTLOG_WARNING_TYPE;
s[0] = FileName;
Count = 1;
break;
case MSG_RESTORE_FAILURE_MAX_RETRIES:
s[0] = FileName;
Count = 1;
break;
case MSG_SCAN_STARTED:
Count = 0;
break;
case MSG_SCAN_COMPLETED:
Count = 0;
break;
case MSG_SCAN_CANCELLED:
s[0] = LoggedOnUserName;
Count = 1;
break;
case MSG_DISABLE:
Count = 0;
break;
case MSG_DLLCACHE_INVALID:
Count = 0;
break;
case MSG_SXS_INITIALIZATION_FAILED:
Count = 1;
s[0] = LastErrorText;
break;
case MSG_INITIALIZATION_FAILED:
Count = 1;
s[0] = LastErrorText;
break;
case MSG_CATALOG_RESTORE_FAILURE:
Count = 2;
s[0] = FileName;
s[1] = LastErrorText;
break;
default:
ASSERT( FALSE && L"Unknown EventId in SfcReportEvent");
return FALSE;
}
return ReportEvent(
hEventSrc,
wEventType,
0,
EventId,
NULL,
Count,
0,
s,
NULL
);
}