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.
 
 
 
 
 
 

380 lines
9.7 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
errorlog.c
Abstract:
This module implements the error logging in the rdbss.
Author:
Manny Weiser (mannyw) 11-Feb-92
Revision History:
Joe Linn (joelinn) 23-feb-95 Convert for rdbss
--*/
#include "precomp.h"
#pragma hdrstop
#include <align.h>
#include <netevent.h>
//
// The local debug trace level
//
#define MIN(__a,__b) (((__a)<=(__b))?(__a):(__b))
static UNICODE_STRING unknownId = { 6, 6, L"???" };
LONG LDWCount = 0;
NTSTATUS LDWLastStatus;
LARGE_INTEGER LDWLastTime;
PVOID LDWContext;
VOID
RxLogEventWithAnnotation(
IN PRDBSS_DEVICE_OBJECT DeviceObject,
IN ULONG Id,
IN NTSTATUS NtStatus,
IN PVOID RawDataBuffer,
IN USHORT RawDataLength,
IN PUNICODE_STRING Annotations,
IN ULONG AnnotationCount
)
/*++
Routine Description:
This function allocates an I/O error log record, fills it in and writes it
to the I/O error log.
--*/
{
PIO_ERROR_LOG_PACKET ErrorLogEntry;
ULONG AnnotationStringLength = 0;
ULONG i;
PWCHAR Buffer;
USHORT PaddedRawDataLength = 0;
for ( i = 0; i < AnnotationCount ; i++ ) {
AnnotationStringLength += (Annotations[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(
(PDEVICE_OBJECT)DeviceObject,
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
PaddedRawDataLength + AnnotationStringLength)
);
if (ErrorLogEntry != NULL) {
//
// Fill in the error log entry
//
ErrorLogEntry->ErrorCode = Id;
ErrorLogEntry->MajorFunctionCode = 0;
ErrorLogEntry->RetryCount = 0;
ErrorLogEntry->UniqueErrorValue = 0;
ErrorLogEntry->FinalStatus = NtStatus;
ErrorLogEntry->IoControlCode = 0;
ErrorLogEntry->DeviceOffset.QuadPart = 0;
ErrorLogEntry->DumpDataSize = RawDataLength;
ErrorLogEntry->StringOffset =
(USHORT)(FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + PaddedRawDataLength);
ErrorLogEntry->NumberOfStrings = (USHORT)AnnotationCount;
ErrorLogEntry->SequenceNumber = 0;
//
// Append the extra information.
//
if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
RtlCopyMemory(
ErrorLogEntry->DumpData,
RawDataBuffer,
RawDataLength
);
}
Buffer = (PWCHAR)((PCHAR)ErrorLogEntry->DumpData + PaddedRawDataLength);
for ( i = 0; i < AnnotationCount ; i++ ) {
RtlCopyMemory(
Buffer,
Annotations[i].Buffer,
Annotations[i].Length
);
Buffer += (Annotations[i].Length/2);
*Buffer++ = L'\0';
}
//
// Write the entry
//
IoWriteErrorLogEntry(ErrorLogEntry);
}
}
VOID
RxLogEventWithBufferDirect (
IN PRDBSS_DEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING OriginatorId,
IN ULONG EventId,
IN NTSTATUS Status,
IN PVOID DataBuffer,
IN USHORT DataBufferLength,
IN ULONG LineNumber
)
{
ULONG LocalBuffer[ 20 ];
if( !ARGUMENT_PRESENT( OriginatorId ) || OriginatorId->Length == 0 ) {
OriginatorId = &unknownId;
}
LocalBuffer[0] = Status;
LocalBuffer[1] = LineNumber;
RtlCopyMemory(
&LocalBuffer[2],
DataBuffer,
MIN( DataBufferLength, sizeof( LocalBuffer ) - 2*sizeof( LocalBuffer[0] ) )
);
RxLogEventWithAnnotation(
DeviceObject,
EventId,
Status,
LocalBuffer,
(USHORT)MIN( DataBufferLength + sizeof( LocalBuffer[0] ), sizeof( LocalBuffer ) ),
OriginatorId,
1
);
}
VOID
RxLogEventDirect (
IN PRDBSS_DEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING OriginatorId,
IN ULONG EventId,
IN NTSTATUS Status,
IN ULONG Line
)
/*++
Routine Description:
This function logs an error. You should use the 'RdrLogFailure'
macro instead of calling this routine directly.
Arguments:
Status is the status code showing the failure
Line is where it happened
Return Value:
None.
--*/
{
ULONG LineAndStatus[2];
LineAndStatus[0] = Line;
LineAndStatus[1] = Status;
if( !ARGUMENT_PRESENT( OriginatorId ) || OriginatorId->Length == 0 ) {
OriginatorId = &unknownId;
}
RxLogEventWithAnnotation(
DeviceObject,
EventId,
Status,
&LineAndStatus,
sizeof(LineAndStatus),
OriginatorId,
1
);
}
BOOLEAN
RxCcLogError(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING FileName,
IN NTSTATUS Error,
IN NTSTATUS DeviceError,
IN UCHAR IrpMajorCode,
IN PVOID Context
)
/*++
Routine Description:
This routine writes an eventlog entry to the eventlog.
Arguments:
DeviceObject - The device object who owns the file where it occurred.
FileName - The filename to use in logging the error (usually the DOS-side name)
Error - The error to log in the eventlog record
DeviceError - The actual error that occured in the device - will be logged
as user data
Return Value:
True if successful, false if internal memory allocation failed
--*/
{
UCHAR ErrorPacketLength;
UCHAR BasePacketLength;
ULONG StringLength;
PIO_ERROR_LOG_PACKET ErrorLogEntry = NULL;
BOOLEAN Result = FALSE;
PWCHAR String;
PAGED_CODE();
//
// Get our error packet, holding the string and status code. Note we log against the
// true filesystem if this is available.
//
// The sizing of the packet is a bit slimy since the dumpdata is already grown by a
// ULONG onto the end of the packet. Since NTSTATUS is ULONG, well, we just work in
// place.
//
BasePacketLength = sizeof(IO_ERROR_LOG_PACKET);
if ((BasePacketLength + FileName->Length + sizeof(WCHAR)) <= ERROR_LOG_MAXIMUM_SIZE) {
ErrorPacketLength = (UCHAR)(BasePacketLength + FileName->Length + sizeof(WCHAR));
} else {
ErrorPacketLength = ERROR_LOG_MAXIMUM_SIZE;
}
if( Error == IO_LOST_DELAYED_WRITE )
{
IoRaiseInformationalHardError( STATUS_LOST_WRITEBEHIND_DATA, FileName, NULL );
// Increment the CC counter here!
InterlockedIncrement( &LDWCount );
KeQuerySystemTime( &LDWLastTime );
LDWLastStatus = DeviceError;
LDWContext = Context;
}
ErrorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject,
ErrorPacketLength );
if (ErrorLogEntry) {
//
// Fill in the nonzero members of the packet.
//
ErrorLogEntry->MajorFunctionCode = IrpMajorCode;
ErrorLogEntry->ErrorCode = Error;
ErrorLogEntry->FinalStatus = DeviceError;
ErrorLogEntry->DumpDataSize = sizeof(NTSTATUS);
RtlCopyMemory( &ErrorLogEntry->DumpData, &DeviceError, sizeof(NTSTATUS) );
//
// The filename string is appended to the end of the error log entry. We may
// have to smash the middle to fit it in the limited space.
//
StringLength = ErrorPacketLength - BasePacketLength - sizeof(WCHAR);
ASSERT(!(StringLength % sizeof(WCHAR)));
String = (PWCHAR) ((PUCHAR)ErrorLogEntry + BasePacketLength);
ErrorLogEntry->NumberOfStrings = 1;
ErrorLogEntry->StringOffset = BasePacketLength;
//
// If the name does not fit in the packet, divide the name equally to the
// prefix and suffix, with an ellipsis " .. " (4 wide characters) to indicate
// the loss.
//
if (StringLength < FileName->Length) {
//
// Remember, prefix + " .. " + suffix is the length. Calculate by figuring
// the prefix and then get the suffix by whacking the ellipsis and prefix off
// the total.
//
ULONG NamePrefixSegmentLength = ((StringLength/sizeof(WCHAR))/2 - 2)*sizeof(WCHAR);
ULONG NameSuffixSegmentLength = StringLength - 4*sizeof(WCHAR) - NamePrefixSegmentLength;
ASSERT(!(NamePrefixSegmentLength % sizeof(WCHAR)));
ASSERT(!(NameSuffixSegmentLength % sizeof(WCHAR)));
RtlCopyMemory( String,
FileName->Buffer,
NamePrefixSegmentLength );
String = (PWCHAR)((PCHAR)String + NamePrefixSegmentLength);
RtlCopyMemory( String,
L" .. ",
4*sizeof(WCHAR) );
String += 4;
RtlCopyMemory( String,
(PUCHAR)FileName->Buffer +
FileName->Length - NameSuffixSegmentLength,
NameSuffixSegmentLength );
String = (PWCHAR)((PCHAR)String + NameSuffixSegmentLength);
} else {
RtlCopyMemory( String,
FileName->Buffer,
FileName->Length );
String += FileName->Length/sizeof(WCHAR);
}
//
// Null terminate the string and send the packet.
//
*String = L'\0';
IoWriteErrorLogEntry( ErrorLogEntry );
Result = TRUE;
}
return Result;
}