You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
363 lines
7.8 KiB
363 lines
7.8 KiB
/*++
|
|
|
|
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 ];
|
|
ULONG count;
|
|
|
|
PAGED_CODE( );
|
|
|
|
if( !SrvEnableInvalidSmbLogging )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// 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->ClientMachineNameString.Length != 0) ) {
|
|
|
|
clientName = &WorkContext->Connection->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
|