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.
476 lines
15 KiB
476 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Abstract:
|
|
|
|
Implementation of standard logs support:
|
|
setupact.log, setuperr.log and debug.log.
|
|
|
|
Author:
|
|
|
|
Souren Aghajanyan (sourenag) 24-Sep-2001
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
#include "mem.h"
|
|
|
|
#include "setuplog.h"
|
|
|
|
ILogManager * g_pLogManager = NULL;
|
|
HINSTANCE g_ModuleInstance = NULL;
|
|
DWORD g_ProcessID = 0;
|
|
|
|
#define L_QUOTE1(x) L##x
|
|
#define L_QUOTE(x) L_QUOTE1(x)
|
|
|
|
#define TOO_LONG_MESSAGEA "Log: Too Long Message"
|
|
#define TOO_LONG_MESSAGEW L_QUOTE(TOO_LONG_MESSAGEA)
|
|
|
|
#define FAILED_TO_GET_MSG_FROM_IDA "Log: Failed To Get Msg From ID"
|
|
|
|
#define STANDART_LOG_FIELD_SEVERITY L"Severity"
|
|
#define STANDART_LOG_FIELD_MESSAGE L"Message"
|
|
#define STANDART_LOG_FIELD_CONDITION L"Condition"
|
|
#define STANDART_LOG_FIELD_SOURCELINENUMBER L"SourceLineNumber"
|
|
#define STANDART_LOG_FIELD_SOURCEFILE L"SourceFile"
|
|
#define STANDART_LOG_FIELD_SOURCEFUNCTION L"SourceFunction"
|
|
#define STANDART_LOG_PROCESS_ID L"ProcessID"
|
|
#define STANDART_LOG_THREAD_ID L"ThreadID"
|
|
|
|
static LOG_FIELD_INFO g_infoFields[] = {
|
|
{LT_DWORD, TRUE, STANDART_LOG_FIELD_SEVERITY},
|
|
{LT_SZ, TRUE, STANDART_LOG_FIELD_MESSAGE},
|
|
{LT_DWORD, TRUE, STANDART_LOG_PROCESS_ID},
|
|
{LT_DWORD, TRUE, STANDART_LOG_THREAD_ID},
|
|
{LT_SZ, FALSE, STANDART_LOG_FIELD_CONDITION},
|
|
{LT_DWORD, FALSE, STANDART_LOG_FIELD_SOURCELINENUMBER},
|
|
{LT_SZ, FALSE, STANDART_LOG_FIELD_SOURCEFILE},
|
|
{LT_SZ, FALSE, STANDART_LOG_FIELD_SOURCEFUNCTION},
|
|
};
|
|
|
|
#define NUMBER_OF_FIELDS (sizeof(g_infoFields) / sizeof(g_infoFields[0]))
|
|
|
|
ILogManager *
|
|
STD_CALL_TYPE
|
|
LogStandardInit(
|
|
IN PCWSTR pDebugLogFileName,
|
|
IN HINSTANCE hModuleInstance, OPTIONAL
|
|
IN BOOL bCreateNew, OPTIONAL
|
|
IN BOOL bExcludeSetupActLog, OPTIONAL
|
|
IN BOOL bExcludeSetupErrLog, OPTIONAL
|
|
IN BOOL bExcludeXMLLog, OPTIONAL
|
|
IN BOOL bExcludeDebugFilter OPTIONAL
|
|
)
|
|
{
|
|
BOOL bResult;
|
|
ILogManager * pLogManager;
|
|
UINT uiNumberOfFields;
|
|
DWORD dwFlags = bCreateNew? DEVICE_CREATE_NEW: 0;
|
|
CHAR winDirectory[MAX_PATH];
|
|
WCHAR setupactDir[MAX_PATH];
|
|
WCHAR setuperrDir[MAX_PATH];
|
|
WCHAR setupxmlDir[MAX_PATH];
|
|
|
|
|
|
if(g_pLogManager){
|
|
return NULL;
|
|
}
|
|
|
|
uiNumberOfFields = NUMBER_OF_FIELDS;
|
|
|
|
LogRegisterStockProviders();
|
|
|
|
pLogManager = LogCreateLog(L"SetupLog", g_infoFields, uiNumberOfFields);
|
|
if(!pLogManager){
|
|
return NULL;
|
|
}
|
|
|
|
bResult = FALSE;
|
|
|
|
GetWindowsDirectoryA(winDirectory, sizeof(winDirectory) / sizeof(winDirectory[0]));
|
|
|
|
swprintf(setupactDir, L"%S\\%s", winDirectory, L"setupact.log");
|
|
swprintf(setuperrDir, L"%S\\%s", winDirectory, L"setuperr.log");
|
|
swprintf(setupxmlDir, L"%S\\%s", winDirectory, L"setuplog.xml");
|
|
|
|
__try{
|
|
LOG_DEVICE_PROV_INIT_DATA deviceActInitData = {setupactDir, dwFlags | DEVICE_WRITE_THROUGH, 0, 0};
|
|
LOG_DEVICE_PROV_INIT_DATA deviceErrInitData = {setuperrDir, dwFlags, 0, 0};
|
|
LOG_DEVICE_PROV_INIT_DATA deviceDbgInitData = {pDebugLogFileName, dwFlags, 0, 0};
|
|
LOG_DEVICE_PROV_INIT_DATA deviceXMLInitData = {setupxmlDir, dwFlags, 0, 0};
|
|
|
|
LOG_SETUPLOG_FORMAT_PROV_INIT_DATA formatterInitData = {
|
|
STANDART_LOG_FIELD_SEVERITY,
|
|
STANDART_LOG_FIELD_MESSAGE,
|
|
0
|
|
};
|
|
|
|
LOG_DEBUG_FORMAT_AND_DEVICE_PROV_INIT_DATA debugFormatterAndDevice = {
|
|
STANDART_LOG_FIELD_SEVERITY,
|
|
STANDART_LOG_FIELD_MESSAGE,
|
|
STANDART_LOG_FIELD_CONDITION,
|
|
STANDART_LOG_FIELD_SOURCELINENUMBER,
|
|
STANDART_LOG_FIELD_SOURCEFILE,
|
|
STANDART_LOG_FIELD_SOURCEFUNCTION
|
|
};
|
|
|
|
LOG_SETUPLOG_FILTER_PROV_INIT_DATA filterActInitData = {STANDART_LOG_FIELD_SEVERITY, LOG_INFO, TRUE};
|
|
LOG_SETUPLOG_FILTER_PROV_INIT_DATA filterErrInitData = {STANDART_LOG_FIELD_SEVERITY, LOG_ERROR, TRUE};
|
|
//LOG_SETUPLOG_FILTER_PROV_INIT_DATA filterDbgInitData = {L"Severity", LOG_INFO, L"Debug", FALSE};
|
|
|
|
if(!bExcludeSetupActLog){
|
|
if(!ILogManager_AddStack(pLogManager,
|
|
&GUID_STANDARD_SETUPLOG_FILTER, &filterActInitData,
|
|
&GUID_STANDARD_SETUPLOG_FORMATTER, &formatterInitData,
|
|
&GUID_FILE_DEVICE, &deviceActInitData,
|
|
NULL)){
|
|
__leave;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if(!bExcludeSetupErrLog){
|
|
if(!ILogManager_AddStack(pLogManager,
|
|
&GUID_STANDARD_SETUPLOG_FILTER, &filterErrInitData,
|
|
&GUID_STANDARD_SETUPLOG_FORMATTER, &formatterInitData,
|
|
&GUID_FILE_DEVICE, &deviceErrInitData,
|
|
NULL)){
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
if(pDebugLogFileName){
|
|
if(!ILogManager_AddStack(pLogManager,
|
|
NULL, NULL,
|
|
&GUID_STANDARD_SETUPLOG_FORMATTER, &formatterInitData,
|
|
&GUID_FILE_DEVICE, &deviceDbgInitData,
|
|
NULL)){
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
if(!bExcludeDebugFilter){
|
|
if(!ILogManager_AddStack(pLogManager,
|
|
&GUID_DEBUG_FILTER, &debugFormatterAndDevice,
|
|
&GUID_DEBUG_FORMATTER_AND_DEVICE, &debugFormatterAndDevice,
|
|
NULL, NULL,
|
|
NULL)){
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
if(!bExcludeXMLLog){
|
|
if(!ILogManager_AddStack(pLogManager,
|
|
NULL, NULL,
|
|
&GUID_XML_FORMATTER, NULL,
|
|
&GUID_FILE_DEVICE, &deviceXMLInitData,
|
|
NULL)){
|
|
__leave;
|
|
}
|
|
}
|
|
|
|
g_ProcessID = GetCurrentProcessId();
|
|
|
|
bResult = TRUE;
|
|
}
|
|
__finally{
|
|
if(!bResult){
|
|
LogDestroyStandard();
|
|
pLogManager = NULL;
|
|
}
|
|
}
|
|
|
|
g_pLogManager = pLogManager;
|
|
|
|
return pLogManager;
|
|
}
|
|
|
|
VOID
|
|
STD_CALL_TYPE
|
|
LogDestroyStandard(
|
|
VOID
|
|
)
|
|
{
|
|
if(!g_pLogManager){
|
|
return;
|
|
}
|
|
|
|
LogDestroyLog(g_pLogManager);
|
|
|
|
LogUnRegisterStockProviders();
|
|
}
|
|
|
|
LOGRESULT
|
|
STD_CALL_TYPE
|
|
LogMessageW(
|
|
IN PLOG_PARTIAL_MSG pPartialMsg,
|
|
IN PCSTR Condition,
|
|
IN DWORD SourceLineNumber,
|
|
IN PCWSTR SourceFile,
|
|
IN PCWSTR SourceFunction
|
|
)
|
|
{
|
|
LOGRESULT logResult;
|
|
WCHAR unicodeConditionBuffer[MAX_MESSAGE_CHAR];
|
|
PCWSTR pUnicodeCondition;
|
|
DWORD lastError = GetLastError();
|
|
|
|
if(!g_pLogManager || !pPartialMsg){
|
|
return logError;
|
|
}
|
|
|
|
if(Condition){
|
|
_snwprintf(unicodeConditionBuffer, MAX_MESSAGE_CHAR, L"%S", Condition);
|
|
pUnicodeCondition = unicodeConditionBuffer;
|
|
}
|
|
else{
|
|
pUnicodeCondition = NULL;
|
|
}
|
|
|
|
logResult = ILogManager(g_pLogManager)->LogW(g_pLogManager,
|
|
NUMBER_OF_FIELDS,
|
|
pPartialMsg->Severity,
|
|
pPartialMsg->Message.pWStr,
|
|
g_ProcessID,
|
|
GetCurrentThreadId(),
|
|
pUnicodeCondition,
|
|
SourceLineNumber,
|
|
SourceFile,
|
|
SourceFunction);
|
|
|
|
if(logAbortProcess == logResult){
|
|
LogDestroyStandard();
|
|
ExitProcess(0);
|
|
}
|
|
|
|
FREE(pPartialMsg);
|
|
|
|
SetLastError (lastError);
|
|
|
|
return logResult;
|
|
}
|
|
|
|
LOGRESULT
|
|
STD_CALL_TYPE
|
|
LogMessageA(
|
|
IN PLOG_PARTIAL_MSG pPartialMsg,
|
|
IN PCSTR Condition,
|
|
IN DWORD SourceLineNumber,
|
|
IN PCSTR SourceFile,
|
|
IN PCSTR SourceFunction
|
|
)
|
|
{
|
|
LOGRESULT logResult;
|
|
DWORD lastError = GetLastError();
|
|
|
|
if(!g_pLogManager || !pPartialMsg){
|
|
return logError;
|
|
}
|
|
|
|
logResult = ILogManager(g_pLogManager)->LogA(g_pLogManager,
|
|
NUMBER_OF_FIELDS,
|
|
pPartialMsg->Severity,
|
|
pPartialMsg->Message.pAStr,
|
|
g_ProcessID,
|
|
GetCurrentThreadId(),
|
|
Condition,
|
|
SourceLineNumber,
|
|
SourceFile,
|
|
SourceFunction);
|
|
|
|
if(logAbortProcess == logResult){
|
|
LogDestroyStandard();
|
|
ExitProcess(0);
|
|
}
|
|
|
|
|
|
FREE(pPartialMsg);
|
|
|
|
SetLastError (lastError);
|
|
|
|
return logResult;
|
|
}
|
|
|
|
PLOG_PARTIAL_MSG
|
|
STD_CALL_TYPE
|
|
ConstructPartialMsgVA(
|
|
IN DWORD dwSeverity,
|
|
IN PCSTR Format,
|
|
IN va_list args
|
|
)
|
|
{
|
|
PLOG_PARTIAL_MSG partialMsg;
|
|
PSTR ptrString;
|
|
|
|
if(!g_pLogManager){
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// improve later, by using TLS
|
|
//
|
|
partialMsg = (PLOG_PARTIAL_MSG)MALLOC(sizeof(LOG_PARTIAL_MSG));
|
|
|
|
if(partialMsg){
|
|
partialMsg->Severity = dwSeverity;
|
|
|
|
if(Format){
|
|
ptrString = NULL;
|
|
|
|
if(!(HIWORD(Format))){
|
|
//
|
|
// StringID
|
|
//
|
|
if(!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
g_ModuleInstance,
|
|
(DWORD)LOWORD(Format),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(PVOID)&ptrString,
|
|
0,
|
|
&args)){
|
|
Format = FAILED_TO_GET_MSG_FROM_IDA;
|
|
}
|
|
else{
|
|
Format = ptrString;
|
|
}
|
|
}
|
|
|
|
if(_vsnprintf(partialMsg->Message.pAStr,
|
|
MAX_MESSAGE_CHAR,
|
|
Format,
|
|
args) < 0){
|
|
strcpy(partialMsg->Message.pAStr, TOO_LONG_MESSAGEA);
|
|
}
|
|
|
|
if(ptrString){
|
|
LocalFree(ptrString);
|
|
}
|
|
}
|
|
else{
|
|
partialMsg->Message.pAStr[0] = '0';
|
|
}
|
|
|
|
}
|
|
|
|
return partialMsg;
|
|
}
|
|
|
|
PLOG_PARTIAL_MSG
|
|
STD_CALL_TYPE
|
|
ConstructPartialMsgVW(
|
|
IN DWORD dwSeverity,
|
|
IN PCSTR Format,
|
|
IN va_list args
|
|
)
|
|
{
|
|
PLOG_PARTIAL_MSG partialMsg;
|
|
PWSTR ptrString;
|
|
PCWSTR unicodeFormatString = NULL;
|
|
PCWSTR pStringToFree = NULL;
|
|
WCHAR unicodeBuffer[MAX_MESSAGE_CHAR];
|
|
|
|
if(!g_pLogManager){
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// improve later, by using TLS
|
|
//
|
|
partialMsg = (PLOG_PARTIAL_MSG)MALLOC(sizeof(LOG_PARTIAL_MSG));
|
|
|
|
if(partialMsg){
|
|
partialMsg->Severity = dwSeverity;
|
|
|
|
if(Format){
|
|
ptrString = NULL;
|
|
|
|
if(!(HIWORD(Format))){
|
|
//
|
|
// StringID
|
|
//
|
|
if(!FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
g_ModuleInstance,
|
|
(DWORD)LOWORD(Format),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(PVOID)&ptrString,
|
|
0,
|
|
&args)){
|
|
Format = FAILED_TO_GET_MSG_FROM_IDA;
|
|
}
|
|
else{
|
|
unicodeFormatString = ptrString;
|
|
}
|
|
}
|
|
|
|
if(!unicodeFormatString){
|
|
_snwprintf(unicodeBuffer, MAX_MESSAGE_CHAR, L"%S", Format);
|
|
unicodeBuffer[MAX_MESSAGE_CHAR - 1] = 0;
|
|
unicodeFormatString = unicodeBuffer;
|
|
}
|
|
|
|
if(_vsnwprintf(partialMsg->Message.pWStr,
|
|
MAX_MESSAGE_CHAR,
|
|
unicodeFormatString,
|
|
args) < 0){
|
|
wcscpy(partialMsg->Message.pWStr, TOO_LONG_MESSAGEW);
|
|
}
|
|
|
|
if(ptrString){
|
|
LocalFree(ptrString);
|
|
}
|
|
}
|
|
else{
|
|
partialMsg->Message.pWStr[0] = '0';
|
|
}
|
|
}
|
|
|
|
return partialMsg;
|
|
}
|
|
|
|
PLOG_PARTIAL_MSG
|
|
STD_CALL_TYPE
|
|
ConstructPartialMsgIfA(
|
|
IN BOOL bCondition,
|
|
IN DWORD dwSeverity,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list args;
|
|
|
|
if(!bCondition){
|
|
return NULL;
|
|
}
|
|
|
|
va_start(args, Format);
|
|
|
|
return ConstructPartialMsgVA(dwSeverity, Format, args);
|
|
}
|
|
|
|
PLOG_PARTIAL_MSG
|
|
STD_CALL_TYPE
|
|
ConstructPartialMsgIfW(
|
|
IN BOOL bCondition,
|
|
IN DWORD dwSeverity,
|
|
IN PCSTR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list args;
|
|
|
|
if(!bCondition){
|
|
return NULL;
|
|
}
|
|
|
|
va_start(args, Format);
|
|
|
|
return ConstructPartialMsgVW(dwSeverity, Format, args);
|
|
}
|