You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
626 lines
14 KiB
626 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
dbgutil.hxx
|
|
|
|
Abstract:
|
|
|
|
LSA Utility functions header
|
|
|
|
Author:
|
|
|
|
Larry Zhu (Lzhu) May 1, 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#ifndef _LSAUTIL_HXX_
|
|
#define _LSAUTIL_HXX_
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <align.h>
|
|
|
|
namespace LSA_NS {
|
|
|
|
enum ELsaExceptionCode {
|
|
kInvalid,
|
|
kIncorrectSymbols,
|
|
kExitOnControlC,
|
|
};
|
|
|
|
LPCTSTR
|
|
StripPathFromFileName(
|
|
IN LPCTSTR pszFile
|
|
);
|
|
|
|
ULONG
|
|
GetStructFieldVerbose(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructFieldName,
|
|
IN ULONG BufferSize,
|
|
OUT PVOID Buffer);
|
|
|
|
ULONG
|
|
GetStructPtrFieldVerbose(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructFieldName,
|
|
OUT PULONG64 Buffer);
|
|
|
|
HRESULT
|
|
GetCurrentProcessor(
|
|
IN PDEBUG_CLIENT Client,
|
|
OPTIONAL OUT PULONG pProcessor,
|
|
OPTIONAL OUT PHANDLE phCurrentThread);
|
|
|
|
PCSTR
|
|
ReadStructStrField(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructStringFieldName);
|
|
|
|
PCWSTR
|
|
ReadStructWStrField(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructWStringFieldName);
|
|
BOOL
|
|
WINAPI
|
|
LsaLookupAccountNameA(
|
|
IN LPCSTR lpSystemName,
|
|
IN LPCSTR lpAccountName,
|
|
OUT PSID Sid,
|
|
IN OUT LPDWORD cbSid,
|
|
OUT LPSTR ReferencedDomainName,
|
|
IN OUT LPDWORD cbReferencedDomainName,
|
|
OUT PSID_NAME_USE peUse
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
LsaLookupAccountSidA(
|
|
IN LPCSTR lpSystemName,
|
|
IN PSID Sid,
|
|
OUT LPSTR Name,
|
|
IN OUT LPDWORD cbName,
|
|
OUT LPSTR ReferencedDomainName,
|
|
IN OUT LPDWORD cbReferencedDomainName,
|
|
OUT PSID_NAME_USE peUse
|
|
);
|
|
|
|
void LocalPrintGuid(IN const GUID *pGuid);
|
|
|
|
BOOL IsAddressInNonePAEKernelAddressSpace(IN ULONG64 addr);
|
|
|
|
HRESULT HResultFromWin32(IN DWORD dwError);
|
|
|
|
HRESULT GetLastErrorAsHResult(void);
|
|
|
|
BOOLEAN IsEmpty(IN PCSTR pszArgs);
|
|
|
|
void debugPrintHandle(IN HANDLE handle);
|
|
|
|
NTSTATUS NtStatusFromWin32(IN DWORD dwError);
|
|
|
|
NTSTATUS GetLastErrorAsNtStatus(void);
|
|
|
|
HRESULT ProcessKnownOptions(IN PCSTR pszArgs OPTIONAL);
|
|
|
|
HRESULT ProcessHelpRequest(IN PCSTR pszArgs OPTIONAL);
|
|
|
|
LARGE_INTEGER
|
|
ULONG642LargeInteger(
|
|
IN ULONG64 value
|
|
);
|
|
|
|
VOID
|
|
ShowSystemTimeAsLocalTime(
|
|
IN PCSTR pszBanner,
|
|
IN ULONG64 ul64Time
|
|
);
|
|
|
|
void handleLsaException(
|
|
IN ELsaExceptionCode eExceptionCode,
|
|
IN PCSTR pszMsg, OPTIONAL
|
|
IN PCSTR pszSymHint OPTIONAL
|
|
);
|
|
|
|
HRESULT GetFileNamePart(IN PCSTR pszFullPath, OUT PCSTR *ppszFileName);
|
|
|
|
void debugPrintHex(IN const void* buffer, IN ULONG cbBuffer);
|
|
|
|
#define LSA_NONE 0x00
|
|
#define LSA_WARN 0x01
|
|
#define LSA_ERROR 0x02
|
|
#define LSA_LOG 0x04
|
|
#define LSA_LOG_MORE 0x08
|
|
#define LSA_LOG_ALL 0x10
|
|
|
|
inline void debugPrintLevel(IN ULONG ulLevel)
|
|
{
|
|
PCSTR pszText = NULL;
|
|
|
|
switch (ulLevel) {
|
|
case LSA_WARN:
|
|
pszText = "[warn] ";
|
|
break;
|
|
|
|
case LSA_ERROR:
|
|
pszText = "[error] ";
|
|
break;
|
|
|
|
case LSA_LOG:
|
|
pszText = "[log] ";
|
|
break;
|
|
|
|
case LSA_LOG_MORE:
|
|
pszText = "[more] ";
|
|
break;
|
|
|
|
case LSA_LOG_ALL:
|
|
pszText = "[all] ";
|
|
break;
|
|
|
|
default:
|
|
pszText = kstrInvalid;
|
|
break;
|
|
}
|
|
|
|
OutputDebugStringA(pszText);
|
|
}
|
|
|
|
inline void debugPrintf(IN PCSTR pszFmt, ...)
|
|
{
|
|
CHAR szBuffer[4096] = {0};
|
|
|
|
OutputDebugStringA(g_Globals.pszDbgPrompt ? g_Globals.pszDbgPrompt : kstrEmptyA);
|
|
|
|
va_list pArgs;
|
|
|
|
va_start(pArgs, pszFmt);
|
|
|
|
_vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFmt, pArgs);
|
|
|
|
OutputDebugStringA(szBuffer);
|
|
|
|
va_end(pArgs);
|
|
}
|
|
|
|
inline PCSTR IoctlErrorStatusToStr(IN PCSTR pszPad, IN ULONG err)
|
|
{
|
|
static CHAR szBuf[1024] = {0};
|
|
|
|
#define BRANCH_AND_PRINT(x) \
|
|
\
|
|
do { \
|
|
if (x == err) { \
|
|
_snprintf(szBuf, sizeof(szBuf) - 1, "%s%s", pszPad, #x); \
|
|
return szBuf; \
|
|
} \
|
|
} while (0)
|
|
|
|
BRANCH_AND_PRINT(MEMORY_READ_ERROR);
|
|
BRANCH_AND_PRINT(SYMBOL_TYPE_INDEX_NOT_FOUND);
|
|
BRANCH_AND_PRINT(SYMBOL_TYPE_INFO_NOT_FOUND);
|
|
BRANCH_AND_PRINT(FIELDS_DID_NOT_MATCH);
|
|
BRANCH_AND_PRINT(NULL_SYM_DUMP_PARAM);
|
|
BRANCH_AND_PRINT(NULL_FIELD_NAME);
|
|
BRANCH_AND_PRINT(INCORRECT_VERSION_INFO);
|
|
BRANCH_AND_PRINT(EXIT_ON_CONTROLC);
|
|
BRANCH_AND_PRINT(CANNOT_ALLOCATE_MEMORY);
|
|
BRANCH_AND_PRINT(INSUFFICIENT_SPACE_TO_COPY);
|
|
|
|
#undef BRANCH_AND_PRINT
|
|
|
|
_snprintf(szBuf, sizeof(szBuf) - 1, "%s%#x", pszPad, err);
|
|
|
|
return szBuf;
|
|
}
|
|
|
|
BOOL IsPtr64WithVoidStar(void);
|
|
|
|
inline ULONG64 toPtr(IN ULONG64 addr)
|
|
{
|
|
static BOOL bIsPtr64 = IsPtr64WithVoidStar();
|
|
|
|
if (!bIsPtr64) {
|
|
|
|
addr = static_cast<ULONG>(addr);
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
inline ULONG GetPtrSize(void)
|
|
{
|
|
static ULONG cbPtrSize = 0;
|
|
|
|
if (!cbPtrSize) {
|
|
|
|
cbPtrSize = IsPtr64WithVoidStar() ? sizeof(ULONG64) : sizeof(ULONG);
|
|
}
|
|
|
|
return cbPtrSize;
|
|
}
|
|
|
|
inline ULONG ReadPtrSize(void)
|
|
{
|
|
static ULONG cbPtrSize = GetPtrSize();
|
|
|
|
if (!cbPtrSize) {
|
|
|
|
throw "ReadPtrSize failed";
|
|
}
|
|
|
|
return cbPtrSize;
|
|
}
|
|
|
|
inline ULONG GetPtrWithVoidStar(IN ULONG64 Addr, IN ULONG64* pPointer)
|
|
{
|
|
return GetFieldData(Addr, kstrVoidStar, NULL, sizeof(ULONG64), (PVOID) pPointer);
|
|
}
|
|
|
|
inline PCSTR EasyStr(IN PCSTR pszName)
|
|
{
|
|
return pszName ? pszName : kstrNullPtrA;
|
|
}
|
|
|
|
inline void HandleIoctlErrors(IN PCSTR pszBanner, IN ULONG ErrorCode)
|
|
{
|
|
if (SYMBOL_TYPE_INFO_NOT_FOUND == ErrorCode) {
|
|
|
|
throw kIncorrectSymbols;
|
|
|
|
} else if (ErrorCode) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("%s: Ioctl failed with error code %s\n", EasyStr(pszBanner), EasyStr(IoctlErrorStatusToStr(kstrEmptyA, ErrorCode))));
|
|
|
|
throw "Ioctl failed";
|
|
}
|
|
}
|
|
|
|
inline ULONG64 ReadPtrWithVoidStar(IN ULONG64 Addr)
|
|
{
|
|
ULONG64 Pointer = 0;
|
|
|
|
HandleIoctlErrors("ReadPtrWithVoidStar", GetFieldData(Addr, kstrVoidStar, NULL, sizeof(ULONG64), &Pointer));
|
|
|
|
return Pointer;
|
|
}
|
|
|
|
inline ULONG64 ReadStructPtrField(IN ULONG64 addrStructBase, IN PCSTR pszStructTypeName, IN PCSTR pszStructFieldName)
|
|
{
|
|
ULONG64 addr = 0;
|
|
|
|
DBG_LOG(LSA_LOG, ("ReadStructPtrField %s %#I64x %s\n", EasyStr(pszStructTypeName), addrStructBase, EasyStr(pszStructFieldName)));
|
|
|
|
HandleIoctlErrors("ReadStructPtrField", GetStructPtrFieldVerbose(addrStructBase, pszStructTypeName, pszStructFieldName, &addr));
|
|
|
|
return toPtr(addr);
|
|
}
|
|
|
|
inline ULONG64 ForwardAdjustPtrAddr(IN ULONG64 addr)
|
|
{
|
|
static ULONG uPtrSize = ReadPtrSize();
|
|
|
|
ULONG64 alignedPtrAddr = addr;
|
|
|
|
//
|
|
// Only 64bit machines have alignment requirement
|
|
//
|
|
if (uPtrSize == sizeof(ULONG64)) {
|
|
|
|
alignedPtrAddr = ROUND_UP_COUNT(addr, sizeof(ULONG64)); // ((addr + uPtrSize - 1) / uPtrSize) * uPtrSize;
|
|
|
|
if (alignedPtrAddr != addr) {
|
|
|
|
DBG_LOG(LSA_LOG, ("ForwardAdjustPtrAddr adjusted addr from %#I64x to %#I64x\n", addr, alignedPtrAddr));
|
|
}
|
|
}
|
|
|
|
return alignedPtrAddr;
|
|
}
|
|
|
|
inline ULONG64 ReadPtrVar(IN ULONG64 addr)
|
|
{
|
|
static uPtrSize = ReadPtrSize();
|
|
|
|
ULONG64 value = 0;
|
|
ULONG errorCode = 0;
|
|
|
|
//
|
|
// Assume 64 bit machine has alignment requirement for pointers
|
|
//
|
|
|
|
if (uPtrSize == sizeof(ULONG64)) {
|
|
|
|
ULONG64 alignedAddr = addr;
|
|
|
|
alignedAddr = ForwardAdjustPtrAddr(addr);
|
|
|
|
if (alignedAddr != addr) {
|
|
|
|
DBG_LOG(LSA_WARN, ("Adjust pointer address %#I64x to 8 byte boundary %#I64x\n", addr, alignedAddr));
|
|
}
|
|
|
|
addr = alignedAddr;
|
|
}
|
|
|
|
HandleIoctlErrors("ReadPtrVar", GetPtrWithVoidStar(addr, &value));
|
|
|
|
return toPtr(value);
|
|
}
|
|
|
|
inline UCHAR ReadUCHARVar(IN ULONG64 addr)
|
|
{
|
|
UCHAR value = 0;
|
|
|
|
if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Can not ReadUCHARVar at %#I64x\n", addr));
|
|
|
|
throw "ReadUCHARVar failed";
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
inline USHORT ReadUSHORTVar(IN ULONG64 addr)
|
|
{
|
|
USHORT value = 0;
|
|
|
|
if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Can not ReadUSHORTVar at %#I64x\n", addr));
|
|
|
|
throw "ReadUSHORTVar failed";
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
inline ULONG ReadULONGVar(IN ULONG64 addr)
|
|
{
|
|
ULONG value = 0;
|
|
|
|
if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Can not ReadULONGVar at %#I64x\n", addr));
|
|
|
|
throw "ReadULONGVar failed";
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
inline ULONG64 ReadULONG64Var(IN ULONG64 addr)
|
|
{
|
|
ULONG64 value = 0;
|
|
|
|
if (!ReadMemory(addr, &value, sizeof(value), NULL)) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Can not ReadULONG64Var at %#I64x\n", addr));
|
|
|
|
throw "ReadULONG64Var failed";
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
inline ULONG ReadTypeSize(IN PCSTR pszTypeName)
|
|
{
|
|
ULONG typeSize = 0;
|
|
|
|
typeSize = GetTypeSize(pszTypeName);
|
|
|
|
DBG_LOG(LSA_LOG, ("Read type size of \"%s\"\n", EasyStr(pszTypeName)));
|
|
|
|
if (!typeSize) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Can not GetTypeSize on %s\n", EasyStr(pszTypeName)));
|
|
|
|
throw "ReadTypeSize failed\n";
|
|
}
|
|
|
|
return typeSize;
|
|
}
|
|
|
|
inline ULONG ReadFieldOffset(IN PCSTR pszTypeName, IN PCSTR pszFieldName)
|
|
{
|
|
ULONG fieldOffset = 0;
|
|
|
|
DBG_LOG(LSA_LOG, ("Read field offset of \"%s\" from \"%s\"\n", EasyStr(pszFieldName), EasyStr(pszTypeName)));
|
|
|
|
HandleIoctlErrors("ReadFieldOffset", GetFieldOffset(pszTypeName, pszFieldName, &fieldOffset));
|
|
|
|
return fieldOffset;
|
|
}
|
|
|
|
inline void ReadStructField(IN ULONG64 addrStructBase, IN PCSTR pszStructTypeName, IN PCSTR pszStructFieldName, IN ULONG fieldSize, OUT void* pFieldValue)
|
|
{
|
|
DBG_LOG(LSA_LOG, ("ReadStructField %s %#I64x %s\n", EasyStr(pszStructTypeName), addrStructBase, EasyStr(pszStructFieldName)));
|
|
|
|
HandleIoctlErrors("ReadStructField", GetStructFieldVerbose(addrStructBase, pszStructTypeName, pszStructFieldName, fieldSize, pFieldValue));
|
|
}
|
|
|
|
inline void LsaReadMemory(IN ULONG64 addr, IN ULONG cbBuffer, OUT void* buffer)
|
|
{
|
|
if (!ReadMemory(addr, buffer, cbBuffer, NULL)) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Unable to read %#x bytes from memory location %#I64x\n", cbBuffer, toPtr(addr)));
|
|
|
|
throw "LsaReadMemory failed";
|
|
}
|
|
}
|
|
|
|
//
|
|
// Used to read in value of a short (<= 8 bytes) fields
|
|
//
|
|
// This is essentially the same as GetShortField with one difference that
|
|
// it throws exceptions on failures
|
|
//
|
|
|
|
inline ULONG64 ReadShortField(IN ULONG64 TypeAddress, IN PCSTR pszName, IN USHORT StoreAddress)
|
|
{
|
|
static ULONG64 SavedAddress = 0;
|
|
static PCSTR pszSavedName = NULL;
|
|
static ULONG ReadPhysical = 0;
|
|
|
|
ULONG Err = 0;
|
|
|
|
FIELD_INFO flds = {reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszName)), NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL};
|
|
SYM_DUMP_PARAM Sym = {
|
|
sizeof (SYM_DUMP_PARAM), reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszSavedName)), DBG_DUMP_NO_PRINT | ((StoreAddress & 2) ? DBG_DUMP_READ_PHYSICAL : 0),
|
|
SavedAddress, NULL, NULL, NULL, 1, &flds
|
|
};
|
|
|
|
if (StoreAddress) {
|
|
|
|
Sym.sName = reinterpret_cast<UCHAR*>(const_cast<PSTR>(pszName));
|
|
Sym.nFields = 0;
|
|
pszSavedName = pszName;
|
|
Sym.addr = SavedAddress = TypeAddress;
|
|
ReadPhysical = (StoreAddress & 2);
|
|
|
|
if (!SavedAddress) {
|
|
|
|
throw "Invalid arguments to ReadShortField";
|
|
}
|
|
|
|
Err = Ioctl(IG_DUMP_SYMBOL_INFO, &Sym, Sym.size);
|
|
|
|
DBG_LOG(LSA_LOG, ("Save address %s %#I64x\n", EasyStr(pszName), TypeAddress));
|
|
|
|
HandleIoctlErrors("ReadShortField (save address) failed", Err);
|
|
|
|
return 0; // zero on success
|
|
|
|
} else {
|
|
|
|
Sym.Options |= ReadPhysical ? DBG_DUMP_READ_PHYSICAL : 0;
|
|
}
|
|
|
|
Err = Ioctl(IG_DUMP_SYMBOL_INFO, &Sym, Sym.size);
|
|
|
|
DBG_LOG(LSA_LOG, ("Read %s %#I64x %s\n", EasyStr(pszSavedName), SavedAddress, EasyStr(pszName)));
|
|
|
|
HandleIoctlErrors("ReadShortField (read value) failed", Err);
|
|
|
|
return flds.address;
|
|
}
|
|
|
|
inline ULONG ReadTypeSizeInArray(IN PCSTR pszType)
|
|
{
|
|
ULONG cbOneItem = 0;
|
|
ULONG cbTwoItems = 0;
|
|
CHAR szTypeTmp[256] = {0};
|
|
|
|
DBG_LOG(LSA_LOG, ("ReadTypeSizeInArray %s\n", pszType));
|
|
|
|
cbOneItem = GetTypeSize(pszType);
|
|
|
|
if (_snprintf(szTypeTmp, sizeof(szTypeTmp) - 1, "%s[2]", pszType) < 0) {
|
|
|
|
throw "ReadTypeSizeInArray failed with insufficient buffer";
|
|
}
|
|
|
|
cbTwoItems = GetTypeSize(szTypeTmp);
|
|
cbOneItem = cbTwoItems - cbOneItem;
|
|
|
|
if (!cbOneItem) {
|
|
|
|
dprintf("Unable to read type size in array for %s\n", pszType);
|
|
throw "ReadTypeSizeInArray failed";
|
|
}
|
|
|
|
return cbOneItem;
|
|
}
|
|
|
|
inline ULONG64 ReadPtrField(IN PCSTR Field)
|
|
{
|
|
return toPtr(ReadShortField(0, Field, 0));
|
|
}
|
|
|
|
inline void ExitIfControlC(void)
|
|
{
|
|
if (CheckControlC()) {
|
|
|
|
throw kExitOnControlC;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This func is not thread safe
|
|
//
|
|
|
|
inline PCSTR PtrToStr(IN ULONG64 addr)
|
|
{
|
|
static CHAR szBuffer[64] = {0};
|
|
|
|
if (!addr) {
|
|
|
|
return kstrNullPtrA;
|
|
}
|
|
|
|
_snprintf(szBuffer, sizeof(szBuffer) - 1, "%#I64x", addr);
|
|
|
|
return szBuffer;
|
|
}
|
|
|
|
//
|
|
// This func is not thread safe because it calls PtrToStr which is not
|
|
// thread safe
|
|
//
|
|
|
|
inline PCSTR GetSymbolStr(IN ULONG64 addr, IN PCSTR pszBuffer)
|
|
{
|
|
ExitIfControlC();
|
|
|
|
//
|
|
// null
|
|
//
|
|
if (!addr) {
|
|
|
|
return kstrNullPtrA;
|
|
}
|
|
|
|
//
|
|
// No symbols resolved, return address
|
|
//
|
|
if (!pszBuffer || !*pszBuffer) {
|
|
|
|
return PtrToStr(addr);
|
|
}
|
|
|
|
//
|
|
// Return symbols
|
|
//
|
|
return pszBuffer;
|
|
}
|
|
|
|
inline void PrintPtrWithSymbolsLn(IN PCSTR pszBanner, IN ULONG64 addr)
|
|
{
|
|
CHAR szBuffer[MAX_PATH] = {0};
|
|
ULONG64 Disp = 0;
|
|
|
|
GetSymbol(addr, szBuffer, &Disp);
|
|
dprintf(kstr2StrLn, pszBanner, GetSymbolStr(addr, szBuffer));
|
|
}
|
|
|
|
inline void PrintSpaces(IN LONG cSpaces)
|
|
{
|
|
for (LONG i = 0; i < cSpaces; i++) {
|
|
|
|
dprintf(kstrSpace);
|
|
}
|
|
}
|
|
|
|
} // LSA_NS
|
|
|
|
#endif
|