358 lines
7.4 KiB
C
358 lines
7.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
errorlog.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the error logging in the server.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Manny Weiser (mannyw) 11-Feb-92
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#include "errorlog.tmh"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text( PAGE, SrvLogInvalidSmbDirect )
|
|||
|
#pragma alloc_text( PAGE, SrvLogServiceFailureDirect )
|
|||
|
#if DBG
|
|||
|
#pragma alloc_text( PAGE, SrvLogTableFullError )
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
#if 0
|
|||
|
NOT PAGEABLE -- SrvLogError
|
|||
|
NOT PAGEABLE -- SrvCheckSendCompletionStatus
|
|||
|
NOT PAGEABLE -- SrvIsLoggableError
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SrvLogInvalidSmbDirect (
|
|||
|
IN PWORK_CONTEXT WorkContext,
|
|||
|
IN ULONG LineNumber
|
|||
|
)
|
|||
|
{
|
|||
|
UNICODE_STRING unknownClient;
|
|||
|
PUNICODE_STRING clientName;
|
|||
|
ULONG LocalBuffer[ 13 ];
|
|||
|
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Let this client log at most one SMB error
|
|||
|
//
|
|||
|
if( ARGUMENT_PRESENT( WorkContext ) ) {
|
|||
|
|
|||
|
if( WorkContext->Connection->PagedConnection->LoggedInvalidSmb ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
WorkContext->Connection->PagedConnection->LoggedInvalidSmb = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT(WorkContext) &&
|
|||
|
(WorkContext->Connection->PagedConnection->ClientMachineNameString.Length != 0) ) {
|
|||
|
|
|||
|
clientName = &WorkContext->Connection->PagedConnection->ClientMachineNameString;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
RtlInitUnicodeString( &unknownClient, StrUnknownClient );
|
|||
|
clientName = &unknownClient;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT(WorkContext) ) {
|
|||
|
|
|||
|
LocalBuffer[0] = LineNumber;
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
&LocalBuffer[1],
|
|||
|
WorkContext->RequestHeader,
|
|||
|
MIN( WorkContext->RequestBuffer->DataLength, sizeof( LocalBuffer ) - sizeof( LocalBuffer[0] ) )
|
|||
|
);
|
|||
|
|
|||
|
SrvLogError(
|
|||
|
SrvDeviceObject,
|
|||
|
EVENT_SRV_INVALID_REQUEST,
|
|||
|
STATUS_INVALID_SMB,
|
|||
|
LocalBuffer,
|
|||
|
(USHORT)MIN( WorkContext->RequestBuffer->DataLength + sizeof( LocalBuffer[0] ), sizeof( LocalBuffer ) ),
|
|||
|
clientName,
|
|||
|
1
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SrvLogError(
|
|||
|
SrvDeviceObject,
|
|||
|
EVENT_SRV_INVALID_REQUEST,
|
|||
|
STATUS_INVALID_SMB,
|
|||
|
&LineNumber,
|
|||
|
(USHORT)sizeof( LineNumber ),
|
|||
|
clientName,
|
|||
|
1
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // SrvLogInvalidSmb
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
SrvIsLoggableError( IN NTSTATUS Status )
|
|||
|
{
|
|||
|
NTSTATUS *pstatus;
|
|||
|
BOOLEAN ret = TRUE;
|
|||
|
|
|||
|
for( pstatus = SrvErrorLogIgnore; *pstatus; pstatus++ ) {
|
|||
|
if( *pstatus == Status ) {
|
|||
|
ret = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SrvLogServiceFailureDirect (
|
|||
|
IN ULONG LineAndService,
|
|||
|
IN NTSTATUS Status
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function logs a srv svc error. You should use the 'SrvLogServiceFailure'
|
|||
|
macro instead of calling this routine directly.
|
|||
|
|
|||
|
Arguments:
|
|||
|
LineAndService consists of the line number of the original call in the highword, and
|
|||
|
the service code in the lowword
|
|||
|
|
|||
|
Status is the status code of the called routine
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
//
|
|||
|
// Don't log certain errors that are expected to happen occasionally.
|
|||
|
//
|
|||
|
|
|||
|
if( (LineAndService & 01) || SrvIsLoggableError( Status ) ) {
|
|||
|
|
|||
|
SrvLogError(
|
|||
|
SrvDeviceObject,
|
|||
|
EVENT_SRV_SERVICE_FAILED,
|
|||
|
Status,
|
|||
|
&LineAndService,
|
|||
|
sizeof(LineAndService),
|
|||
|
NULL,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
} // SrvLogServiceFailure
|
|||
|
|
|||
|
//
|
|||
|
// I have disabled this for retail builds because it is not a good idea to
|
|||
|
// allow an evil client to so easily fill the server's system log
|
|||
|
//
|
|||
|
VOID
|
|||
|
SrvLogTableFullError (
|
|||
|
IN ULONG Type
|
|||
|
)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
PAGED_CODE( );
|
|||
|
|
|||
|
SrvLogError(
|
|||
|
SrvDeviceObject,
|
|||
|
EVENT_SRV_CANT_GROW_TABLE,
|
|||
|
STATUS_INSUFFICIENT_RESOURCES,
|
|||
|
&Type,
|
|||
|
sizeof(ULONG),
|
|||
|
NULL,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
return;
|
|||
|
#endif
|
|||
|
|
|||
|
} // SrvLogTableFullError
|
|||
|
|
|||
|
VOID
|
|||
|
SrvLogError(
|
|||
|
IN PVOID DeviceOrDriverObject,
|
|||
|
IN ULONG UniqueErrorCode,
|
|||
|
IN NTSTATUS NtStatusCode,
|
|||
|
IN PVOID RawDataBuffer,
|
|||
|
IN USHORT RawDataLength,
|
|||
|
IN PUNICODE_STRING InsertionString OPTIONAL,
|
|||
|
IN ULONG InsertionStringCount
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
ULONG insertionStringLength = 0;
|
|||
|
ULONG i;
|
|||
|
PWCHAR buffer;
|
|||
|
USHORT paddedRawDataLength = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Update the server error counts
|
|||
|
//
|
|||
|
|
|||
|
if ( UniqueErrorCode == EVENT_SRV_NETWORK_ERROR ) {
|
|||
|
SrvUpdateErrorCount( &SrvNetworkErrorRecord, TRUE );
|
|||
|
} else {
|
|||
|
SrvUpdateErrorCount( &SrvErrorRecord, TRUE );
|
|||
|
}
|
|||
|
|
|||
|
for ( i = 0; i < InsertionStringCount ; i++ ) {
|
|||
|
insertionStringLength += (InsertionString[i].Length + sizeof(WCHAR));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// pad the raw data buffer so that the insertion string starts
|
|||
|
// on an even address.
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
|
|||
|
paddedRawDataLength = (RawDataLength + 1) & ~1;
|
|||
|
}
|
|||
|
|
|||
|
errorLogEntry = IoAllocateErrorLogEntry(
|
|||
|
DeviceOrDriverObject,
|
|||
|
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
|
|||
|
paddedRawDataLength + insertionStringLength)
|
|||
|
);
|
|||
|
|
|||
|
if (errorLogEntry != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// 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.QuadPart = 0;
|
|||
|
errorLogEntry->DumpDataSize = RawDataLength;
|
|||
|
errorLogEntry->StringOffset =
|
|||
|
(USHORT)(FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + paddedRawDataLength);
|
|||
|
errorLogEntry->NumberOfStrings = (USHORT)InsertionStringCount;
|
|||
|
|
|||
|
errorLogEntry->SequenceNumber = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Append the extra information. This information is typically
|
|||
|
// an SMB header.
|
|||
|
//
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
errorLogEntry->DumpData,
|
|||
|
RawDataBuffer,
|
|||
|
RawDataLength
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
buffer = (PWCHAR)((PCHAR)errorLogEntry->DumpData + paddedRawDataLength);
|
|||
|
|
|||
|
for ( i = 0; i < InsertionStringCount ; i++ ) {
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
buffer,
|
|||
|
InsertionString[i].Buffer,
|
|||
|
InsertionString[i].Length
|
|||
|
);
|
|||
|
|
|||
|
buffer += (InsertionString[i].Length/2);
|
|||
|
*buffer++ = L'\0';
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Write the entry
|
|||
|
//
|
|||
|
|
|||
|
IoWriteErrorLogEntry(errorLogEntry);
|
|||
|
}
|
|||
|
|
|||
|
} // SrvLogError
|
|||
|
|
|||
|
VOID
|
|||
|
SrvCheckSendCompletionStatus(
|
|||
|
IN NTSTATUS Status,
|
|||
|
IN ULONG LineNumber
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Routine to log send completion errors.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if( SrvIsLoggableError( Status ) ) {
|
|||
|
|
|||
|
SrvLogError( SrvDeviceObject,
|
|||
|
EVENT_SRV_NETWORK_ERROR,
|
|||
|
Status,
|
|||
|
&LineNumber, sizeof(LineNumber),
|
|||
|
NULL, 0 );
|
|||
|
}
|
|||
|
|
|||
|
} // SrvCheckSendCompletionStatus
|