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.
671 lines
14 KiB
671 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
lsautil.cxx
|
|
|
|
Abstract:
|
|
|
|
Lsa Utility functions
|
|
|
|
Author:
|
|
|
|
Larry Zhu (Lzhu) May 1, 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
namespace LSA_NS {
|
|
|
|
/*++
|
|
|
|
Title:
|
|
|
|
StripPathFromFileName
|
|
|
|
Routine Description:
|
|
|
|
Function used stip the path component from a fully
|
|
qualified file name.
|
|
|
|
Arguments:
|
|
|
|
pszFile - pointer to full file name.
|
|
|
|
Return Value:
|
|
|
|
Pointer to start of file name in path.
|
|
|
|
--*/
|
|
LPCTSTR
|
|
StripPathFromFileName(
|
|
IN LPCTSTR pszFile
|
|
)
|
|
{
|
|
LPCTSTR pszFileName;
|
|
|
|
if (pszFile)
|
|
{
|
|
pszFileName = _tcsrchr( pszFile, _T('\\') );
|
|
|
|
if (pszFileName)
|
|
{
|
|
pszFileName++;
|
|
}
|
|
else
|
|
{
|
|
pszFileName = pszFile;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszFileName = kstrEmpty;
|
|
}
|
|
|
|
return pszFileName;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
ULONG
|
|
GetStructFieldVerbose(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructFieldName,
|
|
IN ULONG BufferSize,
|
|
OUT PVOID Buffer)
|
|
{
|
|
ULONG FieldOffset;
|
|
ULONG ErrorCode;
|
|
BOOL Success;
|
|
|
|
Success = FALSE;
|
|
|
|
//
|
|
// Get the field offset
|
|
//
|
|
ErrorCode = GetFieldOffset(pszStructTypeName, pszStructFieldName, &FieldOffset );
|
|
|
|
if (ErrorCode == NO_ERROR) {
|
|
|
|
//
|
|
// Read the data
|
|
//
|
|
Success = ReadMemory(addrStructBase + FieldOffset, Buffer, BufferSize, NULL);
|
|
|
|
if (Success != TRUE) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Cannot read structure field value at 0x%p, error %u\n", addrStructBase + FieldOffset, ErrorCode));
|
|
|
|
return MEMORY_READ_ERROR;
|
|
}
|
|
} else {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Cannot get field offset of %s in %s, error %u\n", EasyStr(pszStructFieldName), EasyStr(pszStructTypeName), ErrorCode));
|
|
|
|
return ErrorCode;
|
|
}
|
|
|
|
return 0; // 0 on success
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
ULONG
|
|
GetStructPtrFieldVerbose(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructFieldName,
|
|
IN PULONG64 Buffer)
|
|
{
|
|
ULONG FieldOffset = 0;
|
|
ULONG ErrorCode = 0;
|
|
|
|
//
|
|
// Get the field offset inside the structure
|
|
//
|
|
ErrorCode = GetFieldOffset(pszStructTypeName, pszStructFieldName, &FieldOffset);
|
|
|
|
if (ErrorCode == NO_ERROR) {
|
|
|
|
//
|
|
// Read the data
|
|
//
|
|
|
|
ErrorCode = GetPtrWithVoidStar(addrStructBase + FieldOffset, Buffer);
|
|
|
|
if (ErrorCode != S_OK) {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Cannot read structure field value at 0x%p, error %u\n", addrStructBase + FieldOffset, ErrorCode));
|
|
}
|
|
} else {
|
|
|
|
DBG_LOG(LSA_ERROR, ("Cannot get field offset of %s in structure %s, error %u\n", EasyStr(pszStructFieldName), EasyStr(pszStructTypeName), ErrorCode));
|
|
}
|
|
|
|
return ErrorCode;
|
|
}
|
|
|
|
//
|
|
// This function is stolen from !process
|
|
//
|
|
|
|
HRESULT
|
|
GetCurrentProcessor(
|
|
IN PDEBUG_CLIENT Client,
|
|
OPTIONAL OUT PULONG pProcessor,
|
|
OPTIONAL OUT PHANDLE phCurrentThread
|
|
)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
PDEBUG_SYSTEM_OBJECTS DebugSystem;
|
|
ULONG64 hCurrentThread;
|
|
|
|
if (phCurrentThread != NULL) *phCurrentThread = NULL;
|
|
if (pProcessor != NULL) *pProcessor = 0;
|
|
|
|
if (Client == NULL ||
|
|
(hr = Client->QueryInterface(__uuidof(IDebugSystemObjects),
|
|
(void **)&DebugSystem)) != S_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = DebugSystem->GetCurrentThreadHandle(&hCurrentThread);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
if (phCurrentThread != NULL)
|
|
{
|
|
*phCurrentThread = (HANDLE) hCurrentThread;
|
|
}
|
|
|
|
if (pProcessor != NULL)
|
|
{
|
|
*pProcessor = (ULONG) hCurrentThread - 1;
|
|
}
|
|
}
|
|
|
|
DebugSystem->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
void LocalPrintGuid(IN const GUID *pGuid)
|
|
{
|
|
UNICODE_STRING GuidString = {0};
|
|
|
|
NTSTATUS Status;
|
|
|
|
if (pGuid) {
|
|
|
|
Status = RtlStringFromGUID(*pGuid, &GuidString);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
dprintf("%wZ", &GuidString);
|
|
}
|
|
else
|
|
{
|
|
dprintf( "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
|
pGuid->Data1, pGuid->Data2, pGuid->Data3, pGuid->Data4[0],
|
|
pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], pGuid->Data4[4],
|
|
pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7] );
|
|
}
|
|
}
|
|
|
|
if (GuidString.Buffer)
|
|
{
|
|
RtlFreeUnicodeString(&GuidString);
|
|
}
|
|
}
|
|
|
|
BOOL IsAddressInNonePAEKernelAddressSpace(IN ULONG64 addr)
|
|
{
|
|
static BOOL bIsPtr64 = IsPtr64WithVoidStar();
|
|
|
|
if (!bIsPtr64) {
|
|
|
|
return static_cast<LONG>(addr) < 0;
|
|
|
|
} else {
|
|
|
|
return static_cast<LONG64>(addr) < 0;
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
HResultFromWin32
|
|
|
|
Routine Description:
|
|
|
|
Returns the last error as an HRESULT assuming a failure.
|
|
|
|
Arguments:
|
|
|
|
dwError - Win32 error code
|
|
|
|
Return Value:
|
|
|
|
An HRESULT
|
|
|
|
--*/
|
|
HRESULT HResultFromWin32(IN DWORD dwError)
|
|
{
|
|
return HRESULT_FROM_WIN32(dwError);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
GetLastErrorAsHResult
|
|
|
|
Routine Description:
|
|
|
|
Returns the last error as an HRESULT assuming a failure.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
An HRESULT.
|
|
|
|
--*/
|
|
HRESULT GetLastErrorAsHResult(void)
|
|
{
|
|
return HResultFromWin32(GetLastError());
|
|
}
|
|
|
|
NTSTATUS NtStatusFromWin32(IN DWORD dwError)
|
|
{
|
|
return (STATUS_SEVERITY_ERROR << 30) | (FACILITY_DEBUGGER << 16) | dwError;
|
|
}
|
|
|
|
NTSTATUS GetLastErrorAsNtStatus(void)
|
|
{
|
|
return NtStatusFromWin32(GetLastError());
|
|
}
|
|
|
|
BOOLEAN IsEmpty(IN PCSTR pszArgs)
|
|
{
|
|
if (!pszArgs) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
for (; *pszArgs; pszArgs++) {
|
|
|
|
if (!isspace(*pszArgs)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void debugPrintHandle(IN HANDLE handle)
|
|
{
|
|
ULONG64 addrHandle = reinterpret_cast<ULONG_PTR>(handle);
|
|
|
|
dprintf("%s", PtrToStr(addrHandle));
|
|
}
|
|
|
|
void PrintMessages(
|
|
IN PCSTR pszMsg, OPTIONAL
|
|
IN PCSTR pszSymHint OPTIONAL
|
|
)
|
|
{
|
|
if (pszMsg || pszSymHint) {
|
|
|
|
dprintf(kstrNewLine);
|
|
}
|
|
|
|
if (pszMsg) {
|
|
|
|
dprintf(kstrStrLn, pszMsg);
|
|
}
|
|
|
|
if (pszSymHint) {
|
|
|
|
dprintf(kstrCheckSym, pszSymHint);
|
|
}
|
|
}
|
|
|
|
void handleLsaException(
|
|
IN ELsaExceptionCode eExceptionCode,
|
|
IN PCSTR pszMsg, OPTIONAL
|
|
IN PCSTR pszSymHint OPTIONAL
|
|
)
|
|
{
|
|
switch (eExceptionCode) {
|
|
case kIncorrectSymbols:
|
|
DBG_LOG(LSA_ERROR, ("\n%s", kstrIncorrectSymbols));
|
|
PrintMessages(pszMsg, pszSymHint);
|
|
break;
|
|
|
|
case kExitOnControlC:
|
|
DBG_LOG(LSA_LOG, (kstrStrLn, kstrExitOnControlC));
|
|
dprintf(kstrNewLine);
|
|
dprintf(kstrStrLn, kstrExitOnControlC);
|
|
break;
|
|
|
|
case kInvalid:
|
|
default:
|
|
DBG_LOG(LSA_ERROR, ("Invalid LSA exception code\n"));
|
|
PrintMessages(pszMsg, pszSymHint);
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL IsPtr64WithVoidStar(void)
|
|
{
|
|
static ULONG cbPtrSize = GetTypeSize(kstrVoidStar);
|
|
|
|
return sizeof(ULONG64) == cbPtrSize;
|
|
}
|
|
|
|
PCSTR
|
|
ReadStructStrField(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructStringFieldName)
|
|
{
|
|
ULONG fieldOffset = 0;
|
|
|
|
fieldOffset = ReadFieldOffset(pszStructTypeName, pszStructStringFieldName);
|
|
|
|
return TSTRING(addrStructBase + fieldOffset).toStrDirect();
|
|
}
|
|
|
|
PCWSTR
|
|
ReadStructWStrField(
|
|
IN ULONG64 addrStructBase,
|
|
IN PCSTR pszStructTypeName,
|
|
IN PCSTR pszStructWStringFieldName)
|
|
{
|
|
ULONG fieldOffset = 0;
|
|
|
|
fieldOffset = ReadFieldOffset(pszStructTypeName, pszStructWStringFieldName);
|
|
|
|
return TSTRING(addrStructBase + fieldOffset).toWStrDirect();
|
|
}
|
|
|
|
HRESULT ProcessKnownOptions(IN PCSTR pszArgs OPTIONAL)
|
|
{
|
|
HRESULT hRetval = S_OK;
|
|
|
|
for (; SUCCEEDED(hRetval) && (pszArgs && *pszArgs); pszArgs++) {
|
|
|
|
if (*pszArgs == '-' || *pszArgs == '/') {
|
|
|
|
switch (*++pszArgs) {
|
|
case '?':
|
|
hRetval = E_INVALIDARG;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
HRESULT ProcessHelpRequest(IN PCSTR pszArgs OPTIONAL)
|
|
{
|
|
HRESULT hRetval = S_OK;
|
|
|
|
for (; SUCCEEDED(hRetval) && (pszArgs && *pszArgs); pszArgs++) {
|
|
|
|
if (*pszArgs == '-' || *pszArgs == '/') {
|
|
|
|
switch (*++pszArgs) {
|
|
case '?':
|
|
hRetval = E_INVALIDARG;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
|
|
HRESULT GetFileNamePart(IN PCSTR pszFullPath, OUT PCSTR *ppszFileName)
|
|
{
|
|
HRESULT hRetval = E_FAIL;
|
|
CHAR szfname[_MAX_FNAME] = {0};
|
|
|
|
hRetval = pszFullPath && ppszFileName ? S_OK : E_INVALIDARG;
|
|
|
|
if (SUCCEEDED(hRetval)) {
|
|
|
|
_splitpath(pszFullPath, NULL, NULL, szfname, NULL);
|
|
*ppszFileName = strstr(pszFullPath, szfname);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
|
|
CHAR toChar(IN CHAR c)
|
|
{
|
|
if (isprint(c)) {
|
|
|
|
return c;
|
|
}
|
|
|
|
return '.';
|
|
}
|
|
|
|
void spaceIt(IN CHAR* buf, IN ULONG len)
|
|
{
|
|
memset(buf, ' ', len);
|
|
}
|
|
|
|
CHAR toHex(IN ULONG c)
|
|
{
|
|
static PCSTR pszDigits = "0123456789abcdef";
|
|
static ULONG len = strlen(pszDigits);
|
|
|
|
if (c <= len) { // c >= 0
|
|
return pszDigits[c];
|
|
}
|
|
|
|
return '*';
|
|
}
|
|
|
|
void debugPrintHex(IN const void* buffer, IN ULONG cbBuffer)
|
|
{
|
|
const UCHAR* p = reinterpret_cast<const UCHAR*>(buffer);
|
|
CHAR tmp[16] = {0};
|
|
ULONG high = 0;
|
|
ULONG low = 0;
|
|
CHAR line[256] = {0};
|
|
ULONG i = 0;
|
|
|
|
if (!cbBuffer) return;
|
|
|
|
spaceIt(line, 72);
|
|
|
|
for (i = 0; i < cbBuffer; i++) {
|
|
high = p[i] / 16;
|
|
low = p[i] % 16;
|
|
|
|
line[3 * (i % 16)] = toHex(high);
|
|
line[3 * (i % 16) + 1] = toHex(low);
|
|
line [52 + (i % 16)] = toChar(p[i]);
|
|
|
|
if (i % 16 == 7 && i != (cbBuffer - 1)) {
|
|
line[3 * (i % 16) + 2] = '-';
|
|
}
|
|
|
|
if (i % 16 == 15) {
|
|
|
|
dprintf(" %s\n", line);
|
|
spaceIt(line, 72);
|
|
}
|
|
}
|
|
|
|
dprintf(" %s\n", line);
|
|
}
|
|
|
|
typedef
|
|
BOOL
|
|
(* PFuncLookupAccountNameA)(
|
|
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
|
|
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
|
|
)
|
|
{
|
|
PFuncLookupAccountNameA pFuncLookupAccountNameA = NULL;
|
|
BOOL bRetval = FALSE;
|
|
|
|
HMODULE hLib = LoadLibrary("advapi32.dll");
|
|
|
|
if (hLib)
|
|
{
|
|
pFuncLookupAccountNameA = (PFuncLookupAccountNameA) GetProcAddress(hLib, "LookupAccountNameA");
|
|
|
|
if (pFuncLookupAccountNameA)
|
|
{
|
|
bRetval = pFuncLookupAccountNameA(lpSystemName, lpAccountName, Sid, cbSid, ReferencedDomainName, cbReferencedDomainName, peUse);
|
|
}
|
|
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
return bRetval;
|
|
}
|
|
|
|
typedef
|
|
BOOL
|
|
(* PFuncLookupAccountSidA)(
|
|
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
|
|
);
|
|
|
|
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
|
|
)
|
|
{
|
|
PFuncLookupAccountSidA pFuncLookupAccountSidA = NULL;
|
|
BOOL bRetval = FALSE;
|
|
|
|
HMODULE hLib = LoadLibrary("advapi32.dll");
|
|
|
|
if (hLib)
|
|
{
|
|
pFuncLookupAccountSidA = (PFuncLookupAccountSidA) GetProcAddress(hLib, "LookupAccountSidA");
|
|
|
|
if (pFuncLookupAccountSidA)
|
|
{
|
|
bRetval = pFuncLookupAccountSidA(lpSystemName, Sid, Name, cbName, ReferencedDomainName, cbReferencedDomainName, peUse);
|
|
}
|
|
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
return bRetval;
|
|
|
|
}
|
|
|
|
LARGE_INTEGER ULONG642LargeInteger(IN ULONG64 value)
|
|
{
|
|
LARGE_INTEGER tmp = {0};
|
|
|
|
C_ASSERT(sizeof(ULONG64) == sizeof(LARGE_INTEGER));
|
|
|
|
memcpy(&tmp, &value, sizeof(LARGE_INTEGER));
|
|
|
|
return tmp;
|
|
}
|
|
|
|
VOID
|
|
ShowSystemTimeAsLocalTime(
|
|
IN PCSTR pszBanner,
|
|
IN ULONG64 ul64Time
|
|
)
|
|
{
|
|
LARGE_INTEGER Time = ULONG642LargeInteger(ul64Time);
|
|
LARGE_INTEGER LocalTime = {0};
|
|
TIME_FIELDS TimeFields = {0};
|
|
|
|
NTSTATUS Status = RtlSystemTimeToLocalTime(&Time, &LocalTime);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
dprintf("Can't convert file time from GMT to Local time: 0x%lx\n", Status);
|
|
}
|
|
else
|
|
{
|
|
RtlTimeToTimeFields(&LocalTime, &TimeFields);
|
|
|
|
if (pszBanner) {
|
|
|
|
dprintf("%s %ld/%ld/%ld %ld:%2.2ld:%2.2ld (L%8.8lx H%8.8lx)\n",
|
|
pszBanner,
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Time.LowPart,
|
|
Time.HighPart);
|
|
} else {
|
|
dprintf("%ld/%ld/%ld %ld:%2.2ld:%2.2ld (L%8.8lx H%8.8lx)\n",
|
|
TimeFields.Month,
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second,
|
|
Time.LowPart,
|
|
Time.HighPart);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // LSA_NS
|