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.
396 lines
7.8 KiB
396 lines
7.8 KiB
/*++
|
|
|
|
Copyright (c) 1993-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
log.cpp
|
|
|
|
Abstract:
|
|
|
|
This file implements the access to the postmortem log file.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 1-May-1993
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#include "pch.cpp"
|
|
|
|
|
|
#define BYTE_ORDER_MARK 0xFEFF
|
|
#define MAX_PRINTF_BUF_SIZE (1024 * 4)
|
|
|
|
enum LOG_TYPE {
|
|
LT_ANSI,
|
|
LT_UNICODE
|
|
};
|
|
|
|
//
|
|
// global variables for this module
|
|
//
|
|
static HANDLE hFile = NULL;
|
|
static DWORD dwStartingPos = 0;
|
|
static WCHAR wchBOM = BYTE_ORDER_MARK;
|
|
static DWORD dwLogType = LT_ANSI;
|
|
|
|
void
|
|
WriteAnsiCharsToLogFile(
|
|
WCHAR *pszUnicode,
|
|
DWORD dwCharCount
|
|
)
|
|
{
|
|
char szAnsiBuf[MAX_PRINTF_BUF_SIZE] = {0};
|
|
DWORD nCharTranslated;
|
|
WCHAR szWcharBuf[MAX_PRINTF_BUF_SIZE] = {0};
|
|
|
|
nCharTranslated = WideCharToMultiByte(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
|
|
pszUnicode, dwCharCount,
|
|
szAnsiBuf, sizeof(szAnsiBuf), NULL, NULL);
|
|
|
|
WriteFile( hFile, szAnsiBuf, nCharTranslated, &nCharTranslated, NULL );
|
|
#if 0
|
|
nCharTranslated = MultiByteToWideChar(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
|
|
szAnsiBuf, nCharTranslated,
|
|
szWcharBuf, sizeof(szWcharBuf)/sizeof(WCHAR));
|
|
|
|
WriteFile( hFile, szWcharBuf, nCharTranslated, &nCharTranslated, NULL );
|
|
#endif
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
lprintf(
|
|
DWORD dwFormatId,
|
|
...
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is function is a printf style function for printing messages
|
|
in a message file.
|
|
|
|
Arguments:
|
|
|
|
dwFormatId - format id in the message file
|
|
|
|
... - var args
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
_TCHAR buf[MAX_PRINTF_BUF_SIZE] = {0};
|
|
DWORD dwCount;
|
|
va_list args;
|
|
|
|
va_start( args, dwFormatId );
|
|
|
|
dwCount = FormatMessage(
|
|
FORMAT_MESSAGE_FROM_HMODULE,
|
|
NULL,
|
|
dwFormatId,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), // Default language
|
|
buf,
|
|
sizeof(buf) / sizeof(_TCHAR),
|
|
&args
|
|
);
|
|
|
|
va_end(args);
|
|
|
|
if (dwCount == 0) {
|
|
// Failure, nothing to write.
|
|
return;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
// We currently want all of the output to be in ANSI
|
|
if (dwLogType == LT_ANSI) {
|
|
WriteAnsiCharsToLogFile(buf, dwCount);
|
|
} else {
|
|
WriteFile( hFile, buf, dwCount * sizeof(_TCHAR), &dwCount, NULL );
|
|
}
|
|
#else
|
|
WriteFile( hFile, buf, dwCount, &dwCount, NULL );
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
lprintfs(
|
|
_TCHAR *format,
|
|
...
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is function is a printf replacement that writes the output to
|
|
the DrWatson log file.
|
|
|
|
Arguments:
|
|
|
|
format - print format
|
|
|
|
... - var args
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
_TCHAR buf[MAX_PRINTF_BUF_SIZE] = {0};
|
|
int chars;
|
|
DWORD cb;
|
|
|
|
va_list arg_ptr;
|
|
va_start(arg_ptr, format);
|
|
chars = _vsntprintf(buf, _tsizeof(buf), format, arg_ptr);
|
|
buf[_tsizeof(buf) - 1] = 0;
|
|
if (chars < 0 || chars == _tsizeof(buf)) {
|
|
cb = _tsizeof(buf) - 1;
|
|
} else {
|
|
cb = chars;
|
|
}
|
|
va_end(arg_ptr);
|
|
Assert( hFile != NULL );
|
|
|
|
#ifdef UNICODE
|
|
// We currently want all of the output to be in ANSI
|
|
if (dwLogType == LT_ANSI) {
|
|
WriteAnsiCharsToLogFile(buf, cb);
|
|
} else {
|
|
WriteFile( hFile, buf, cb * sizeof(_TCHAR), &cb, NULL );
|
|
}
|
|
#else
|
|
WriteFile( hFile, buf, cb * sizeof(_TCHAR), &cb, NULL );
|
|
#endif
|
|
}
|
|
|
|
void
|
|
OpenLogFile(
|
|
_TCHAR *szFileName,
|
|
BOOL fAppend,
|
|
BOOL fVisual
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens the DrWatson logfile for reading & writting.
|
|
|
|
Arguments:
|
|
|
|
szFileName - logfile name
|
|
|
|
fAppend - append the new data to the end of the file or
|
|
create a new file
|
|
|
|
fVisual - visual notification
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD size;
|
|
DWORD Retries = 10;
|
|
|
|
//
|
|
// The log file may be in use by another instance
|
|
// of Dr. Watson, so try and open it several times
|
|
// with a wait inbetween.
|
|
//
|
|
|
|
for (;;) {
|
|
|
|
hFile = CreateFile( szFileName,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
fAppend ? OPEN_ALWAYS : CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
break;
|
|
}
|
|
|
|
if (fVisual) {
|
|
NonFatalError( LoadRcString(IDS_INVALID_LOGFILE) );
|
|
_tgetcwd( szFileName, MAX_PATH );
|
|
if (!BrowseForDirectory(NULL, szFileName, MAX_PATH )) {
|
|
FatalError( GetLastError(),
|
|
LoadRcString(IDS_CANT_OPEN_LOGFILE) );
|
|
}
|
|
MakeLogFileName( szFileName );
|
|
}
|
|
else if (Retries-- == 0) {
|
|
ExitProcess( 1 );
|
|
}
|
|
else {
|
|
Sleep(1000);
|
|
}
|
|
}
|
|
|
|
if (!fAppend || GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
|
|
//
|
|
// The file was just created, so put a header in it.
|
|
//
|
|
|
|
dwLogType = LT_UNICODE;
|
|
WriteFile( hFile, &wchBOM, sizeof(_TCHAR), &size, NULL );
|
|
lprintfs( _T("\r\n") );
|
|
lprintf( MSG_BANNER );
|
|
lprintfs( _T("\r\n") );
|
|
|
|
} else {
|
|
|
|
#ifdef UNICODE
|
|
//
|
|
// Check if the file is Unicode or ANSI
|
|
//
|
|
WCHAR wchHdr = 0;
|
|
|
|
dwLogType = LT_ANSI;
|
|
if (ReadFile( hFile, &wchHdr, sizeof(TCHAR), &size, NULL )) {
|
|
if (wchHdr == wchBOM) {
|
|
dwLogType = LT_UNICODE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SetFilePointer( hFile, 0, 0, FILE_END );
|
|
}
|
|
|
|
dwStartingPos = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
|
|
}
|
|
|
|
void
|
|
CloseLogFile(
|
|
void
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Closes the DrWatson logfile & releases the semaphore that
|
|
protects it.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
CloseHandle( hFile );
|
|
}
|
|
|
|
_TCHAR *
|
|
GetLogFileData(
|
|
PDWORD pdwLogFileDataSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads in all of the logfile data that has been written since it was
|
|
opened. The data is placed into a buffer allocated by this function.
|
|
The caller is responsible for freeing the memory.
|
|
|
|
Arguments:
|
|
|
|
pdwLogFileDataSize - pointer to a dword that contains the size
|
|
in bytes of the data that is read.
|
|
|
|
Return Value:
|
|
|
|
Valid character pointer to the logfile data
|
|
|
|
NULL - could not read the data.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwCurrPos;
|
|
_TCHAR *p;
|
|
DWORD size;
|
|
|
|
|
|
dwCurrPos = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
|
|
|
|
*pdwLogFileDataSize = 0;
|
|
size = dwCurrPos - dwStartingPos;
|
|
|
|
p = (_TCHAR *) calloc( size, sizeof(_TCHAR) );
|
|
if (p == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
SetFilePointer( hFile, dwStartingPos, NULL, FILE_BEGIN );
|
|
|
|
if (!ReadFile( hFile, p, size, &size, NULL )) {
|
|
free( p );
|
|
p = NULL;
|
|
size = 0;
|
|
}
|
|
|
|
SetFilePointer( hFile, dwCurrPos, NULL, FILE_BEGIN );
|
|
|
|
*pdwLogFileDataSize = size;
|
|
|
|
return p;
|
|
}
|
|
|
|
void
|
|
MakeLogFileName(
|
|
_TCHAR *szName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Concatenates the base logfile name on to the string passed in.
|
|
|
|
Arguments:
|
|
|
|
szName - buffer for the logfile name.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (_tcslen(szName) + 16 < MAX_PATH) {
|
|
_tcscat( szName, _T("\\drwtsn32.log") );
|
|
}
|
|
}
|