461 lines
14 KiB
C
461 lines
14 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
atkerror.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the event logging and all error log code.
|
|
|
|
Author:
|
|
|
|
Jameel Hyder (jameelh@microsoft.com)
|
|
Nikhil Kamkolkar (nikhilk@microsoft.com)
|
|
|
|
Revision History:
|
|
19 Jun 1992 Initial Version
|
|
|
|
Notes: Tab stop: 4
|
|
--*/
|
|
|
|
#include <atalk.h>
|
|
#pragma hdrstop
|
|
#define FILENUM ATKERROR
|
|
|
|
|
|
LONG AtalkLastRawDataLen = 0;
|
|
NTSTATUS AtalkLastErrorCode = STATUS_SUCCESS;
|
|
ULONG AtalkLastErrorCount = 0;
|
|
LONG AtalkLastErrorTime = 0;
|
|
BYTE AtalkLastRawData[PORT_MAXIMUM_MESSAGE_LENGTH - \
|
|
sizeof(IO_ERROR_LOG_PACKET)] = {0};
|
|
|
|
VOID
|
|
AtalkWriteErrorLogEntry(
|
|
IN PPORT_DESCRIPTOR pPortDesc OPTIONAL,
|
|
IN NTSTATUS UniqueErrorCode,
|
|
IN ULONG UniqueErrorValue,
|
|
IN NTSTATUS NtStatusCode,
|
|
IN PVOID RawDataBuf OPTIONAL,
|
|
IN LONG RawDataLen
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
PIO_ERROR_LOG_PACKET errorLogEntry;
|
|
int AdapterNameLen = 0;
|
|
PUNICODE_STRING pAdapterName = NULL;
|
|
|
|
if (pPortDesc != NULL)
|
|
{
|
|
// do we have the friendly name (always yes, unless mem alloc failed)
|
|
if (pPortDesc->pd_FriendlyAdapterName.Buffer)
|
|
{
|
|
pAdapterName = &pPortDesc->pd_FriendlyAdapterName;
|
|
}
|
|
else
|
|
{
|
|
pAdapterName = &pPortDesc->pd_AdapterKey;
|
|
}
|
|
|
|
AdapterNameLen += pAdapterName->Length;
|
|
}
|
|
|
|
//ASSERT ((AdapterNameLen + sizeof(IO_ERROR_LOG_PACKET)) <
|
|
//PORT_MAXIMUM_MESSAGE_LENGTH);
|
|
|
|
#if DBG
|
|
if ((AdapterNameLen + sizeof(IO_ERROR_LOG_PACKET)) > PORT_MAXIMUM_MESSAGE_LENGTH)
|
|
{
|
|
DBGPRINT(DBG_COMP_UTILS, DBG_LEVEL_ERR,
|
|
("AtalkWriteErrorLogEntry: Adapter Name for Port Descriptor has length = %d, which is greater than space allocated for it in the port message buffer = %d. The adapter name will be truncated in the log.\n", AdapterNameLen, PORT_MAXIMUM_MESSAGE_LENGTH-sizeof(IO_ERROR_LOG_PACKET)));
|
|
}
|
|
#endif
|
|
|
|
// make sure the adaptername isn't huge: if it is, chop it
|
|
if ((AdapterNameLen + sizeof(IO_ERROR_LOG_PACKET)) > PORT_MAXIMUM_MESSAGE_LENGTH)
|
|
{
|
|
AdapterNameLen = PORT_MAXIMUM_MESSAGE_LENGTH - sizeof(IO_ERROR_LOG_PACKET);
|
|
}
|
|
|
|
//
|
|
if ((RawDataLen + AdapterNameLen + sizeof(IO_ERROR_LOG_PACKET)) >
|
|
PORT_MAXIMUM_MESSAGE_LENGTH)
|
|
{
|
|
RawDataLen = PORT_MAXIMUM_MESSAGE_LENGTH -
|
|
(AdapterNameLen + sizeof(IO_ERROR_LOG_PACKET));
|
|
}
|
|
|
|
// 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 == AtalkLastErrorCode)
|
|
{
|
|
AtalkLastErrorCount++;
|
|
if ((AtalkLastRawDataLen == RawDataLen) &&
|
|
(AtalkFixedCompareCaseSensitive(AtalkLastRawData,
|
|
RawDataLen,
|
|
RawDataBuf,
|
|
RawDataLen)) &&
|
|
((AtalkLastErrorCount % ERROR_CONSEQ_FREQ) != 0) &&
|
|
((AtalkGetCurrentTick() - AtalkLastErrorTime) < ERROR_CONSEQ_TIME))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
AtalkLastErrorCode = UniqueErrorCode;
|
|
AtalkLastErrorCount = 0;
|
|
AtalkLastErrorTime = AtalkGetCurrentTick();
|
|
ASSERT(RawDataLen < (PORT_MAXIMUM_MESSAGE_LENGTH -
|
|
sizeof(IO_ERROR_LOG_PACKET)));
|
|
|
|
if (RawDataLen != 0)
|
|
{
|
|
AtalkLastRawDataLen = RawDataLen;
|
|
RtlCopyMemory(
|
|
AtalkLastRawData,
|
|
RawDataBuf,
|
|
RawDataLen);
|
|
}
|
|
|
|
errorLogEntry =
|
|
(PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
|
|
(PDEVICE_OBJECT)AtalkDeviceObject[0],
|
|
(UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
|
|
AdapterNameLen + RawDataLen));
|
|
|
|
if (errorLogEntry != NULL)
|
|
{
|
|
// Fill in the Error log entry
|
|
errorLogEntry->ErrorCode = UniqueErrorCode;
|
|
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
|
|
errorLogEntry->MajorFunctionCode = 0;
|
|
errorLogEntry->RetryCount = 0;
|
|
errorLogEntry->FinalStatus = NtStatusCode;
|
|
errorLogEntry->IoControlCode = 0;
|
|
errorLogEntry->DeviceOffset.LowPart = 0;
|
|
errorLogEntry->DeviceOffset.HighPart = 0;
|
|
errorLogEntry->DumpDataSize = (USHORT)RawDataLen;
|
|
|
|
errorLogEntry->StringOffset =
|
|
(USHORT)(FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + RawDataLen);
|
|
|
|
errorLogEntry->NumberOfStrings = (ARGUMENT_PRESENT(pPortDesc)) ? 1 : 0;
|
|
|
|
if (ARGUMENT_PRESENT(RawDataBuf))
|
|
{
|
|
ASSERT(RawDataLen > 0);
|
|
RtlCopyMemory((PCHAR)&errorLogEntry->DumpData[0], RawDataBuf, RawDataLen);
|
|
}
|
|
|
|
if (ARGUMENT_PRESENT(pPortDesc))
|
|
{
|
|
RtlCopyMemory((PCHAR)errorLogEntry->DumpData + RawDataLen,
|
|
pAdapterName->Buffer,
|
|
AdapterNameLen);
|
|
}
|
|
|
|
// Write the entry
|
|
IoWriteErrorLogEntry(errorLogEntry);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(DBG_ALL, DBG_LEVEL_FATAL,
|
|
("AtalkWriteErrorLogEntry: IoAllocErrorlogEntry Failed %d = %d+%d+%d\n",
|
|
sizeof(IO_ERROR_LOG_PACKET)+AdapterNameLen+RawDataLen,
|
|
sizeof(IO_ERROR_LOG_PACKET),AdapterNameLen,RawDataLen));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtalkLogBadPacket(
|
|
IN struct _PORT_DESCRIPTOR * pPortDesc,
|
|
IN PATALK_ADDR pSrcAddr,
|
|
IN PATALK_ADDR pDstAddr OPTIONAL,
|
|
IN PBYTE pPkt,
|
|
IN USHORT PktLen
|
|
)
|
|
{
|
|
PBYTE RawData;
|
|
|
|
if ((RawData = AtalkAllocMemory(PktLen + sizeof(ATALK_ADDR) + sizeof(ATALK_ADDR))) != NULL)
|
|
{
|
|
RtlCopyMemory(RawData,
|
|
pSrcAddr,
|
|
sizeof(ATALK_ADDR));
|
|
if (ARGUMENT_PRESENT(pDstAddr))
|
|
{
|
|
RtlCopyMemory(RawData + sizeof(ATALK_ADDR),
|
|
pDstAddr,
|
|
sizeof(ATALK_ADDR));
|
|
}
|
|
else RtlZeroMemory(RawData + sizeof(ATALK_ADDR), sizeof(ATALK_ADDR));
|
|
RtlCopyMemory(RawData + sizeof(ATALK_ADDR) + sizeof(ATALK_ADDR),
|
|
pPkt,
|
|
PktLen);
|
|
LOG_ERRORONPORT(pPortDesc,
|
|
EVENT_ATALK_PACKETINVALID,
|
|
0,
|
|
RawData,
|
|
PktLen + sizeof(ATALK_ADDR) + sizeof(ATALK_ADDR));
|
|
AtalkFreeMemory(RawData);
|
|
}
|
|
}
|
|
|
|
struct _NdisToAtalkCodes
|
|
{
|
|
NDIS_STATUS _NdisCode;
|
|
ATALK_ERROR _AtalkCode;
|
|
} atalkNdisToAtalkCodes[] =
|
|
{
|
|
{ NDIS_STATUS_SUCCESS, ATALK_NO_ERROR },
|
|
{ NDIS_STATUS_PENDING, ATALK_PENDING },
|
|
{ NDIS_STATUS_RESOURCES, ATALK_RESR_MEM },
|
|
{ NDIS_STATUS_UNSUPPORTED_MEDIA, ATALK_INIT_MEDIA_INVALID },
|
|
{ NDIS_STATUS_BAD_VERSION, ATALK_INIT_REGPROTO_FAIL },
|
|
{ NDIS_STATUS_BAD_CHARACTERISTICS, ATALK_INIT_REGPROTO_FAIL },
|
|
{ NDIS_STATUS_BUFFER_TOO_SHORT, ATALK_BUFFER_TOO_SMALL },
|
|
{ NDIS_STATUS_ADAPTER_NOT_FOUND, ATALK_INIT_BINDFAIL },
|
|
{ NDIS_STATUS_OPEN_FAILED, ATALK_INIT_BINDFAIL },
|
|
{ NDIS_STATUS_OPEN_LIST_FULL, ATALK_INIT_BINDFAIL },
|
|
{ NDIS_STATUS_ADAPTER_NOT_READY, ATALK_INIT_BINDFAIL }
|
|
};
|
|
|
|
ATALK_ERROR FASTCALL
|
|
AtalkNdisToAtalkError(
|
|
IN NDIS_STATUS Error
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
ATALK_ERROR err = ATALK_FAILURE; // default
|
|
int i;
|
|
struct _NdisToAtalkCodes *pCodes;
|
|
|
|
for (i = 0, pCodes = &atalkNdisToAtalkCodes[0];
|
|
i < sizeof(atalkNdisToAtalkCodes)/sizeof(struct _NdisToAtalkCodes);
|
|
i++, pCodes++)
|
|
{
|
|
if (pCodes->_NdisCode == Error)
|
|
{
|
|
err = pCodes->_AtalkCode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
|
|
|
|
|
|
struct _AtalkToNtCodes
|
|
{
|
|
ATALK_ERROR _AtalkCode;
|
|
NTSTATUS _NtCode;
|
|
} atalkToNtCodes[] =
|
|
{
|
|
{ ATALK_NO_ERROR, STATUS_SUCCESS },
|
|
{ ATALK_PENDING, STATUS_PENDING },
|
|
{ ATALK_RESR_MEM, STATUS_INSUFFICIENT_RESOURCES },
|
|
{ ATALK_CONNECTION_TIMEOUT, STATUS_REMOTE_DISCONNECT },
|
|
{ ATALK_LOCAL_CLOSE, STATUS_LOCAL_DISCONNECT },
|
|
{ ATALK_REMOTE_CLOSE, STATUS_REMOTE_DISCONNECT },
|
|
{ ATALK_INVALID_PARAMETER, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_BUFFER_TOO_SMALL, STATUS_BUFFER_TOO_SMALL },
|
|
{ ATALK_INVALID_REQUEST, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ATALK_DEVICE_NOT_READY, STATUS_DEVICE_NOT_READY },
|
|
{ ATALK_REQUEST_NOT_ACCEPTED, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ATALK_NEW_SOCKET, STATUS_INVALID_ADDRESS },
|
|
{ ATALK_TIMEOUT, STATUS_IO_TIMEOUT },
|
|
{ ATALK_SHARING_VIOLATION, STATUS_SHARING_VIOLATION },
|
|
{ ATALK_INIT_BINDFAIL, (NTSTATUS)NDIS_STATUS_OPEN_FAILED },
|
|
{ ATALK_INIT_REGPROTO_FAIL, (NTSTATUS)NDIS_STATUS_BAD_VERSION },
|
|
{ ATALK_INIT_MEDIA_INVALID, (NTSTATUS)NDIS_STATUS_UNSUPPORTED_MEDIA },
|
|
{ ATALK_PORT_INVALID, STATUS_INVALID_PORT_HANDLE },
|
|
{ ATALK_PORT_CLOSING, STATUS_PORT_DISCONNECTED },
|
|
{ ATALK_NODE_FINDING, STATUS_TOO_MANY_COMMANDS },
|
|
{ ATALK_NODE_NONEXISTENT, STATUS_INVALID_ADDRESS_COMPONENT },
|
|
{ ATALK_NODE_CLOSING, STATUS_ADDRESS_CLOSED },
|
|
{ ATALK_NODE_NOMORE, STATUS_TOO_MANY_NODES },
|
|
{ ATALK_SOCKET_INVALID, STATUS_INVALID_ADDRESS_COMPONENT },
|
|
{ ATALK_SOCKET_NODEFULL, STATUS_TOO_MANY_ADDRESSES },
|
|
{ ATALK_SOCKET_EXISTS, STATUS_ADDRESS_ALREADY_EXISTS },
|
|
{ ATALK_SOCKET_CLOSED, STATUS_ADDRESS_CLOSED },
|
|
{ ATALK_DDP_CLOSING, STATUS_ADDRESS_CLOSED },
|
|
{ ATALK_DDP_NOTFOUND, STATUS_INVALID_ADDRESS },
|
|
{ ATALK_DDP_INVALID_LEN, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_DDP_INVALID_SRC, STATUS_INVALID_ADDRESS },
|
|
{ ATALK_DDP_INVALID_DEST, STATUS_INVALID_ADDRESS },
|
|
{ ATALK_DDP_INVALID_ADDR, STATUS_INVALID_ADDRESS },
|
|
{ ATALK_DDP_INVALID_PARAM, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_ATP_RESP_TIMEOUT, STATUS_SUCCESS },
|
|
{ ATALK_ATP_INVALID_RETRYCNT, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_ATP_INVALID_TIMERVAL, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_ATP_INVALID_RELINT, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_ATP_RESP_CANCELLED, STATUS_CANCELLED },
|
|
{ ATALK_ATP_REQ_CANCELLED, STATUS_CANCELLED },
|
|
{ ATALK_ATP_GET_REQ_CANCELLED, STATUS_CANCELLED },
|
|
{ ATALK_ASP_INVALID_REQUEST, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ATALK_PAP_INVALID_REQUEST, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ATALK_PAP_TOO_MANY_READS, STATUS_TOO_MANY_COMMANDS },
|
|
{ ATALK_PAP_TOO_MANY_WRITES, STATUS_TOO_MANY_COMMANDS },
|
|
{ ATALK_PAP_CONN_NOT_ACTIVE, STATUS_INVALID_CONNECTION },
|
|
{ ATALK_PAP_ADDR_CLOSING, STATUS_INVALID_HANDLE },
|
|
{ ATALK_PAP_CONN_CLOSING, STATUS_INVALID_HANDLE },
|
|
{ ATALK_PAP_CONN_NOT_FOUND, STATUS_INVALID_HANDLE },
|
|
{ ATALK_PAP_SERVER_BUSY, STATUS_REMOTE_NOT_LISTENING },
|
|
{ ATALK_PAP_INVALID_STATUS, STATUS_INVALID_PARAMETER },
|
|
{ ATALK_PAP_PARTIAL_RECEIVE, STATUS_RECEIVE_PARTIAL },
|
|
{ ATALK_ADSP_INVALID_REQUEST, STATUS_REQUEST_NOT_ACCEPTED },
|
|
{ ATALK_ADSP_CONN_NOT_ACTIVE, STATUS_INVALID_CONNECTION },
|
|
{ ATALK_ADSP_ADDR_CLOSING, STATUS_INVALID_HANDLE },
|
|
{ ATALK_ADSP_CONN_CLOSING, STATUS_INVALID_HANDLE },
|
|
{ ATALK_ADSP_CONN_NOT_FOUND, STATUS_INVALID_HANDLE },
|
|
{ ATALK_ADSP_CONN_RESET, STATUS_CONNECTION_RESET },
|
|
{ ATALK_ADSP_SERVER_BUSY, STATUS_REMOTE_NOT_LISTENING },
|
|
{ ATALK_ADSP_PARTIAL_RECEIVE, STATUS_RECEIVE_PARTIAL },
|
|
{ ATALK_ADSP_EXPED_RECEIVE, STATUS_RECEIVE_EXPEDITED },
|
|
{ ATALK_ADSP_PAREXPED_RECEIVE, STATUS_RECEIVE_PARTIAL_EXPEDITED },
|
|
{ ATALK_ADSP_REMOTE_RESR, STATUS_REMOTE_RESOURCES }
|
|
};
|
|
|
|
NTSTATUS FASTCALL
|
|
AtalkErrorToNtStatus(
|
|
ATALK_ERROR AtalkError
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL; // default
|
|
int i;
|
|
struct _AtalkToNtCodes *pCodes;
|
|
|
|
for (i = 0, pCodes = &atalkToNtCodes[0];
|
|
i < sizeof(atalkToNtCodes)/sizeof(struct _AtalkToNtCodes);
|
|
i++, pCodes++)
|
|
{
|
|
if (pCodes->_AtalkCode == AtalkError)
|
|
{
|
|
Status = pCodes->_NtCode;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
struct
|
|
{
|
|
ULONG DumpMask;
|
|
DUMP_ROUTINE DumpRoutine;
|
|
} AtalkDumpTable[32] =
|
|
{
|
|
{ DBG_DUMP_PORTINFO, AtalkPortDumpInfo },
|
|
{ DBG_DUMP_AMT, AtalkAmtDumpTable },
|
|
{ DBG_DUMP_ZONETABLE, AtalkZoneDumpTable },
|
|
{ DBG_DUMP_RTES, AtalkRtmpDumpTable },
|
|
{ DBG_DUMP_TIMERS, AtalkTimerDumpList },
|
|
{ DBG_DUMP_ATPINFO, NULL },
|
|
{ DBG_DUMP_ASPSESSIONS, AtalkAspDumpSessions },
|
|
{ DBG_DUMP_PAPJOBS, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
LONG FASTCALL
|
|
AtalkDumpComponents(
|
|
IN PTIMERLIST Context,
|
|
IN BOOLEAN TimerShuttingDown
|
|
)
|
|
{
|
|
int i;
|
|
|
|
if (!TimerShuttingDown)
|
|
{
|
|
for (i = 0;AtalkDebugDump && (i < 32); i++)
|
|
{
|
|
if ((AtalkDebugDump & AtalkDumpTable[i].DumpMask) &&
|
|
(AtalkDumpTable[i].DumpRoutine != NULL))
|
|
{
|
|
(*AtalkDumpTable[i].DumpRoutine)();
|
|
}
|
|
}
|
|
|
|
if (AtalkDumpInterval == 0)
|
|
{
|
|
AtalkDumpInterval = DBG_DUMP_DEF_INTERVAL;
|
|
}
|
|
}
|
|
else AtalkDumpInterval = ATALK_TIMER_NO_REQUEUE;
|
|
|
|
return AtalkDumpInterval;
|
|
}
|
|
|
|
#endif
|