Windows-Server-2003/net/wlbs/driver/log.c

149 lines
5.8 KiB
C

/*++
Copyright(c) 1998,99 Microsoft Corporation
Module Name:
log.c
Abstract:
Windows Load Balancing Service (WLBS)
Driver - event logging support
Author:
kyrilf
shouse
--*/
#include <ntddk.h>
#include "log.h"
#include "univ.h"
#include "trace.h" // For wmi event tracing
#include "log.tmh"
static ULONG log_module_id = LOG_MODULE_LOG;
BOOLEAN Log_event (NTSTATUS code, PWSTR msg1, PWSTR msg2, PWSTR msg3, ULONG loc, ULONG d1, ULONG d2)
{
PIO_ERROR_LOG_PACKET ErrorLogEntry;
UNICODE_STRING ErrorStr[3];
PWCHAR InsertStr;
ULONG EntrySizeMinimum;
ULONG EntrySize;
ULONG BytesLeft;
ULONG volatile i;
/* Initialize the three log strings. */
RtlInitUnicodeString(&ErrorStr[0], msg1);
RtlInitUnicodeString(&ErrorStr[1], msg2);
RtlInitUnicodeString(&ErrorStr[2], msg3);
/* Remember the insertion string should be NUL terminated. So we allocate the
extra space of WCHAR. The first parameter to IoAllocateErrorLogEntry can
be either the driver object or the device object. If it is given a device
object, the name of the device (used in IoCreateDevice) will show up in the
place of %1 in the message. See the message file (.mc) for more details. */
EntrySize = sizeof(IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG) +
ErrorStr[0].Length + ErrorStr[1].Length + ErrorStr[2].Length + 3 * sizeof(WCHAR);
/* This is the minimum that we can get by with - at least enough room for all
of the data dump entries and the 3 NUL terminating characters. */
EntrySizeMinimum = sizeof(IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG) + 3 * sizeof(WCHAR);
/* If we can't even allocate the minimum amount of space, then bail out - this
is a critical error that should never happen, as these limits are set at
compile time, not run time, so unless we do something really dumb, like
try to allow 50 strings of 1KB of dump data, this will never happen. */
if (EntrySizeMinimum > ERROR_LOG_MAXIMUM_SIZE) {
UNIV_PRINT_CRIT(("Log_event: Log entry size too large, exiting: min=%u, max=%u", EntrySizeMinimum, ERROR_LOG_MAXIMUM_SIZE));
TRACE_CRIT("%!FUNC! Log entry size too large, exiting: min=%u, max=%u", EntrySizeMinimum, ERROR_LOG_MAXIMUM_SIZE);
return FALSE;
}
/* Truncate the size of the entry if necessary. In this case, we'll put in
whatever we can fit and truncate or eliminate the strings that don't fit. */
if (EntrySize > ERROR_LOG_MAXIMUM_SIZE) {
UNIV_PRINT_CRIT(("Log_event: Log entry size too large, truncating: size=%u, max=%u", EntrySize, ERROR_LOG_MAXIMUM_SIZE));
TRACE_CRIT("%!FUNC! Log entry size too large, truncating: size=%u, max=%u", EntrySize, ERROR_LOG_MAXIMUM_SIZE);
EntrySize = ERROR_LOG_MAXIMUM_SIZE;
}
/* Allocate the log structure. */
ErrorLogEntry = IoAllocateErrorLogEntry(univ_driver_ptr, (UCHAR)(EntrySize));
if (!ErrorLogEntry) {
#if DBG
/* Convert Unicode string to AnsiCode; %ls can only be used in PASSIVE_LEVEL
Since this function is called from pretty much EVERYWHERE, we cannot
assume what IRQ level we're running at, so be cautious. */
CHAR AnsiString[64];
for (i = 0; (i < sizeof(AnsiString) - 1) && (i < ErrorStr[0].Length); i++)
AnsiString[i] = (CHAR)msg1[i];
AnsiString[i] = '\0';
UNIV_PRINT_CRIT(("Log_event: Error allocating log entry %s", AnsiString));
TRACE_CRIT("%!FUNC! Error allocating log entry %s", AnsiString);
#endif
return FALSE;
}
/* Fill in the necessary information into the header. */
ErrorLogEntry->ErrorCode = code;
ErrorLogEntry->SequenceNumber = 0;
ErrorLogEntry->MajorFunctionCode = 0;
ErrorLogEntry->RetryCount = 0;
ErrorLogEntry->UniqueErrorValue = 0;
ErrorLogEntry->FinalStatus = STATUS_SUCCESS;
ErrorLogEntry->DumpDataSize = (LOG_NUMBER_DUMP_DATA_ENTRIES + 1) * sizeof (ULONG);
ErrorLogEntry->StringOffset = sizeof (IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG);
ErrorLogEntry->NumberOfStrings = 3;
/* load the NUMBER_DUMP_DATA_ENTRIES plus location id here */
ErrorLogEntry->DumpData [0] = loc;
ErrorLogEntry->DumpData [1] = d1;
ErrorLogEntry->DumpData [2] = d2;
/* Calculate the number of bytes available in the string storage area. */
BytesLeft = EntrySize - ErrorLogEntry->StringOffset;
/* Set a pointer to the beginning of the string storage area. */
InsertStr = (PWCHAR)((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
/* Loop through all strings and put in as much of them as we can - we reserve
at least enough room for all three NUL terminating characters. */
for (i = 0; i < 3; i++) {
ULONG Length;
/* If we're inside the loop there should ALWAYS be at least two bytes left. */
UNIV_ASSERT(BytesLeft);
/* Find out how much of this string we can fit into the buffer - save room for the NUL characters. */
Length = (ErrorStr[i].Length <= (BytesLeft - ((3 - i) * sizeof(WCHAR)))) ? ErrorStr[i].Length : BytesLeft - ((3 - i) * sizeof(WCHAR));
/* Copy the number of characters that will fit. */
RtlMoveMemory(InsertStr, ErrorStr[i].Buffer, Length);
/* Put the NUL character at the end. */
*(PWCHAR)((PCHAR)InsertStr + Length) = L'\0';
/* Move the string pointer past the string. */
InsertStr = (PWCHAR)((PCHAR)InsertStr + Length + sizeof(WCHAR));
/* Calculate the number of bytes left now. */
BytesLeft -= (Length + sizeof(WCHAR));
}
/* Write the log entry. */
IoWriteErrorLogEntry(ErrorLogEntry);
return TRUE;
}