windows-nt/Source/XPSP1/NT/base/fs/rdr2/bowser/errorlog.c

287 lines
7 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}