Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

357 lines
7.4 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 ];
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