863 lines
15 KiB
C
863 lines
15 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1998-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
dbgutil.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Utility functions for dealing with the kernel debugger.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Keith Moore (keithmo) 17-Jun-1998
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Private constants.
|
|||
|
//
|
|||
|
|
|||
|
#define EXT_DLL "kdexts.dll"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Private globals.
|
|||
|
//
|
|||
|
|
|||
|
PSTR WeekdayNames[] =
|
|||
|
{
|
|||
|
"Sunday",
|
|||
|
"Monday",
|
|||
|
"Tuesday",
|
|||
|
"Wednesday",
|
|||
|
"Thursday",
|
|||
|
"Friday",
|
|||
|
"Saturday"
|
|||
|
};
|
|||
|
|
|||
|
PSTR MonthNames[] =
|
|||
|
{
|
|||
|
"",
|
|||
|
"January",
|
|||
|
"February",
|
|||
|
"March",
|
|||
|
"April",
|
|||
|
"May",
|
|||
|
"June",
|
|||
|
"July",
|
|||
|
"August",
|
|||
|
"September",
|
|||
|
"October",
|
|||
|
"November",
|
|||
|
"December"
|
|||
|
};
|
|||
|
|
|||
|
HMODULE ExtensionDll = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Public functions.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SystemTimeToString(
|
|||
|
IN LONGLONG Value,
|
|||
|
OUT PSTR Buffer
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Maps a LONGLONG representing system time to a displayable string.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Value - The LONGLONG time to map.
|
|||
|
|
|||
|
Buffer - Receives the mapped time.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS status;
|
|||
|
LARGE_INTEGER systemTime;
|
|||
|
LARGE_INTEGER localTime;
|
|||
|
TIME_FIELDS timeFields;
|
|||
|
|
|||
|
systemTime.QuadPart = Value;
|
|||
|
|
|||
|
status = RtlSystemTimeToLocalTime( &systemTime, &localTime );
|
|||
|
|
|||
|
if( !NT_SUCCESS(status) ) {
|
|||
|
sprintf( Buffer, "%I64d", Value );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
RtlTimeToTimeFields( &localTime, &timeFields );
|
|||
|
|
|||
|
sprintf(
|
|||
|
Buffer,
|
|||
|
"%s %s %2d %4d %02d:%02d:%02d.%03d",
|
|||
|
WeekdayNames[timeFields.Weekday],
|
|||
|
MonthNames[timeFields.Month],
|
|||
|
timeFields.Day,
|
|||
|
timeFields.Year,
|
|||
|
timeFields.Hour,
|
|||
|
timeFields.Minute,
|
|||
|
timeFields.Second,
|
|||
|
timeFields.Milliseconds
|
|||
|
);
|
|||
|
|
|||
|
} // SystemTimeToString
|
|||
|
|
|||
|
PSTR
|
|||
|
SignatureToString(
|
|||
|
IN ULONG CurrentSignature,
|
|||
|
IN ULONG ValidSignature,
|
|||
|
IN ULONG FreedSignature,
|
|||
|
OUT PSTR Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR pstr = Buffer;
|
|||
|
int i;
|
|||
|
UCHAR ch;
|
|||
|
|
|||
|
*pstr++ = '\'';
|
|||
|
|
|||
|
for (i = 0; i < 4; ++i)
|
|||
|
{
|
|||
|
ch = (UCHAR)((CurrentSignature >> (8 * i)) & 0xFF);
|
|||
|
*pstr++ = isprint(ch) ? (ch) : '?';
|
|||
|
}
|
|||
|
|
|||
|
*pstr++ = '\'';
|
|||
|
*pstr++ = ' ';
|
|||
|
*pstr = '\0';
|
|||
|
|
|||
|
if (CurrentSignature == ValidSignature)
|
|||
|
{
|
|||
|
strcat(pstr, "OK");
|
|||
|
}
|
|||
|
else if (CurrentSignature == FreedSignature)
|
|||
|
{
|
|||
|
strcat(pstr, "FREED");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
strcat(pstr, "INVALID");
|
|||
|
}
|
|||
|
|
|||
|
return Buffer;
|
|||
|
} // SignatureToString
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
ParseStateToString(
|
|||
|
IN PARSE_STATE State
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
switch (State)
|
|||
|
{
|
|||
|
case ParseVerbState:
|
|||
|
result = "ParseVerbState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseUrlState:
|
|||
|
result = "ParseUrlState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseVersionState:
|
|||
|
result = "ParseVersionState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseHeadersState:
|
|||
|
result = "ParseHeadersState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseCookState:
|
|||
|
result = "ParseCookState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseEntityBodyState:
|
|||
|
result = "ParseEntityBodyState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseTrailerState:
|
|||
|
result = "ParseTrailerState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseDoneState:
|
|||
|
result = "ParseDoneState";
|
|||
|
break;
|
|||
|
|
|||
|
case ParseErrorState:
|
|||
|
result = "ParseErrorState";
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
result = "INVALID";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
|
|||
|
} // ParseStateToString
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
UlEnabledStateToString(
|
|||
|
IN HTTP_ENABLED_STATE State
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
switch (State)
|
|||
|
{
|
|||
|
case HttpEnabledStateActive:
|
|||
|
result = "HttpEnabledStateActive";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpEnabledStateInactive:
|
|||
|
result = "HttpEnabledStateInactive";
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
result = "INVALID";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
CachePolicyToString(
|
|||
|
IN HTTP_CACHE_POLICY_TYPE PolicyType
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
switch (PolicyType)
|
|||
|
{
|
|||
|
case HttpCachePolicyNocache:
|
|||
|
result = "HttpCachePolicyNocache";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpCachePolicyUserInvalidates:
|
|||
|
result = "HttpCachePolicyUserInvalidates";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpCachePolicyTimeToLive:
|
|||
|
result = "HttpCachePolicyTimeToLive";
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
result = "INVALID";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
VerbToString(
|
|||
|
IN HTTP_VERB Verb
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
switch (Verb)
|
|||
|
{
|
|||
|
case HttpVerbUnparsed:
|
|||
|
result = "UnparsedVerb";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbGET:
|
|||
|
result = "GET";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbPUT:
|
|||
|
result = "PUT";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbHEAD:
|
|||
|
result = "HEAD";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbPOST:
|
|||
|
result = "POST";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbDELETE:
|
|||
|
result = "DELETE";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbTRACE:
|
|||
|
result = "TRACE";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbOPTIONS:
|
|||
|
result = "OPTIONS";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbCONNECT:
|
|||
|
result = "CONNECT";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbMOVE:
|
|||
|
result = "MOVE";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbCOPY:
|
|||
|
result = "COPY";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbPROPFIND:
|
|||
|
result = "PROPFIND";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbPROPPATCH:
|
|||
|
result = "PROPPATCH";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbMKCOL:
|
|||
|
result = "MKCOL";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbLOCK:
|
|||
|
result = "LOCK";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbUNLOCK:
|
|||
|
result = "LOCK";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbSEARCH:
|
|||
|
result = "SEARCH";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbUnknown:
|
|||
|
result = "UnknownVerb";
|
|||
|
break;
|
|||
|
|
|||
|
case HttpVerbInvalid:
|
|||
|
result = "InvalidVerb";
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
result = "INVALID";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
|
|||
|
} // VerbToString
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
VersionToString(
|
|||
|
IN HTTP_VERSION Version
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
if (HTTP_EQUAL_VERSION(Version, 0, 9))
|
|||
|
{
|
|||
|
result = "Version09";
|
|||
|
}
|
|||
|
else
|
|||
|
if (HTTP_EQUAL_VERSION(Version, 1, 0))
|
|||
|
{
|
|||
|
result = "Version10";
|
|||
|
}
|
|||
|
else
|
|||
|
if (HTTP_EQUAL_VERSION(Version, 1, 1))
|
|||
|
{
|
|||
|
result = "Version11";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
result = "INVALID";
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
|
|||
|
} // VersionToString
|
|||
|
|
|||
|
PSTR
|
|||
|
QueueStateToString(
|
|||
|
IN QUEUE_STATE QueueState
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR result;
|
|||
|
|
|||
|
switch (QueueState)
|
|||
|
{
|
|||
|
case QueueUnroutedState:
|
|||
|
result = "QueueUnroutedState";
|
|||
|
break;
|
|||
|
|
|||
|
case QueueDeliveredState:
|
|||
|
result = "QueueDeliveredState";
|
|||
|
break;
|
|||
|
|
|||
|
case QueueCopiedState:
|
|||
|
result = "QueueCopiedState";
|
|||
|
break;
|
|||
|
|
|||
|
case QueueUnlinkedState:
|
|||
|
result = "QueueUnlinkedState";
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
result = "INVALID";
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BuildSymbol(
|
|||
|
IN PVOID RemoteAddress,
|
|||
|
OUT PSTR Symbol
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG_PTR offset;
|
|||
|
CHAR tmpSymbol[MAX_SYMBOL_LENGTH];
|
|||
|
|
|||
|
tmpSymbol[0] = '\0';
|
|||
|
GetSymbol( RemoteAddress, tmpSymbol, &offset );
|
|||
|
|
|||
|
if (tmpSymbol[0] == '\0')
|
|||
|
{
|
|||
|
Symbol[0] = '\0';
|
|||
|
}
|
|||
|
else
|
|||
|
if (offset == 0)
|
|||
|
{
|
|||
|
strcpy( Symbol, (PCHAR)tmpSymbol );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sprintf( Symbol, "%s+0x%p", tmpSymbol, offset );
|
|||
|
}
|
|||
|
|
|||
|
} // BuildSymbol
|
|||
|
|
|||
|
PSTR
|
|||
|
GetSpinlockState(
|
|||
|
IN PUL_SPIN_LOCK SpinLock
|
|||
|
)
|
|||
|
{
|
|||
|
if (*((PULONG_PTR)SpinLock) == 0)
|
|||
|
{
|
|||
|
return "FREE";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return "ACQUIRED";
|
|||
|
}
|
|||
|
|
|||
|
} // GetSpinlockState
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
EnumLinkedList(
|
|||
|
IN PLIST_ENTRY RemoteListHead,
|
|||
|
IN PENUM_LINKED_LIST_CALLBACK Callback,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
LIST_ENTRY localListEntry;
|
|||
|
PLIST_ENTRY nextRemoteListEntry;
|
|||
|
ULONG result;
|
|||
|
|
|||
|
//
|
|||
|
// Try to read the list head.
|
|||
|
//
|
|||
|
|
|||
|
if (!ReadMemory(
|
|||
|
(ULONG_PTR)RemoteListHead,
|
|||
|
&localListEntry,
|
|||
|
sizeof(localListEntry),
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop through the entries.
|
|||
|
//
|
|||
|
|
|||
|
nextRemoteListEntry = localListEntry.Flink;
|
|||
|
|
|||
|
while (nextRemoteListEntry != RemoteListHead)
|
|||
|
{
|
|||
|
if (CheckControlC())
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!(Callback)( nextRemoteListEntry, Context ))
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!ReadMemory(
|
|||
|
(ULONG_PTR)nextRemoteListEntry,
|
|||
|
&localListEntry,
|
|||
|
sizeof(localListEntry),
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
nextRemoteListEntry = localListEntry.Flink;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // EnumLinkedList
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
EnumSList(
|
|||
|
IN PSLIST_HEADER RemoteSListHead,
|
|||
|
IN PENUM_SLIST_CALLBACK Callback,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
SLIST_HEADER localSListHead;
|
|||
|
SINGLE_LIST_ENTRY localSListEntry;
|
|||
|
PSINGLE_LIST_ENTRY nextRemoteSListEntry;
|
|||
|
ULONG result;
|
|||
|
|
|||
|
//
|
|||
|
// Try to read the list head.
|
|||
|
//
|
|||
|
|
|||
|
if (!ReadMemory(
|
|||
|
(ULONG_PTR)RemoteSListHead,
|
|||
|
&localSListHead,
|
|||
|
sizeof(localSListHead),
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop through the entries.
|
|||
|
//
|
|||
|
|
|||
|
nextRemoteSListEntry = SLIST_HEADER_NEXT(&localSListHead);
|
|||
|
|
|||
|
while (nextRemoteSListEntry != NULL)
|
|||
|
{
|
|||
|
if (CheckControlC())
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!(Callback)( nextRemoteSListEntry, Context ))
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!ReadMemory(
|
|||
|
(ULONG_PTR)nextRemoteSListEntry,
|
|||
|
&localSListEntry,
|
|||
|
sizeof(localSListEntry),
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
nextRemoteSListEntry = localSListEntry.Next;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // EnumSList
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PSTR
|
|||
|
BuildResourceState(
|
|||
|
IN PUL_ERESOURCE LocalAddress,
|
|||
|
OUT PSTR Buffer
|
|||
|
)
|
|||
|
{
|
|||
|
PERESOURCE pResource;
|
|||
|
|
|||
|
pResource = (PERESOURCE)LocalAddress;
|
|||
|
|
|||
|
if (pResource->ActiveCount == 0)
|
|||
|
{
|
|||
|
sprintf(
|
|||
|
Buffer,
|
|||
|
"UNOWNED"
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ((pResource->Flag & ResourceOwnedExclusive) != 0)
|
|||
|
{
|
|||
|
sprintf(
|
|||
|
Buffer,
|
|||
|
"OWNED EXCLUSIVE BY %p [%ld]",
|
|||
|
pResource->OwnerThreads[0].OwnerThread,
|
|||
|
pResource->OwnerThreads[0].OwnerCount
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
sprintf(
|
|||
|
Buffer,
|
|||
|
"OWNED SHARED"
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Buffer;
|
|||
|
|
|||
|
} // BuildResourceState
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
IsThisACheckedBuild(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG_PTR address;
|
|||
|
ULONG value = 0;
|
|||
|
ULONG result;
|
|||
|
BOOLEAN isChecked = FALSE;
|
|||
|
|
|||
|
address = GetExpression( "&http!g_UlCheckedBuild" );
|
|||
|
|
|||
|
if (address != 0)
|
|||
|
{
|
|||
|
if (ReadMemory(
|
|||
|
address,
|
|||
|
&value,
|
|||
|
sizeof(value),
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
isChecked = (value != 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return isChecked;
|
|||
|
|
|||
|
} // IsThisACheckedBuild
|
|||
|
|
|||
|
VOID
|
|||
|
DumpBitVector(
|
|||
|
IN PSTR Prefix1,
|
|||
|
IN PSTR Prefix2,
|
|||
|
IN ULONG Vector,
|
|||
|
IN PVECTORMAP VectorMap
|
|||
|
)
|
|||
|
{
|
|||
|
while ((Vector != 0) && (VectorMap->Vector != 0))
|
|||
|
{
|
|||
|
if (Vector & VectorMap->Vector)
|
|||
|
{
|
|||
|
dprintf(
|
|||
|
"%s%s%s\n",
|
|||
|
Prefix1,
|
|||
|
Prefix2,
|
|||
|
VectorMap->Name
|
|||
|
);
|
|||
|
|
|||
|
Vector &= ~(VectorMap->Vector);
|
|||
|
}
|
|||
|
|
|||
|
VectorMap++;
|
|||
|
}
|
|||
|
|
|||
|
if (Vector != 0)
|
|||
|
{
|
|||
|
dprintf(
|
|||
|
"%s%sExtra Bits = %08lx\n",
|
|||
|
Prefix1,
|
|||
|
Prefix2,
|
|||
|
Vector
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
} // DumpBitVector
|
|||
|
|
|||
|
VOID
|
|||
|
DumpRawData(
|
|||
|
IN PSTR Prefix,
|
|||
|
IN ULONG_PTR RemoteAddress,
|
|||
|
IN ULONG BufferLength
|
|||
|
)
|
|||
|
{
|
|||
|
PSTR lineScan;
|
|||
|
ULONG lineLength;
|
|||
|
ULONG i;
|
|||
|
ULONG result;
|
|||
|
UCHAR ch;
|
|||
|
UCHAR rawData[16];
|
|||
|
CHAR formattedData[sizeof("1234567812345678 11 22 33 44 55 66 77 88-99 aa bb cc dd ee ff 00 123456789abcdef0")];
|
|||
|
|
|||
|
while (BufferLength > 0)
|
|||
|
{
|
|||
|
lineLength = (BufferLength > 16) ? 16 : BufferLength;
|
|||
|
|
|||
|
if (!ReadMemory(
|
|||
|
RemoteAddress,
|
|||
|
rawData,
|
|||
|
lineLength,
|
|||
|
&result
|
|||
|
))
|
|||
|
{
|
|||
|
dprintf( "%sCannot read memory @ %p\n", Prefix, RemoteAddress );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
lineScan = formattedData;
|
|||
|
|
|||
|
lineScan += sprintf( lineScan, "%p ", RemoteAddress );
|
|||
|
|
|||
|
for (i = 0 ; i < 16 ; i++)
|
|||
|
{
|
|||
|
if (i < lineLength)
|
|||
|
{
|
|||
|
lineScan += sprintf(
|
|||
|
lineScan,
|
|||
|
"%02X%c",
|
|||
|
rawData[i],
|
|||
|
(i == 7)
|
|||
|
? '-'
|
|||
|
: ' '
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*lineScan++ = ' ';
|
|||
|
*lineScan++ = ' ';
|
|||
|
*lineScan++ = ' ';
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*lineScan++ = ' ';
|
|||
|
*lineScan++ = ' ';
|
|||
|
|
|||
|
for (i = 0 ; i < 16 ; i++)
|
|||
|
{
|
|||
|
if (i < lineLength)
|
|||
|
{
|
|||
|
ch = rawData[i];
|
|||
|
|
|||
|
if ((ch < ' ') || (ch > '~'))
|
|||
|
{
|
|||
|
ch = '.';
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ch = ' ';
|
|||
|
}
|
|||
|
|
|||
|
*lineScan++ = ch;
|
|||
|
}
|
|||
|
|
|||
|
*lineScan = '\0';
|
|||
|
|
|||
|
dprintf(
|
|||
|
"%s%s\n",
|
|||
|
Prefix,
|
|||
|
formattedData
|
|||
|
);
|
|||
|
|
|||
|
BufferLength -= lineLength;
|
|||
|
RemoteAddress += (ULONG_PTR)lineLength;
|
|||
|
}
|
|||
|
|
|||
|
} // DumpRawData
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
CallExtensionRoutine(
|
|||
|
IN PSTR RoutineName,
|
|||
|
IN PSTR ArgumentString
|
|||
|
)
|
|||
|
{
|
|||
|
#if _WIN64
|
|||
|
PWINDBG_EXTENSION_ROUTINE64 ExtRoutine;
|
|||
|
#else
|
|||
|
PWINDBG_EXTENSION_ROUTINE ExtRoutine;
|
|||
|
#endif
|
|||
|
|
|||
|
BOOLEAN result = FALSE;
|
|||
|
|
|||
|
#ifdef EXT_DLL
|
|||
|
if (ExtensionDll == NULL)
|
|||
|
{
|
|||
|
ExtensionDll = LoadLibraryA( EXT_DLL );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
if (ExtensionDll != NULL)
|
|||
|
{
|
|||
|
#if _WIN64
|
|||
|
ExtRoutine = (PWINDBG_EXTENSION_ROUTINE64)GetProcAddress(
|
|||
|
ExtensionDll,
|
|||
|
RoutineName
|
|||
|
);
|
|||
|
#else
|
|||
|
ExtRoutine = (PWINDBG_EXTENSION_ROUTINE)GetProcAddress(
|
|||
|
ExtensionDll,
|
|||
|
RoutineName
|
|||
|
);
|
|||
|
#endif
|
|||
|
if (ExtRoutine != NULL)
|
|||
|
{
|
|||
|
(ExtRoutine)(
|
|||
|
g_hCurrentProcess,
|
|||
|
g_hCurrentThread,
|
|||
|
g_dwCurrentPc,
|
|||
|
g_dwProcessor,
|
|||
|
ArgumentString
|
|||
|
);
|
|||
|
|
|||
|
result = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
|
|||
|
} // CallExtensionRoutine
|
|||
|
|