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

446 lines
9.4 KiB
C++

/*++
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 HANDLE hLogProtect = 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);
Assert( dwCount != 0 );
#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};
DWORD cb;
va_list arg_ptr;
va_start(arg_ptr, format);
cb = _vsntprintf(buf, sizeof(buf) / sizeof(_TCHAR), format, arg_ptr);
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.
--*/
{
_TCHAR szName[1024];
SECURITY_ATTRIBUTES SecAttrib;
SECURITY_DESCRIPTOR SecDescript;
DWORD size;
szName[0] = 0;
GetAppName( szName, sizeof(szName) / sizeof(_TCHAR) );
_tcscat( szName, _T("LogProtect") );
hLogProtect = OpenSemaphore( SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, szName);
if (hLogProtect == NULL) {
hLogProtect = CreateSemaphore( NULL, 0, 1, szName );
Assert( hLogProtect != NULL );
}
else {
WaitForSingleObject( hLogProtect, INFINITE );
}
openagain:
// Create a DACL that allows all access to the directory
SecAttrib.nLength=sizeof(SECURITY_ATTRIBUTES);
SecAttrib.lpSecurityDescriptor=&SecDescript;
SecAttrib.bInheritHandle=FALSE;
InitializeSecurityDescriptor(&SecDescript, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&SecDescript, TRUE, NULL, FALSE);
hFile = CreateFile( szFileName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
&SecAttrib,
fAppend ? OPEN_EXISTING : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (fAppend) {
if (hFile == INVALID_HANDLE_VALUE) {
//
// file does not exist, so lets create a new file
//
hFile = CreateFile( szFileName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
&SecAttrib,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
if (fVisual) {
NonFatalError( LoadRcString(IDS_INVALID_LOGFILE) );
_tgetcwd( szFileName, MAX_PATH );
if (!BrowseForDirectory(NULL, szFileName )) {
FatalError( GetLastError(),
LoadRcString(IDS_CANT_OPEN_LOGFILE) );
}
MakeLogFileName( szFileName );
goto openagain;
}
else {
ExitProcess( 1 );
}
}
//
// write the file banner
//
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;
SetFilePointer( hFile, 0, 0, FILE_BEGIN );
if (ReadFile( hFile, &wchHdr, sizeof(TCHAR), &size, NULL )) {
if (wchHdr == wchBOM) {
dwLogType = LT_UNICODE;
}
}
#endif
}
SetFilePointer( hFile, 0, 0, FILE_END );
Assert( hFile != INVALID_HANDLE_VALUE );
}
else {
Assert( hFile != INVALID_HANDLE_VALUE );
if (hFile == INVALID_HANDLE_VALUE) {
if (fVisual) {
NonFatalError( LoadRcString(IDS_INVALID_LOGFILE) );
_tgetcwd( szFileName, MAX_PATH );
if (!BrowseForDirectory(NULL, szFileName )) {
FatalError( GetLastError(),
LoadRcString(IDS_CANT_OPEN_LOGFILE) );
}
MakeLogFileName( szFileName );
goto openagain;
}
else {
ExitProcess( 1 );
}
}
//
// write the file banner
//
WriteFile( hFile, &wchBOM, sizeof(_TCHAR), &size, NULL );
dwLogType = LT_UNICODE;
lprintfs( _T("\r\n") );
lprintf( MSG_BANNER );
lprintfs( _T("\r\n") );
}
dwStartingPos = SetFilePointer( hFile, 0, NULL, FILE_CURRENT );
return;
}
void
CloseLogFile(
void
)
/*++
Routine Description:
Closes the DrWatson logfile & releases the semaphore that
protects it.
Arguments:
None.
Return Value:
None.
--*/
{
CloseHandle( hFile );
ReleaseSemaphore( hLogProtect, 1, NULL );
CloseHandle( hLogProtect );
}
_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.
--*/
{
_tcscat( szName, _T("\\drwtsn32.log") );
}