windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/ul/ulkd/dbgutil.c

863 lines
15 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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