814 lines
18 KiB
C
814 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 1992-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
kdexts.c
|
|
|
|
Abstract:
|
|
|
|
This function contains some example KD debugger extensions
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 6-Aug-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
|
|
|
// Forward function definitions
|
|
|
|
PCHAR
|
|
FindPreamble(
|
|
CHAR * BufferPointer,
|
|
BOOLEAN FirstTime
|
|
);
|
|
|
|
VOID
|
|
ParseBuffer(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseOidRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseTimeRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseStringRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseSchedRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseRecvRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
PCHAR
|
|
ParseSendRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
);
|
|
|
|
static PCHAR SchedModules[] = {
|
|
"NOP",
|
|
"TB CONFORMER",
|
|
"SHAPER",
|
|
"DRR SEQ",
|
|
"CBQ"};
|
|
|
|
static PCHAR SchedActions[] = {
|
|
"NOP",
|
|
"ENQUEUE",
|
|
"DEQUEUE",
|
|
"CONFORMANCE",
|
|
"DISCARD"};
|
|
|
|
static PCHAR SendRecvActions[] = {
|
|
"",
|
|
"ENTER",
|
|
"NO_RESOURCES",
|
|
"LOW_RESOURCES",
|
|
"INDICATING",
|
|
"RETURNED",
|
|
"NOT_OURS",
|
|
"OURS",
|
|
"RETURNING",
|
|
"TRANSFERRING",
|
|
"NOT READY"};
|
|
|
|
static PCHAR RecvEvents[] = {
|
|
"",
|
|
"CL_RECV_PACKET",
|
|
"MP_RETURN_PACKET",
|
|
"CL_RECV_INDICATION",
|
|
"CL_RECV_COMPLETE",
|
|
"MP_TRANSFER_DATA",
|
|
"CL_TRANSFER_COMPLETE"};
|
|
|
|
static PCHAR SendEvents[] = {
|
|
"",
|
|
"MP_SEND",
|
|
"MP_CO_SEND",
|
|
"DUP_PACKET",
|
|
"DROP_PACKET",
|
|
"CL_SEND_COMPLETE" };
|
|
|
|
|
|
|
|
//
|
|
// globals
|
|
//
|
|
|
|
CHAR Preamble[] = {(CHAR)0xef,(CHAR)0xbe,(CHAR)0xad,(CHAR)0xde};
|
|
|
|
ULONG ByteCheck = 0;
|
|
ULONG SafetyLimit;
|
|
|
|
BOOL
|
|
SafeRead(
|
|
DWORD offset,
|
|
LPVOID lpBuffer,
|
|
DWORD cb,
|
|
LPDWORD lpcbBytesRead
|
|
)
|
|
{
|
|
if(ByteCheck <= SafetyLimit){
|
|
ReadMemory(offset, lpBuffer, cb, lpcbBytesRead);
|
|
ByteCheck += cb;
|
|
return TRUE;
|
|
}
|
|
else{
|
|
dprintf("SafetyLimit of %d, exceeded, quitting!\n", SafetyLimit);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
MyOpenFile (
|
|
IN PCHAR Name,
|
|
IN PWINDBG_OUTPUT_ROUTINE out,
|
|
OUT HANDLE *File
|
|
)
|
|
|
|
{
|
|
HANDLE hFile;
|
|
hFile = CreateFile(Name,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS ,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (INVALID_HANDLE_VALUE == hFile) {
|
|
out ("MyOpenFile: CreateFile Failed.\n");
|
|
}
|
|
|
|
*File = hFile;
|
|
|
|
return(INVALID_HANDLE_VALUE == hFile ? (!(ERROR_SUCCESS)) : ERROR_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
MyWriteFile (
|
|
PCHAR buffer,
|
|
HANDLE file,
|
|
IN PWINDBG_OUTPUT_ROUTINE out
|
|
)
|
|
|
|
{
|
|
LONG len;
|
|
BOOL bRv;
|
|
DWORD dwWritten;
|
|
|
|
if (!buffer) {
|
|
out("MyWriteFile: Buffer is null\n");
|
|
}
|
|
|
|
len = strlen(buffer);
|
|
|
|
bRv = WriteFile( file, buffer, len, &dwWritten, NULL );
|
|
|
|
if (!bRv) {
|
|
out("WriteFile: Puked\n");
|
|
}
|
|
}
|
|
|
|
CHAR * BufferBase; // Start address of trace buffer, in host memory
|
|
CHAR * BufferEnd; // End address of trace buffer, in host memory
|
|
CHAR * BufferPointer; // Current location in host memory buffer
|
|
LONG BufferSize; // Total size of host memory buffer, in bytes.
|
|
LONG BufferCount; // Total count of traced bytes.
|
|
LONG TotalValidBytesRead = 0;
|
|
|
|
#define OUTPUT_ERROR 0
|
|
#define OUTPUT_FILE 1
|
|
#define OUTPUT_CONSOLE 2
|
|
|
|
CHAR FileIt;
|
|
HANDLE FileHandle;
|
|
ULONG LineNumber = 0;
|
|
|
|
DECLARE_API( tt )
|
|
{
|
|
DWORD hostAddress;
|
|
CHAR DeviceName[] = "c:\\tmp\\";
|
|
CHAR buffer[255];
|
|
DWORD status;
|
|
LONG pBufferBase;
|
|
LONG pBufferCount;
|
|
LONG pBufferSize;
|
|
BOOL success;
|
|
DWORD bytesread;
|
|
CHAR *s, *dataStart;
|
|
ULONG skip=0;
|
|
|
|
char SchedBufBase[] = {"&psched!SchedTraceBuffer"};
|
|
char SchedCount[] = {"&psched!SchedTraced"};
|
|
char BuffSize[] = {"&psched!SchedBufferSize"};
|
|
|
|
TotalValidBytesRead = 0;
|
|
LineNumber = 0;
|
|
FileIt = OUTPUT_ERROR;
|
|
|
|
if ( *args != '\0' ) {
|
|
|
|
// First argument is the file name.
|
|
s = strtok((LPSTR)args, " ");
|
|
|
|
strcpy( buffer, DeviceName );
|
|
strcat( buffer, s );
|
|
|
|
// next arg is the optional args.
|
|
while((s = strtok(NULL, " ")) != NULL)
|
|
{
|
|
if(s[0] == '-')
|
|
{
|
|
switch(s[1])
|
|
{
|
|
case 's':
|
|
case 'S':
|
|
skip = atoi(&s[2]);
|
|
break;
|
|
|
|
default:
|
|
dprintf("Usage: !tt [filename] [-S<#>] \n");
|
|
dprintf(" S : No of records (from head) to skip \n");
|
|
goto cleanup;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
status = MyOpenFile( buffer, dprintf, &FileHandle );
|
|
if ( status == ERROR_SUCCESS ) {
|
|
FileIt = OUTPUT_FILE;
|
|
}
|
|
else {
|
|
goto cleanup;
|
|
}
|
|
dprintf( "handle =%x status=%x FileIt=%d\n", FileHandle, status, FileIt );
|
|
}
|
|
else {
|
|
FileIt = OUTPUT_CONSOLE;
|
|
}
|
|
|
|
hostAddress = GetExpression(SchedBufBase);
|
|
pBufferBase = (LONG)hostAddress;
|
|
|
|
if (!pBufferBase){
|
|
dprintf("bad string conversion (%s) \n", SchedBufBase);
|
|
goto cleanup;
|
|
}
|
|
|
|
hostAddress = GetExpression(SchedCount);
|
|
pBufferCount = hostAddress;
|
|
|
|
if (!pBufferCount) {
|
|
dprintf( " bad string conversion (%s) \n", SchedCount );
|
|
goto cleanup;
|
|
}
|
|
|
|
hostAddress = GetExpression(BuffSize);
|
|
pBufferSize = hostAddress;
|
|
|
|
if (!pBufferSize) {
|
|
dprintf( " bad string conversion (%s) \n", SchedCount );
|
|
goto cleanup;
|
|
}
|
|
|
|
success = ReadMemory((ULONG)pBufferCount, &BufferCount, sizeof(LONG), &bytesread );
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", pBufferCount, sizeof(LONG));
|
|
goto cleanup;
|
|
}
|
|
|
|
success = ReadMemory((ULONG)pBufferSize, &BufferSize, sizeof(LONG), &bytesread );
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", pBufferSize, sizeof(LONG));
|
|
goto cleanup;
|
|
}
|
|
|
|
success = ReadMemory((ULONG)pBufferBase, &BufferBase, sizeof(LONG), &bytesread );
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", pBufferBase, sizeof(LONG));
|
|
goto cleanup;
|
|
}
|
|
|
|
SafetyLimit = (ULONG)-1;
|
|
|
|
if(!BufferCount){
|
|
dprintf("No data in buffer.\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
dprintf("struct@%x, total bytes traced: %d, buffer size: %d\n", BufferBase, BufferCount, BufferSize);
|
|
|
|
// Find the starting point. If we haven't wrapped the buffer, it's at BufferBase.
|
|
// If we have wrapped the buffer, we start right after our current pointer.
|
|
// In either case, BufferPointer is the host address at which we should
|
|
// start looking for data.
|
|
|
|
if(BufferCount <= BufferSize){
|
|
BufferPointer = BufferBase;
|
|
}
|
|
else{
|
|
BufferPointer = BufferBase + (BufferCount % BufferSize);
|
|
}
|
|
|
|
BufferEnd = BufferBase + BufferSize;
|
|
|
|
// dataStart will point to the first location after the
|
|
// first preamble (in host memory), or - will be zero,
|
|
// indicating that no preamble was found.
|
|
|
|
dataStart = FindPreamble(BufferPointer, TRUE);
|
|
|
|
if(dataStart){
|
|
ParseBuffer(dataStart, skip);
|
|
}
|
|
else{
|
|
dprintf("Error reading token trace buffer. Could not find preamble.\n");
|
|
}
|
|
|
|
cleanup:
|
|
if(FileIt == OUTPUT_FILE){
|
|
CloseHandle( FileHandle );
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
FindPreamble(
|
|
CHAR * BufferPointer,
|
|
BOOLEAN FirstTime
|
|
)
|
|
{
|
|
LONG count;
|
|
LONG i;
|
|
CHAR * readFrom;
|
|
CHAR hold;
|
|
BOOL success;
|
|
DWORD bytesread;
|
|
|
|
count = 0;
|
|
i = 0;
|
|
|
|
readFrom = BufferPointer;
|
|
|
|
while(TRUE){
|
|
|
|
success = SafeRead((ULONG)readFrom, &hold, 1, &bytesread );
|
|
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", readFrom, 1);
|
|
break;
|
|
}
|
|
|
|
if(hold == Preamble[i]){
|
|
i++;
|
|
}
|
|
else{
|
|
i=0;
|
|
}
|
|
|
|
if(i == sizeof(TRACE_PREAMBLE)){
|
|
if(FirstTime){
|
|
dprintf("Found start of first record at %d.\n", readFrom+1 - BufferBase);
|
|
}
|
|
TotalValidBytesRead += sizeof(TRACE_PREAMBLE);
|
|
readFrom++;
|
|
break;
|
|
}
|
|
|
|
readFrom++;
|
|
|
|
if(readFrom > BufferEnd){
|
|
readFrom = BufferBase;
|
|
}
|
|
|
|
count++;
|
|
|
|
if(count == TRACE_BUFFER_SIZE){
|
|
readFrom = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(readFrom);
|
|
}
|
|
|
|
VOID
|
|
ParseBuffer(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
CHAR * dataStart;
|
|
CHAR * recordEnd;
|
|
LONG records;
|
|
BOOL success;
|
|
CHAR hold;
|
|
DWORD bytesread;
|
|
|
|
records = 0;
|
|
dataStart = DataStart;
|
|
|
|
while(TRUE){
|
|
|
|
success = SafeRead((ULONG)dataStart, &hold, 1, &bytesread );
|
|
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", dataStart, 1);
|
|
break;
|
|
}
|
|
|
|
switch(hold){
|
|
|
|
case RECORD_TSTRING:
|
|
|
|
recordEnd = ParseStringRecord(dataStart, SkipCnt);
|
|
break;
|
|
|
|
case RECORD_OID:
|
|
recordEnd = ParseOidRecord(dataStart, SkipCnt);
|
|
break;
|
|
|
|
case RECORD_SCHED:
|
|
|
|
recordEnd = ParseSchedRecord(dataStart, SkipCnt);
|
|
break;
|
|
|
|
case RECORD_RECV:
|
|
recordEnd = ParseRecvRecord(dataStart, SkipCnt);
|
|
break;
|
|
|
|
case RECORD_SEND:
|
|
recordEnd = ParseSendRecord(dataStart, SkipCnt);
|
|
break;
|
|
default:
|
|
|
|
dprintf("Unrecognized record type!\n");
|
|
}
|
|
|
|
records++;
|
|
|
|
if(TotalValidBytesRead >= BufferCount){
|
|
dprintf("\nCompleted parsing trace buffer. %d records found.\n", records);
|
|
break;
|
|
}
|
|
|
|
dataStart = FindPreamble(recordEnd, FALSE);
|
|
|
|
if(dataStart == DataStart){
|
|
dprintf("\nCompleted parsing trace buffer. %d records found.\n", records);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
GetBytesToRead(
|
|
CHAR * DataStart,
|
|
LONG RecordSize,
|
|
LONG * BytesToReadFirst,
|
|
LONG * BytesToReadNext
|
|
)
|
|
{
|
|
if((DataStart + RecordSize - sizeof(TRACE_PREAMBLE)) > BufferEnd){
|
|
*BytesToReadFirst = BufferEnd - DataStart;
|
|
*BytesToReadNext = RecordSize - sizeof(TRACE_PREAMBLE) - *BytesToReadFirst;
|
|
}
|
|
else{
|
|
*BytesToReadFirst = RecordSize - sizeof(TRACE_PREAMBLE);
|
|
*BytesToReadNext = 0;
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
ParseAnyRecord(
|
|
CHAR * DataStart,
|
|
CHAR * Record,
|
|
LONG RecordSize
|
|
)
|
|
{
|
|
LONG bytesToReadFirst;
|
|
LONG bytesToReadNext;
|
|
BOOL success;
|
|
CHAR * nextDataStart;
|
|
DWORD bytesread;
|
|
CHAR * pRecordData;
|
|
CHAR buffer[255];
|
|
|
|
GetBytesToRead(DataStart, RecordSize, &bytesToReadFirst, &bytesToReadNext);
|
|
pRecordData = Record + sizeof(TRACE_PREAMBLE);
|
|
|
|
success = SafeRead((ULONG)DataStart, pRecordData, bytesToReadFirst, &bytesread );
|
|
TotalValidBytesRead += bytesToReadFirst;
|
|
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", DataStart, 1);
|
|
}
|
|
|
|
nextDataStart = DataStart + bytesToReadFirst;
|
|
|
|
if(bytesToReadNext){
|
|
|
|
success = SafeRead((ULONG)BufferBase,
|
|
pRecordData + bytesToReadFirst,
|
|
bytesToReadNext,
|
|
&bytesread);
|
|
|
|
TotalValidBytesRead += bytesToReadNext;
|
|
|
|
if (!success){
|
|
dprintf("problems reading memory at %x for %x bytes\n", BufferBase, 1);
|
|
}
|
|
|
|
nextDataStart = BufferBase + bytesToReadNext;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|
|
PCHAR
|
|
ParseOidRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
TRACE_RECORD_OID record;
|
|
CHAR buffer[255];
|
|
CHAR * nextDataStart;
|
|
static PCHAR OIDActions[] =
|
|
{
|
|
"",
|
|
"MpSetInformation",
|
|
"MpQueryInformation",
|
|
"SetRequestComplete",
|
|
"QueryRequestComplete"
|
|
};
|
|
|
|
nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_OID));
|
|
|
|
if(++LineNumber < SkipCnt)
|
|
return nextDataStart;
|
|
if(record.Now.QuadPart){
|
|
|
|
wsprintf(buffer, "[%4d]:[%u.%u]: OID: %5s:%9s:%08X:%08X:%08X \n",
|
|
LineNumber,
|
|
record.Now.HighPart,
|
|
record.Now.LowPart,
|
|
OIDActions[record.Action],
|
|
record.Local == TRUE?"Local":"Non Local",
|
|
record.Adapter,
|
|
record.Oid,
|
|
record.Status);
|
|
}
|
|
else {
|
|
wsprintf(buffer, "[%4d]: OID: %5s:%9s:%08X:%08X:%08X \n",
|
|
LineNumber,
|
|
OIDActions[record.Action],
|
|
record.Local == TRUE?"Local":"Non Local",
|
|
record.Adapter,
|
|
record.Oid,
|
|
record.Status);
|
|
}
|
|
|
|
switch(FileIt)
|
|
{
|
|
case OUTPUT_FILE:
|
|
MyWriteFile(buffer, FileHandle, dprintf);
|
|
break;
|
|
case OUTPUT_CONSOLE:
|
|
dprintf(buffer);
|
|
break;
|
|
default:
|
|
dprintf("Failed to create file! Check for tmp directory.\n");
|
|
break;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|
|
|
|
PCHAR
|
|
ParseStringRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
TRACE_RECORD_STRING record;
|
|
LONG bytesToReadFirst;
|
|
LONG bytesToReadNext;
|
|
BOOL success;
|
|
CHAR * nextDataStart;
|
|
DWORD bytesread;
|
|
CHAR * pRecordData;
|
|
CHAR buffer[255];
|
|
|
|
nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_STRING));
|
|
|
|
if(++LineNumber < SkipCnt)
|
|
return nextDataStart;
|
|
|
|
if(record.Now.QuadPart){
|
|
wsprintf(buffer, "[%4d]:[%u.%u]:%s",
|
|
LineNumber,
|
|
record.Now.HighPart,
|
|
record.Now.LowPart,
|
|
record.StringStart);
|
|
}
|
|
else{
|
|
wsprintf(buffer, "[%4d]:%s",
|
|
LineNumber,
|
|
record.StringStart);
|
|
}
|
|
|
|
switch(FileIt)
|
|
{
|
|
case OUTPUT_FILE:
|
|
MyWriteFile(buffer, FileHandle, dprintf);
|
|
break;
|
|
case OUTPUT_CONSOLE:
|
|
dprintf(buffer);
|
|
break;
|
|
default:
|
|
dprintf("Failed to create file! Check for tmp directory.\n");
|
|
break;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|
|
PCHAR
|
|
ParseSchedRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
TRACE_RECORD_SCHED record;
|
|
LONG bytesToReadFirst;
|
|
LONG bytesToReadNext;
|
|
BOOL success;
|
|
CHAR * nextDataStart;
|
|
DWORD bytesread;
|
|
CHAR * pRecordData;
|
|
ULONG now;
|
|
CHAR buffer[255];
|
|
LARGE_INTEGER ConformanceTime;
|
|
|
|
nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record, sizeof(TRACE_RECORD_SCHED));
|
|
if(++LineNumber < SkipCnt)
|
|
return nextDataStart;
|
|
ConformanceTime.QuadPart = record.ConformanceTime;
|
|
|
|
wsprintf(buffer,
|
|
"[%4d]:[%u.%u]:%s:VC %x:%x:%u:%s:%d:%d:%u:%u\n",
|
|
LineNumber,
|
|
record.Now.HighPart,
|
|
record.Now.LowPart,
|
|
SchedModules[record.SchedulerComponent],
|
|
record.VC,
|
|
record.Packet,
|
|
record.PacketLength,
|
|
SchedActions[record.Action],
|
|
record.Priority,
|
|
ConformanceTime.HighPart,
|
|
ConformanceTime.LowPart,
|
|
record.PacketsInComponent);
|
|
|
|
switch(FileIt)
|
|
{
|
|
case OUTPUT_FILE:
|
|
MyWriteFile(buffer, FileHandle, dprintf);
|
|
break;
|
|
case OUTPUT_CONSOLE:
|
|
dprintf(buffer);
|
|
break;
|
|
default:
|
|
dprintf("Failed to create file! Check for tmp directory.\n");
|
|
break;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|
|
PCHAR
|
|
ParseRecvRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
TRACE_RECORD_RECV record;
|
|
LONG bytesToReadFirst;
|
|
LONG bytesToReadNext;
|
|
BOOL success;
|
|
CHAR * nextDataStart;
|
|
DWORD bytesread;
|
|
CHAR * pRecordData;
|
|
CHAR buffer[255];
|
|
|
|
nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record,
|
|
sizeof(TRACE_RECORD_RECV));
|
|
|
|
if(++LineNumber < SkipCnt)
|
|
return nextDataStart;
|
|
wsprintf(buffer,
|
|
"[%4d]:[%u.%u]:Adapter %08X:%s:%s:%x:%x \n",
|
|
LineNumber,
|
|
record.Now.HighPart,
|
|
record.Now.LowPart,
|
|
record.Adapter,
|
|
RecvEvents[record.Event],
|
|
SendRecvActions[record.Action],
|
|
record.Packet1,
|
|
record.Packet2);
|
|
|
|
switch(FileIt)
|
|
{
|
|
case OUTPUT_FILE:
|
|
MyWriteFile(buffer, FileHandle, dprintf);
|
|
break;
|
|
case OUTPUT_CONSOLE:
|
|
dprintf(buffer);
|
|
break;
|
|
default:
|
|
dprintf("Failed to create file! Check for tmp directory.\n");
|
|
break;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|
|
PCHAR
|
|
ParseSendRecord(
|
|
CHAR * DataStart,
|
|
ULONG SkipCnt
|
|
)
|
|
{
|
|
TRACE_RECORD_SEND record;
|
|
LONG bytesToReadFirst;
|
|
LONG bytesToReadNext;
|
|
BOOL success;
|
|
CHAR * nextDataStart;
|
|
DWORD bytesread;
|
|
CHAR * pRecordData;
|
|
CHAR buffer[255];
|
|
|
|
nextDataStart = ParseAnyRecord(DataStart, (CHAR *)&record,
|
|
sizeof(TRACE_RECORD_SEND));
|
|
|
|
if(++LineNumber < SkipCnt)
|
|
return nextDataStart;
|
|
wsprintf(buffer,
|
|
"[%4d]:[%u.%u]:Adapter %08X:%s:%s:%x:%x:%x\n",
|
|
LineNumber,
|
|
record.Now.HighPart,
|
|
record.Now.LowPart,
|
|
record.Adapter,
|
|
SendEvents[record.Event],
|
|
SendRecvActions[record.Action],
|
|
record.Vc,
|
|
record.Packet1,
|
|
record.Packet2);
|
|
|
|
switch(FileIt)
|
|
{
|
|
case OUTPUT_FILE:
|
|
MyWriteFile(buffer, FileHandle, dprintf);
|
|
break;
|
|
case OUTPUT_CONSOLE:
|
|
dprintf(buffer);
|
|
break;
|
|
default:
|
|
dprintf("Failed to create file! Check for tmp directory.\n");
|
|
break;
|
|
}
|
|
|
|
return(nextDataStart);
|
|
}
|
|
|