windows-nt/Source/XPSP1/NT/windows/appcompat/appverifier/log.cpp
2020-09-26 16:20:57 +08:00

511 lines
11 KiB
C++

#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
}