287 lines
7 KiB
C
287 lines
7 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
errorlog.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the error logging in the server.
|
|||
|
|
|||
|
!!! This module must be nonpageable.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Manny Weiser (mannyw) 11-Feb-92
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// Local procedure forwards
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
BowserLogIllegalNameWorker(
|
|||
|
IN PVOID Ctx
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, BowserWriteErrorLogEntry)
|
|||
|
#pragma alloc_text(PAGE, BowserLogIllegalNameWorker )
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
BowserSequenceNumber = 0;
|
|||
|
|
|||
|
//#pragma optimize("",off)
|
|||
|
|
|||
|
VOID
|
|||
|
_cdecl
|
|||
|
BowserWriteErrorLogEntry(
|
|||
|
IN ULONG UniqueErrorCode,
|
|||
|
IN NTSTATUS NtStatusCode,
|
|||
|
IN PVOID ExtraInformationBuffer,
|
|||
|
IN USHORT ExtraInformationLength,
|
|||
|
IN USHORT NumberOfInsertionStrings,
|
|||
|
...
|
|||
|
)
|
|||
|
|
|||
|
#define LAST_NAMED_ARGUMENT NumberOfInsertionStrings
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function allocates an I/O error log record, fills it in and writes it
|
|||
|
to the I/O error log.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
PIO_ERROR_LOG_PACKET ErrorLogEntry;
|
|||
|
int TotalErrorLogEntryLength;
|
|||
|
ULONG SizeOfStringData = 0;
|
|||
|
va_list ParmPtr; // Pointer to stack parms.
|
|||
|
ULONG Length;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (NumberOfInsertionStrings != 0) {
|
|||
|
ULONG i;
|
|||
|
|
|||
|
va_start(ParmPtr, LAST_NAMED_ARGUMENT);
|
|||
|
|
|||
|
for (i = 0; i < NumberOfInsertionStrings; i += 1) {
|
|||
|
|
|||
|
PWSTR String = va_arg(ParmPtr, PWSTR);
|
|||
|
|
|||
|
Length = wcslen(String);
|
|||
|
while ( (Length > 0) && (String[Length-1] == L' ') ) {
|
|||
|
Length--;
|
|||
|
}
|
|||
|
|
|||
|
SizeOfStringData += (Length + 1) * sizeof(WCHAR);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Ideally we want the packet to hold the servername and ExtraInformation.
|
|||
|
// Usually the ExtraInformation gets truncated.
|
|||
|
//
|
|||
|
|
|||
|
TotalErrorLogEntryLength =
|
|||
|
min( ExtraInformationLength + sizeof(IO_ERROR_LOG_PACKET) + 1 + SizeOfStringData,
|
|||
|
ERROR_LOG_MAXIMUM_SIZE );
|
|||
|
|
|||
|
ErrorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
|
|||
|
(PDEVICE_OBJECT)BowserDeviceObject,
|
|||
|
(UCHAR)TotalErrorLogEntryLength
|
|||
|
);
|
|||
|
|
|||
|
if (ErrorLogEntry != NULL) {
|
|||
|
PCHAR DumpData;
|
|||
|
ULONG RemainingSpace = TotalErrorLogEntryLength -
|
|||
|
FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData);
|
|||
|
ULONG i;
|
|||
|
ULONG SizeOfRawData;
|
|||
|
|
|||
|
if (RemainingSpace > SizeOfStringData) {
|
|||
|
SizeOfRawData = RemainingSpace - SizeOfStringData;
|
|||
|
} else {
|
|||
|
SizeOfStringData = RemainingSpace;
|
|||
|
|
|||
|
SizeOfRawData = 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the error log entry
|
|||
|
//
|
|||
|
|
|||
|
ErrorLogEntry->ErrorCode = UniqueErrorCode;
|
|||
|
ErrorLogEntry->MajorFunctionCode = 0;
|
|||
|
ErrorLogEntry->RetryCount = 0;
|
|||
|
ErrorLogEntry->UniqueErrorValue = 0;
|
|||
|
ErrorLogEntry->FinalStatus = NtStatusCode;
|
|||
|
ErrorLogEntry->IoControlCode = 0;
|
|||
|
ErrorLogEntry->DeviceOffset.LowPart = 0;
|
|||
|
ErrorLogEntry->DeviceOffset.HighPart = 0;
|
|||
|
ErrorLogEntry->SequenceNumber = (ULONG)BowserSequenceNumber ++;
|
|||
|
ErrorLogEntry->StringOffset = (USHORT)(ROUND_UP_COUNT(
|
|||
|
FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + SizeOfRawData,
|
|||
|
ALIGN_WORD));
|
|||
|
|
|||
|
DumpData = (PCHAR)ErrorLogEntry->DumpData;
|
|||
|
|
|||
|
//
|
|||
|
// Append the extra information. This information is typically
|
|||
|
// an SMB header.
|
|||
|
//
|
|||
|
|
|||
|
if (( ARGUMENT_PRESENT( ExtraInformationBuffer )) &&
|
|||
|
( SizeOfRawData != 0 )) {
|
|||
|
ULONG Length;
|
|||
|
|
|||
|
Length = min(ExtraInformationLength, (USHORT)SizeOfRawData);
|
|||
|
RtlCopyMemory(
|
|||
|
DumpData,
|
|||
|
ExtraInformationBuffer,
|
|||
|
Length);
|
|||
|
ErrorLogEntry->DumpDataSize = (USHORT)Length;
|
|||
|
} else {
|
|||
|
ErrorLogEntry->DumpDataSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
ErrorLogEntry->NumberOfStrings = 0;
|
|||
|
|
|||
|
if (NumberOfInsertionStrings != 0) {
|
|||
|
PWSTR StringOffset = (PWSTR)((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
|
|||
|
PWSTR InsertionString;
|
|||
|
|
|||
|
//
|
|||
|
// Set up ParmPtr to point to first of the caller's parameters.
|
|||
|
//
|
|||
|
|
|||
|
va_start(ParmPtr, LAST_NAMED_ARGUMENT);
|
|||
|
|
|||
|
for (i = 0 ; i < NumberOfInsertionStrings ; i+= 1) {
|
|||
|
InsertionString = va_arg(ParmPtr, PWSTR);
|
|||
|
Length = wcslen(InsertionString);
|
|||
|
while ( (Length > 0) && (InsertionString[Length-1] == L' ') ) {
|
|||
|
Length--;
|
|||
|
}
|
|||
|
|
|||
|
if ( ((Length + 1) * sizeof(WCHAR)) > SizeOfStringData ) {
|
|||
|
Length = (SizeOfStringData/sizeof(WCHAR))-1;
|
|||
|
}
|
|||
|
|
|||
|
if ( Length > 0 ) {
|
|||
|
RtlCopyMemory(StringOffset, InsertionString, Length*sizeof(WCHAR));
|
|||
|
StringOffset += Length;
|
|||
|
*StringOffset++ = L'\0';
|
|||
|
|
|||
|
SizeOfStringData -= (Length + 1) * sizeof(WCHAR);
|
|||
|
|
|||
|
ErrorLogEntry->NumberOfStrings += 1;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
IoWriteErrorLogEntry(ErrorLogEntry);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
typedef struct _ILLEGAL_NAME_CONTEXT {
|
|||
|
WORK_QUEUE_ITEM WorkItem;
|
|||
|
PTRANSPORT_NAME TransportName;
|
|||
|
NTSTATUS EventStatus;
|
|||
|
NTSTATUS NtStatusCode;
|
|||
|
USHORT BufferSize;
|
|||
|
UCHAR Buffer[1];
|
|||
|
} ILLEGAL_NAME_CONTEXT, *PILLEGAL_NAME_CONTEXT;
|
|||
|
|
|||
|
VOID
|
|||
|
BowserLogIllegalName(
|
|||
|
IN NTSTATUS NtStatusCode,
|
|||
|
IN PVOID NameBuffer,
|
|||
|
IN USHORT NameBufferSize
|
|||
|
)
|
|||
|
{
|
|||
|
KIRQL OldIrql;
|
|||
|
NTSTATUS ErrorStatus = STATUS_SUCCESS;
|
|||
|
|
|||
|
ACQUIRE_SPIN_LOCK(&BowserTimeSpinLock, &OldIrql);
|
|||
|
|
|||
|
if (BowserIllegalNameCount > 0) {
|
|||
|
BowserIllegalNameCount -= 1;
|
|||
|
|
|||
|
ErrorStatus = EVENT_BOWSER_NAME_CONVERSION_FAILED;
|
|||
|
|
|||
|
} else if (!BowserIllegalNameThreshold) {
|
|||
|
BowserIllegalNameThreshold = TRUE;
|
|||
|
ErrorStatus = EVENT_BOWSER_NAME_CONVERSION_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
RELEASE_SPIN_LOCK(&BowserTimeSpinLock, OldIrql);
|
|||
|
|
|||
|
if (ErrorStatus != STATUS_SUCCESS) {
|
|||
|
PILLEGAL_NAME_CONTEXT Context = NULL;
|
|||
|
|
|||
|
Context = ALLOCATE_POOL(NonPagedPool, sizeof(ILLEGAL_NAME_CONTEXT)+NameBufferSize, POOL_ILLEGALDGRAM);
|
|||
|
|
|||
|
if (Context != NULL) {
|
|||
|
Context->EventStatus = ErrorStatus;
|
|||
|
Context->NtStatusCode = NtStatusCode;
|
|||
|
Context->BufferSize = NameBufferSize;
|
|||
|
|
|||
|
RtlCopyMemory( Context->Buffer, NameBuffer, NameBufferSize );
|
|||
|
|
|||
|
ExInitializeWorkItem(&Context->WorkItem, BowserLogIllegalNameWorker, Context);
|
|||
|
|
|||
|
BowserQueueDelayedWorkItem( &Context->WorkItem );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
BowserLogIllegalNameWorker(
|
|||
|
IN PVOID Ctx
|
|||
|
)
|
|||
|
{
|
|||
|
PILLEGAL_NAME_CONTEXT Context = Ctx;
|
|||
|
NTSTATUS EventContext = Context->EventStatus;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
BowserWriteErrorLogEntry( Context->EventStatus,
|
|||
|
Context->NtStatusCode,
|
|||
|
Context->Buffer,
|
|||
|
Context->BufferSize,
|
|||
|
0 );
|
|||
|
|
|||
|
FREE_POOL(Context);
|
|||
|
|
|||
|
}
|