/*++ 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(addr) < 0; } else { return static_cast(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(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(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