#include "precomp.h" typedef struct _VLOG_GLOBAL_DATA { BOOL bLoggingDisabled; WCHAR szSessionLog[MAX_PATH]; WCHAR szProcessLog[MAX_PATH]; } VLOG_GLOBAL_DATA, *PVLOG_GLOBAL_DATA; PVLOG_GLOBAL_DATA g_pData = NULL; HANDLE g_hMap = NULL; // mapping handle for global data BOOL g_bVerifierLogInited = FALSE; // have we been through the init sequence? BOOL g_bLoggingDisabled = TRUE; // have we been through the init sequence? WCHAR g_szSessionLog[MAX_PATH]; WCHAR g_szProcessLog[MAX_PATH]; #define DEBUGGER_LOG L"DEBUGGER" #define DEBUGGER_ENTRY_CRASH L"Crash" #define DEBUGGER_ENTRY_CRASH_DESCRIPTION L"An AV occured. The application exited." void WriteToProcessLog( LPCSTR szLine ); void WriteToSessionLog( LPCSTR szLine ); void GetExeName( LPWSTR szProcessPath, LPWSTR szProcessName ) { LPWSTR pszLast = NULL; LPWSTR psz; LPWSTR pszFound = NULL; psz = szProcessPath; while (psz) { pszFound = wcschr(psz, L'\\'); if (pszFound != NULL) { pszLast = pszFound; psz = pszFound + 1; } else { psz = pszFound; } } if (pszLast != NULL) { psz = pszLast + 1; } else { psz = szProcessPath; } pszFound = wcschr(psz, L'.'); if (pszFound != NULL) { wcsncpy(szProcessName, psz, pszFound - psz); } else { wcscpy(szProcessName, psz); } } /*++ Function Description: Initializes the support for file logging. Return Value: TRUE if successful, FALSE if failed History: 04/26/2001 dmunsil Created --*/ BOOL InitVerifierLogSupport( LPWSTR szProcessPath, DWORD dwID ) { WCHAR szShared[128]; WCHAR szVLogPath[MAX_PATH]; WCHAR szProcessName[MAX_PATH]; WCHAR szTime[128]; char szTemp[400]; HANDLE hFile; SYSTEMTIME LocalTime; int nTemp; BOOL bAlreadyInited; DWORD dwErr; // // if we've already been inited, get out // if (g_bVerifierLogInited) { return FALSE; } g_bVerifierLogInited = TRUE; swprintf(szShared, L"VeriferLog_%08X", dwID); g_hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szShared); if (g_hMap) { bAlreadyInited = TRUE; } else { bAlreadyInited = FALSE; g_hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(VLOG_GLOBAL_DATA), szShared); } if (!g_hMap) { DPF("Cannot get shared global data."); g_bLoggingDisabled = TRUE; return FALSE; } g_pData = (PVLOG_GLOBAL_DATA)MapViewOfFile(g_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (!g_pData) { DPF("Cannot map shared global data."); g_bLoggingDisabled = TRUE; return FALSE; } if (bAlreadyInited) { if (g_pData->szProcessLog[0] == 0 || g_pData->szSessionLog[0] == 0) { g_bLoggingDisabled = TRUE; g_pData->bLoggingDisabled = TRUE; return FALSE; } g_bLoggingDisabled = g_pData->bLoggingDisabled; wcscpy(g_szSessionLog, g_pData->szSessionLog); wcscpy(g_szProcessLog, g_pData->szProcessLog); return TRUE; } else { // // just in case -- make sure these are NULL // ZeroMemory(g_pData, sizeof(VLOG_GLOBAL_DATA)); } // // we need to init the file mapping, so temporarily disable logging, just in case. // g_pData->bLoggingDisabled = TRUE; // // init the CString objects // // // the verifier log will be located in %windir%\AppPatch\VLog // // // First, check that VLog exists; if not, we're not logging // GetSystemWindowsDirectoryW(szVLogPath, MAX_PATH); wcscat(szVLogPath, L"\\AppPatch\\VLog"); if (GetFileAttributesW(szVLogPath) == -1) { if (!CreateDirectory(szVLogPath, NULL)) { DPF("No log directory %ls. Logging disabled.", szVLogPath); g_bLoggingDisabled = TRUE; return FALSE; } } // // Next, check for the existence of session.log. If it's not there, // we're not logging // wcscpy(g_szSessionLog, szVLogPath); wcscat(g_szSessionLog, L"\\session.log"); if (GetFileAttributesW(g_szSessionLog) == -1) { hFile = CreateFile(g_szSessionLog, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } else { DPF("No session log file '%ls'. Logging disabled.", g_szSessionLog); g_bLoggingDisabled = TRUE; return FALSE; } } // // get the process log file name // GetExeName(szProcessPath, szProcessName); // // combine into log name, find first available // nTemp = 0; do { swprintf(g_szProcessLog, L"%ls\\%ls%d.%ls", szVLogPath, szProcessName, nTemp, L"log"); nTemp++; } while (GetFileAttributesW(g_szProcessLog) != -1); // // open the file. create it if it doesn't exist, and truncate // hFile = CreateFileW(g_szProcessLog, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { dwErr = GetLastError(); DPF("Cannot create verifier process log file '%ls'. Error 0x%08X.", g_szProcessLog, dwErr); g_bLoggingDisabled = TRUE; return FALSE; } CloseHandle(hFile); // // put the info in the session log and the process log // g_pData->bLoggingDisabled = FALSE; g_bLoggingDisabled = FALSE; // // I realize these pointers point to process-specific memory, but since // this mapping is only shared by this process, it seems safe. // wcscpy(g_pData->szProcessLog, g_szProcessLog); wcscpy(g_pData->szSessionLog, g_szSessionLog); GetLocalTime(&LocalTime); swprintf(szTime, L"%d/%d/%d %d:%02d:%02d", LocalTime.wMonth, LocalTime.wDay, LocalTime.wYear, LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond); sprintf(szTemp, "# LOG_BEGIN %ls '%ls' '%ls'", szTime, szProcessPath, g_szProcessLog); WriteToProcessLog(szTemp); WriteToSessionLog(szTemp); // // Dump the log provider info // sprintf(szTemp, "# SHIM_BEGIN %ls 1", DEBUGGER_LOG); WriteToProcessLog(szTemp); sprintf(szTemp, "# LOGENTRY %ls 0 '%ls", DEBUGGER_LOG, DEBUGGER_ENTRY_CRASH); WriteToProcessLog(szTemp); WriteToProcessLog("# DESCRIPTION BEGIN"); sprintf(szTemp, "%ls", DEBUGGER_ENTRY_CRASH_DESCRIPTION); WriteToProcessLog(szTemp); WriteToProcessLog("# DESCRIPTION END"); return TRUE; } /*++ Function Description: clean up all our shared file resources History: 04/26/2001 dmunsil Created --*/ void ReleaseLogSupport( void ) { g_bLoggingDisabled = TRUE; if (g_pData) { UnmapViewOfFile(g_pData); g_pData = NULL; if (g_hMap) { CloseHandle(g_hMap); g_hMap = NULL; } } } /*++ Function Description: Logs a problem that the verifier has found History: 04/26/2001 dmunsil Created --*/ void VLog( LPCSTR pszFmt, ... ) { char szT[1024]; char* szTemp; int nLen; int nRemain; va_list arglist; if (g_bLoggingDisabled) { return; } _snprintf(szT, 1023, "| %ls 0 '", DEBUGGER_LOG); nLen = lstrlenA(szT); szTemp = szT + nLen; nRemain = 1023 - nLen; if (nRemain > 0) { va_start(arglist, pszFmt); _vsnprintf(szTemp, nRemain, pszFmt, arglist); va_end(arglist); } szT[1023] = 0; WriteToProcessLog(szT); } /*++ Function Description: Writes a line of text to the process log file Return Value: History: 04/26/2001 dmunsil Created --*/ void WriteToProcessLog( LPCSTR szLine ) { HANDLE hFile; DWORD bytesWritten; if (g_bLoggingDisabled) { return; } // open the log file hFile = CreateFileW(g_szProcessLog, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { DPF("Cannot open verifier log file '%s'", g_szProcessLog); return; } // go to the end of the file SetFilePointer(hFile, 0, NULL, FILE_END); // make sure we have no '\n' or '\r' at the end of the string. int len = lstrlenA(szLine); while (len && (szLine[len - 1] == '\n' || szLine[len - 1] == '\r')) { len--; } // write the actual log WriteFile(hFile, szLine, len, &bytesWritten, NULL); // new line WriteFile(hFile, "\r\n", 2, &bytesWritten, NULL); CloseHandle(hFile); // dump it in the debugger as well on checked builds #if DBG DPF((LPSTR)szLine); #endif // DBG } /*++ Function Description: Writes a line of text to the session log file Return Value: History: 04/26/2001 dmunsil Created --*/ void WriteToSessionLog( LPCSTR szLine ) { HANDLE hFile; DWORD bytesWritten; if (g_bLoggingDisabled) { return; } // open the log file hFile = CreateFileW(g_szSessionLog, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { DPF("Cannot open verifier log file '%s'", g_szSessionLog); return; } // go to the end of the file SetFilePointer(hFile, 0, NULL, FILE_END); // make sure we have no '\n' or '\r' at the end of the string. int len = lstrlenA(szLine); while (len && (szLine[len - 1] == '\n' || szLine[len - 1] == '\r')) { len--; } // write the actual log WriteFile(hFile, szLine, len, &bytesWritten, NULL); // new line WriteFile(hFile, "\r\n", 2, &bytesWritten, NULL); CloseHandle(hFile); // dump it in the debugger as well on checked builds #if DBG DPF((LPSTR)szLine); #endif // DBG }