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