935 lines
20 KiB
C
935 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
eventlog.c
|
||
|
||
Abstract:
|
||
|
||
This module provides common eventlog services for the cluster service
|
||
|
||
Author:
|
||
|
||
John Vert (jvert) 9/13/1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#define UNICODE 1
|
||
#include "clusrtlp.h"
|
||
|
||
HANDLE LocalEventLog=NULL;
|
||
CRITICAL_SECTION EventLogLock;
|
||
|
||
//
|
||
// [GN] June 19/1999: added Async EventReporting
|
||
//
|
||
// Use ClRtlEventLogSetWorkQueue to set a queue
|
||
// for async event reporting. If it the queue is not set,
|
||
// event reporting is synchronous as it used to be before
|
||
//
|
||
|
||
static CLRTL_WORK_ITEM EvtReporterWorkItem;
|
||
static PCLRTL_WORK_QUEUE EvtReporterWorkQueue;
|
||
|
||
typedef struct _EVENT_LOG_PACKET {
|
||
WORD wType;
|
||
WORD wCategory;
|
||
DWORD dwEventID;
|
||
WORD wNumStrings;
|
||
DWORD dwDataSize;
|
||
LPVOID lpRawData;
|
||
LPWSTR lpStrings[0];
|
||
} *PEVENT_LOG_PACKET, EVENT_LOG_PACKET;
|
||
|
||
VOID
|
||
ClRtlEventLogSetWorkQueue(
|
||
PCLRTL_WORK_QUEUE WorkQueue
|
||
)
|
||
{
|
||
EnterCriticalSection( &EventLogLock );
|
||
|
||
EvtReporterWorkQueue = WorkQueue;
|
||
|
||
LeaveCriticalSection( &EventLogLock );
|
||
}
|
||
|
||
VOID
|
||
EvtReporter(
|
||
IN PCLRTL_WORK_ITEM WorkItem,
|
||
IN DWORD Status,
|
||
IN DWORD BytesTransferred,
|
||
IN ULONG_PTR IoContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reports queued event via advapi32!ReportEvent
|
||
|
||
Arguments:
|
||
|
||
IoContext == EVENT_LOG_PACKET
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
{
|
||
PEVENT_LOG_PACKET data = (PEVENT_LOG_PACKET)IoContext;
|
||
|
||
ReportEventW(LocalEventLog,
|
||
data->wType,
|
||
data->wCategory,
|
||
data->dwEventID,
|
||
NULL,
|
||
data->wNumStrings,
|
||
data->dwDataSize,
|
||
data->lpStrings,
|
||
data->lpRawData);
|
||
LocalFree(data);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
ClRtlEventLogInit(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
initializes the event log
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
InitializeCriticalSection(&EventLogLock);
|
||
|
||
EvtReporterWorkQueue = 0;
|
||
|
||
ClRtlInitializeWorkItem(
|
||
&EvtReporterWorkItem,
|
||
EvtReporter,
|
||
0
|
||
);
|
||
}
|
||
|
||
VOID
|
||
ClRtlEventLogCleanup(
|
||
VOID
|
||
)
|
||
{
|
||
DeleteCriticalSection( &EventLogLock );
|
||
}
|
||
|
||
PEVENT_LOG_PACKET
|
||
ClRtlpBuildEventPacket(
|
||
WORD wType,
|
||
WORD wCategory,
|
||
DWORD dwEventID,
|
||
WORD wNumStrings,
|
||
DWORD dwDataSize,
|
||
LPCWSTR *lpStrings,
|
||
LPVOID lpRawData
|
||
)
|
||
{
|
||
PEVENT_LOG_PACKET data = 0;
|
||
DWORD Count;
|
||
UINT i;
|
||
LPBYTE ptr;
|
||
|
||
Count = sizeof(EVENT_LOG_PACKET) +
|
||
dwDataSize +
|
||
wNumStrings * (sizeof(LPCWSTR) + sizeof(UNICODE_NULL));
|
||
|
||
for (i = 0; i < wNumStrings; ++i) {
|
||
int len = lstrlenW( lpStrings[i] );
|
||
Count += len * sizeof(WCHAR); // (null is already accounted for)
|
||
}
|
||
|
||
data = LocalAlloc(LMEM_FIXED, Count);
|
||
if (!data) {
|
||
return 0;
|
||
}
|
||
|
||
data->wType = wType;
|
||
data->wCategory = wCategory;
|
||
data->dwEventID = dwEventID;
|
||
data->wNumStrings = wNumStrings;
|
||
data->dwDataSize = dwDataSize;
|
||
data->lpRawData = &data->lpStrings[wNumStrings];
|
||
// lpStrings will be filled later
|
||
|
||
if (dwDataSize) {
|
||
CopyMemory(data->lpRawData, lpRawData, dwDataSize);
|
||
}
|
||
|
||
ptr = (LPBYTE)data->lpRawData + dwDataSize;
|
||
for (i = 0; i < wNumStrings; ++i) {
|
||
int nBytes = (lstrlenW( lpStrings[i] ) + 1) * sizeof(WCHAR);
|
||
CopyMemory(ptr, lpStrings[i], nBytes);
|
||
data->lpStrings[i] = (LPWSTR)ptr;
|
||
ptr += nBytes;
|
||
}
|
||
|
||
CL_ASSERT(ptr <= (LPBYTE)data + Count);
|
||
return data;
|
||
}
|
||
|
||
|
||
|
||
|
||
VOID
|
||
ClRtlpReportEvent(
|
||
WORD wType,
|
||
WORD wCategory,
|
||
DWORD dwEventID,
|
||
WORD wNumStrings,
|
||
DWORD dwDataSize,
|
||
LPCWSTR *lpStrings,
|
||
LPVOID lpRawData
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Common routine for reporting an event to the event log. Opens a handle
|
||
to the event log if necessary.
|
||
|
||
Arguments:
|
||
|
||
Identical arguments to ReportEventW
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success = FALSE;
|
||
DWORD Status;
|
||
|
||
//
|
||
// If the event log hasn't been opened, try and open it now.
|
||
//
|
||
if (LocalEventLog == NULL) {
|
||
EnterCriticalSection(&EventLogLock);
|
||
if (LocalEventLog == NULL) {
|
||
LocalEventLog = RegisterEventSource(NULL, L"ClusSvc");
|
||
}
|
||
LeaveCriticalSection(&EventLogLock);
|
||
if (LocalEventLog == NULL) {
|
||
Status = GetLastError();
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (EvtReporterWorkQueue) {
|
||
PEVENT_LOG_PACKET data =
|
||
ClRtlpBuildEventPacket(wType,
|
||
wCategory,
|
||
dwEventID,
|
||
wNumStrings,
|
||
dwDataSize,
|
||
lpStrings,
|
||
lpRawData);
|
||
if (data) {
|
||
EnterCriticalSection( &EventLogLock );
|
||
if (EvtReporterWorkQueue) {
|
||
Status = ClRtlPostItemWorkQueue(
|
||
EvtReporterWorkQueue,
|
||
&EvtReporterWorkItem,
|
||
0,
|
||
(ULONG_PTR)data
|
||
);
|
||
if (Status == ERROR_SUCCESS) {
|
||
// worker will free data //
|
||
data = NULL;
|
||
Success = TRUE;
|
||
}
|
||
}
|
||
LeaveCriticalSection( &EventLogLock );
|
||
LocalFree( data ); // free(0) is OK
|
||
if (Success) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
Success = ReportEventW(LocalEventLog,
|
||
wType,
|
||
wCategory,
|
||
dwEventID,
|
||
NULL,
|
||
wNumStrings,
|
||
dwDataSize,
|
||
lpStrings,
|
||
lpRawData);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogEvent0(
|
||
IN DWORD LogLevel,
|
||
IN DWORD LogModule,
|
||
IN LPSTR FileName,
|
||
IN DWORD LineNumber,
|
||
IN DWORD MessageId,
|
||
IN DWORD dwByteCount,
|
||
IN PVOID lpBytes
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an event to the event log
|
||
|
||
Arguments:
|
||
|
||
LogLevel - Supplies the logging level, one of
|
||
LOG_CRITICAL 1
|
||
LOG_UNUSUAL 2
|
||
LOG_NOISE 3
|
||
|
||
LogModule - Supplies the module ID.
|
||
|
||
FileName - Supplies the filename of the caller
|
||
|
||
LineNumber - Supplies the line number of the caller
|
||
|
||
MessageId - Supplies the message ID to be logged.
|
||
|
||
dwByteCount - Supplies the number of error-specific bytes to log. If this
|
||
is zero, lpBytes is ignored.
|
||
|
||
lpBytes - Supplies the error-specific bytes to log.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
DWORD Status;
|
||
WORD wType;
|
||
|
||
switch (LogLevel) {
|
||
case LOG_CRITICAL:
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
break;
|
||
case LOG_UNUSUAL:
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
break;
|
||
case LOG_NOISE:
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
break;
|
||
default:
|
||
// Assert if invalid so that in retail we don't bring down the entire process.
|
||
//
|
||
CL_ASSERT( 0 );
|
||
// Fall through to normal logging...
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
}
|
||
|
||
ClRtlpReportEvent(wType,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
0,
|
||
dwByteCount,
|
||
NULL,
|
||
lpBytes);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogEvent1(
|
||
IN DWORD LogLevel,
|
||
IN DWORD LogModule,
|
||
IN LPSTR FileName,
|
||
IN DWORD LineNumber,
|
||
IN DWORD MessageId,
|
||
IN DWORD dwByteCount,
|
||
IN PVOID lpBytes,
|
||
IN LPCWSTR Arg1
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an event to the event log
|
||
|
||
Arguments:
|
||
|
||
LogLevel - Supplies the logging level, one of
|
||
LOG_CRITICAL 1
|
||
LOG_UNUSUAL 2
|
||
LOG_NOISE 3
|
||
|
||
LogModule - Supplies the module ID.
|
||
|
||
FileName - Supplies the filename of the caller
|
||
|
||
LineNumber - Supplies the line number of the caller
|
||
|
||
MessageId - Supplies the message ID to be logged.
|
||
|
||
dwByteCount - Supplies the number of error-specific bytes to log. If this
|
||
is zero, lpBytes is ignored.
|
||
|
||
lpBytes - Supplies the error-specific bytes to log.
|
||
|
||
Arg1 - Supplies an insertion string
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
DWORD Status;
|
||
WORD wType;
|
||
|
||
switch (LogLevel) {
|
||
case LOG_CRITICAL:
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
break;
|
||
case LOG_UNUSUAL:
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
break;
|
||
case LOG_NOISE:
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
break;
|
||
default:
|
||
// Assert if invalid so that in retail we don't bring down the entire process.
|
||
//
|
||
CL_ASSERT( 0 );
|
||
// Fall through to normal logging...
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
}
|
||
ClRtlpReportEvent(wType,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
1,
|
||
dwByteCount,
|
||
&Arg1,
|
||
lpBytes);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogEvent2(
|
||
IN DWORD LogLevel,
|
||
IN DWORD LogModule,
|
||
IN LPSTR FileName,
|
||
IN DWORD LineNumber,
|
||
IN DWORD MessageId,
|
||
IN DWORD dwByteCount,
|
||
IN PVOID lpBytes,
|
||
IN LPCWSTR Arg1,
|
||
IN LPCWSTR Arg2
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an event to the event log
|
||
|
||
Arguments:
|
||
|
||
LogLevel - Supplies the logging level, one of
|
||
LOG_CRITICAL 1
|
||
LOG_UNUSUAL 2
|
||
LOG_NOISE 3
|
||
|
||
LogModule - Supplies the module ID.
|
||
|
||
FileName - Supplies the filename of the caller
|
||
|
||
LineNumber - Supplies the line number of the caller
|
||
|
||
MessageId - Supplies the message ID to be logged.
|
||
|
||
dwByteCount - Supplies the number of error-specific bytes to log. If this
|
||
is zero, lpBytes is ignored.
|
||
|
||
lpBytes - Supplies the error-specific bytes to log.
|
||
|
||
Arg1 - Supplies the first insertion string
|
||
|
||
Arg2 - Supplies the second insertion string
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
DWORD Status;
|
||
WORD wType;
|
||
LPCWSTR ArgArray[2];
|
||
|
||
switch (LogLevel) {
|
||
case LOG_CRITICAL:
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
break;
|
||
case LOG_UNUSUAL:
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
break;
|
||
case LOG_NOISE:
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
break;
|
||
default:
|
||
// Assert if invalid so that in retail we don't bring down the entire process.
|
||
//
|
||
CL_ASSERT( 0 );
|
||
// Fall through to normal logging...
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
}
|
||
|
||
ArgArray[0] = Arg1;
|
||
ArgArray[1] = Arg2;
|
||
|
||
ClRtlpReportEvent(wType,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
2,
|
||
dwByteCount,
|
||
ArgArray,
|
||
lpBytes);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogEvent3(
|
||
IN DWORD LogLevel,
|
||
IN DWORD LogModule,
|
||
IN LPSTR FileName,
|
||
IN DWORD LineNumber,
|
||
IN DWORD MessageId,
|
||
IN DWORD dwByteCount,
|
||
IN PVOID lpBytes,
|
||
IN LPCWSTR Arg1,
|
||
IN LPCWSTR Arg2,
|
||
IN LPCWSTR Arg3
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an event to the event log
|
||
|
||
Arguments:
|
||
|
||
LogLevel - Supplies the logging level, one of
|
||
LOG_CRITICAL 1
|
||
LOG_UNUSUAL 2
|
||
LOG_NOISE 3
|
||
|
||
LogModule - Supplies the module ID.
|
||
|
||
FileName - Supplies the filename of the caller
|
||
|
||
LineNumber - Supplies the line number of the caller
|
||
|
||
MessageId - Supplies the message ID to be logged.
|
||
|
||
dwByteCount - Supplies the number of error-specific bytes to log. If this
|
||
is zero, lpBytes is ignored.
|
||
|
||
lpBytes - Supplies the error-specific bytes to log.
|
||
|
||
Arg1 - Supplies the first insertion string
|
||
|
||
Arg2 - Supplies the second insertion string
|
||
|
||
Arg3 - Supplies the third insertion string
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
DWORD Status;
|
||
WORD wType;
|
||
LPCWSTR ArgArray[3];
|
||
|
||
switch (LogLevel) {
|
||
case LOG_CRITICAL:
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
break;
|
||
case LOG_UNUSUAL:
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
break;
|
||
case LOG_NOISE:
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
break;
|
||
default:
|
||
// Assert if invalid so that in retail we don't bring down the entire process.
|
||
//
|
||
CL_ASSERT( 0 );
|
||
// Fall through to normal logging...
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
}
|
||
|
||
ArgArray[0] = Arg1;
|
||
ArgArray[1] = Arg2;
|
||
ArgArray[2] = Arg3;
|
||
|
||
ClRtlpReportEvent(wType,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
3,
|
||
dwByteCount,
|
||
ArgArray,
|
||
lpBytes);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogEvent4(
|
||
IN DWORD LogLevel,
|
||
IN DWORD LogModule,
|
||
IN LPSTR FileName,
|
||
IN DWORD LineNumber,
|
||
IN DWORD MessageId,
|
||
IN DWORD dwByteCount,
|
||
IN PVOID lpBytes,
|
||
IN LPCWSTR Arg1,
|
||
IN LPCWSTR Arg2,
|
||
IN LPCWSTR Arg3,
|
||
IN LPCWSTR Arg4
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an event to the event log
|
||
|
||
Arguments:
|
||
|
||
LogLevel - Supplies the logging level, one of
|
||
LOG_CRITICAL 1
|
||
LOG_UNUSUAL 2
|
||
LOG_NOISE 3
|
||
|
||
LogModule - Supplies the module ID.
|
||
|
||
FileName - Supplies the filename of the caller
|
||
|
||
LineNumber - Supplies the line number of the caller
|
||
|
||
MessageId - Supplies the message ID to be logged.
|
||
|
||
dwByteCount - Supplies the number of error-specific bytes to log. If this
|
||
is zero, lpBytes is ignored.
|
||
|
||
lpBytes - Supplies the error-specific bytes to log.
|
||
|
||
Arg1 - Supplies the first insertion string
|
||
|
||
Arg2 - Supplies the second insertion string
|
||
|
||
Arg3 - Supplies the third insertion string
|
||
|
||
Arg4 - Supplies the fourth insertion string
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL Success;
|
||
DWORD Status;
|
||
WORD wType;
|
||
LPCWSTR ArgArray[4];
|
||
|
||
switch (LogLevel) {
|
||
case LOG_CRITICAL:
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
break;
|
||
case LOG_UNUSUAL:
|
||
wType = EVENTLOG_WARNING_TYPE;
|
||
break;
|
||
case LOG_NOISE:
|
||
wType = EVENTLOG_INFORMATION_TYPE;
|
||
break;
|
||
default:
|
||
// Assert if invalid so that in retail we don't bring down the entire process.
|
||
//
|
||
CL_ASSERT( 0 );
|
||
// Fall through to normal logging...
|
||
wType = EVENTLOG_ERROR_TYPE;
|
||
}
|
||
|
||
ArgArray[0] = Arg1;
|
||
ArgArray[1] = Arg2;
|
||
ArgArray[2] = Arg3;
|
||
ArgArray[3] = Arg4;
|
||
|
||
ClRtlpReportEvent(wType,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
4,
|
||
dwByteCount,
|
||
ArgArray,
|
||
lpBytes);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterCommonLogError(
|
||
IN ULONG MessageId,
|
||
IN ULONG LogModule,
|
||
IN ULONG Line,
|
||
IN LPSTR File,
|
||
IN ULONG ErrCode
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an error to the eventlog
|
||
|
||
Arguments:
|
||
|
||
MessageId - Supplies the message ID to use.
|
||
|
||
LogModule - Supplies the module.
|
||
|
||
Line - Supplies the line number of the caller.
|
||
|
||
File - Supplies the filename of the caller.
|
||
|
||
ErrCode - Supplies the specific error code.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
WCHAR LineString[20];
|
||
WCHAR ErrString[32];
|
||
WCHAR FileName[255];
|
||
WCHAR Buffer[256];
|
||
LPWSTR Strings[3];
|
||
DWORD Bytes;
|
||
|
||
swprintf(LineString, L"%d", Line);
|
||
swprintf(ErrString, L"%d", ErrCode);
|
||
mbstowcs(FileName, File, sizeof(FileName)/sizeof(WCHAR));
|
||
Strings[0] = LineString;
|
||
Strings[1] = FileName;
|
||
Strings[2] = ErrString;
|
||
|
||
ClRtlpReportEvent(EVENTLOG_ERROR_TYPE,
|
||
(WORD)LogModule,
|
||
MessageId,
|
||
3,
|
||
0,
|
||
Strings,
|
||
NULL);
|
||
|
||
Bytes = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE |
|
||
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
||
FORMAT_MESSAGE_MAX_WIDTH_MASK, // remove embedded line breaks
|
||
NULL,
|
||
MessageId,
|
||
0,
|
||
Buffer,
|
||
sizeof(Buffer) / sizeof(WCHAR),
|
||
(va_list *)Strings);
|
||
|
||
if (Bytes != 0) {
|
||
OutputDebugStringW(Buffer);
|
||
ClRtlLogPrint(LOG_CRITICAL, "%1!ws!\n",Buffer);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogFatalError(
|
||
IN ULONG LogModule,
|
||
IN ULONG Line,
|
||
IN LPSTR File,
|
||
IN ULONG ErrCode
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs a fatal error to the eventlog and breaks into the debugger if present.
|
||
Exits the process on fatal error.
|
||
|
||
Arguments:
|
||
|
||
LogModule - Supplies the module.
|
||
|
||
Line - Supplies the line number of the caller.
|
||
|
||
File - Supplies the filename of the caller.
|
||
|
||
ErrCode - Supplies the specific error code.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ClusterCommonLogError(UNEXPECTED_FATAL_ERROR,
|
||
LogModule,
|
||
Line,
|
||
File,
|
||
ErrCode);
|
||
|
||
if (IsDebuggerPresent()) {
|
||
DebugBreak();
|
||
}
|
||
|
||
ClRtlpFlushLogBuffers();
|
||
ExitProcess(ErrCode);
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogNonFatalError(
|
||
IN ULONG LogModule,
|
||
IN ULONG Line,
|
||
IN LPSTR File,
|
||
IN ULONG ErrCode
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs a nonfatal error to the eventlog
|
||
|
||
Arguments:
|
||
|
||
LogModule - Supplies the module.
|
||
|
||
Line - Supplies the line number of the caller.
|
||
|
||
File - Supplies the filename of the caller.
|
||
|
||
ErrCode - Supplies the specific error code.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ClusterCommonLogError(LOG_FAILURE,
|
||
LogModule,
|
||
Line,
|
||
File,
|
||
ErrCode);
|
||
}
|
||
|
||
|
||
VOID
|
||
ClusterLogAssertionFailure(
|
||
IN ULONG LogModule,
|
||
IN ULONG Line,
|
||
IN LPSTR File,
|
||
IN LPSTR Expression
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Logs an assertion failure to the eventlog.
|
||
|
||
Arguments:
|
||
|
||
LogModule - Supplies the module.
|
||
|
||
Line - Supplies the line number of the caller.
|
||
|
||
File - Supplies the filename of the caller.
|
||
|
||
Express - Supplies the ASSERTion expression
|
||
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
WCHAR LineString[10];
|
||
WCHAR FileName[255];
|
||
WCHAR Buffer[256];
|
||
LPWSTR Strings[4];
|
||
DWORD Bytes;
|
||
|
||
swprintf(LineString, L"%d", Line);
|
||
mbstowcs(FileName, File, sizeof(FileName)/sizeof(WCHAR));
|
||
mbstowcs(Buffer, Expression, sizeof(Buffer)/sizeof(WCHAR));
|
||
Strings[0] = LineString;
|
||
Strings[1] = FileName;
|
||
Strings[2] = Buffer;
|
||
|
||
ClRtlpReportEvent(EVENTLOG_ERROR_TYPE,
|
||
(WORD)LogModule,
|
||
ASSERTION_FAILURE,
|
||
3,
|
||
0,
|
||
Strings,
|
||
NULL);
|
||
|
||
Bytes = FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE |
|
||
FORMAT_MESSAGE_ARGUMENT_ARRAY |
|
||
FORMAT_MESSAGE_MAX_WIDTH_MASK, // removed embedded line breaks
|
||
NULL,
|
||
ASSERTION_FAILURE,
|
||
0,
|
||
Buffer,
|
||
sizeof(Buffer) / sizeof(WCHAR),
|
||
(va_list *)Strings);
|
||
if (Bytes != 0) {
|
||
OutputDebugStringW(Buffer);
|
||
ClRtlLogPrint(LOG_CRITICAL, "%1!ws!\n",Buffer);
|
||
}
|
||
if (IsDebuggerPresent()) {
|
||
DebugBreak();
|
||
} else {
|
||
ClRtlpFlushLogBuffers();
|
||
ExitProcess(Line);
|
||
}
|
||
}
|
||
|