329 lines
9.2 KiB
C
329 lines
9.2 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
spxerror.c
|
|
|
|
Abstract:
|
|
|
|
This module contains code which provides error logging support.
|
|
|
|
Author:
|
|
|
|
Nikhil Kamkolkar (nikhilk) 11-November-1993
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifndef __PREFAST__
|
|
#pragma warning(disable:4068)
|
|
#endif
|
|
#pragma prefast(disable:276, "The assignments are harmless")
|
|
|
|
|
|
// Define module number for event logging entries
|
|
#define FILENUM SPXERROR
|
|
|
|
LONG SpxLastRawDataLen = 0;
|
|
NTSTATUS SpxLastUniqueErrorCode = STATUS_SUCCESS;
|
|
NTSTATUS SpxLastNtStatusCode = STATUS_SUCCESS;
|
|
ULONG SpxLastErrorCount = 0;
|
|
LONG SpxLastErrorTime = 0;
|
|
BYTE SpxLastRawData[PORT_MAXIMUM_MESSAGE_LENGTH - \
|
|
sizeof(IO_ERROR_LOG_PACKET)] = {0};
|
|
|
|
BOOLEAN
|
|
SpxFilterErrorLogEntry(
|
|
IN NTSTATUS UniqueErrorCode,
|
|
IN NTSTATUS NtStatusCode,
|
|
IN PVOID RawDataBuf OPTIONAL,
|
|
IN LONG RawDataLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
int insertionStringLength = 0;
|
|
|
|
// Filter out events such that the same event recurring close together does not
|
|
// cause errorlog clogging. The scheme is - if the event is same as the last event
|
|
// and the elapsed time is > THRESHOLD and ERROR_CONSEQ_FREQ simulataneous errors
|
|
// have happened, then log it else skip
|
|
if ((UniqueErrorCode == SpxLastUniqueErrorCode) &&
|
|
(NtStatusCode == SpxLastNtStatusCode))
|
|
{
|
|
SpxLastErrorCount++;
|
|
if ((SpxLastRawDataLen == RawDataLen) &&
|
|
(RtlEqualMemory(SpxLastRawData, RawDataBuf, RawDataLen)) &&
|
|
((SpxLastErrorCount % ERROR_CONSEQ_FREQ) != 0) &&
|
|
((SpxGetCurrentTime() - SpxLastErrorTime) < ERROR_CONSEQ_TIME))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
SpxLastUniqueErrorCode = UniqueErrorCode;
|
|
SpxLastNtStatusCode = NtStatusCode;
|
|
SpxLastErrorCount = 0;
|
|
SpxLastErrorTime = SpxGetCurrentTime();
|
|
if (RawDataLen != 0)
|
|
{
|
|
SpxLastRawDataLen = RawDataLen;
|
|
RtlCopyMemory(
|
|
SpxLastRawData,
|
|
RawDataBuf,
|
|
RawDataLen);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
SpxWriteResourceErrorLog(
|
|
IN PDEVICE Device,
|
|
IN ULONG BytesNeeded,
|
|
IN ULONG UniqueErrorValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates and writes an error log entry indicating
|
|
an out of resources condition.
|
|
|
|
Arguments:
|
|
|
|
Device - Pointer to the device context.
|
|
|
|
BytesNeeded - If applicable, the number of bytes that could not
|
|
be allocated.
|
|
|
|
UniqueErrorValue - Used as the UniqueErrorValue in the error log
|
|
packet.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_ERROR_LOG_PACKET errorLogEntry;
|
|
UCHAR EntrySize;
|
|
PUCHAR StringLoc;
|
|
ULONG TempUniqueError;
|
|
static WCHAR UniqueErrorBuffer[4] = L"000";
|
|
INT i;
|
|
|
|
if (!SpxFilterErrorLogEntry(
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
STATUS_INSUFFICIENT_RESOURCES,
|
|
(PVOID)&BytesNeeded,
|
|
sizeof(BytesNeeded)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
|
|
Device->dev_DeviceNameLen +
|
|
sizeof(UniqueErrorBuffer);
|
|
|
|
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
|
|
(PDEVICE_OBJECT)Device,
|
|
EntrySize);
|
|
|
|
// Convert the error value into a buffer.
|
|
TempUniqueError = UniqueErrorValue;
|
|
for (i=1; i>=0; i--)
|
|
{
|
|
UniqueErrorBuffer[i] = (WCHAR)((TempUniqueError % 10) + L'0');
|
|
TempUniqueError /= 10;
|
|
}
|
|
|
|
if (errorLogEntry != NULL)
|
|
{
|
|
errorLogEntry->MajorFunctionCode = (UCHAR)-1;
|
|
errorLogEntry->RetryCount = (UCHAR)-1;
|
|
errorLogEntry->DumpDataSize = sizeof(ULONG);
|
|
errorLogEntry->NumberOfStrings = 2;
|
|
errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
|
|
errorLogEntry->EventCategory = 0;
|
|
errorLogEntry->ErrorCode = EVENT_TRANSPORT_RESOURCE_POOL;
|
|
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
|
|
errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
errorLogEntry->SequenceNumber = (ULONG)-1;
|
|
errorLogEntry->IoControlCode = 0;
|
|
errorLogEntry->DumpData[0] = BytesNeeded;
|
|
|
|
StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
|
|
RtlCopyMemory(
|
|
StringLoc, Device->dev_DeviceName, Device->dev_DeviceNameLen);
|
|
|
|
StringLoc += Device->dev_DeviceNameLen;
|
|
RtlCopyMemory(
|
|
StringLoc, UniqueErrorBuffer, sizeof(UniqueErrorBuffer));
|
|
|
|
IoWriteErrorLogEntry(errorLogEntry);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
SpxWriteGeneralErrorLog(
|
|
IN PDEVICE Device,
|
|
IN NTSTATUS ErrorCode,
|
|
IN ULONG UniqueErrorValue,
|
|
IN NTSTATUS FinalStatus,
|
|
IN PWSTR SecondString,
|
|
IN PVOID RawDataBuf OPTIONAL,
|
|
IN LONG RawDataLen
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates and writes an error log entry indicating
|
|
a general problem as indicated by the parameters. It handles
|
|
event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND,
|
|
TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these
|
|
events have messages with one or two strings in them.
|
|
|
|
Arguments:
|
|
|
|
Device - Pointer to the device context, or this may be
|
|
a driver object instead.
|
|
|
|
ErrorCode - The transport event code.
|
|
|
|
UniqueErrorValue - Used as the UniqueErrorValue in the error log
|
|
packet.
|
|
|
|
FinalStatus - Used as the FinalStatus in the error log packet.
|
|
|
|
SecondString - If not NULL, the string to use as the %3
|
|
value in the error log packet.
|
|
|
|
RawDataBuf - The number of ULONGs of dump data.
|
|
|
|
RawDataLen - Dump data for the packet.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_ERROR_LOG_PACKET errorLogEntry;
|
|
UCHAR EntrySize;
|
|
ULONG SecondStringSize;
|
|
PUCHAR StringLoc;
|
|
static WCHAR DriverName[4] = L"Spx";
|
|
|
|
if (!SpxFilterErrorLogEntry(
|
|
ErrorCode,
|
|
FinalStatus,
|
|
RawDataBuf,
|
|
RawDataLen))
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DBG
|
|
if ( sizeof(IO_ERROR_LOG_PACKET) + RawDataLen > 255) {
|
|
DbgPrint("Size greater than maximum entry size 255.\n");
|
|
}
|
|
#endif
|
|
|
|
EntrySize = (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) + RawDataLen);
|
|
if (Device->dev_Type == SPX_DEVICE_SIGNATURE)
|
|
{
|
|
EntrySize += (UCHAR)Device->dev_DeviceNameLen;
|
|
}
|
|
else
|
|
{
|
|
EntrySize += sizeof(DriverName);
|
|
}
|
|
|
|
if (SecondString)
|
|
{
|
|
SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
|
|
EntrySize += (UCHAR)SecondStringSize;
|
|
}
|
|
|
|
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
|
|
(PDEVICE_OBJECT)Device,
|
|
EntrySize);
|
|
|
|
if (errorLogEntry != NULL)
|
|
{
|
|
errorLogEntry->MajorFunctionCode = (UCHAR)-1;
|
|
errorLogEntry->RetryCount = (UCHAR)-1;
|
|
errorLogEntry->DumpDataSize = (USHORT)RawDataLen;
|
|
errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2;
|
|
errorLogEntry->StringOffset = (USHORT)
|
|
(sizeof(IO_ERROR_LOG_PACKET) + RawDataLen);
|
|
errorLogEntry->EventCategory = 0;
|
|
errorLogEntry->ErrorCode = ErrorCode;
|
|
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
|
|
errorLogEntry->FinalStatus = FinalStatus;
|
|
errorLogEntry->SequenceNumber = (ULONG)-1;
|
|
errorLogEntry->IoControlCode = 0;
|
|
|
|
if (RawDataLen != 0)
|
|
{
|
|
RtlCopyMemory(errorLogEntry->DumpData, RawDataBuf, RawDataLen);
|
|
}
|
|
|
|
StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
|
|
if (Device->dev_Type == SPX_DEVICE_SIGNATURE)
|
|
{
|
|
RtlCopyMemory(
|
|
StringLoc, Device->dev_DeviceName, Device->dev_DeviceNameLen);
|
|
|
|
StringLoc += Device->dev_DeviceNameLen;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory (StringLoc, DriverName, sizeof(DriverName));
|
|
StringLoc += sizeof(DriverName);
|
|
}
|
|
|
|
if (SecondString)
|
|
{
|
|
RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
|
|
}
|
|
|
|
IoWriteErrorLogEntry(errorLogEntry);
|
|
}
|
|
|
|
return;
|
|
}
|