diff --git a/CHANGELOG.md b/CHANGELOG.md index 09481406..2991903a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [1.4.1] - 2022-03-26 + +### Fixed +- fixed singleapp not working +- the xprocesshacker.sys driver is now signed with a new certificate and shoudl load on win 11 + +### Changed +- updated PHlib to version 3.0.4706 + ## [1.4.0] - 2021-10-05 diff --git a/ProcessHacker/XProcessHacker/KProcessHacker.vcxproj b/ProcessHacker/XProcessHacker/KProcessHacker.vcxproj index b12aa9c1..1fbf0f1d 100644 --- a/ProcessHacker/XProcessHacker/KProcessHacker.vcxproj +++ b/ProcessHacker/XProcessHacker/KProcessHacker.vcxproj @@ -28,7 +28,7 @@ KProcessHacker $(VCTargetsPath11) - 10.0.17763.0 + 10.0.19041.0 WindowsKernelModeDriver10.0 @@ -41,24 +41,28 @@ true Unicode false + false Windows7 false Unicode false + false Windows7 true Unicode false + false Windows7 false Unicode false + false diff --git a/ProcessHacker/XProcessHacker/resource.rc b/ProcessHacker/XProcessHacker/resource.rc index ca42f86d..f0478b24 100644 --- a/ProcessHacker/XProcessHacker/resource.rc +++ b/ProcessHacker/XProcessHacker/resource.rc @@ -18,10 +18,10 @@ #define VER_PRERELEASE 0 #define VER_COMPANYNAME_STR "wj32\0" -#define VER_FILEDESCRIPTION_STR "KProcessHacker\0" +#define VER_FILEDESCRIPTION_STR "XProcessHacker\0" #define VER_LEGALCOPYRIGHT_STR "Licensed under the GNU GPL, v3.\0" -#define VER_ORIGINALFILENAME_STR "kprocesshacker.sys\0" -#define VER_PRODUCTNAME_STR "KProcessHacker\0" +#define VER_ORIGINALFILENAME_STR "xprocesshacker.sys\0" +#define VER_PRODUCTNAME_STR "XProcessHacker\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION diff --git a/ProcessHacker/phlib/apiimport.c b/ProcessHacker/phlib/apiimport.c index 05e29793..9d722445 100644 --- a/ProcessHacker/phlib/apiimport.c +++ b/ProcessHacker/phlib/apiimport.c @@ -41,7 +41,7 @@ PVOID PhpImportProcedure( module = PhGetLoaderEntryDllBase(ModuleName); if (!module) - module = PhLoadLibrarySafe(ModuleName); + module = PhLoadLibrary(ModuleName); if (module) { @@ -79,6 +79,8 @@ PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryDefaultLocale); PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryDefaultUILanguage); PH_DEFINE_IMPORT(L"ntdll.dll", NtTraceControl); PH_DEFINE_IMPORT(L"ntdll.dll", NtQueryOpenSubKeysEx); +PH_DEFINE_IMPORT(L"ntdll.dll", NtCreateProcessStateChange); +PH_DEFINE_IMPORT(L"ntdll.dll", NtChangeProcessState); PH_DEFINE_IMPORT(L"ntdll.dll", RtlDefaultNpAcl); PH_DEFINE_IMPORT(L"ntdll.dll", RtlGetTokenNamedObjectPath); diff --git a/ProcessHacker/phlib/appresolver.c b/ProcessHacker/phlib/appresolver.c index cd88f42b..57bd8093 100644 --- a/ProcessHacker/phlib/appresolver.c +++ b/ProcessHacker/phlib/appresolver.c @@ -99,7 +99,7 @@ static BOOLEAN PhpKernelAppCoreInitialized( { PVOID kernelBaseModuleHandle; - if (kernelBaseModuleHandle = PhLoadLibrarySafe(L"kernelbase.dll")) // kernel.appcore.dll + if (kernelBaseModuleHandle = PhLoadLibrary(L"kernelbase.dll")) // kernel.appcore.dll { AppContainerDeriveSidFromMoniker_I = PhGetDllBaseProcedureAddress(kernelBaseModuleHandle, "AppContainerDeriveSidFromMoniker", 0); AppContainerLookupMoniker_I = PhGetDllBaseProcedureAddress(kernelBaseModuleHandle, "AppContainerLookupMoniker", 0); @@ -897,6 +897,90 @@ HRESULT PhAppResolverEndCrashDumpTask( return status; } +HRESULT PhAppResolverGetEdpContextForWindow( + _In_ HWND WindowHandle, + _Out_ EDP_CONTEXT_STATES* State + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + HRESULT status; + PEDP_CONTEXT context; + + if (PhBeginInitOnce(&initOnce)) + { + if (WindowsVersion >= WINDOWS_10) + { + PVOID edputilModuleHandle; + + if (edputilModuleHandle = PhLoadLibrary(L"edputil.dll")) + { + EdpGetContextForWindow_I = PhGetDllBaseProcedureAddress(edputilModuleHandle, "EdpGetContextForWindow", 0); + EdpFreeContext_I = PhGetDllBaseProcedureAddress(edputilModuleHandle, "EdpFreeContext", 0); + } + } + + PhEndInitOnce(&initOnce); + } + + if (!(EdpGetContextForWindow_I && EdpFreeContext_I)) + return E_FAIL; + + status = EdpGetContextForWindow_I( + WindowHandle, + &context + ); + + if (SUCCEEDED(status)) + { + *State = context->contextStates; + EdpFreeContext_I(context); + } + + return status; +} + +HRESULT PhAppResolverGetEdpContextForProcess( + _In_ HANDLE ProcessId, + _Out_ EDP_CONTEXT_STATES* State + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + HRESULT status; + PEDP_CONTEXT context; + + if (PhBeginInitOnce(&initOnce)) + { + if (WindowsVersion >= WINDOWS_10) + { + PVOID edputilModuleHandle; + + if (edputilModuleHandle = PhLoadLibrary(L"edputil.dll")) + { + EdpGetContextForProcess_I = PhGetDllBaseProcedureAddress(edputilModuleHandle, "EdpGetContextForProcess", 0); + EdpFreeContext_I = PhGetDllBaseProcedureAddress(edputilModuleHandle, "EdpFreeContext", 0); + } + } + + PhEndInitOnce(&initOnce); + } + + if (!(EdpGetContextForWindow_I && EdpFreeContext_I)) + return E_FAIL; + + status = EdpGetContextForProcess_I( + HandleToUlong(ProcessId), + &context + ); + + if (SUCCEEDED(status)) + { + *State = context->contextStates; + EdpFreeContext_I(context); + } + + return status; +} + // TODO: FIXME //HICON PhAppResolverGetPackageIcon( // _In_ HANDLE ProcessId, diff --git a/ProcessHacker/phlib/basesup.c b/ProcessHacker/phlib/basesup.c index 9b60c08a..3ea7923c 100644 --- a/ProcessHacker/phlib/basesup.c +++ b/ProcessHacker/phlib/basesup.c @@ -73,12 +73,7 @@ #define PH_VECTOR_LEVEL_SSE2 1 #define PH_VECTOR_LEVEL_AVX 2 -#if (_MSC_VER < 1920 || DEBUG) -// Newer versions of the CRT support AVX/SSE vectorization for string routines -// but keep using our vectorization for debug builds since optimizations are -// disabled for the debug CRT and slower than our routines in this case. (dmex) -#define PH_LEGACY_CRT_SUPPORT 1 -#endif +#define PH_NATIVE_STRING_CONVERSION 1 typedef struct _PHP_BASE_THREAD_CONTEXT { @@ -150,7 +145,10 @@ BOOLEAN PhBaseInitialization( // NOTE: This is unused for now. /*if (USER_SHARED_DATA->XState.EnabledFeatures & XSTATE_MASK_AVX) PhpVectorLevel = PH_VECTOR_LEVEL_AVX; - else*/ if (USER_SHARED_DATA->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE]) + else if (USER_SHARED_DATA->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE]) + PhpVectorLevel = PH_VECTOR_LEVEL_SSE2;*/ + + if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) PhpVectorLevel = PH_VECTOR_LEVEL_SSE2; PhStringType = PhCreateObjectType(L"String", 0, NULL); @@ -226,6 +224,64 @@ NTSTATUS PhpBaseThreadStart( return status; } +// rev from RtlCreateUserThread (dmex) +NTSTATUS PhCreateUserThread( + _Out_opt_ PHANDLE ThreadHandle, + _In_ HANDLE ProcessHandle, + _In_ ULONG CreateFlags, + _In_opt_ SIZE_T StackSize, + _In_ PUSER_THREAD_START_ROUTINE StartAddress, + _In_opt_ PVOID Parameter + ) +{ + NTSTATUS status; + HANDLE threadHandle; + OBJECT_ATTRIBUTES objectAttributes; + UCHAR buffer[FIELD_OFFSET(PS_ATTRIBUTE_LIST, Attributes) + sizeof(PS_ATTRIBUTE[2])] = { 0 }; + PPS_ATTRIBUTE_LIST attributeList = (PPS_ATTRIBUTE_LIST)buffer; + CLIENT_ID clientId = { 0 }; + PTEB teb = NULL; + + InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL); + attributeList->TotalLength = sizeof(buffer); + attributeList->Attributes[0].Attribute = PS_ATTRIBUTE_CLIENT_ID; + attributeList->Attributes[0].Size = sizeof(CLIENT_ID); + attributeList->Attributes[0].ValuePtr = &clientId; + attributeList->Attributes[0].ReturnLength = NULL; + attributeList->Attributes[1].Attribute = PS_ATTRIBUTE_TEB_ADDRESS; + attributeList->Attributes[1].Size = sizeof(PTEB); + attributeList->Attributes[1].ValuePtr = &teb; + attributeList->Attributes[1].ReturnLength = NULL; + + status = NtCreateThreadEx( + &threadHandle, + THREAD_ALL_ACCESS, + &objectAttributes, + ProcessHandle, + StartAddress, + Parameter, + CreateFlags, + 0, + StackSize, + StackSize, + 0 // attributeList + ); + + if (NT_SUCCESS(status)) + { + if (ThreadHandle) + { + *ThreadHandle = threadHandle; + } + else if (threadHandle) + { + NtClose(threadHandle); + } + } + + return status; +} + /** * Creates a thread. * @@ -612,7 +668,7 @@ SIZE_T PhCountStringZ( _In_ PWSTR String ) { -#if (PH_LEGACY_CRT_SUPPORT && !defined(_ARM64_)) +#ifndef _ARM64_ if (PhpVectorLevel >= PH_VECTOR_LEVEL_SSE2) { PWSTR p; @@ -1433,7 +1489,7 @@ ULONG_PTR PhFindCharInStringRef( if (!IgnoreCase) { -#if (PH_LEGACY_CRT_SUPPORT && !defined(_ARM64_)) +#ifndef _ARM64_ if (PhpVectorLevel >= PH_VECTOR_LEVEL_SSE2) { SIZE_T length16; @@ -1526,7 +1582,7 @@ ULONG_PTR PhFindLastCharInStringRef( if (!IgnoreCase) { -#if (PH_LEGACY_CRT_SUPPORT && !defined(_ARM64_)) +#ifndef _ARM64_ if (PhpVectorLevel >= PH_VECTOR_LEVEL_SSE2) { SIZE_T length16; @@ -5234,6 +5290,79 @@ ULONG PhHashStringRef( return hash; } +ULONG PhHashStringRefEx( + _In_ PPH_STRINGREF String, + _In_ BOOLEAN IgnoreCase, + _In_ PH_STRING_HASH HashAlgorithm + ) +{ + switch (HashAlgorithm) + { + case PH_STRING_HASH_DEFAULT: + case PH_STRING_HASH_FNV1A: + return PhHashStringRef(String, IgnoreCase); + case PH_STRING_HASH_X65599: + { + ULONG hash = 0; + PWCHAR end; + PWCHAR p; + + if (String->Length == 0) + return 0; + + end = String->Buffer + (String->Length / sizeof(WCHAR)); + + if (IgnoreCase) + { + // This is the fastest implementation (copied from ReactOS) (dmex) + for (p = String->Buffer; p != end; p++) + { + hash = ((65599 * (hash)) + (ULONG)(((*p) >= L'a' && (*p) <= L'z') ? (*p) - L'a' + L'A' : (*p))); + } + + // Medium fast + //UNICODE_STRING unicodeString; + // + //if (!PhStringRefToUnicodeString(String, &unicodeString)) + // return 0; + // + //if (!NT_SUCCESS(RtlHashUnicodeString(&unicodeString, TRUE, HASH_STRING_ALGORITHM_X65599, &hash))) + // return 0; + // + // Slower than the above two (based on PhHashBytes) (dmex) + //SIZE_T count = String->Length / sizeof(WCHAR); + //PWCHAR p = String->Buffer; + //do + //{ + // hash += (USHORT)RtlUpcaseUnicodeChar(*p++); // __ascii_towupper(*p++); + // hash *= 0x1003F; + //} while (--count != 0); + } + else + { + // This is the fastest implementation (copied from ReactOS) (dmex) + for (p = String->Buffer; p != end; p++) + { + hash = ((65599 * (hash)) + (ULONG)(*p)); + } + + // This is fast but slightly slower (based on PhHashBytes) (dmex) + //SIZE_T count = String->Length / sizeof(WCHAR); + //PWCHAR p = String->Buffer; + //do + //{ + // hash *= 0x1003F; + // hash += *p++; + //} while (--count != 0); + } + + return hash; + } + } + + return 0; +} + BOOLEAN NTAPI PhpSimpleHashtableEqualFunction( _In_ PVOID Entry1, _In_ PVOID Entry2 diff --git a/ProcessHacker/phlib/bcd.cpp b/ProcessHacker/phlib/bcd.cpp index 6bc56566..4787768c 100644 --- a/ProcessHacker/phlib/bcd.cpp +++ b/ProcessHacker/phlib/bcd.cpp @@ -2,7 +2,7 @@ * Process Hacker - * Boot Configuration Data (BCD) wrappers * - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -42,7 +42,7 @@ static BOOLEAN PhpBcdApiInitialized( if (PhBeginInitOnce(&initOnce)) { - if (BcdDllBaseAddress = PhLoadLibrarySafe(L"bcd.dll")) + if (BcdDllBaseAddress = PhLoadLibrary(L"bcd.dll")) { BcdOpenSystemStore_I = reinterpret_cast(PhGetDllBaseProcedureAddress(BcdDllBaseAddress, const_cast("BcdOpenSystemStore"), 0)); BcdCloseStore_I = reinterpret_cast(PhGetDllBaseProcedureAddress(BcdDllBaseAddress, const_cast("BcdCloseStore"), 0)); @@ -200,9 +200,6 @@ NTSTATUS PhBcdEnumerateObjects( if (!PhpBcdApiInitialized()) return STATUS_UNSUCCESSFUL; - if (!BcdDllBaseAddress) - return STATUS_UNSUCCESSFUL; - if (!BcdEnumerateObjects_I) { BcdEnumerateObjects_I = reinterpret_cast( @@ -237,7 +234,7 @@ NTSTATUS PhBcdGetElementString( return STATUS_UNSUCCESSFUL; stringLength = 0x80; - string = PhCreateStringEx(NULL, stringLength); + string = PhCreateStringEx(nullptr, stringLength); status = PhBcdGetElementData( ObjectHandle, ElementType, @@ -248,7 +245,7 @@ NTSTATUS PhBcdGetElementString( if (status == STATUS_BUFFER_TOO_SMALL) { PhDereferenceObject(string); - string = PhCreateStringEx(NULL, stringLength); + string = PhCreateStringEx(nullptr, stringLength); status = PhBcdGetElementData( ObjectHandle, @@ -342,8 +339,8 @@ NTSTATUS PhBcdGetElementData2( ) { NTSTATUS status; - HANDLE storeHandle = NULL; - HANDLE objectHandle = NULL; + HANDLE storeHandle = nullptr; + HANDLE objectHandle = nullptr; if (!PhpBcdApiInitialized()) return STATUS_UNSUCCESSFUL; @@ -387,8 +384,8 @@ NTSTATUS PhBcdSetElementData2( ) { NTSTATUS status; - HANDLE storeHandle = NULL; - HANDLE objectHandle = NULL; + HANDLE storeHandle = nullptr; + HANDLE objectHandle = nullptr; if (!PhpBcdApiInitialized()) return STATUS_UNSUCCESSFUL; @@ -430,8 +427,8 @@ NTSTATUS PhBcdSetAdvancedOptionsOneTime( ) { NTSTATUS status; - HANDLE storeHandle = NULL; - HANDLE objectHandle = NULL; + HANDLE storeHandle = nullptr; + HANDLE objectHandle = nullptr; status = PhBcdOpenSystemStore(&storeHandle); @@ -469,8 +466,8 @@ NTSTATUS PhBcdSetBootApplicationOneTime( ) { NTSTATUS status; - HANDLE storeHandle = NULL; - HANDLE objectHandle = NULL; + HANDLE storeHandle = nullptr; + HANDLE objectHandle = nullptr; BCD_ELEMENT_OBJECT_LIST objectElementList[1]; status = PhBcdOpenSystemStore(&storeHandle); @@ -560,8 +557,8 @@ NTSTATUS PhBcdSetFirmwareBootApplicationOneTime( ) { NTSTATUS status; - HANDLE storeHandle = NULL; - HANDLE objectHandle = NULL; + HANDLE storeHandle = nullptr; + HANDLE objectHandle = nullptr; BCD_ELEMENT_OBJECT_LIST objectElementList[1]; status = PhBcdOpenSystemStore(&storeHandle); @@ -604,7 +601,7 @@ static VOID PhpBcdEnumerateOsLoaderList( NTSTATUS status; ULONG objectCount = 0; ULONG objectSize = 0; - PBCD_OBJECT object = NULL; + PBCD_OBJECT object = nullptr; BCD_OBJECT_DESCRIPTION description; description.Version = BCD_OBJECT_DESCRIPTION_VERSION; @@ -620,7 +617,7 @@ static VOID PhpBcdEnumerateOsLoaderList( if (status == STATUS_BUFFER_TOO_SMALL) { - object = (PBCD_OBJECT)PhAllocate(objectSize); + object = static_cast(PhAllocate(objectSize)); memset(object, 0, objectSize); status = PhBcdEnumerateObjects( @@ -661,8 +658,7 @@ static VOID PhpBcdEnumerateOsLoaderList( { PPH_BCD_OBJECT_LIST entry; - entry = (PPH_BCD_OBJECT_LIST)PhAllocate(sizeof(PH_BCD_OBJECT_LIST)); - memset(entry, 0, sizeof(PH_BCD_OBJECT_LIST)); + entry = static_cast(PhAllocateZero(sizeof(PH_BCD_OBJECT_LIST))); memcpy(&entry->ObjectGuid, &object[i].Identifer, sizeof(GUID)); entry->ObjectName = objectDescription; @@ -676,7 +672,7 @@ static VOID PhpBcdEnumerateOsLoaderList( HANDLE objectHandle; PPH_STRING objectDescription; - // Manually add the memory test application since it's a seperate guid. (dmex) + // Manually add the memory test application since it's a separate guid. (dmex) if (NT_SUCCESS(PhBcdOpenObject(StoreHandle, &GUID_WINDOWS_MEMORY_TESTER, &objectHandle))) { @@ -684,8 +680,7 @@ static VOID PhpBcdEnumerateOsLoaderList( { PPH_BCD_OBJECT_LIST entry; - entry = (PPH_BCD_OBJECT_LIST)PhAllocate(sizeof(PH_BCD_OBJECT_LIST)); - memset(entry, 0, sizeof(PH_BCD_OBJECT_LIST)); + entry = static_cast(PhAllocateZero(sizeof(PH_BCD_OBJECT_LIST))); memcpy(&entry->ObjectGuid, &GUID_WINDOWS_MEMORY_TESTER, sizeof(GUID)); entry->ObjectName = objectDescription; @@ -707,8 +702,8 @@ static VOID PhpBcdEnumerateBootMgrList( ) { NTSTATUS status; - HANDLE objectHandle = NULL; - BCD_ELEMENT_OBJECT_LIST objectElementList[32] = { 0 }; // dynamic? + HANDLE objectHandle = nullptr; + BCD_ELEMENT_OBJECT_LIST objectElementList[32] = { }; // dynamic? ULONG objectListLength = sizeof(objectElementList); status = PhBcdOpenObject( @@ -752,7 +747,7 @@ static VOID PhpBcdEnumerateBootMgrList( { PPH_BCD_OBJECT_LIST entry; - entry = (PPH_BCD_OBJECT_LIST)PhAllocateZero(sizeof(PH_BCD_OBJECT_LIST)); + entry = static_cast(PhAllocateZero(sizeof(PH_BCD_OBJECT_LIST))); memcpy(&entry->ObjectGuid, &objectElementList->ObjectList[i], sizeof(GUID)); entry->ObjectName = objectEntryDescription; @@ -778,7 +773,7 @@ PPH_LIST PhBcdQueryBootApplicationList( status = PhBcdOpenSystemStore(&storeHandle); if (!NT_SUCCESS(status)) - return NULL; + return nullptr; objectApplicationList = PhCreateList(5); @@ -822,7 +817,7 @@ PPH_LIST PhBcdQueryFirmwareBootApplicationList( status = PhBcdOpenSystemStore(&storeHandle); if (!NT_SUCCESS(status)) - return NULL; + return nullptr; objectApplicationList = PhCreateList(5); @@ -850,7 +845,7 @@ VOID PhBcdDestroyBootApplicationList( { for (ULONG i = 0; i < ObjectApplicationList->Count; i++) { - PPH_BCD_OBJECT_LIST entry = (PPH_BCD_OBJECT_LIST)ObjectApplicationList->Items[i]; + PPH_BCD_OBJECT_LIST entry = static_cast(ObjectApplicationList->Items[i]); PhDereferenceObject(entry->ObjectName); PhFree(entry); diff --git a/ProcessHacker/phlib/colorbox.c b/ProcessHacker/phlib/colorbox.c index f126f16a..e7e195e2 100644 --- a/ProcessHacker/phlib/colorbox.c +++ b/ProcessHacker/phlib/colorbox.c @@ -111,6 +111,12 @@ UINT_PTR CALLBACK PhpColorBoxDlgHookProc( PhInitializeWindowTheme(hwndDlg, context->EnableThemeSupport); } break; + case WM_CTLCOLORBTN: + return HANDLE_WM_CTLCOLORBTN(hwndDlg, wParam, lParam, PhWindowThemeControlColor); + case WM_CTLCOLORDLG: + return HANDLE_WM_CTLCOLORDLG(hwndDlg, wParam, lParam, PhWindowThemeControlColor); + case WM_CTLCOLORSTATIC: + return HANDLE_WM_CTLCOLORSTATIC(hwndDlg, wParam, lParam, PhWindowThemeControlColor); } return FALSE; @@ -147,12 +153,12 @@ LRESULT CALLBACK PhpColorBoxWndProc( { PPHP_COLORBOX_CONTEXT context; - context = (PPHP_COLORBOX_CONTEXT)GetWindowLongPtr(hwnd, 0); + context = PhGetWindowContext(hwnd, MAXCHAR); if (uMsg == WM_CREATE) { PhpCreateColorBoxContext(&context); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)context); + PhSetWindowContext(hwnd, MAXCHAR, context); } if (!context) @@ -167,7 +173,7 @@ LRESULT CALLBACK PhpColorBoxWndProc( break; case WM_DESTROY: { - SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + PhRemoveWindowContext(hwnd, MAXCHAR); PhpFreeColorBoxContext(context); } break; diff --git a/ProcessHacker/phlib/cpysave.c b/ProcessHacker/phlib/cpysave.c index 11e92917..c51d0099 100644 --- a/ProcessHacker/phlib/cpysave.c +++ b/ProcessHacker/phlib/cpysave.c @@ -3,6 +3,7 @@ * copy/save code for listviews and treelists * * Copyright (C) 2010-2012 wj32 + * Copyright (C) 2018-2020 dmex * * This file is part of Process Hacker. * diff --git a/ProcessHacker/phlib/data.c b/ProcessHacker/phlib/data.c index ecb468cd..8901a378 100644 --- a/ProcessHacker/phlib/data.c +++ b/ProcessHacker/phlib/data.c @@ -239,5 +239,7 @@ WCHAR *PhKWaitReasonNames[MaximumWaitReason] = L"WrRundown", L"WrAlertByThreadId", L"WrDeferredPreempt", - L"WrPhysicalFault" + L"WrPhysicalFault", + L"WrIoRing", + L"WrMdlCache", }; diff --git a/ProcessHacker/phlib/global.c b/ProcessHacker/phlib/global.c index d1748443..6e355784 100644 --- a/ProcessHacker/phlib/global.c +++ b/ProcessHacker/phlib/global.c @@ -170,10 +170,18 @@ VOID PhInitializeWindowsVersion( // Windows 10, Windows Server 2016 else if (majorVersion == 10 && minorVersion == 0) { - if (buildVersion >= 22000) + if (buildVersion >= 22500) + { + WindowsVersion = WINDOWS_11_22H1; + } + else if (buildVersion >= 22000) { WindowsVersion = WINDOWS_11; } + else if (buildVersion >= 19044) + { + WindowsVersion = WINDOWS_10_21H2; + } else if (buildVersion >= 19043) { WindowsVersion = WINDOWS_10_21H1; diff --git a/ProcessHacker/phlib/graph.c b/ProcessHacker/phlib/graph.c index 8d3356c2..9bc61541 100644 --- a/ProcessHacker/phlib/graph.c +++ b/ProcessHacker/phlib/graph.c @@ -3,7 +3,7 @@ * graph control * * Copyright (C) 2010-2016 wj32 - * Copyright (C) 2017-2020 dmex + * Copyright (C) 2017-2021 dmex * * This file is part of Process Hacker. * @@ -33,12 +33,23 @@ typedef struct _PHP_GRAPH_CONTEXT { HWND Handle; + HWND ParentHandle; ULONG Style; ULONG_PTR Id; PH_GRAPH_DRAW_INFO DrawInfo; PH_GRAPH_OPTIONS Options; - BOOLEAN NeedsUpdate; - BOOLEAN NeedsDraw; + + union + { + USHORT Flags; + struct + { + USHORT NeedsUpdate : 1; + USHORT NeedsDraw : 1; + USHORT Hot : 1; + USHORT Spare : 13; + }; + }; HDC BufferedContext; HBITMAP BufferedOldBitmap; @@ -910,7 +921,7 @@ VOID PhpUpdateDrawInfo( getDrawInfo.Header.code = GCN_GETDRAWINFO; getDrawInfo.DrawInfo = &Context->DrawInfo; - SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&getDrawInfo); + SendMessage(Context->ParentHandle, WM_NOTIFY, 0, (LPARAM)&getDrawInfo); } VOID PhpDrawGraphControl( @@ -961,7 +972,7 @@ VOID PhpDrawGraphControl( drawPanel.hdc = Context->BufferedContext; drawPanel.Rect = Context->BufferedContextRect; - SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&drawPanel); + SendMessage(Context->ParentHandle, WM_NOTIFY, 0, (LPARAM)&drawPanel); } } @@ -974,12 +985,12 @@ LRESULT CALLBACK PhpGraphWndProc( { PPHP_GRAPH_CONTEXT context; - context = (PPHP_GRAPH_CONTEXT)GetWindowLongPtr(hwnd, 0); + context = PhGetWindowContext(hwnd, MAXCHAR); if (uMsg == WM_CREATE) { PhpCreateGraphContext(&context); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)context); + PhSetWindowContext(hwnd, MAXCHAR, context); } if (!context) @@ -1016,13 +1027,14 @@ LRESULT CALLBACK PhpGraphWndProc( CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam; context->Handle = hwnd; + context->ParentHandle = GetParent(hwnd); context->Style = createStruct->style; context->Id = (ULONG_PTR)createStruct->hMenu; } break; case WM_DESTROY: { - SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + PhRemoveWindowContext(hwnd, MAXCHAR); if (context->TooltipHandle) DestroyWindow(context->TooltipHandle); @@ -1170,7 +1182,7 @@ LRESULT CALLBACK PhpGraphWndProc( getTooltipText.Text.Buffer = NULL; getTooltipText.Text.Length = 0; - SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&getTooltipText); + SendMessage(context->ParentHandle, WM_NOTIFY, 0, (LPARAM)&getTooltipText); if (getTooltipText.Text.Buffer) { @@ -1205,6 +1217,28 @@ LRESULT CALLBACK PhpGraphWndProc( SendMessage(context->TooltipHandle, TTM_UPDATE, 0, 0); context->LastCursorLocation = point; } + + if (!context->Hot) + { + TRACKMOUSEEVENT trackMouseEvent; + + context->Hot = TRUE; + trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + trackMouseEvent.dwFlags = TME_LEAVE; + trackMouseEvent.hwndTrack = hwnd; + trackMouseEvent.dwHoverTime = 0; + TrackMouseEvent(&trackMouseEvent); + } + } + } + break; + case WM_MOUSELEAVE: + { + context->Hot = FALSE; + + if (context->TooltipHandle) + { + SendMessage(context->TooltipHandle, TTM_POP, 0, 0); } } break; @@ -1231,7 +1265,7 @@ LRESULT CALLBACK PhpGraphWndProc( mouseEvent.Index = (clientRect.right - mouseEvent.Point.x - 1) / context->DrawInfo.Step; mouseEvent.TotalCount = context->DrawInfo.LineDataCount; - SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM)&mouseEvent); + SendMessage(context->ParentHandle, WM_NOTIFY, 0, (LPARAM)&mouseEvent); } break; case GCM_GETDRAWINFO: diff --git a/ProcessHacker/phlib/guisup.c b/ProcessHacker/phlib/guisup.c index 5967fbbf..a029636b 100644 --- a/ProcessHacker/phlib/guisup.c +++ b/ProcessHacker/phlib/guisup.c @@ -3,7 +3,7 @@ * GUI support functions * * Copyright (C) 2009-2016 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -61,7 +62,6 @@ HFONT PhApplicationFont = NULL; HFONT PhTreeWindowFont = NULL; PH_INTEGER_PAIR PhSmallIconSize = { 16, 16 }; PH_INTEGER_PAIR PhLargeIconSize = { 32, 32 }; -_IsImmersiveProcess IsImmersiveProcess_I = NULL; static PH_INITONCE SharedIconCacheInitOnce = PH_INITONCE_INIT; static PPH_HASHTABLE SharedIconCacheHashtable; @@ -101,11 +101,6 @@ VOID PhGuiSupportInitialization( PhGlobalDpi = GetDeviceCaps(hdc, LOGPIXELSY); ReleaseDC(NULL, hdc); } - - if (WindowsVersion >= WINDOWS_8) - { - IsImmersiveProcess_I = PhGetDllProcedureAddress(L"user32.dll", "IsImmersiveProcess", 0); - } } VOID PhSetControlTheme( @@ -1022,6 +1017,37 @@ HWND PhCreateDialog( return dialogHandle; } +HWND PhCreateWindow( + _In_ ULONG ExStyle, + _In_opt_ PCWSTR ClassName, + _In_opt_ PCWSTR WindowName, + _In_ ULONG Style, + _In_ INT X, + _In_ INT Y, + _In_ INT Width, + _In_ INT Height, + _In_opt_ HWND ParentWindow, + _In_opt_ HMENU MenuHandle, + _In_opt_ PVOID InstanceHandle, + _In_opt_ PVOID Parameter + ) +{ + return CreateWindowEx( + ExStyle, + ClassName, + WindowName, + Style, + X, + Y, + Width, + Height, + ParentWindow, + MenuHandle, + InstanceHandle, + Parameter + ); +} + BOOLEAN PhModalPropertySheet( _Inout_ PROPSHEETHEADER *Header ) @@ -1556,8 +1582,8 @@ HWND PhGetProcessMainWindowEx( else PhOpenProcess(&processHandle, PROCESS_QUERY_LIMITED_INFORMATION, ProcessId); - if (processHandle && WindowsVersion >= WINDOWS_8 && IsImmersiveProcess_I) - context.IsImmersive = !!IsImmersiveProcess_I(processHandle); + if (processHandle && WindowsVersion >= WINDOWS_8) + context.IsImmersive = PhIsImmersiveProcess(processHandle); PhEnumWindows(PhpGetProcessMainWindowEnumWindowsProc, &context); //PhEnumChildWindows(NULL, 0x800, PhpGetProcessMainWindowEnumWindowsProc, &context); @@ -1652,15 +1678,15 @@ static BOOLEAN NTAPI PhpWindowCallbackHashtableEqualFunction( ) { return - (*(PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION *)Entry1)->WindowHandle == - (*(PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION *)Entry2)->WindowHandle; + ((PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION)Entry1)->WindowHandle == + ((PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION)Entry2)->WindowHandle; } static ULONG NTAPI PhpWindowCallbackHashtableHashFunction( _In_ PVOID Entry ) { - return PhHashIntPtr((ULONG_PTR)(*(PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION *)Entry)->WindowHandle); + return PhHashIntPtr((ULONG_PTR)((PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION)Entry)->WindowHandle); } VOID PhRegisterWindowCallback( @@ -1669,11 +1695,10 @@ VOID PhRegisterWindowCallback( _In_opt_ PVOID Context ) { - PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION entry; + PH_PLUGIN_WINDOW_CALLBACK_REGISTRATION entry; - entry = PhAllocate(sizeof(PH_PLUGIN_WINDOW_CALLBACK_REGISTRATION)); - entry->WindowHandle = WindowHandle; - entry->Type = Type; + entry.WindowHandle = WindowHandle; + entry.Type = Type; switch (Type) // HACK { @@ -1693,27 +1718,14 @@ VOID PhUnregisterWindowCallback( ) { PH_PLUGIN_WINDOW_CALLBACK_REGISTRATION lookupEntry; - PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION lookupEntryPtr = &lookupEntry; - PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION *entryPtr; PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION entry; lookupEntry.WindowHandle = WindowHandle; PhAcquireQueuedLockExclusive(&WindowCallbackListLock); - - entryPtr = (PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION*)PhFindEntryHashtable( - WindowCallbackHashTable, - &lookupEntryPtr - ); - - assert(entryPtr); - - if (entryPtr && PhRemoveEntryHashtable(WindowCallbackHashTable, entryPtr)) - { - entry = *entryPtr; - PhFree(entry); - } - + entry = PhFindEntryHashtable(WindowCallbackHashTable, &lookupEntry); + assert(entry); + PhRemoveEntryHashtable(WindowCallbackHashTable, entry); PhReleaseQueuedLockExclusive(&WindowCallbackListLock); } @@ -1721,16 +1733,16 @@ VOID PhWindowNotifyTopMostEvent( _In_ BOOLEAN TopMost ) { - PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION *entry; + PPH_PLUGIN_WINDOW_CALLBACK_REGISTRATION entry; ULONG i = 0; PhAcquireQueuedLockExclusive(&WindowCallbackListLock); - while (PhEnumHashtable(WindowCallbackHashTable, (PVOID*)&entry, &i)) + while (PhEnumHashtable(WindowCallbackHashTable, &entry, &i)) { - if ((*entry)->Type & PH_PLUGIN_WINDOW_EVENT_TYPE_TOPMOST) + if (entry->Type & PH_PLUGIN_WINDOW_EVENT_TYPE_TOPMOST) { - PhSetWindowAlwaysOnTop((*entry)->WindowHandle, TopMost); + PhSetWindowAlwaysOnTop(entry->WindowHandle, TopMost); } } @@ -1752,7 +1764,7 @@ HICON PhGetInternalWindowIcon( { PVOID shell32Handle; - if (shell32Handle = PhLoadLibrarySafe(L"shell32.dll")) + if (shell32Handle = PhLoadLibrary(L"shell32.dll")) { InternalGetWindowIcon_I = PhGetDllBaseProcedureAddress(shell32Handle, "InternalGetWindowIcon", 0); } @@ -1783,6 +1795,28 @@ HANDLE PhGetGlobalTimerQueue( return PhTimerQueueHandle; } +BOOLEAN PhIsImmersiveProcess( + _In_ HANDLE ProcessHandle + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static BOOL (WINAPI* IsImmersiveProcess_I)( + _In_ HANDLE ProcessHandle + ) = NULL; + + if (PhBeginInitOnce(&initOnce)) + { + if (WindowsVersion >= WINDOWS_8) + IsImmersiveProcess_I = PhGetDllProcedureAddress(L"user32.dll", "IsImmersiveProcess", 0); + PhEndInitOnce(&initOnce); + } + + if (!IsImmersiveProcess_I) + return FALSE; + + return !!IsImmersiveProcess_I(ProcessHandle); +} + // rev from ExtractIconExW _Success_(return) BOOLEAN PhExtractIcon( @@ -1928,6 +1962,12 @@ BOOLEAN PhLoadIconFromResourceDirectory( return TRUE; } +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((ULONG)(BYTE)(ch0) | ((ULONG)(BYTE)(ch1) << 8) | \ + ((ULONG)(BYTE)(ch2) << 16) | ((ULONG)(BYTE)(ch3) << 24 )) +#endif + // https://docs.microsoft.com/en-us/windows/win32/menurc/newheader // One or more RESDIR structures immediately follow the NEWHEADER structure. typedef struct _NEWHEADER @@ -1981,7 +2021,7 @@ HICON PhCreateIconFromResourceDirectory( ) { // CreateIconFromResourceEx seems to know what formats are supported so these - // size/format checks are probably redundant and not required? + // size/format checks are probably redundant and not required? (dmex) return NULL; } @@ -2020,8 +2060,8 @@ PPH_STRING PhpGetImageMunResourcePath( } // 19H1 and above relocated binary resources into the \SystemResources\ directory. - // This is implemented as a hook inside EnumResouceNamesExW: - // PrivateExtractIconExW -> EnumResouceNamesExW -> GetMunResourceModuleForEnumIfExist. + // This is implemented as a hook inside EnumResourceNamesExW: + // PrivateExtractIconExW -> EnumResourceNamesExW -> GetMunResourceModuleForEnumIfExist. // // GetMunResourceModuleForEnumIfExist trims the path and inserts '\SystemResources\' and '.mun' // to locate the binary with the icon resources. For example: @@ -2363,6 +2403,19 @@ HICON PhImageListGetIcon( return iconhandle; } +BOOLEAN PhImageListGetIconSize( + _In_ HIMAGELIST ImageListHandle, + _Out_ PINT cx, + _Out_ PINT cy + ) +{ + return SUCCEEDED(IImageList2_GetIconSize( + (IImageList2*)ImageListHandle, + cx, + cy + )); +} + BOOLEAN PhImageListReplace( _In_ HIMAGELIST ImageListHandle, _In_ UINT Index, @@ -2384,7 +2437,8 @@ BOOLEAN PhImageListDrawIcon( _In_ HDC Hdc, _In_ INT x, _In_ INT y, - _In_ UINT Style + _In_ UINT Style, + _In_ BOOLEAN Disabled ) { return PhImageListDrawEx( @@ -2397,7 +2451,8 @@ BOOLEAN PhImageListDrawIcon( 0, CLR_DEFAULT, CLR_DEFAULT, - Style + Style, + Disabled ? ILS_SATURATE : ILS_NORMAL ); } @@ -2411,7 +2466,8 @@ BOOLEAN PhImageListDrawEx( _In_ INT dy, _In_ COLORREF BackColor, _In_ COLORREF ForeColor, - _In_ UINT Style + _In_ UINT Style, + _In_ DWORD State ) { IMAGELISTDRAWPARAMS imagelistDraw; @@ -2428,6 +2484,7 @@ BOOLEAN PhImageListDrawEx( imagelistDraw.rgbBk = BackColor; imagelistDraw.rgbFg = ForeColor; imagelistDraw.fStyle = Style; + imagelistDraw.fState = State; return SUCCEEDED(IImageList2_Draw((IImageList2*)ImageListHandle, &imagelistDraw)); } @@ -2440,8 +2497,6 @@ VOID PhCustomDrawTreeTimeLine( _In_ PLARGE_INTEGER CreateTime ) { - #define PhInflateRect(rect, dx, dy) \ - { (rect)->left -= (dx); (rect)->top -= (dy); (rect)->right += (dx); (rect)->bottom += (dy); } HBRUSH previousBrush = NULL; RECT rect = CellRect; RECT borderRect = CellRect; @@ -2494,8 +2549,18 @@ VOID PhCustomDrawTreeTimeLine( createTime.QuadPart = systemTime.QuadPart - CreateTime->QuadPart; } + // Note: Time is 8 bytes, Float is 4 bytes. Use DOUBLE type at some stage. (dmex) percent = (FLOAT)createTime.QuadPart / (FLOAT)startTime.QuadPart * 100.f; + if (!(Flags & PH_DRAW_TIMELINE_OVERFLOW)) + { + // Prevent overflow from changing the system time to an earlier date. (dmex) + if (fabsf(percent) > 100.f) + percent = 100.f; + if (fabsf(percent) < 0.0005f) + percent = 0.f; + } + if (Flags & PH_DRAW_TIMELINE_DARKTHEME) FillRect(Hdc, &rect, PhMenuBackgroundBrush); else @@ -2527,9 +2592,15 @@ VOID PhCustomDrawTreeTimeLine( previousBrush = SelectBrush(Hdc, GetStockBrush(DC_BRUSH)); } - // Prevent overflow from changing the system time to an earlier date. (dmex) - if (percent > 100.f) percent = 100.f; - // TODO: This still loses a small fraction of precision compared to PE here causing a 1px difference. (dmex) + if (Flags & PH_DRAW_TIMELINE_OVERFLOW) + { + // Prevent overflow from changing the system time to an earlier date. (dmex) + if (fabsf(percent) > 100.f) + percent = 100.f; + if (fabsf(percent) < 0.0005f) + percent = 0.f; + } + //rect.right = ((LONG)(rect.left + ((rect.right - rect.left) * (LONG)percent) / 100)); //rect.left = ((LONG)(rect.right + ((rect.left - rect.right) * (LONG)percent) / 100)); rect.left = (LONG)(rect.right + ((rect.left - rect.right) * percent / 100)); diff --git a/ProcessHacker/phlib/handle.c b/ProcessHacker/phlib/handle.c index d3708b25..0bd6d90c 100644 --- a/ProcessHacker/phlib/handle.c +++ b/ProcessHacker/phlib/handle.c @@ -860,7 +860,7 @@ PPH_HANDLE_TABLE_ENTRY PhpLookupHandleTableEntry( tableLevel = tableValue & PH_HANDLE_TABLE_LEVEL_MASK; tableValue -= tableLevel; - // No additional checking needed; aleady checked against NextValue. + // No additional checking needed; already checked against NextValue. switch (tableLevel) { diff --git a/ProcessHacker/phlib/hexedit.c b/ProcessHacker/phlib/hexedit.c index c843a3a7..d5f31cb5 100644 --- a/ProcessHacker/phlib/hexedit.c +++ b/ProcessHacker/phlib/hexedit.c @@ -108,12 +108,12 @@ LRESULT CALLBACK PhpHexEditWndProc( { PPHP_HEXEDIT_CONTEXT context; - context = (PPHP_HEXEDIT_CONTEXT)GetWindowLongPtr(hwnd, 0); + context = PhGetWindowContext(hwnd, MAXCHAR); if (uMsg == WM_CREATE) { PhpCreateHexEditContext(&context); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)context); + PhSetWindowContext(hwnd, MAXCHAR, context); } if (!context) @@ -128,7 +128,7 @@ LRESULT CALLBACK PhpHexEditWndProc( break; case WM_DESTROY: { - SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + PhRemoveWindowContext(hwnd, MAXCHAR); PhpFreeHexEditContext(context); } break; diff --git a/ProcessHacker/phlib/hndlinfo.c b/ProcessHacker/phlib/hndlinfo.c index f5196da2..6346de94 100644 --- a/ProcessHacker/phlib/hndlinfo.c +++ b/ProcessHacker/phlib/hndlinfo.c @@ -449,7 +449,7 @@ VOID PhInitializeEtwTraceGuidCache( PhInitializeArray(EtwTraceGuidArrayList, sizeof(PH_ETW_TRACEGUID_ENTRY), 2000); - if (!(jsonObject = PhCreateJsonParser(capabilityListString->Buffer))) + if (!(jsonObject = PhCreateJsonParserEx(capabilityListString, FALSE))) return; if (!(arrayLength = PhGetJsonArrayLength(jsonObject))) @@ -607,7 +607,7 @@ PPH_STRING PhGetPnPDeviceName( { PVOID cfgmgr32; - if (cfgmgr32 = PhLoadLibrarySafe(L"cfgmgr32.dll")) + if (cfgmgr32 = PhLoadLibrary(L"cfgmgr32.dll")) { DevGetObjects_I = PhGetDllBaseProcedureAddress(cfgmgr32, "DevGetObjects", 0); DevFreeObjects_I = PhGetDllBaseProcedureAddress(cfgmgr32, "DevFreeObjects", 0); @@ -1018,13 +1018,13 @@ NTSTATUS PhpGetBestObjectName( { if (PhStartsWithString2(ObjectName, L"\\Device\\", TRUE)) { - // The device might be a PDO... Query the PnP manager for the friendy name of the device. + // The device might be a PDO... Query the PnP manager for the friendly name of the device. (dmex) bestObjectName = PhGetPnPDeviceName(ObjectName); } if (!bestObjectName) { - // The file doesn't have a DOS filename and doesn't have a PnP friendy name. + // The file doesn't have a DOS filename and doesn't have a PnP friendly name. PhSetReference(&bestObjectName, ObjectName); } } diff --git a/ProcessHacker/phlib/http.c b/ProcessHacker/phlib/http.c index 2afc5291..b421d2c2 100644 --- a/ProcessHacker/phlib/http.c +++ b/ProcessHacker/phlib/http.c @@ -2,7 +2,7 @@ * Process Hacker - * http/http2/dns wrappers * - * Copyright (C) 2017-2020 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -122,16 +122,44 @@ VOID PhHttpSocketDestroy( if (!HttpContext) return; - if (HttpContext->RequestHandle) - WinHttpCloseHandle(HttpContext->RequestHandle); - if (HttpContext->ConnectionHandle) - WinHttpCloseHandle(HttpContext->ConnectionHandle); - if (HttpContext->SessionHandle) - WinHttpCloseHandle(HttpContext->SessionHandle); + PhHttpSocketClose(HttpContext, ULONG_MAX); PhFree(HttpContext); } +VOID PhHttpSocketClose( + _In_ PPH_HTTP_CONTEXT HttpContext, + _In_ PH_HTTP_SOCKET_CLOSE_TYPE Type + ) +{ + if (Type & PH_HTTP_SOCKET_CLOSE_SESSION) + { + if (HttpContext->SessionHandle) + { + WinHttpCloseHandle(HttpContext->SessionHandle); + HttpContext->SessionHandle = NULL; + } + } + + if (Type & PH_HTTP_SOCKET_CLOSE_CONNECTION) + { + if (HttpContext->ConnectionHandle) + { + WinHttpCloseHandle(HttpContext->ConnectionHandle); + HttpContext->ConnectionHandle = NULL; + } + } + + if (Type & PH_HTTP_SOCKET_CLOSE_REQUEST) + { + if (HttpContext->RequestHandle) + { + WinHttpCloseHandle(HttpContext->RequestHandle); + HttpContext->RequestHandle = NULL; + } + } +} + BOOLEAN PhHttpSocketConnect( _In_ PPH_HTTP_CONTEXT HttpContext, _In_ PWSTR ServerName, @@ -671,6 +699,8 @@ NTSTATUS PhHttpSocketDownloadToFile( return status; } + memset(buffer, 0, sizeof(buffer)); + while (PhHttpSocketReadData(HttpContext, buffer, PAGE_SIZE, &numberOfBytesRead)) { if (numberOfBytesRead == 0) diff --git a/ProcessHacker/phlib/icotobmp.c b/ProcessHacker/phlib/icotobmp.c index 2d3662d8..531cd6eb 100644 --- a/ProcessHacker/phlib/icotobmp.c +++ b/ProcessHacker/phlib/icotobmp.c @@ -182,7 +182,6 @@ HBITMAP PhIconToBitmap( // Default to unbuffered painting. FillRect(hdc, &iconRectangle, (HBRUSH)(COLOR_WINDOW + 1)); DrawIconEx(hdc, 0, 0, Icon, Width, Height, 0, NULL, DI_NORMAL); - //SelectBitmap(hdc, oldBitmap); // ?? (dmex) } SelectBitmap(hdc, oldBitmap); diff --git a/ProcessHacker/phlib/imgcoherency.c b/ProcessHacker/phlib/imgcoherency.c index e66ff68b..9d26cb49 100644 --- a/ProcessHacker/phlib/imgcoherency.c +++ b/ProcessHacker/phlib/imgcoherency.c @@ -3,7 +3,7 @@ * Image Coherency * * Copyright (C) 2020 jxy-s - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -118,9 +118,9 @@ ULONG PhpGetSectionScanSize( * * \return TRUE if the section should be scanned for the given scan type, FALSE otherwise. */ -ULONG PhpShouldScanSection( - PH_IMAGE_COHERENCY_SCAN_TYPE Type, - PIMAGE_SECTION_HEADER SectionHeader +BOOLEAN PhpShouldScanSection( + _In_ PH_IMAGE_COHERENCY_SCAN_TYPE Type, + _In_ PIMAGE_SECTION_HEADER SectionHeader ) { switch (Type) @@ -218,13 +218,13 @@ PPH_IMAGE_COHERENCY_CONTEXT PhpCreateImageCoherencyContext( PH_MAPPED_IMAGE_RELOC relocs; // - // Build a hash table for the relocation entires to skip later. + // Build a hash table for the relocation entries to skip later. // This hash table will map the RVA to the number of bytes to skip. // - if (NT_SUCCESS(PhGetMappedImageRelocations(&context->MappedImage, - &relocs))) + if (NT_SUCCESS(PhGetMappedImageRelocations(&context->MappedImage, &relocs))) { context->MappedImageReloc = PhCreateSimpleHashtable(relocs.NumberOfEntries); + for (ULONG i = 0; i < relocs.NumberOfEntries; i++) { PPH_IMAGE_RELOC_ENTRY entry; @@ -296,7 +296,7 @@ PPH_IMAGE_COHERENCY_CONTEXT PhpCreateImageCoherencyContext( * for each inspected byte, the callback may return any number of bytes to skip. * \param[in] SkipCallbackContext - Optional, callback context passed to the skip callback. */ -VOID PhpAnalyzeImageCoherencyInsepct( +VOID PhpAnalyzeImageCoherencyInspect( _In_opt_ PBYTE LeftBuffer, _In_ ULONG LeftCount, _In_opt_ PBYTE RightBuffer, @@ -433,7 +433,7 @@ VOID PhpAnalyzeImageCoherencyCommonByRva( // // Do the inspection, clamp the bytes to the minimum // - PhpAnalyzeImageCoherencyInsepct(fileBytes, + PhpAnalyzeImageCoherencyInspect(fileBytes, (ULONG)bytes, buffer, (ULONG)bytes, @@ -457,7 +457,7 @@ VOID PhpAnalyzeImageCoherencyCommonByRva( * \param[in] Context - Image coherency context. * \param[in] ExpectedByte - Expected byte in the entire range. */ -VOID PhpAnalyzeImageCoherencyCommonByRvaExepctBytes( +VOID PhpAnalyzeImageCoherencyCommonByRvaExpectBytes( _In_ HANDLE ProcessHandle, _In_ ULONG Rva, _In_ ULONG Size, @@ -500,7 +500,7 @@ VOID PhpAnalyzeImageCoherencyCommonByRvaExepctBytes( // // Do the inspection // - PhpAnalyzeImageCoherencyInsepct(expected, + PhpAnalyzeImageCoherencyInspect(expected, (ULONG)bytesRead, buffer, (ULONG)bytesRead, @@ -569,13 +569,9 @@ VOID PhpAnalyzeImageCoherencyCommonAsNative( _In_ PPH_IMAGE_COHERENCY_CONTEXT Context ) { - BOOL inspectedEntry; - DWORD addressOfEntry; + ULONG addressOfEntry = 0; PIMAGE_SECTION_HEADER entrySection; - inspectedEntry = FALSE; - addressOfEntry = 0; - switch (Context->MappedImage.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: @@ -620,8 +616,8 @@ VOID PhpAnalyzeImageCoherencyCommonAsNative( mappedSection = &Context->MappedImage.Sections[i]; remoteMappedSection = &Context->MappedImage.Sections[i]; - if ((PhpShouldScanSection(Context->Type, mappedSection) != FALSE) || - (PhpShouldScanSection(Context->Type, remoteMappedSection) != FALSE)) + if (PhpShouldScanSection(Context->Type, mappedSection) || + PhpShouldScanSection(Context->Type, remoteMappedSection)) { ULONG size; SIZE_T prevTotal; @@ -683,7 +679,7 @@ VOID PhpAnalyzeImageCoherencyCommonAsNative( ((mappedSection->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0) && (mappedSection->Misc.VirtualSize > mappedSection->SizeOfRawData)) { - PhpAnalyzeImageCoherencyCommonByRvaExepctBytes( + PhpAnalyzeImageCoherencyCommonByRvaExpectBytes( ProcessHandle, mappedSection->VirtualAddress + mappedSection->SizeOfRawData, mappedSection->Misc.VirtualSize - mappedSection->SizeOfRawData, @@ -844,7 +840,7 @@ VOID PhpAnalyzeImageCoherencyCommon( if ((i < Context->MappedImage.NumberOfSections) && (i < Context->RemoteMappedImage.NumberOfSections)) { - PhpAnalyzeImageCoherencyInsepct((PBYTE)&Context->MappedImage.Sections[i], + PhpAnalyzeImageCoherencyInspect((PBYTE)&Context->MappedImage.Sections[i], sizeof(IMAGE_SECTION_HEADER), (PBYTE)&Context->RemoteMappedImage.Sections[i], sizeof(IMAGE_SECTION_HEADER), @@ -925,7 +921,7 @@ NTSTATUS PhpAnalyzeImageCoherencyNt32( // // Inspect the header // - PhpAnalyzeImageCoherencyInsepct((PBYTE)Context->MappedImage.NtHeaders32, + PhpAnalyzeImageCoherencyInspect((PBYTE)Context->MappedImage.NtHeaders32, UFIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader), (PBYTE)Context->RemoteMappedImage.NtHeaders32, UFIELD_OFFSET(IMAGE_NT_HEADERS32, OptionalHeader), @@ -937,7 +933,7 @@ NTSTATUS PhpAnalyzeImageCoherencyNt32( // // Inspect the optional header // - PhpAnalyzeImageCoherencyInsepct((PBYTE)fileOptHeader, + PhpAnalyzeImageCoherencyInspect((PBYTE)fileOptHeader, sizeof(IMAGE_OPTIONAL_HEADER32), (PBYTE)procOptHeader, sizeof(IMAGE_OPTIONAL_HEADER32), @@ -1003,7 +999,7 @@ NTSTATUS PhpAnalyzeImageCoherencyNt64( // // Inspect the header // - PhpAnalyzeImageCoherencyInsepct((PBYTE)Context->MappedImage.NtHeaders, + PhpAnalyzeImageCoherencyInspect((PBYTE)Context->MappedImage.NtHeaders, UFIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader), (PBYTE)Context->RemoteMappedImage.NtHeaders, UFIELD_OFFSET(IMAGE_NT_HEADERS64, OptionalHeader), @@ -1014,7 +1010,7 @@ NTSTATUS PhpAnalyzeImageCoherencyNt64( // // And the optional header // - PhpAnalyzeImageCoherencyInsepct((PBYTE)fileOptHeader, + PhpAnalyzeImageCoherencyInspect((PBYTE)fileOptHeader, sizeof(IMAGE_OPTIONAL_HEADER64), (PBYTE)procOptHeader, sizeof(IMAGE_OPTIONAL_HEADER64), diff --git a/ProcessHacker/phlib/include/apiimport.h b/ProcessHacker/phlib/include/apiimport.h index 9de5bfdd..c1eb7d8a 100644 --- a/ProcessHacker/phlib/include/apiimport.h +++ b/ProcessHacker/phlib/include/apiimport.h @@ -60,6 +60,23 @@ typedef NTSTATUS (NTAPI *_NtQueryOpenSubKeysEx)( _Out_ PULONG RequiredSize ); +typedef NTSTATUS (NTAPI* _NtCreateProcessStateChange)( + _Out_ PHANDLE ProcessStateChangeHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ProcessHandle, + _In_opt_ ULONG64 Reserved + ); + +typedef NTSTATUS (NTAPI* _NtChangeProcessState)( + _In_ HANDLE ProcessStateChangeHandle, + _In_ HANDLE ProcessHandle, + _In_ PROCESS_STATE_CHANGE_TYPE StateChangeType, + _In_opt_ PVOID ExtendedInformation, + _In_opt_ SIZE_T ExtendedInformationLength, + _In_opt_ ULONG64 Reserved + ); + typedef NTSTATUS (NTAPI* _RtlDefaultNpAcl)( _Out_ PACL* Acl ); @@ -227,6 +244,8 @@ PH_DECLARE_IMPORT(NtQueryDefaultLocale); PH_DECLARE_IMPORT(NtQueryDefaultUILanguage); PH_DECLARE_IMPORT(NtTraceControl); PH_DECLARE_IMPORT(NtQueryOpenSubKeysEx); +PH_DECLARE_IMPORT(NtCreateProcessStateChange); +PH_DECLARE_IMPORT(NtChangeProcessState); PH_DECLARE_IMPORT(RtlDefaultNpAcl); PH_DECLARE_IMPORT(RtlGetTokenNamedObjectPath); diff --git a/ProcessHacker/phlib/include/appresolverp.h b/ProcessHacker/phlib/include/appresolverp.h index d83ab95c..5cbda8ea 100644 --- a/ProcessHacker/phlib/include/appresolverp.h +++ b/ProcessHacker/phlib/include/appresolverp.h @@ -693,4 +693,39 @@ DECLARE_INTERFACE_IID(IOSTaskCompletion2, IOSTaskCompletion) #define IOSTaskCompletion_BeginTaskByHandleEx(This, ProcessHandle, Flags, TaskFlags) \ ((This)->lpVtbl->BeginTaskByHandleEx(This, ProcessHandle, Flags, TaskFlags)) +// EDP + +typedef enum _EDP_CONTEXT_STATES +{ + EDP_CONTEXT_NONE = 0, + EDP_CONTEXT_IS_EXEMPT = 1, + EDP_CONTEXT_IS_ENLIGHTENED = 2, + EDP_CONTEXT_IS_UNENLIGHTENED_ALLOWED = 4, + EDP_CONTEXT_IS_PERMISSIVE = 8, + EDP_CONTEXT_IS_COPY_EXEMPT = 16, + EDP_CONTEXT_IS_DENIED = 32, +} EDP_CONTEXT_STATES; + +typedef struct _EDP_CONTEXT +{ + EDP_CONTEXT_STATES contextStates; + ULONG allowedEnterpriseIdCount; + PWSTR enterpriseIdForUIEnforcement; + WCHAR allowedEnterpriseIds[1]; +} EDP_CONTEXT, *PEDP_CONTEXT; + +static HRESULT (WINAPI* EdpGetContextForWindow_I)( + _In_ HWND WindowHandle, + _Out_ PEDP_CONTEXT* EdpContext + ) = NULL; + +static HRESULT (WINAPI* EdpGetContextForProcess_I)( + _In_ ULONG ProcessId, + _Out_ PEDP_CONTEXT* EdpContext + ) = NULL; + +static VOID (WINAPI* EdpFreeContext_I)( + _In_ PEDP_CONTEXT EdpContext + ) = NULL; + #endif diff --git a/ProcessHacker/phlib/include/exlf.h b/ProcessHacker/phlib/include/exlf.h index 8aba12ab..5430c75d 100644 --- a/ProcessHacker/phlib/include/exlf.h +++ b/ProcessHacker/phlib/include/exlf.h @@ -2,7 +2,7 @@ #define _PH_EXLF_H /* - * This file contains the required types for ELF bianires. + * This file contains the required types for ELF binaries. * * References: * http://man7.org/linux/man-pages/man5/elf.5.html diff --git a/ProcessHacker/phlib/include/exprodid.h b/ProcessHacker/phlib/include/exprodid.h index e2653e53..0d49a45b 100644 --- a/ProcessHacker/phlib/include/exprodid.h +++ b/ProcessHacker/phlib/include/exprodid.h @@ -296,7 +296,6 @@ typedef enum _PRODID prodidUtc1900_POGO_O_CPP = 0x010e } PRODID; -// private #define DwProdidFromProdidWBuild(Prodid, Build) ((((ULONG)(Prodid)) << 16) | (Build)) #define ProdidFromDwProdid(Prodid) ((PRODID)((Prodid) >> 16)) #define WBuildFromDwProdid(Prodid) ((Prodid) & 0xFFFF) diff --git a/ProcessHacker/phlib/include/guisup.h b/ProcessHacker/phlib/include/guisup.h index 40954d26..1fe9e230 100644 --- a/ProcessHacker/phlib/include/guisup.h +++ b/ProcessHacker/phlib/include/guisup.h @@ -11,10 +11,6 @@ extern "C" { // guisup -typedef BOOL (WINAPI *_IsImmersiveProcess)( - _In_ HANDLE ProcessHandle - ); - #define RFF_NOBROWSE 0x0001 #define RFF_NODEFAULT 0x0002 #define RFF_CALCDIRECTORY 0x0004 @@ -46,7 +42,6 @@ typedef HANDLE HTHEME; #define DCX_USESTYLE 0x00010000 #define DCX_NODELETERGN 0x00040000 -extern _IsImmersiveProcess IsImmersiveProcess_I; extern PH_INTEGER_PAIR PhSmallIconSize; extern PH_INTEGER_PAIR PhLargeIconSize; @@ -441,6 +436,24 @@ PhCreateDialog( _In_opt_ PVOID Parameter ); +PHLIBAPI +HWND +NTAPI +PhCreateWindow( + _In_ ULONG ExStyle, + _In_opt_ PCWSTR ClassName, + _In_opt_ PCWSTR WindowName, + _In_ ULONG Style, + _In_ INT X, + _In_ INT Y, + _In_ INT Width, + _In_ INT Height, + _In_opt_ HWND ParentWindow, + _In_opt_ HMENU MenuHandle, + _In_opt_ PVOID InstanceHandle, + _In_opt_ PVOID Parameter + ); + PHLIBAPI BOOLEAN PhModalPropertySheet( _Inout_ PROPSHEETHEADER *Header @@ -949,6 +962,13 @@ PhGetGlobalTimerQueue( VOID ); +PHLIBAPI +BOOLEAN +NTAPI +PhIsImmersiveProcess( + _In_ HANDLE ProcessHandle + ); + _Success_(return) PHLIBAPI BOOLEAN @@ -1063,7 +1083,8 @@ PhImageListDrawIcon( _In_ HDC Hdc, _In_ INT x, _In_ INT y, - _In_ UINT Style + _In_ UINT Style, + _In_ BOOLEAN Disabled ); PHLIBAPI @@ -1079,7 +1100,8 @@ PhImageListDrawEx( _In_ INT dy, _In_ COLORREF BackColor, _In_ COLORREF ForeColor, - _In_ UINT Style + _In_ UINT Style, + _In_ DWORD State ); #define PH_DRAW_TIMELINE_OVERFLOW 0x1 @@ -1103,6 +1125,7 @@ PHLIBAPI extern HFONT PhTreeWindowFont; // phapppub PHLIBAPI extern HBRUSH PhMenuBackgroundBrush; extern COLORREF PhThemeWindowForegroundColor; extern COLORREF PhThemeWindowBackgroundColor; +extern COLORREF PhThemeWindowTextColor; PHLIBAPI VOID @@ -1133,6 +1156,16 @@ PhInitializeThemeWindowFrame( _In_ HWND WindowHandle ); +PHLIBAPI +HBRUSH +NTAPI +PhWindowThemeControlColor( + _In_ HWND WindowHandle, + _In_ HDC Hdc, + _In_ HWND ChildWindowHandle, + _In_ INT Type + ); + PHLIBAPI VOID NTAPI @@ -1215,6 +1248,34 @@ PhDuplicateFontWithNewHeight( return NULL; } +FORCEINLINE +VOID +PhInflateRect( + _In_ PRECT Rect, + _In_ INT dx, + _In_ INT dy + ) +{ + Rect->left -= dx; + Rect->top -= dy; + Rect->right += dx; + Rect->bottom += dy; +} + +FORCEINLINE +VOID +PhOffsetRect( + _In_ PRECT Rect, + _In_ INT dx, + _In_ INT dy + ) +{ + Rect->left += dx; + Rect->top += dy; + Rect->right += dx; + Rect->bottom += dy; +} + #ifdef __cplusplus } #endif diff --git a/ProcessHacker/phlib/include/handlep.h b/ProcessHacker/phlib/include/handlep.h index 06cf2cf8..580d1f4a 100644 --- a/ProcessHacker/phlib/include/handlep.h +++ b/ProcessHacker/phlib/include/handlep.h @@ -56,7 +56,7 @@ FORCEINLINE VOID PhpUnlockHandleTableShared( PhReleaseQueuedLockShared(&HandleTable->Locks[Index]); } -// Handle values work by specifying indicies into each +// Handle values work by specifying indices into each // level. // // Bits 0-7: level 0 diff --git a/ProcessHacker/phlib/include/json.h b/ProcessHacker/phlib/include/json.h index 27ba6163..1aa45b52 100644 --- a/ProcessHacker/phlib/include/json.h +++ b/ProcessHacker/phlib/include/json.h @@ -40,6 +40,14 @@ PhCreateJsonParser( _In_ PSTR JsonString ); +PHLIBAPI +PVOID +NTAPI +PhCreateJsonParserEx( + _In_ PVOID JsonString, + _In_ BOOLEAN Unicode + ); + PHLIBAPI VOID NTAPI @@ -243,6 +251,15 @@ PhSaveJsonObjectToFile( _In_ PVOID Object ); +// XML + +PHLIBAPI +PVOID +NTAPI +PhLoadXmlObjectFromString( + _In_ PSTR String + ); + PHLIBAPI NTSTATUS NTAPI @@ -267,10 +284,29 @@ PhFreeXmlObject( _In_ PVOID XmlRootObject ); +PHLIBAPI +PVOID +NTAPI +PhGetXmlObject( + _In_ PVOID XmlNodeObject, + _In_ PSTR Path + ); + +PHLIBAPI +PVOID +NTAPI +PhFindXmlObject( + _In_ PVOID XmlNodeObject, + _In_opt_ PVOID XmlTopObject, + _In_opt_ PSTR Element, + _In_opt_ PSTR Attribute, + _In_opt_ PSTR Value + ); + PHLIBAPI PPH_STRING NTAPI -PhGetOpaqueXmlNodeText( +PhGetXmlNodeOpaqueText( _In_ PVOID XmlNodeObject ); @@ -344,15 +380,110 @@ PhCreateXmlOpaqueNode( _In_ PSTR Value ); -typedef BOOLEAN (NTAPI* PPH_ENUM_XML_NODE_CALLBACK)( +typedef PVOID (NTAPI* PH_XML_LOAD_OBJECT_FROM_STRING)( + _In_ PSTR String + ); + +typedef NTSTATUS (NTAPI* PH_XML_LOAD_OBJECT_FROM_FILE)( + _In_ PWSTR FileName, + _Out_opt_ PVOID* XmlRootNode + ); + +typedef NTSTATUS (NTAPI* PH_XML_SAVE_OBJECT_TO_FILE)( + _In_ PWSTR FileName, + _In_ PVOID XmlRootObject, + _In_opt_ PVOID XmlSaveCallback + ); + +typedef VOID (NTAPI* PH_XML_FREE_OBJECT)( + _In_ PVOID XmlRootObject + ); + +typedef PVOID (NTAPI* PH_XML_GET_OBJECT)( _In_ PVOID XmlNodeObject, - _In_opt_ PVOID Context + _In_ PSTR Path ); -BOOLEAN PhEnumXmlNode( +typedef PVOID (NTAPI* PH_XML_CREATE_NODE)( + _In_opt_ PVOID ParentNode, + _In_ PSTR Name + ); + +typedef PVOID (NTAPI* PH_XML_CREATE_OPAQUE_NODE)( + _In_opt_ PVOID ParentNode, + _In_ PSTR Value + ); + +typedef PVOID (NTAPI* PH_XML_FIND_OBJECT)( _In_ PVOID XmlNodeObject, - _In_ PPH_ENUM_XML_NODE_CALLBACK Callback, - _In_opt_ PVOID Context + _In_ PVOID XmlTopObject, + _In_ PSTR Element, + _In_ PSTR Attribute, + _In_ PSTR Value + ); + +typedef PVOID (NTAPI* PH_XML_GET_NODE_FIRST_CHILD)( + _In_ PVOID XmlNodeObject + ); + +typedef PVOID (NTAPI* PH_XML_GET_NODE_NEXT_CHILD)( + _In_ PVOID XmlNodeObject + ); + +typedef PPH_STRING (NTAPI* PH_XML_GET_XML_NODE_OPAQUE_TEXT)( + _In_ PVOID XmlNodeObject + ); + +typedef PSTR (NTAPI* PH_XML_GET_XML_NODE_ELEMENT_TEXT)( + _In_ PVOID XmlNodeObject + ); + +typedef PPH_STRING (NTAPI* PH_XML_GET_XML_NODE_ATTRIBUTE_TEXT)( + _In_ PVOID XmlNodeObject, + _In_ PSTR AttributeName + ); + +typedef PSTR (NTAPI* PH_XML_GET_XML_NODE_ATTRIBUTE_BY_INDEX)( + _In_ PVOID XmlNodeObject, + _In_ INT Index, + _Out_ PSTR* AttributeName + ); + +typedef VOID (NTAPI* PH_XML_SET_XML_NODE_ATTRIBUTE_TEXT)( + _In_ PVOID XmlNodeObject, + _In_ PSTR Name, + _In_ PSTR Value + ); + +typedef INT (NTAPI* PH_XML_GET_XML_NODE_ATTRIBUTE_COUNT)( + _In_ PVOID XmlNodeObject + ); + +typedef struct _PH_XML_INTERFACE +{ + ULONG Version; + PH_XML_LOAD_OBJECT_FROM_STRING LoadXmlObjectFromString; + PH_XML_LOAD_OBJECT_FROM_FILE LoadXmlObjectFromFile; + PH_XML_SAVE_OBJECT_TO_FILE SaveXmlObjectToFile; + PH_XML_FREE_OBJECT FreeXmlObject; + PH_XML_GET_OBJECT GetXmlObject; + PH_XML_CREATE_NODE CreateXmlNode; + PH_XML_CREATE_OPAQUE_NODE CreateXmlOpaqueNode; + PH_XML_FIND_OBJECT FindXmlObject; + PH_XML_GET_NODE_FIRST_CHILD GetXmlNodeFirstChild; + PH_XML_GET_NODE_NEXT_CHILD GetXmlNodeNextChild; + PH_XML_GET_XML_NODE_OPAQUE_TEXT GetXmlNodeOpaqueText; + PH_XML_GET_XML_NODE_ELEMENT_TEXT GetXmlNodeElementText; + PH_XML_GET_XML_NODE_ATTRIBUTE_TEXT GetXmlNodeAttributeText; + PH_XML_GET_XML_NODE_ATTRIBUTE_BY_INDEX GetXmlNodeAttributeByIndex; + PH_XML_SET_XML_NODE_ATTRIBUTE_TEXT SetXmlNodeAttributeText; + PH_XML_GET_XML_NODE_ATTRIBUTE_COUNT GetXmlNodeAttributeCount; +} PH_XML_INTERFACE, *PPH_XML_INTERFACE; + +#define PH_XML_INTERFACE_VERSION 1 + +PPH_XML_INTERFACE PhGetXmlInterface( + _In_ ULONG Version ); #ifdef __cplusplus diff --git a/ProcessHacker/phlib/include/mapimg.h b/ProcessHacker/phlib/include/mapimg.h index af6eb8ee..9a8e957c 100644 --- a/ProcessHacker/phlib/include/mapimg.h +++ b/ProcessHacker/phlib/include/mapimg.h @@ -633,14 +633,14 @@ typedef struct _CODEVIEW_INFO_PDB70 CHAR ImageName[1]; } CODEVIEW_INFO_PDB70, *PCODEVIEW_INFO_PDB70; -#ifndef IMAGE_GUARD_XFG_ENABLED -#define IMAGE_GUARD_XFG_ENABLED 0x00800000 // Module was built with xfg -#endif - // IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT, Windows 20H1 and 21H1 have different values #define IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT_V1 0x00200000 #define IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT_V2 0x00400000 +#ifndef IMAGE_GUARD_XFG_ENABLED +#define IMAGE_GUARD_XFG_ENABLED 0x00800000 // Module was built with xfg +#endif + PHLIBAPI NTSTATUS NTAPI diff --git a/ProcessHacker/phlib/include/ph.h b/ProcessHacker/phlib/include/ph.h index c9512a3c..b894e19b 100644 --- a/ProcessHacker/phlib/include/ph.h +++ b/ProcessHacker/phlib/include/ph.h @@ -6,12 +6,4 @@ #include #include -#ifndef IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT -#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 -#endif - -#ifndef IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS -#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 -#endif - #endif diff --git a/ProcessHacker/phlib/include/phbasesup.h b/ProcessHacker/phlib/include/phbasesup.h index 78c4f44a..eee0cab5 100644 --- a/ProcessHacker/phlib/include/phbasesup.h +++ b/ProcessHacker/phlib/include/phbasesup.h @@ -1028,7 +1028,7 @@ FORCEINLINE VOID PhSkipStringRef( _Inout_ PPH_STRINGREF String, - _In_ LONG_PTR Length + _In_ SIZE_T Length ) { String->Buffer = (PWCH)PTR_ADD_OFFSET(String->Buffer, Length); @@ -3017,6 +3017,22 @@ PhHashStringRef( _In_ BOOLEAN IgnoreCase ); +typedef enum _PH_STRING_HASH +{ + PH_STRING_HASH_DEFAULT, + PH_STRING_HASH_FNV1A, + PH_STRING_HASH_X65599, +} PH_STRING_HASH; + +PHLIBAPI +ULONG +NTAPI +PhHashStringRefEx( + _In_ PPH_STRINGREF String, + _In_ BOOLEAN IgnoreCase, + _In_ PH_STRING_HASH HashAlgorithm + ); + FORCEINLINE ULONG PhHashInt32( diff --git a/ProcessHacker/phlib/include/phconfig.h b/ProcessHacker/phlib/include/phconfig.h index b21e1514..5d5b8f4a 100644 --- a/ProcessHacker/phlib/include/phconfig.h +++ b/ProcessHacker/phlib/include/phconfig.h @@ -34,7 +34,9 @@ extern ULONG WindowsVersion; #define WINDOWS_10_20H1 109 // May, 2020 #define WINDOWS_10_20H2 110 // October, 2020 #define WINDOWS_10_21H1 111 // May, 2021 -#define WINDOWS_11 112 +#define WINDOWS_10_21H2 112 // November, 2021 +#define WINDOWS_11 113 // October, 2021 +#define WINDOWS_11_22H1 114 // February, 2022 #define WINDOWS_NEW ULONG_MAX // Debugging diff --git a/ProcessHacker/phlib/include/phnative.h b/ProcessHacker/phlib/include/phnative.h index 9898df90..71a66662 100644 --- a/ProcessHacker/phlib/include/phnative.h +++ b/ProcessHacker/phlib/include/phnative.h @@ -738,6 +738,14 @@ PhGetProcessIdsUsingFile( _Out_ PFILE_PROCESS_IDS_USING_FILE_INFORMATION *ProcessIdsUsingFile ); +PHLIBAPI +NTSTATUS +NTAPI +PhGetFileUsn( + _In_ HANDLE FileHandle, + _Out_ PLONGLONG Usn + ); + PHLIBAPI NTSTATUS NTAPI @@ -1314,6 +1322,7 @@ typedef struct _PH_MODULE_INFO ULONG Type; PVOID BaseAddress; PVOID ParentBaseAddress; + PVOID OriginalBaseAddress; ULONG Size; PVOID EntryPoint; ULONG Flags; @@ -1758,6 +1767,14 @@ PhGetThreadName( _Out_ PPH_STRING *ThreadName ); +PHLIBAPI +NTSTATUS +NTAPI +PhSetThreadName( + _In_ HANDLE ThreadHandle, + _In_ PCWSTR ThreadName + ); + PHLIBAPI NTSTATUS NTAPI @@ -1777,6 +1794,7 @@ typedef struct _PH_PROCESS_DEBUG_HEAP_ENTRY { ULONG Flags; ULONG Signature; + UCHAR HeapFrontEndType; ULONG NumberOfEntries; PVOID BaseAddress; SIZE_T BytesAllocated; @@ -1787,6 +1805,7 @@ typedef struct _PH_PROCESS_DEBUG_HEAP_ENTRY32 { ULONG Flags; ULONG Signature; + UCHAR HeapFrontEndType; ULONG NumberOfEntries; ULONG BaseAddress; ULONG BytesAllocated; @@ -1807,6 +1826,31 @@ typedef struct _PH_PROCESS_DEBUG_HEAP_INFORMATION32 PH_PROCESS_DEBUG_HEAP_ENTRY32 Heaps[1]; } PH_PROCESS_DEBUG_HEAP_INFORMATION32, *PPH_PROCESS_DEBUG_HEAP_INFORMATION32; +typedef struct _PH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64 { + DWORD BeginAddress; + DWORD EndAddress; + union { + DWORD UnwindInfoAddress; + DWORD UnwindData; + } DUMMYUNIONNAME; +} PH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64, *PPH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64; + +typedef struct _PH_IMAGE_RUNTIME_FUNCTION_ENTRY_ARM64 { + DWORD BeginAddress; + union { + DWORD UnwindData; + struct { + DWORD Flag : 2; + DWORD FunctionLength : 11; + DWORD RegF : 3; + DWORD RegI : 4; + DWORD H : 1; + DWORD CR : 2; + DWORD FrameSize : 9; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; +} PH_IMAGE_RUNTIME_FUNCTION_ENTRY_ARM64, *PPH_IMAGE_RUNTIME_FUNCTION_ENTRY_ARM64; + PHLIBAPI NTSTATUS NTAPI @@ -1840,6 +1884,80 @@ PhGetThreadLastStatusValue( _Out_ PNTSTATUS LastStatusValue ); +typedef enum tagOLETLSFLAGS +{ + OLETLS_LOCALTID = 0x01, // This TID is in the current process. + OLETLS_UUIDINITIALIZED = 0x02, // This Logical thread is init'd. + OLETLS_INTHREADDETACH = 0x04, // This is in thread detach. + OLETLS_CHANNELTHREADINITIALZED = 0x08,// This channel has been init'd + OLETLS_WOWTHREAD = 0x10, // This thread is a 16-bit WOW thread. + OLETLS_THREADUNINITIALIZING = 0x20, // This thread is in CoUninitialize. + OLETLS_DISABLE_OLE1DDE = 0x40, // This thread can't use a DDE window. + OLETLS_APARTMENTTHREADED = 0x80, // This is an STA apartment thread + OLETLS_MULTITHREADED = 0x100, // This is an MTA apartment thread + OLETLS_IMPERSONATING = 0x200, // This thread is impersonating + OLETLS_DISABLE_EVENTLOGGER = 0x400, // Prevent recursion in event logger + OLETLS_INNEUTRALAPT = 0x800, // This thread is in the NTA + OLETLS_DISPATCHTHREAD = 0x1000, // This is a dispatch thread + OLETLS_HOSTTHREAD = 0x2000, // This is a host thread + OLETLS_ALLOWCOINIT = 0x4000, // This thread allows inits + OLETLS_PENDINGUNINIT = 0x8000, // This thread has pending uninit + OLETLS_FIRSTMTAINIT = 0x10000,// First thread to attempt an MTA init + OLETLS_FIRSTNTAINIT = 0x20000,// First thread to attempt an NTA init + OLETLS_APTINITIALIZING = 0x40000, // Apartment Object is initializing + OLETLS_UIMSGSINMODALLOOP = 0x80000, + OLETLS_MARSHALING_ERROR_OBJECT = 0x100000, + OLETLS_WINRT_INITIALIZE = 0x200000, + OLETLS_APPLICATION_STA = 0x400000, + OLETLS_IN_SHUTDOWN_CALLBACKS = 0x800000, + OLETLS_POINTER_INPUT_BLOCKED = 0x1000000, + OLETLS_IN_ACTIVATION_FILTER = 0x2000000, + OLETLS_ASTATOASTAEXEMPT_QUIRK = 0x4000000, + OLETLS_ASTATOASTAEXEMPT_PROXY = 0x8000000, + OLETLS_ASTATOASTAEXEMPT_INDOUBT = 0x10000000, + OLETLS_DETECTED_USER_INITIALIZED = 0x20000000, + OLETLS_BRIDGE_STA = 0x40000000, + OLETLS_NAINITIALIZING = 0x80000000UL +} OLETLSFLAGS, *POLETLSFLAGS; + +PHLIBAPI +NTSTATUS +NTAPI +PhGetThreadApartmentState( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ProcessHandle, + _Out_ POLETLSFLAGS ApartmentState + ); + +PHLIBAPI +NTSTATUS +NTAPI +PhGetThreadStackLimits( + _In_ HANDLE ThreadHandle, + _In_ HANDLE ProcessHandle, + _Out_ PULONG_PTR LowPart, + _Out_ PULONG_PTR HighPart + ); + +PHLIBAPI +NTSTATUS +NTAPI +PhGetThreadStackSize( + _In_ HANDLE ThreadHandle, + _In_ HANDLE ProcessHandle, + _Out_ PULONG_PTR StackUsage, + _Out_ PULONG_PTR StackLimit + ); + +PHLIBAPI +NTSTATUS +NTAPI +PhGetThreadIsFiber( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ProcessHandle, + _Out_ PBOOLEAN ThreadIsFiber + ); + PHLIBAPI BOOLEAN NTAPI @@ -1862,6 +1980,34 @@ PhDestroyExecutionRequiredRequest( _In_ HANDLE PowerRequestHandle ); +PHLIBAPI +BOOLEAN +NTAPI +PhIsProcessStateFrozen( + _In_ HANDLE ProcessId + ); + +PHLIBAPI +NTSTATUS +NTAPI +PhFreezeProcess( + _In_ HANDLE ProcessId + ); + +PHLIBAPI +NTSTATUS +NTAPI +PhThawProcess( + _In_ HANDLE ProcessId + ); + +PHLIBAPI +BOOLEAN +NTAPI +PhIsKnownDllFileName( + _In_ PPH_STRING FileName + ); + #ifdef __cplusplus } #endif diff --git a/ProcessHacker/phlib/include/phnativeinl.h b/ProcessHacker/phlib/include/phnativeinl.h index 15b40d7c..b21500f5 100644 --- a/ProcessHacker/phlib/include/phnativeinl.h +++ b/ProcessHacker/phlib/include/phnativeinl.h @@ -632,6 +632,38 @@ PhGetProcessIsCFGuardEnabled( return status; } +FORCEINLINE +NTSTATUS +PhGetProcessIsXFGuardEnabled( + _In_ HANDLE ProcessHandle, + _Out_ PBOOLEAN IsXFGuardEnabled +) +{ + NTSTATUS status; + PROCESS_MITIGATION_POLICY_INFORMATION policyInfo; + + policyInfo.Policy = ProcessControlFlowGuardPolicy; + + status = NtQueryInformationProcess( + ProcessHandle, + ProcessMitigationPolicy, + &policyInfo, + sizeof(PROCESS_MITIGATION_POLICY_INFORMATION), + NULL + ); + + if (NT_SUCCESS(status)) + { +#if !defined(NTDDI_WIN10_CO) || (NTDDI_VERSION < NTDDI_WIN10_CO) + *IsXFGuardEnabled = _bittest((const PLONG)&policyInfo.ControlFlowGuardPolicy.Flags, 3); +#else + *IsXFGuardEnabled = !!policyInfo.ControlFlowGuardPolicy.EnableXfg; +#endif + } + + return status; +} + FORCEINLINE NTSTATUS PhGetProcessHandleCount( diff --git a/ProcessHacker/phlib/include/phnet.h b/ProcessHacker/phlib/include/phnet.h index 05780e20..36d54969 100644 --- a/ProcessHacker/phlib/include/phnet.h +++ b/ProcessHacker/phlib/include/phnet.h @@ -177,6 +177,21 @@ PhHttpSocketDestroy( _In_ _Frees_ptr_ PPH_HTTP_CONTEXT HttpContext ); +typedef enum _PH_HTTP_SOCKET_CLOSE_TYPE +{ + PH_HTTP_SOCKET_CLOSE_SESSION = 0x0, + PH_HTTP_SOCKET_CLOSE_CONNECTION = 0x1, + PH_HTTP_SOCKET_CLOSE_REQUEST = 0x2, +} PH_HTTP_SOCKET_CLOSE_TYPE; + +PHLIBAPI +VOID +NTAPI +PhHttpSocketClose( + _In_ PPH_HTTP_CONTEXT HttpContext, + _In_ PH_HTTP_SOCKET_CLOSE_TYPE Type + ); + #define PH_HTTP_DEFAULT_PORT 0 // use the protocol-specific default port #define PH_HTTP_DEFAULT_HTTP_PORT 80 #define PH_HTTP_DEFAULT_HTTPS_PORT 443 diff --git a/ProcessHacker/phlib/include/phsup.h b/ProcessHacker/phlib/include/phsup.h index ad2ae463..0caec22f 100644 --- a/ProcessHacker/phlib/include/phsup.h +++ b/ProcessHacker/phlib/include/phsup.h @@ -417,14 +417,6 @@ FORCEINLINE VOID PhPrintUInt32( _ultow(UInt32, Destination, 10); } -FORCEINLINE VOID PhPrintUInt32Hex( - _Out_writes_(PH_PTR_STR_LEN_1) PWSTR Destination, - _In_ ULONG UInt32 - ) -{ - _ultow(UInt32, Destination, 16); -} - FORCEINLINE VOID PhPrintInt64( _Out_writes_(PH_INT64_STR_LEN_1) PWSTR Destination, _In_ LONG64 Int64 @@ -472,6 +464,21 @@ FORCEINLINE ULONG PhCountBits( return count; } +FORCEINLINE ULONG PhCountBitsUlongPtr( + _In_ ULONG_PTR Value + ) +{ + ULONG count = 0; + + while (Value) + { + count++; + Value &= Value - 1; + } + + return count; +} + FORCEINLINE ULONG64 PhRoundNumber( _In_ ULONG64 Value, _In_ ULONG64 Granularity diff --git a/ProcessHacker/phlib/include/phutil.h b/ProcessHacker/phlib/include/phutil.h index 6735d555..4a07e3fb 100644 --- a/ProcessHacker/phlib/include/phutil.h +++ b/ProcessHacker/phlib/include/phutil.h @@ -7,6 +7,7 @@ extern "C" { extern WCHAR *PhSizeUnitNames[7]; extern ULONG PhMaxSizeUnit; +extern USHORT PhMaxPrecisionUnit; typedef struct _PH_INTEGER_PAIR { @@ -1338,15 +1339,16 @@ PhGetDllFileName( PHLIBAPI PVOID NTAPI -PhGetLoaderEntryDllBase( - _In_ PWSTR DllName +PhGetLoaderEntryStringRefDllBase( + _In_opt_ PPH_STRINGREF FullDllName, + _In_opt_ PPH_STRINGREF BaseDllName ); PHLIBAPI PVOID NTAPI -PhGetLoaderEntryFullDllBase( - _In_ PWSTR FullDllName +PhGetLoaderEntryDllBase( + _In_ PWSTR DllName ); PHLIBAPI @@ -1358,6 +1360,15 @@ PhGetDllBaseProcedureAddress( _In_opt_ USHORT ProcedureNumber ); +PHLIBAPI +PVOID +NTAPI +PhGetDllBaseProcedureAddressWithHint( + _In_ PVOID BaseAddress, + _In_ PSTR ProcedureName, + _In_ USHORT ProcedureHint + ); + PHLIBAPI PVOID NTAPI @@ -1452,6 +1463,14 @@ PhLoaderEntryLoadDll( _Out_ PVOID* BaseAddress ); +PHLIBAPI +NTSTATUS +NTAPI +PhLoaderEntryLoadAllImportsForDll( + _In_ PVOID BaseAddress, + _In_ PSTR ImportDllName + ); + PHLIBAPI NTSTATUS NTAPI @@ -1499,10 +1518,9 @@ PhGetClassObject( ); PHLIBAPI -_Ret_maybenull_ PVOID NTAPI -PhLoadLibrarySafe( +PhLoadLibrary( _In_ PCWSTR LibFileName ); @@ -1528,6 +1546,35 @@ PhDelayExecution( _In_ ULONG Milliseconds ); +PHLIBAPI +ULONGLONG +NTAPI +PhReadTimeStampCounter( + VOID + ); + +PHLIBAPI +VOID +NTAPI +PhQueryPerformanceCounter( + _Out_ PLARGE_INTEGER PerformanceCounter, + _Out_opt_ PLARGE_INTEGER PerformanceFrequency + ); + +PHLIBAPI +VOID +NTAPI +PhQueryPerformanceFrequency( + _Out_ PLARGE_INTEGER PerformanceFrequency + ); + +PHLIBAPI +PPH_STRING +NTAPI +PhApiSetResolveToHost( + _In_ PPH_STRINGREF ApiSetName + ); + #ifdef __cplusplus } #endif diff --git a/ProcessHacker/phlib/include/settings.h b/ProcessHacker/phlib/include/settings.h index 1359296c..534dbefc 100644 --- a/ProcessHacker/phlib/include/settings.h +++ b/ProcessHacker/phlib/include/settings.h @@ -134,7 +134,7 @@ PhGetExpandStringSetting( setting = PhGetStringSetting(Name); #ifdef __cplusplus - PhMoveReference((PVOID*)&setting, PhExpandEnvironmentStrings(&setting->sr)); + PhMoveReference(reinterpret_cast(&setting), PhExpandEnvironmentStrings(&setting->sr)); #else PhMoveReference(&setting, PhExpandEnvironmentStrings(&setting->sr)); #endif diff --git a/ProcessHacker/phlib/include/svcsup.h b/ProcessHacker/phlib/include/svcsup.h index e91b24b0..0eb5c340 100644 --- a/ProcessHacker/phlib/include/svcsup.h +++ b/ProcessHacker/phlib/include/svcsup.h @@ -23,19 +23,16 @@ PhEnumServices( PHLIBAPI SC_HANDLE NTAPI -PhOpenService( - _In_ PWSTR ServiceName, - _In_ ACCESS_MASK DesiredAccess +PhGetServiceManagerHandle( + VOID ); PHLIBAPI -NTSTATUS +SC_HANDLE NTAPI -PhOpenServiceEx( +PhOpenService( _In_ PWSTR ServiceName, - _In_ ACCESS_MASK DesiredAccess, - _In_opt_ SC_HANDLE ScManagerHandle, - _Out_ SC_HANDLE* ServiceHandle + _In_ ACCESS_MASK DesiredAccess ); PHLIBAPI diff --git a/ProcessHacker/phlib/include/symprvp.h b/ProcessHacker/phlib/include/symprvp.h index a1b5f7de..f8bd2951 100644 --- a/ProcessHacker/phlib/include/symprvp.h +++ b/ProcessHacker/phlib/include/symprvp.h @@ -200,13 +200,28 @@ typedef ULONG (WINAPI *_UnDecorateSymbolNameW)( ); // undocumented -typedef BOOL (WINAPI* _SymGetDiaSession)( +typedef BOOLEAN (WINAPI *_SymGetDiaSource)( + _In_ HANDLE ProcessHandle, + _In_ ULONG64 BaseOfDll, + _Out_ PVOID* IDiaDataSource + ); + +// undocumented +typedef BOOLEAN (WINAPI *_SymGetDiaSession)( _In_ HANDLE ProcessHandle, _In_ ULONG64 BaseOfDll, _Out_ PVOID* IDiaSession ); -typedef VOID (WINAPI* _SymFreeDiaString)( +// undocumented +typedef BOOLEAN (WINAPI *_SymSetDiaSession)( + _In_ HANDLE ProcessHandle, + _In_ ULONG64 BaseOfDll, + _In_ PVOID IDiaSession + ); + +// undocumented +typedef VOID (WINAPI *_SymFreeDiaString)( _In_ PWSTR DiaString ); diff --git a/ProcessHacker/phlib/include/treenew.h b/ProcessHacker/phlib/include/treenew.h index 3619d1de..dc0e53e5 100644 --- a/ProcessHacker/phlib/include/treenew.h +++ b/ProcessHacker/phlib/include/treenew.h @@ -111,6 +111,7 @@ typedef struct _PH_TREENEW_NODE #define TN_STYLE_NO_COLUMN_HEADER 0x80 #define TN_STYLE_CUSTOM_COLORS 0x100 #define TN_STYLE_ALWAYS_SHOW_SELECTION 0x200 +#define TN_STYLE_CUSTOM_HEADERDRAW 0x400 // Extended flags #define TN_FLAG_ITEM_DRAG_SELECT 0x1 @@ -216,6 +217,7 @@ typedef enum _PH_TREENEW_MESSAGE TreeNewKeyDown, // PPH_TREENEW_KEY_EVENT Parameter1 TreeNewLeftClick, // PPH_TREENEW_MOUSE_EVENT Parameter1 TreeNewRightClick, // PPH_TREENEW_MOUSE_EVENT Parameter1 + TreeNewMiddleClick, // PPH_TREENEW_MOUSE_EVENT Parameter1 TreeNewLeftDoubleClick, // PPH_TREENEW_MOUSE_EVENT Parameter1 TreeNewRightDoubleClick, // PPH_TREENEW_MOUSE_EVENT Parameter1 TreeNewContextMenu, // PPH_TREENEW_CONTEXT_MENU Parameter1 @@ -229,6 +231,8 @@ typedef enum _PH_TREENEW_MESSAGE TreeNewDestroying, TreeNewGetDialogCode, // ULONG Parameter1, PULONG Parameter2 + TreeNewGetHeaderText, + MaxTreeNewMessage } PH_TREENEW_MESSAGE; @@ -360,6 +364,14 @@ typedef struct _PH_TREENEW_SEARCH_EVENT PH_STRINGREF String; } PH_TREENEW_SEARCH_EVENT, *PPH_TREENEW_SEARCH_EVENT; +typedef struct _PH_TREENEW_GET_HEADER_TEXT +{ + PPH_TREENEW_COLUMN Column; + PH_STRINGREF Text; + PWSTR TextCache; + ULONG TextCacheSize; +} PH_TREENEW_GET_HEADER_TEXT, *PPH_TREENEW_GET_HEADER_TEXT; + #define TNM_FIRST (WM_USER + 1) #define TNM_SETCALLBACK (WM_USER + 1) #define TNM_NODESADDED (WM_USER + 2) // unimplemented diff --git a/ProcessHacker/phlib/include/treenewp.h b/ProcessHacker/phlib/include/treenewp.h index cd82157f..9997273c 100644 --- a/ProcessHacker/phlib/include/treenewp.h +++ b/ProcessHacker/phlib/include/treenewp.h @@ -165,6 +165,22 @@ typedef struct _PH_TREENEW_CONTEXT WNDPROC HeaderWindowProc; WNDPROC FixedHeaderWindowProc; HIMAGELIST ImageListHandle; + + union + { + ULONG HeaderFlags; + struct + { + ULONG HeaderCustomDraw : 1; + ULONG HeaderMouseActive : 1; + ULONG HeaderDragging : 1; + ULONG HeaderUnused : 13; + + ULONG HeaderHotColumn : 16; // HACK (dmex) + }; + }; + HTHEME HeaderThemeHandle; + HFONT HeaderBoldFontHandle; } PH_TREENEW_CONTEXT, *PPH_TREENEW_CONTEXT; LRESULT CALLBACK PhTnpWndProc( diff --git a/ProcessHacker/phlib/include/verify.h b/ProcessHacker/phlib/include/verify.h index 6d13b945..2d2e471e 100644 --- a/ProcessHacker/phlib/include/verify.h +++ b/ProcessHacker/phlib/include/verify.h @@ -27,7 +27,7 @@ typedef enum _VERIFY_RESULT typedef struct _PH_VERIFY_FILE_INFO { - PWSTR FileName; + HANDLE FileHandle; ULONG Flags; // PH_VERIFY_* ULONG FileSizeLimitForHash; // 0 for PH_VERIFY_DEFAULT_SIZE_LIMIT, -1 for unlimited diff --git a/ProcessHacker/phlib/include/verifyp.h b/ProcessHacker/phlib/include/verifyp.h index 06bdae4b..fcd2280b 100644 --- a/ProcessHacker/phlib/include/verifyp.h +++ b/ProcessHacker/phlib/include/verifyp.h @@ -1,20 +1,21 @@ #ifndef _PH_VERIFYP_H #define _PH_VERIFYP_H -#include - typedef struct _PH_VERIFY_CACHE_ENTRY { - PH_AVL_LINKS Links; - PPH_STRING FileName; + ULONGLONG SequenceNumber; VERIFY_RESULT VerifyResult; PPH_STRING VerifySignerName; } PH_VERIFY_CACHE_ENTRY, *PPH_VERIFY_CACHE_ENTRY; -INT NTAPI PhpVerifyCacheCompareFunction( - _In_ PPH_AVL_LINKS Links1, - _In_ PPH_AVL_LINKS Links2 +BOOLEAN PhpVerifyCacheHashtableEqualFunction( + _In_ PVOID Entry1, + _In_ PVOID Entry2 + ); + +ULONG PhpVerifyCacheHashtableHashFunction( + _In_ PVOID Entry ); typedef struct _CATALOG_INFO @@ -35,7 +36,7 @@ typedef struct tagCRYPTUI_VIEWSIGNERINFO_STRUCT { ULONG cStores; HCERTSTORE *rghStores; ULONG cPropSheetPages; - LPCPROPSHEETPAGE rgPropSheetPages; + PVOID rgPropSheetPages; } CRYPTUI_VIEWSIGNERINFO_STRUCT, *PCRYPTUI_VIEWSIGNERINFO_STRUCT; typedef BOOL (WINAPI *_CryptCATAdminCalcHashFromFileHandle)( @@ -179,7 +180,7 @@ typedef struct _SIGNATURE_INFO } SIGNATURE_INFO, *PSIGNATURE_INFO; typedef HRESULT (WINAPI* _WTGetSignatureInfo)( - _In_ PCWSTR pszFile, + _In_opt_ PCWSTR pszFile, _In_opt_ HANDLE hFile, _In_ SIGNATURE_INFO_FLAGS sigInfoFlags, _Inout_ PSIGNATURE_INFO psiginfo, diff --git a/ProcessHacker/phlib/json.c b/ProcessHacker/phlib/json.c index 3e763014..75601cca 100644 --- a/ProcessHacker/phlib/json.c +++ b/ProcessHacker/phlib/json.c @@ -2,7 +2,7 @@ * Process Hacker - * json and xml wrapper * - * Copyright (C) 2017-2020 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -23,12 +23,11 @@ #include #include #include +#include #include "..\tools\thirdparty\jsonc\json.h" #include "..\tools\thirdparty\mxml\mxml.h" -#include - static json_object_ptr json_get_object( _In_ json_object_ptr rootObj, _In_ PSTR key @@ -51,6 +50,72 @@ PVOID PhCreateJsonParser( return json_tokener_parse(JsonString); } +PVOID PhCreateJsonParserEx( + _In_ PVOID JsonString, + _In_ BOOLEAN Unicode + ) +{ + json_tokener* tokenerObject; + json_object_ptr jsonObject; + + if (Unicode) + { + PPH_STRING jsonStringUtf16 = JsonString; + PPH_BYTES jsonStringUtf8; + + if (jsonStringUtf16->Length / sizeof(WCHAR) >= INT32_MAX) + return NULL; + if (!(tokenerObject = json_tokener_new())) + return NULL; + + json_tokener_set_flags( + tokenerObject, + JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8 + ); + + jsonStringUtf8 = PhConvertUtf16ToUtf8Ex( + jsonStringUtf16->Buffer, + jsonStringUtf16->Length + ); + jsonObject = json_tokener_parse_ex( + tokenerObject, + jsonStringUtf8->Buffer, + (INT)jsonStringUtf8->Length + ); + PhDereferenceObject(jsonStringUtf8); + } + else + { + PPH_BYTES jsonStringUtf8 = JsonString; + + if (jsonStringUtf8->Length >= INT32_MAX) + return NULL; + if (!(tokenerObject = json_tokener_new())) + return NULL; + + json_tokener_set_flags( + tokenerObject, + JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8 + ); + + jsonObject = json_tokener_parse_ex( + tokenerObject, + jsonStringUtf8->Buffer, + (INT)jsonStringUtf8->Length + ); + } + + if (json_tokener_get_error(tokenerObject) != json_tokener_success) + { + json_tokener_free(tokenerObject); + return NULL; + } + + json_tokener_free(tokenerObject); + + return jsonObject; +} + VOID PhFreeJsonObject( _In_ PVOID Object ) @@ -313,6 +378,29 @@ VOID PhSaveJsonObjectToFile( // XML support +PVOID PhLoadXmlObjectFromString( + _In_ PSTR String + ) +{ + mxml_node_t* currentNode; + + if (currentNode = mxmlLoadString( + NULL, + String, + MXML_OPAQUE_CALLBACK + )) + { + if (mxmlGetType(currentNode) == MXML_ELEMENT) + { + return currentNode; + } + + mxmlDelete(currentNode); + } + + return NULL; +} + NTSTATUS PhLoadXmlObjectFromFile( _In_ PWSTR FileName, _Out_opt_ PVOID* XmlRootObject @@ -424,6 +512,32 @@ NTSTATUS PhSaveXmlObjectToFile( return status; } +VOID PhFreeXmlObject( + _In_ PVOID XmlRootObject + ) +{ + mxmlDelete(XmlRootObject); +} + +PVOID PhGetXmlObject( + _In_ PVOID XmlNodeObject, + _In_ PSTR Path + ) +{ + mxml_node_t* currentNode; + mxml_node_t* realNode; + + if (currentNode = mxmlFindPath(XmlNodeObject, Path)) + { + if (realNode = mxmlGetParent(currentNode)) + return realNode; + + return currentNode; + } + + return NULL; +} + PVOID PhCreateXmlNode( _In_opt_ PVOID ParentNode, _In_ PSTR Name @@ -440,11 +554,15 @@ PVOID PhCreateXmlOpaqueNode( return mxmlNewOpaque(ParentNode, Value); } -VOID PhFreeXmlObject( - _In_ PVOID XmlRootObject +PVOID PhFindXmlObject( + _In_ PVOID XmlNodeObject, + _In_opt_ PVOID XmlTopObject, + _In_opt_ PSTR Element, + _In_opt_ PSTR Attribute, + _In_opt_ PSTR Value ) { - mxmlDelete(XmlRootObject); + return mxmlFindElement(XmlNodeObject, XmlTopObject, Element, Attribute, Value, MXML_DESCEND); } PVOID PhGetXmlNodeFirstChild( @@ -461,7 +579,7 @@ PVOID PhGetXmlNodeNextChild( return mxmlGetNextSibling(XmlNodeObject); } -PPH_STRING PhGetOpaqueXmlNodeText( +PPH_STRING PhGetXmlNodeOpaqueText( _In_ PVOID XmlNodeObject ) { @@ -549,3 +667,34 @@ BOOLEAN PhEnumXmlNode( return TRUE; } + +PPH_XML_INTERFACE PhGetXmlInterface( + _In_ ULONG Version + ) +{ + static PH_XML_INTERFACE PhXmlInterface = + { + PH_XML_INTERFACE_VERSION, + PhLoadXmlObjectFromString, + PhLoadXmlObjectFromFile, + PhSaveXmlObjectToFile, + PhFreeXmlObject, + PhGetXmlObject, + PhCreateXmlNode, + PhCreateXmlOpaqueNode, + PhFindXmlObject, + PhGetXmlNodeFirstChild, + PhGetXmlNodeNextChild, + PhGetXmlNodeOpaqueText, + PhGetXmlNodeElementText, + PhGetXmlNodeAttributeText, + PhGetXmlNodeAttributeByIndex, + PhSetXmlNodeAttributeText, + PhGetXmlNodeAttributeCount + }; + + if (Version < PH_XML_INTERFACE_VERSION) + return NULL; + + return &PhXmlInterface; +} diff --git a/ProcessHacker/phlib/kphdata.c b/ProcessHacker/phlib/kphdata.c index cb0a4832..c9637439 100644 --- a/ProcessHacker/phlib/kphdata.c +++ b/ProcessHacker/phlib/kphdata.c @@ -127,7 +127,7 @@ NTSTATUS KphInitializeDynamicPackage( Package->StructData.ObDecodeShift = 16; Package->StructData.ObAttributesShift = 17; } - // Windows 10, Windows Server 2016 + // Windows 10, Windows Server 2016, Windows 11, Windows Server 2022 else if (majorVersion == 10 && minorVersion == 0) { ULONG revisionNumber = KphpGetKernelRevisionNumber(); @@ -182,6 +182,14 @@ NTSTATUS KphInitializeDynamicPackage( Package->BuildNumber = 19043; Package->ResultingNtVersion = PHNT_21H1; break; + case 19044: + Package->BuildNumber = 19044; + Package->ResultingNtVersion = PHNT_21H2; + break; + case 22000: + Package->BuildNumber = 22000; + Package->ResultingNtVersion = PHNT_WIN11; + break; default: return STATUS_NOT_SUPPORTED; } @@ -352,6 +360,10 @@ NTSTATUS KphInitializeDynamicPackage( Package->BuildNumber = 19043; Package->ResultingNtVersion = PHNT_21H1; break; + case 19044: + Package->BuildNumber = 19044; + Package->ResultingNtVersion = PHNT_21H2; + break; default: return STATUS_NOT_SUPPORTED; } diff --git a/ProcessHacker/phlib/mapexlf.c b/ProcessHacker/phlib/mapexlf.c index b10371af..aa4fc2fb 100644 --- a/ProcessHacker/phlib/mapexlf.c +++ b/ProcessHacker/phlib/mapexlf.c @@ -248,10 +248,20 @@ ULONG64 PhGetMappedWslImageBaseAddress( { ULONG64 baseAddress = MAXULONG64; PELF64_IMAGE_SEGMENT_HEADER segment; + ULONG loadBias = 0; USHORT i; segment = IMAGE_FIRST_ELF64_SEGMENT(MappedWslImage); + for (i = 0; i < MappedWslImage->Headers64->e_phnum; i++) + { + if (segment[i].p_type == PT_LOAD) + { + loadBias = (ULONG)ALIGN_DOWN_BY(segment[i].p_vaddr, PAGE_SIZE); + break; + } + } + for (i = 0; i < MappedWslImage->Headers64->e_phnum; i++) { if (segment[i].p_type == PT_LOAD) diff --git a/ProcessHacker/phlib/mapimg.c b/ProcessHacker/phlib/mapimg.c index cdd5cdca..7062c02b 100644 --- a/ProcessHacker/phlib/mapimg.c +++ b/ProcessHacker/phlib/mapimg.c @@ -453,6 +453,7 @@ PVOID PhMappedImageRvaToVa( _Must_inspect_result_ _Ret_maybenull_ +_Success_(return != NULL) PVOID PhMappedImageVaToVa( _In_ PPH_MAPPED_IMAGE MappedImage, _In_ ULONG Va, @@ -823,13 +824,13 @@ BOOLEAN PhGetRemoteMappedImageDirectoryEntry( _Success_(return) BOOLEAN PhGetRemoteMappedImageDebugEntryByType( _In_ HANDLE ProcessHandle, - _In_ PPH_REMOTE_MAPPED_IMAGE RemotedMappedImage, + _In_ PPH_REMOTE_MAPPED_IMAGE RemoteMappedImage, _In_ ULONG Type, _Out_opt_ ULONG* DataLength, _Out_ PVOID* DataBuffer ) { - return PhGetRemoteMappedImageDebugEntryByTypeEx(ProcessHandle, RemotedMappedImage, Type, NtReadVirtualMemory, DataLength, DataBuffer); + return PhGetRemoteMappedImageDebugEntryByTypeEx(ProcessHandle, RemoteMappedImage, Type, NtReadVirtualMemory, DataLength, DataBuffer); } _Success_(return) @@ -2150,6 +2151,163 @@ NTSTATUS PhGetMappedImageResources( return status; } +NTSTATUS PhGetMappedImageResource( + _In_ PPH_MAPPED_IMAGE MappedImage, + _In_ PCWSTR Name, + _In_ PCWSTR Type, + _In_ USHORT Language, + _Out_opt_ ULONG *ResourceLength, + _Out_opt_ PVOID *ResourceBuffer + ) +{ + NTSTATUS status; + PIMAGE_DATA_DIRECTORY dataDirectory; + PIMAGE_RESOURCE_DIRECTORY resourceDirectory; + PIMAGE_RESOURCE_DIRECTORY nameDirectory; + PIMAGE_RESOURCE_DIRECTORY languageDirectory; + PIMAGE_RESOURCE_DIRECTORY_ENTRY resourceType; + PIMAGE_RESOURCE_DIRECTORY_ENTRY resourceName; + PIMAGE_RESOURCE_DIRECTORY_ENTRY resourceLanguage; + ULONG resourceCount = 0; + ULONG resourceTypeCount; + ULONG resourceNameCount; + ULONG resourceLanguageCount; + + // Get a pointer to the resource directory. + + status = PhGetMappedImageDataEntry( + MappedImage, + IMAGE_DIRECTORY_ENTRY_RESOURCE, + &dataDirectory + ); + + if (!NT_SUCCESS(status)) + return status; + + resourceDirectory = PhMappedImageRvaToVa( + MappedImage, + dataDirectory->VirtualAddress, + NULL + ); + + if (!resourceDirectory) + return STATUS_INVALID_PARAMETER; + + __try + { + PhpMappedImageProbe(MappedImage, resourceDirectory, sizeof(IMAGE_RESOURCE_DIRECTORY)); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return GetExceptionCode(); + } + + resourceType = PTR_ADD_OFFSET(resourceDirectory, sizeof(IMAGE_RESOURCE_DIRECTORY)); + resourceTypeCount = resourceDirectory->NumberOfNamedEntries + resourceDirectory->NumberOfIdEntries; + + for (ULONG i = 0; i < resourceTypeCount; ++i, ++resourceType) + { + if (!resourceType->DataIsDirectory) + continue; + + nameDirectory = PTR_ADD_OFFSET(resourceDirectory, resourceType->OffsetToDirectory); + resourceName = PTR_ADD_OFFSET(nameDirectory, sizeof(IMAGE_RESOURCE_DIRECTORY)); + resourceNameCount = nameDirectory->NumberOfNamedEntries + nameDirectory->NumberOfIdEntries; + + for (ULONG j = 0; j < resourceNameCount; ++j, ++resourceName) + { + if (!resourceName->DataIsDirectory) + continue; + + languageDirectory = PTR_ADD_OFFSET(resourceDirectory, resourceName->OffsetToDirectory); + resourceLanguage = PTR_ADD_OFFSET(languageDirectory, sizeof(IMAGE_RESOURCE_DIRECTORY)); + resourceLanguageCount = languageDirectory->NumberOfNamedEntries + languageDirectory->NumberOfIdEntries; + + for (ULONG k = 0; k < resourceLanguageCount; ++k, ++resourceLanguage) + { + PIMAGE_RESOURCE_DATA_ENTRY resourceData; + + if (resourceLanguage->DataIsDirectory) + continue; + + if (IS_INTRESOURCE(Type)) + { + if (resourceType->NameIsString) + continue; + if (resourceType->Id != PtrToUshort(Type)) + continue; + } + else + { + PIMAGE_RESOURCE_DIR_STRING_U resourceString; + PH_STRINGREF string1; + PH_STRINGREF string2; + + if (!resourceType->NameIsString) + continue; + + resourceString = PTR_ADD_OFFSET(resourceDirectory, resourceType->NameOffset); + string1.Buffer = resourceString->NameString; + string1.Length = resourceString->Length * sizeof(WCHAR); + PhInitializeStringRefLongHint(&string2, (PWSTR)Type); + + if (!PhEqualStringRef(&string1, &string2, TRUE)) + continue; + } + + if (IS_INTRESOURCE(Name)) + { + if (resourceName->NameIsString) + continue; + if (resourceName->Id != PtrToUshort(Name)) + continue; + } + else + { + PIMAGE_RESOURCE_DIR_STRING_U resourceString; + PH_STRINGREF string1; + PH_STRINGREF string2; + + if (!resourceName->NameIsString) + continue; + + resourceString = PTR_ADD_OFFSET(resourceDirectory, resourceName->NameOffset); + string1.Buffer = resourceString->NameString; + string1.Length = resourceString->Length * sizeof(WCHAR); + PhInitializeStringRefLongHint(&string2, (PWSTR)Name); + + if (!PhEqualStringRef(&string1, &string2, TRUE)) + continue; + } + + if (Language) + { + if (resourceLanguage->NameIsString) + continue; + if (resourceLanguage->Id != Language) + continue; + } + + resourceData = PTR_ADD_OFFSET(resourceDirectory, resourceLanguage->OffsetToData); + + if (ResourceLength) + { + *ResourceLength = resourceData->Size; + } + + if (ResourceBuffer) + { + *ResourceBuffer = PhMappedImageRvaToVa(MappedImage, resourceData->OffsetToData, NULL); + } + + return STATUS_SUCCESS; + } + } + } + + return STATUS_UNSUCCESSFUL; +} + NTSTATUS PhGetMappedImageTlsCallbackDirectory32( _Out_ PPH_MAPPED_IMAGE_TLS_CALLBACKS TlsCallbacks, _In_ PPH_MAPPED_IMAGE MappedImage diff --git a/ProcessHacker/phlib/native.c b/ProcessHacker/phlib/native.c index c8d779d9..febb53f9 100644 --- a/ProcessHacker/phlib/native.c +++ b/ProcessHacker/phlib/native.c @@ -3,7 +3,7 @@ * native wrapper and support functions * * Copyright (C) 2009-2016 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -671,19 +671,42 @@ NTSTATUS PhGetProcessImageFileNameWin32( ) { NTSTATUS status; - PUNICODE_STRING fileName; + PUNICODE_STRING buffer; + ULONG bufferLength; + ULONG returnLength = 0; - status = PhpQueryProcessVariableSize( + bufferLength = sizeof(UNICODE_STRING) + DOS_MAX_PATH_LENGTH; + buffer = PhAllocate(bufferLength); + + status = NtQueryInformationProcess( ProcessHandle, ProcessImageFileNameWin32, - &fileName + buffer, + bufferLength, + &returnLength ); - if (!NT_SUCCESS(status)) - return status; + if (status == STATUS_INFO_LENGTH_MISMATCH) + { + PhFree(buffer); + bufferLength = returnLength; + buffer = PhAllocate(bufferLength); - *FileName = PhCreateStringFromUnicodeString(fileName); - PhFree(fileName); + status = NtQueryInformationProcess( + ProcessHandle, + ProcessImageFileNameWin32, + buffer, + bufferLength, + &returnLength + ); + } + + if (NT_SUCCESS(status)) + { + *FileName = PhCreateStringFromUnicodeString(buffer); + } + + PhFree(buffer); return status; } @@ -1030,21 +1053,44 @@ NTSTATUS PhGetProcessCommandLine( if (WindowsVersion >= WINDOWS_8_1) { NTSTATUS status; - PUNICODE_STRING commandLine; + PUNICODE_STRING buffer; + ULONG bufferLength; + ULONG returnLength = 0; + + bufferLength = sizeof(UNICODE_STRING) + DOS_MAX_PATH_LENGTH; + buffer = PhAllocate(bufferLength); - status = PhpQueryProcessVariableSize( + status = NtQueryInformationProcess( ProcessHandle, ProcessCommandLineInformation, - &commandLine + buffer, + bufferLength, + &returnLength ); - if (NT_SUCCESS(status)) + if (status == STATUS_INFO_LENGTH_MISMATCH) { - *CommandLine = PhCreateStringFromUnicodeString(commandLine); - PhFree(commandLine); + PhFree(buffer); + bufferLength = returnLength; + buffer = PhAllocate(bufferLength); - return status; + status = NtQueryInformationProcess( + ProcessHandle, + ProcessCommandLineInformation, + buffer, + bufferLength, + &returnLength + ); + } + + if (NT_SUCCESS(status)) + { + *CommandLine = PhCreateStringFromUnicodeString(buffer); } + + PhFree(buffer); + + return status; } return PhGetProcessPebString(ProcessHandle, PhpoCommandLine, CommandLine); @@ -2444,7 +2490,7 @@ NTSTATUS PhpQueryTokenVariableSize( ULONG returnLength; returnLength = 0; - bufferSize = 0x40; + bufferSize = 0x80; buffer = PhAllocate(bufferSize); status = NtQueryInformationToken( @@ -3508,6 +3554,55 @@ NTSTATUS PhGetProcessIdsUsingFile( ); } +NTSTATUS PhGetFileUsn( + _In_ HANDLE FileHandle, + _Out_ PLONGLONG Usn + ) +{ + NTSTATUS status; + ULONG recordLength; + PUSN_RECORD_V2 recordBuffer; // USN_RECORD_UNION + IO_STATUS_BLOCK isb; + + recordLength = sizeof(USN_RECORD_V2) + MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR); + recordBuffer = PhAllocate(recordLength); + + status = NtFsControlFile( + FileHandle, + NULL, + NULL, + NULL, + &isb, + FSCTL_READ_FILE_USN_DATA, + NULL, // READ_FILE_USN_DATA + 0, + recordBuffer, + recordLength + ); + + if (NT_SUCCESS(status)) + { + *Usn = recordBuffer->Usn; + + //switch (recordBuffer->Header.MajorVersion) + //{ + //case 2: + // *Usn = recordBuffer->V2.Usn; + // break; + //case 3: + // *Usn = recordBuffer->V3.Usn; + // break; + //case 4: + // *Usn = recordBuffer->V4.Usn; + // break; + //} + } + + PhFree(recordBuffer); + + return status; +} + NTSTATUS PhpQueryTransactionManagerVariableSize( _In_ HANDLE TransactionManagerHandle, _In_ TRANSACTIONMANAGER_INFORMATION_CLASS TransactionManagerInformationClass, @@ -5949,7 +6044,7 @@ static BOOLEAN NTAPI PhpDotNetCorePipeHashCallback( objectName.Length = fileInfo->FileNameLength; objectName.Buffer = fileInfo->FileName; - objectPipe.Hash = PhHashStringRef(&objectName, TRUE); + objectPipe.Hash = PhHashStringRefEx(&objectName, TRUE, PH_STRING_HASH_X65599); PhAddItemArray(Context, &objectPipe); @@ -6100,7 +6195,7 @@ NTSTATUS PhGetProcessIsDotNetEx( objectNameSr.Length = returnLength - sizeof(UNICODE_NULL); objectNameSr.Buffer = formatBuffer; - pipeNameHash = PhHashStringRef(&objectNameSr, TRUE); + pipeNameHash = PhHashStringRefEx(&objectNameSr, TRUE, PH_STRING_HASH_X65599); RtlInitUnicodeString(&objectNameUs, DEVICE_NAMED_PIPE); InitializeObjectAttributes( @@ -6818,11 +6913,12 @@ VOID PhUpdateDosDevicePrefixes( deviceNameBuffer[4] = (WCHAR)('A' + i); deviceName.Buffer = deviceNameBuffer; deviceName.Length = 6 * sizeof(WCHAR); + deviceName.MaximumLength = deviceName.Length + sizeof(UNICODE_NULL); InitializeObjectAttributes( &objectAttributes, &deviceName, - OBJ_CASE_INSENSITIVE, + OBJ_CASE_INSENSITIVE | (WindowsVersion < WINDOWS_10 ? 0 : OBJ_DONT_REPARSE), NULL, NULL ); @@ -7116,12 +7212,14 @@ static BOOLEAN EnumGenericProcessModulesCallback( if (WindowsVersion >= WINDOWS_8) { moduleInfo.ParentBaseAddress = Module->ParentDllBase; + moduleInfo.OriginalBaseAddress = (PVOID)Module->OriginalBase; moduleInfo.LoadReason = (USHORT)Module->LoadReason; moduleInfo.LoadTime = Module->LoadTime; } else { moduleInfo.ParentBaseAddress = NULL; + moduleInfo.OriginalBaseAddress = NULL; moduleInfo.LoadReason = USHRT_MAX; moduleInfo.LoadTime.QuadPart = 0; } @@ -7182,6 +7280,7 @@ VOID PhpRtlModulesToGenericModules( moduleInfo.LoadReason = USHRT_MAX; moduleInfo.LoadTime.QuadPart = 0; moduleInfo.ParentBaseAddress = NULL; + moduleInfo.OriginalBaseAddress = NULL; if (module->OffsetToFileName == 0) { @@ -7253,6 +7352,7 @@ VOID PhpRtlModulesExToGenericModules( moduleInfo.LoadReason = USHRT_MAX; moduleInfo.LoadTime.QuadPart = 0; moduleInfo.ParentBaseAddress = NULL; + moduleInfo.OriginalBaseAddress = NULL; cont = Callback(&moduleInfo, Context); @@ -7293,6 +7393,7 @@ BOOLEAN PhpCallbackMappedFileOrImage( moduleInfo.LoadReason = USHRT_MAX; moduleInfo.LoadTime.QuadPart = 0; moduleInfo.ParentBaseAddress = NULL; + moduleInfo.OriginalBaseAddress = NULL; cont = Callback(&moduleInfo, Context); @@ -7844,16 +7945,18 @@ NTSTATUS PhLoadAppKey( NTSTATUS status; GUID guid; UNICODE_STRING fileName; - UNICODE_STRING objectName; - UNICODE_STRING guidStringUs; + UNICODE_STRING objectName; OBJECT_ATTRIBUTES targetAttributes; OBJECT_ATTRIBUTES sourceAttributes; - WCHAR objectNameBuffer[MAX_PATH] = L""; - - RtlInitEmptyUnicodeString(&objectName, objectNameBuffer, sizeof(objectNameBuffer)); PhGenerateGuid(&guid); +#if (PHNT_USE_NATIVE_APPEND) + UNICODE_STRING guidStringUs; + WCHAR objectNameBuffer[MAXIMUM_FILENAME_LENGTH]; + + RtlInitEmptyUnicodeString(&objectName, objectNameBuffer, sizeof(objectNameBuffer)); + if (!NT_SUCCESS(status = RtlStringFromGUID(&guid, &guidStringUs))) return status; @@ -7862,6 +7965,21 @@ NTSTATUS PhLoadAppKey( if (!NT_SUCCESS(status = RtlAppendUnicodeStringToString(&objectName, &guidStringUs))) goto CleanupExit; +#else + static PH_STRINGREF namespaceString = PH_STRINGREF_INIT(L"\\REGISTRY\\A\\"); + PPH_STRING guidString; + + if (!(guidString = PhFormatGuid(&guid))) + return STATUS_UNSUCCESSFUL; + + PhMoveReference(&guidString, PhConcatStringRef2(&namespaceString, &guidString->sr)); + + if (!PhStringRefToUnicodeString(&guidString->sr, &objectName)) + { + PhDereferenceObject(guidString); + return STATUS_UNSUCCESSFUL; + } +#endif if (!NT_SUCCESS(status = RtlDosPathNameToNtPathName_U_WithStatus( FileName, @@ -7900,8 +8018,13 @@ NTSTATUS PhLoadAppKey( RtlFreeUnicodeString(&fileName); +#if (PHNT_USE_NATIVE_APPEND) CleanupExit: RtlFreeUnicodeString(&guidStringUs); +#else +CleanupExit: + PhDereferenceObject(guidString); +#endif return status; #else @@ -7983,7 +8106,7 @@ NTSTATUS PhQueryValueKey( ULONG bufferSize; ULONG attempts = 16; - if (ValueName) + if (ValueName && ValueName->Length) // Length check for PhQueryRegistryString backwards compat (dmex) { if (!PhStringRefToUnicodeString(ValueName, &valueName)) return STATUS_NAME_TOO_LONG; @@ -9046,7 +9169,7 @@ NTSTATUS PhMoveFileWin32( FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY ); if (!NT_SUCCESS(status)) @@ -9061,6 +9184,7 @@ NTSTATUS PhMoveFileWin32( renameInfo->RootDirectory = NULL; renameInfo->FileNameLength = newFileName.Length; memcpy(renameInfo->FileName, newFileName.Buffer, newFileName.Length); + RtlFreeUnicodeString(&newFileName); status = NtSetInformationFile( fileHandle, @@ -9089,7 +9213,7 @@ NTSTATUS PhMoveFileWin32( FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, NULL ); @@ -9148,7 +9272,6 @@ NTSTATUS PhMoveFileWin32( CleanupExit: NtClose(fileHandle); - RtlFreeUnicodeString(&newFileName); PhFree(renameInfo); return status; @@ -9406,7 +9529,7 @@ NTSTATUS PhConnectPipe( NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_OPEN, + FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 @@ -10001,6 +10124,24 @@ NTSTATUS PhGetThreadName( return status; } +NTSTATUS PhSetThreadName( + _In_ HANDLE ThreadHandle, + _In_ PCWSTR ThreadName + ) +{ + THREAD_NAME_INFORMATION threadNameInfo; + + memset(&threadNameInfo, 0, sizeof(THREAD_NAME_INFORMATION)); + RtlInitUnicodeString(&threadNameInfo.ThreadName, ThreadName); + + return NtSetInformationThread( + ThreadHandle, + ThreadNameInformation, + &threadNameInfo, + sizeof(THREAD_NAME_INFORMATION) + ); +} + NTSTATUS PhImpersonateToken( _In_ HANDLE ThreadHandle, _In_ HANDLE TokenHandle @@ -10101,6 +10242,7 @@ NTSTATUS PhGetProcessHeapSignature( if (WindowsVersion >= WINDOWS_7) { + // dt _HEAP SegmentSignature status = NtReadVirtualMemory( ProcessHandle, PTR_ADD_OFFSET(HeapAddress, IsWow64 ? 0x8 : 0x10), @@ -10119,57 +10261,188 @@ NTSTATUS PhGetProcessHeapSignature( return status; } +NTSTATUS PhGetProcessHeapFrontEndType( + _In_ HANDLE ProcessHandle, + _In_ PVOID HeapAddress, + _In_ ULONG IsWow64, + _Out_ UCHAR *HeapFrontEndType + ) +{ + NTSTATUS status = STATUS_UNSUCCESSFUL; + UCHAR heapFrontEndType = UCHAR_MAX; + + if (WindowsVersion >= WINDOWS_10) + { + // dt _HEAP FrontEndHeapType + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(HeapAddress, IsWow64 ? 0x0ea : 0x1a2), + &heapFrontEndType, + sizeof(UCHAR), + NULL + ); + } + else if (WindowsVersion >= WINDOWS_8_1) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(HeapAddress, IsWow64 ? 0x0d6 : 0x17a), + &heapFrontEndType, + sizeof(UCHAR), + NULL + ); + } + else if (WindowsVersion >= WINDOWS_7) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(HeapAddress, IsWow64 ? 0x0da : 0x182), + &heapFrontEndType, + sizeof(UCHAR), + NULL + ); + } + + if (NT_SUCCESS(status)) + { + if (HeapFrontEndType) + *HeapFrontEndType = heapFrontEndType; + } + + return status; +} + NTSTATUS PhQueryProcessHeapInformation( _In_ HANDLE ProcessId, _Out_ PPH_PROCESS_DEBUG_HEAP_INFORMATION* HeapInformation ) { NTSTATUS status; - PRTL_DEBUG_INFORMATION debugBuffer; - PPH_PROCESS_DEBUG_HEAP_INFORMATION heapDebugInfo; - - if (!(debugBuffer = RtlCreateQueryDebugBuffer(0, FALSE))) - return STATUS_UNSUCCESSFUL; + HANDLE processHandle = NULL; + HANDLE clientProcessId = ProcessId; + RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION reflectionInfo = { 0 }; + PRTL_DEBUG_INFORMATION debugBuffer = NULL; + PPH_PROCESS_DEBUG_HEAP_INFORMATION heapDebugInfo = NULL; + ULONG heapEntrySize; - status = RtlQueryProcessDebugInformation( - ProcessId, - RTL_QUERY_PROCESS_HEAP_SUMMARY | RTL_QUERY_PROCESS_HEAP_ENTRIES_EX, - debugBuffer + status = PhOpenProcess( + &processHandle, + PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE, + ProcessId ); - if (!NT_SUCCESS(status)) + if (NT_SUCCESS(status)) { - RtlDestroyQueryDebugBuffer(debugBuffer); - return status; + // NOTE: RtlQueryProcessDebugInformation injects a thread into the process causing deadlocks and other issues in rare cases. + // We mitigate these problems by reflecting the process and querying heap information from the clone. (dmex) + + status = RtlCreateProcessReflection( + processHandle, + 0, + NULL, + NULL, + NULL, + &reflectionInfo + ); + + if (NT_SUCCESS(status)) + { + clientProcessId = reflectionInfo.ReflectionClientId.UniqueProcess; + } + } + + for (ULONG i = 0x400000; ; i *= 2) // rev from Heap32First/Heap32Next (dmex) + { + if (!(debugBuffer = RtlCreateQueryDebugBuffer(i, FALSE))) + return STATUS_UNSUCCESSFUL; + + status = RtlQueryProcessDebugInformation( + clientProcessId, + RTL_QUERY_PROCESS_HEAP_SUMMARY | RTL_QUERY_PROCESS_HEAP_ENTRIES, + debugBuffer + ); + + if (!NT_SUCCESS(status)) + { + RtlDestroyQueryDebugBuffer(debugBuffer); + debugBuffer = NULL; + } + + if (NT_SUCCESS(status) || status != STATUS_NO_MEMORY) + break; + + if (2 * i <= i) + { + status = STATUS_UNSUCCESSFUL; + break; + } + } + + if (reflectionInfo.ReflectionProcessHandle) + { + PhTerminateProcess(reflectionInfo.ReflectionProcessHandle, STATUS_SUCCESS); + NtClose(reflectionInfo.ReflectionProcessHandle); } + if (reflectionInfo.ReflectionThreadHandle) + NtClose(reflectionInfo.ReflectionThreadHandle); + if (processHandle) + NtClose(processHandle); + + if (!NT_SUCCESS(status)) + return status; + if (!debugBuffer->Heaps) { - // The RtlQueryProcessDebugInformation function has two bugs when querying the ProcessId - // for a frozen (suspended) immersive process. (dmex) + // The RtlQueryProcessDebugInformation function has two bugs on some versions + // when querying the ProcessId for a frozen (suspended) immersive process. (dmex) // // 1) It'll deadlock the current thread for 30 seconds. - // 2) It'll return STATUS_SUCCESS but with a NULL buffer. + // 2) It'll return STATUS_SUCCESS but with a NULL Heaps buffer. + // + // A workaround was implemented using PhCreateExecutionRequiredRequest() (dmex) RtlDestroyQueryDebugBuffer(debugBuffer); return STATUS_UNSUCCESSFUL; } + heapEntrySize = WindowsVersion > WINDOWS_11 ? sizeof(RTL_HEAP_INFORMATION) : RTL_SIZEOF_THROUGH_FIELD(RTL_HEAP_INFORMATION, Entries); heapDebugInfo = PhAllocateZero(sizeof(PH_PROCESS_DEBUG_HEAP_INFORMATION) + debugBuffer->Heaps->NumberOfHeaps * sizeof(PH_PROCESS_DEBUG_HEAP_ENTRY)); heapDebugInfo->NumberOfHeaps = debugBuffer->Heaps->NumberOfHeaps; heapDebugInfo->DefaultHeap = debugBuffer->ProcessHeap; for (ULONG i = 0; i < heapDebugInfo->NumberOfHeaps; i++) { - PRTL_HEAP_INFORMATION heapInfo = &debugBuffer->Heaps->Heaps[i]; - HANDLE processHandle; + PRTL_HEAP_INFORMATION heapInfo = PTR_ADD_OFFSET(debugBuffer->Heaps->Heaps, heapEntrySize * i); + SIZE_T allocated = 0; + SIZE_T committed = 0; + + // go through all heap entries and compute amount of allocated and committed bytes + for (ULONG e = 0; e < heapInfo->NumberOfEntries; e++) + { + PRTL_HEAP_ENTRY entry = &heapInfo->Entries[e]; + + if (entry->Flags & RTL_HEAP_BUSY) + allocated += entry->Size; + if (entry->Flags & RTL_HEAP_SEGMENT) + committed += entry->u.s2.CommittedSize; + } + + // sometimes computed number if commited bytes is few pages smaller than the one reported by API, lets use the higher value + if (committed < heapInfo->BytesCommitted) + committed = heapInfo->BytesCommitted; + + // make sure number of allocated bytes is not higher than number of committed bytes (as that would make no sense) + if (allocated > committed) + allocated = committed; heapDebugInfo->Heaps[i].Flags = heapInfo->Flags; heapDebugInfo->Heaps[i].Signature = ULONG_MAX; + heapDebugInfo->Heaps[i].HeapFrontEndType = UCHAR_MAX; heapDebugInfo->Heaps[i].NumberOfEntries = heapInfo->NumberOfEntries; heapDebugInfo->Heaps[i].BaseAddress = heapInfo->BaseAddress; - heapDebugInfo->Heaps[i].BytesAllocated = heapInfo->BytesAllocated; - heapDebugInfo->Heaps[i].BytesCommitted = heapInfo->BytesCommitted; + heapDebugInfo->Heaps[i].BytesAllocated = allocated; + heapDebugInfo->Heaps[i].BytesCommitted = committed; if (NT_SUCCESS(PhOpenProcess( &processHandle, @@ -10178,6 +10451,7 @@ NTSTATUS PhQueryProcessHeapInformation( ))) { ULONG signature = ULONG_MAX; + UCHAR frontEndType = UCHAR_MAX; #ifndef _WIN64 BOOLEAN isWow64 = TRUE; #else @@ -10195,6 +10469,16 @@ NTSTATUS PhQueryProcessHeapInformation( heapDebugInfo->Heaps[i].Signature = signature; } + if (NT_SUCCESS(PhGetProcessHeapFrontEndType( + processHandle, + heapInfo->BaseAddress, + isWow64, + &frontEndType + ))) + { + heapDebugInfo->Heaps[i].HeapFrontEndType = frontEndType; + } + NtClose(processHandle); } } @@ -10359,10 +10643,10 @@ NTSTATUS PhGetThreadLastStatusValue( if (!ProcessHandle) { - if (!NT_SUCCESS(status = PhOpenThreadProcess( - ThreadHandle, - PROCESS_VM_READ, - &ProcessHandle + if (!NT_SUCCESS(status = PhOpenProcess( + &ProcessHandle, + PROCESS_VM_READ | (WindowsVersion > WINDOWS_7 ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION), + basicInfo.ClientId.UniqueProcess ))) return status; @@ -10400,53 +10684,379 @@ NTSTATUS PhGetThreadLastStatusValue( return status; } -BOOLEAN PhIsFirmwareSupported( - VOID - ) -{ - UNICODE_STRING variableName = RTL_CONSTANT_STRING(L" "); - ULONG variableValueLength = 0; - GUID vendorGuid = { 0 }; - - if (NtQuerySystemEnvironmentValueEx( - &variableName, - &vendorGuid, - NULL, - &variableValueLength, - NULL - ) == STATUS_VARIABLE_NOT_FOUND) - { - return TRUE; - } - - return FALSE; -} - -// rev from RtlpCreateExecutionRequiredRequest -NTSTATUS PhCreateExecutionRequiredRequest( - _In_ HANDLE ProcessHandle, - _Out_ PHANDLE PowerRequestHandle +NTSTATUS PhGetThreadApartmentState( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ProcessHandle, + _Out_ POLETLSFLAGS ApartmentState ) { NTSTATUS status; - HANDLE powerRequestHandle = NULL; - PROCESS_EXTENDED_BASIC_INFORMATION basicInfo; - COUNTED_REASON_CONTEXT powerRequestReason; - POWER_REQUEST_ACTION powerRequestAction; - - status = PhGetProcessExtendedBasicInformation(ProcessHandle, &basicInfo); + THREAD_BASIC_INFORMATION basicInfo; + BOOLEAN openedProcessHandle = FALSE; +#ifdef _WIN64 + BOOLEAN isWow64 = FALSE; +#endif + ULONG_PTR oletlsDataAddress = 0; - if (!NT_SUCCESS(status)) + if (!NT_SUCCESS(status = PhGetThreadBasicInformation(ThreadHandle, &basicInfo))) return status; - if (!basicInfo.IsFrozen) + if (!ProcessHandle) { - // CreateToolhelp32Snapshot uses RtlpCreateExecutionRequiredRequest but it doesn't create an execution request + if (!NT_SUCCESS(status = PhOpenProcess( + &ProcessHandle, + PROCESS_VM_READ | (WindowsVersion > WINDOWS_7 ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION), + basicInfo.ClientId.UniqueProcess + ))) + return status; + + openedProcessHandle = TRUE; + } + +#ifdef _WIN64 + PhGetProcessIsWow64(ProcessHandle, &isWow64); + + if (isWow64) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(WOW64_GET_TEB32(basicInfo.TebBaseAddress), UFIELD_OFFSET(TEB32, ReservedForOle)), + &oletlsDataAddress, + sizeof(ULONG), + NULL + ); + } + else +#endif + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(basicInfo.TebBaseAddress, UFIELD_OFFSET(TEB, ReservedForOle)), + &oletlsDataAddress, + sizeof(ULONG_PTR), + NULL + ); + } + + if (NT_SUCCESS(status) && oletlsDataAddress) + { + PVOID apartmentStateOffset; + + // Note: Teb->ReservedForOle is the SOleTlsData structure + // and ApartmentState is the dwFlags field. (dmex) + +#ifdef _WIN64 + if (isWow64) + apartmentStateOffset = PTR_ADD_OFFSET(oletlsDataAddress, 0xC); + else + apartmentStateOffset = PTR_ADD_OFFSET(oletlsDataAddress, 0x14); +#else + apartmentStateOffset = PTR_ADD_OFFSET(oletlsDataAddress, 0xC); +#endif + + status = NtReadVirtualMemory( + ProcessHandle, + apartmentStateOffset, + ApartmentState, + sizeof(ULONG), + NULL + ); + } + else + { + status = STATUS_UNSUCCESSFUL; + } + + if (openedProcessHandle) + NtClose(ProcessHandle); + + return status; +} + +NTSTATUS PhGetThreadStackLimits( + _In_ HANDLE ThreadHandle, + _In_ HANDLE ProcessHandle, + _Out_ PULONG_PTR LowPart, + _Out_ PULONG_PTR HighPart + ) +{ + NTSTATUS status; + THREAD_BASIC_INFORMATION basicInfo; + NT_TIB ntTib; + //PVOID deallocationStack; +#ifdef _WIN64 + BOOLEAN isWow64 = FALSE; +#endif + + if (!NT_SUCCESS(status = PhGetThreadBasicInformation(ThreadHandle, &basicInfo))) + return status; + + memset(&ntTib, 0, sizeof(NT_TIB)); + +#ifdef _WIN64 + PhGetProcessIsWow64(ProcessHandle, &isWow64); + + if (isWow64) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(WOW64_GET_TEB32(basicInfo.TebBaseAddress), UFIELD_OFFSET(TEB32, NtTib)), + &ntTib, + sizeof(NT_TIB32), + NULL + ); + + //status = NtReadVirtualMemory( + // ProcessHandle, + // PTR_ADD_OFFSET(WOW64_GET_TEB32(basicInfo.TebBaseAddress), UFIELD_OFFSET(TEB32, DeallocationStack)), + // &deallocationStack, + // sizeof(ULONG), + // NULL + // ); + } + else +#endif + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(basicInfo.TebBaseAddress, UFIELD_OFFSET(TEB, NtTib)), + &ntTib, + sizeof(NT_TIB), + NULL + ); + + //status = NtReadVirtualMemory( + // ProcessHandle, + // PTR_ADD_OFFSET(basicInfo.TebBaseAddress, UFIELD_OFFSET(TEB, DeallocationStack)), + // &deallocationStack, + // sizeof(PVOID), + // NULL + // ); + } + + if (NT_SUCCESS(status)) + { +#ifdef _WIN64 + if (isWow64) + { + PNT_TIB32 ntTib32 = (PNT_TIB32)&ntTib; + *LowPart = (ULONG_PTR)UlongToPtr(ntTib32->StackLimit); + *HighPart = (ULONG_PTR)UlongToPtr(ntTib32->StackBase); + } + else + { + *LowPart = (ULONG_PTR)ntTib.StackLimit; + *HighPart = (ULONG_PTR)ntTib.StackBase; + } +#else + *LowPart = (ULONG_PTR)ntTib.StackLimit; + *HighPart = (ULONG_PTR)ntTib.StackBase; +#endif + } + + return status; +} + +NTSTATUS PhGetThreadStackSize( + _In_ HANDLE ThreadHandle, + _In_ HANDLE ProcessHandle, + _Out_ PULONG_PTR StackUsage, + _Out_ PULONG_PTR StackLimit + ) +{ + NTSTATUS status; + THREAD_BASIC_INFORMATION basicInfo; + NT_TIB ntTib; +#ifdef _WIN64 + BOOLEAN isWow64 = FALSE; +#endif + + if (!NT_SUCCESS(status = PhGetThreadBasicInformation(ThreadHandle, &basicInfo))) + return status; + + memset(&ntTib, 0, sizeof(NT_TIB)); + +#ifdef _WIN64 + PhGetProcessIsWow64(ProcessHandle, &isWow64); + + if (isWow64) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(WOW64_GET_TEB32(basicInfo.TebBaseAddress), UFIELD_OFFSET(TEB32, NtTib)), + &ntTib, + sizeof(NT_TIB32), + NULL + ); + } + else +#endif + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(basicInfo.TebBaseAddress, UFIELD_OFFSET(TEB, NtTib)), + &ntTib, + sizeof(NT_TIB), + NULL + ); + } + + if (NT_SUCCESS(status)) + { + MEMORY_BASIC_INFORMATION basicInfo; + PVOID stackBaseAddress = NULL; + PVOID stackLimitAddress = NULL; + +#ifdef _WIN64 + if (isWow64) + { + PNT_TIB32 ntTib32 = (PNT_TIB32)&ntTib; + stackBaseAddress = UlongToPtr(ntTib32->StackBase); + stackLimitAddress = UlongToPtr(ntTib32->StackLimit); + } + else + { + stackBaseAddress = ntTib.StackBase; + stackLimitAddress = ntTib.StackLimit; + } +#else + stackBaseAddress = ntTib.StackBase; + stackLimitAddress = ntTib.StackLimit; +#endif + memset(&basicInfo, 0, sizeof(MEMORY_BASIC_INFORMATION)); + + status = NtQueryVirtualMemory( + ProcessHandle, + stackLimitAddress, + MemoryBasicInformation, + &basicInfo, + sizeof(MEMORY_BASIC_INFORMATION), + NULL + ); + + if (NT_SUCCESS(status)) + { + // TEB->DeallocationStack == basicInfo.AllocationBase + *StackUsage = (ULONG_PTR)PTR_SUB_OFFSET(stackBaseAddress, stackLimitAddress); + *StackLimit = (ULONG_PTR)PTR_SUB_OFFSET(stackBaseAddress, basicInfo.AllocationBase); + } + } + + return status; +} + +NTSTATUS PhGetThreadIsFiber( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ProcessHandle, + _Out_ PBOOLEAN ThreadIsFiber + ) +{ + NTSTATUS status; + THREAD_BASIC_INFORMATION basicInfo; + BOOLEAN openedProcessHandle = FALSE; +#ifdef _WIN64 + BOOLEAN isWow64 = FALSE; +#endif + LONG flags = 0; + + if (!NT_SUCCESS(status = PhGetThreadBasicInformation(ThreadHandle, &basicInfo))) + return status; + + if (!ProcessHandle) + { + if (!NT_SUCCESS(status = PhOpenProcess( + &ProcessHandle, + PROCESS_VM_READ | (WindowsVersion > WINDOWS_7 ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION), + basicInfo.ClientId.UniqueProcess + ))) + return status; + + openedProcessHandle = TRUE; + } + +#ifdef _WIN64 + PhGetProcessIsWow64(ProcessHandle, &isWow64); + + if (isWow64) + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(WOW64_GET_TEB32(basicInfo.TebBaseAddress), UFIELD_OFFSET(TEB32, SameTebFlags)), + &flags, + sizeof(USHORT), + NULL + ); + } + else +#endif + { + status = NtReadVirtualMemory( + ProcessHandle, + PTR_ADD_OFFSET(basicInfo.TebBaseAddress, UFIELD_OFFSET(TEB, SameTebFlags)), + &flags, + sizeof(USHORT), + NULL + ); + } + + if (NT_SUCCESS(status)) + { + *ThreadIsFiber = _bittest(&flags, 2); // HasFiberData offset (dmex) + } + + if (openedProcessHandle) + NtClose(ProcessHandle); + + return status; +} + +BOOLEAN PhIsFirmwareSupported( + VOID + ) +{ + UNICODE_STRING variableName = RTL_CONSTANT_STRING(L" "); + ULONG variableValueLength = 0; + GUID vendorGuid = { 0 }; + + if (NtQuerySystemEnvironmentValueEx( + &variableName, + &vendorGuid, + NULL, + &variableValueLength, + NULL + ) == STATUS_VARIABLE_NOT_FOUND) + { + return TRUE; + } + + return FALSE; +} + +// rev from RtlpCreateExecutionRequiredRequest +NTSTATUS PhCreateExecutionRequiredRequest( + _In_ HANDLE ProcessHandle, + _Out_ PHANDLE PowerRequestHandle + ) +{ + NTSTATUS status; + HANDLE powerRequestHandle = NULL; + PROCESS_EXTENDED_BASIC_INFORMATION basicInfo; + COUNTED_REASON_CONTEXT powerRequestReason; + POWER_REQUEST_ACTION powerRequestAction; + + status = PhGetProcessExtendedBasicInformation(ProcessHandle, &basicInfo); + + if (!NT_SUCCESS(status)) + return status; + + if (!basicInfo.IsFrozen) + { + // CreateToolhelp32Snapshot uses RtlpCreateExecutionRequiredRequest but it doesn't create an execution request // when IsFrozen==false (such as when the immersive window is visible), CreateToolhelp32Snapshot proceeds to // inject the debug thread but if the window closes, there's a race here where the debug thread gets frozen because // RtlpCreateExecutionRequiredRequest never created the execution request. We can resolve the race condition // by removing the above code checking IsFrozen but for now just copy what RtlpCreateExecutionRequiredRequest - // does (and copy the race condition) by returning here instead of always creating the exeution request. (dmex) + // does (and copy the race condition) by returning here instead of always creating the execution request. (dmex) // TODO: We should remove the check for IsFrozen if the race condition becomes an issue at some point in the future. *PowerRequestHandle = NULL; return STATUS_SUCCESS; @@ -10517,3 +11127,386 @@ NTSTATUS PhDestroyExecutionRequiredRequest( return NtClose(PowerRequestHandle); } + +// Process freeze/thaw support + +static PH_INITONCE PhProcessStateInitOnce = PH_INITONCE_INIT; +static PPH_HASHTABLE PhProcessStateHashtable = NULL; + +typedef struct _PH_STATEHANDLE_CACHE_ENTRY +{ + HANDLE ProcessId; + HANDLE StateHandle; +} PH_STATEHANDLE_CACHE_ENTRY, *PPH_STATEHANDLE_CACHE_ENTRY; + +static BOOLEAN NTAPI PhProcessStateHandleHashtableEqualFunction( + _In_ PVOID Entry1, + _In_ PVOID Entry2 + ) +{ + return + ((PPH_STATEHANDLE_CACHE_ENTRY)Entry1)->ProcessId == + ((PPH_STATEHANDLE_CACHE_ENTRY)Entry2)->ProcessId; +} + +static ULONG NTAPI PhProcessStateHandleHashtableHashFunction( + _In_ PVOID Entry + ) +{ + return HandleToUlong(((PPH_STATEHANDLE_CACHE_ENTRY)Entry)->ProcessId) / 4; +} + +BOOLEAN PhInitializeProcessStateHandleTable( + VOID + ) +{ + if (PhBeginInitOnce(&PhProcessStateInitOnce)) + { + PhProcessStateHashtable = PhCreateHashtable( + sizeof(PH_STATEHANDLE_CACHE_ENTRY), + PhProcessStateHandleHashtableEqualFunction, + PhProcessStateHandleHashtableHashFunction, + 1 + ); + + PhEndInitOnce(&PhProcessStateInitOnce); + } + + return TRUE; +} + +BOOLEAN PhIsProcessStateFrozen( + _In_ HANDLE ProcessId + ) +{ + if (PhInitializeProcessStateHandleTable()) + { + PH_STATEHANDLE_CACHE_ENTRY entry; + + entry.ProcessId = ProcessId; + + if (PhFindEntryHashtable(PhProcessStateHashtable, &entry)) + { + return TRUE; + } + } + + return FALSE; +} + +NTSTATUS PhFreezeProcess( + _In_ HANDLE ProcessId + ) +{ + NTSTATUS status; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE processHandle; + HANDLE stateHandle = NULL; + + if (!(NtCreateProcessStateChange_Import() && NtChangeProcessState_Import())) + return STATUS_UNSUCCESSFUL; + + if (PhInitializeProcessStateHandleTable()) + { + PH_STATEHANDLE_CACHE_ENTRY entry; + + entry.ProcessId = ProcessId; + + if (PhFindEntryHashtable(PhProcessStateHashtable, &entry)) + { + return STATUS_SUCCESS; + } + } + + status = PhOpenProcess( + &processHandle, + PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME, + ProcessId + ); + + if (!NT_SUCCESS(status)) + return status; + + InitializeObjectAttributes( + &objectAttributes, + NULL, + OBJ_EXCLUSIVE, + NULL, + NULL + ); + + status = NtCreateProcessStateChange_Import()( + &stateHandle, + STATECHANGE_SET_ATTRIBUTES, + &objectAttributes, + processHandle, + 0 + ); + + if (!NT_SUCCESS(status)) + { + NtClose(processHandle); + return status; + } + + status = NtChangeProcessState_Import()( + stateHandle, + processHandle, + ProcessStateChangeSuspend, + NULL, + 0, + 0 + ); + + if (NT_SUCCESS(status)) + { + PH_STATEHANDLE_CACHE_ENTRY entry; + + entry.ProcessId = ProcessId; + entry.StateHandle = stateHandle; + + PhAddEntryHashtable(PhProcessStateHashtable, &entry); + } + else if (stateHandle) + { + NtClose(stateHandle); + } + + NtClose(processHandle); + + return status; +} + +NTSTATUS PhThawProcess( + _In_ HANDLE ProcessId + ) +{ + NTSTATUS status; + HANDLE stateHandle = NULL; + HANDLE processHandle; + + if (!NtChangeProcessState_Import()) + return STATUS_UNSUCCESSFUL; + + if (PhInitializeProcessStateHandleTable()) + { + PH_STATEHANDLE_CACHE_ENTRY lookupEntry; + PPH_STATEHANDLE_CACHE_ENTRY entry; + + lookupEntry.ProcessId = ProcessId; + + if (entry = PhFindEntryHashtable(PhProcessStateHashtable, &lookupEntry)) + { + stateHandle = entry->StateHandle; + } + } + + if (!stateHandle) + { + return STATUS_UNSUCCESSFUL; + } + + status = PhOpenProcess( + &processHandle, + PROCESS_SET_INFORMATION | PROCESS_SUSPEND_RESUME, + ProcessId + ); + + if (!NT_SUCCESS(status)) + return status; + + status = NtChangeProcessState_Import()( + stateHandle, + processHandle, + ProcessStateChangeResume, + NULL, + 0, + 0 + ); + + if (NT_SUCCESS(status)) + { + PH_STATEHANDLE_CACHE_ENTRY entry; + + entry.ProcessId = ProcessId; + + if (PhRemoveEntryHashtable(PhProcessStateHashtable, &entry)) + { + NtClose(stateHandle); + } + } + + NtClose(processHandle); + + return status; +} + +// KnownDLLs cache support + +static PH_INITONCE PhKnownDllsInitOnce = PH_INITONCE_INIT; +static PPH_HASHTABLE PhKnownDllsHashtable = NULL; + +typedef struct _PH_KNOWNDLL_CACHE_ENTRY +{ + PPH_STRING FileName; +} PH_KNOWNDLL_CACHE_ENTRY, *PPH_KNOWNDLL_CACHE_ENTRY; + +static BOOLEAN NTAPI PhKnownDllsHashtableEqualFunction( + _In_ PVOID Entry1, + _In_ PVOID Entry2 + ) +{ + return PhEqualStringRef(&((PPH_KNOWNDLL_CACHE_ENTRY)Entry1)->FileName->sr, &((PPH_KNOWNDLL_CACHE_ENTRY)Entry2)->FileName->sr, TRUE); +} + +static ULONG NTAPI PhKnownDllsHashtableHashFunction( + _In_ PVOID Entry + ) +{ + return PhHashStringRefEx(&((PPH_KNOWNDLL_CACHE_ENTRY)Entry)->FileName->sr, TRUE, PH_STRING_HASH_X65599); +} + +static BOOLEAN NTAPI PhpKnownDllObjectsCallback( + _In_ PPH_STRINGREF Name, + _In_ PPH_STRINGREF TypeName, + _In_ PVOID Context + ) +{ + NTSTATUS status; + HANDLE sectionHandle; + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING objectNameUs; + PVOID baseAddress = NULL; + SIZE_T viewSize = PAGE_SIZE; + PPH_STRING fileName; + + if (!PhStringRefToUnicodeString(Name, &objectNameUs)) + return TRUE; + + InitializeObjectAttributes( + &objectAttributes, + &objectNameUs, + OBJ_CASE_INSENSITIVE, + Context, + NULL + ); + + status = NtOpenSection( + §ionHandle, + SECTION_MAP_READ, + &objectAttributes + ); + + if (!NT_SUCCESS(status)) + return TRUE; + + status = NtMapViewOfSection( + sectionHandle, + NtCurrentProcess(), + &baseAddress, + 0, + 0, + NULL, + &viewSize, + ViewUnmap, + WindowsVersion < WINDOWS_10_RS2 ? 0 : MEM_MAPPED, + PAGE_READONLY + ); + + NtClose(sectionHandle); + + if (!NT_SUCCESS(status)) + return TRUE; + + status = PhGetProcessMappedFileName( + NtCurrentProcess(), + baseAddress, + &fileName + ); + + NtUnmapViewOfSection(NtCurrentProcess(), baseAddress); + + if (NT_SUCCESS(status)) + { + PH_KNOWNDLL_CACHE_ENTRY entry; + + entry.FileName = fileName; + + PhAddEntryHashtable(PhKnownDllsHashtable, &entry); + } + + return TRUE; +} + +VOID PhInitializeKnownDlls( + _In_ PCWSTR ObjectName + ) +{ + UNICODE_STRING directoryName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE directoryHandle; + + RtlInitUnicodeString(&directoryName, ObjectName); + InitializeObjectAttributes( + &objectAttributes, + &directoryName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + if (NT_SUCCESS(NtOpenDirectoryObject( + &directoryHandle, + DIRECTORY_QUERY, + &objectAttributes + ))) + { + PhEnumDirectoryObjects( + directoryHandle, + PhpKnownDllObjectsCallback, + directoryHandle + ); + NtClose(directoryHandle); + } +} + +BOOLEAN PhInitializeKnownDllsTable( + VOID + ) +{ + if (PhBeginInitOnce(&PhKnownDllsInitOnce)) + { + PhKnownDllsHashtable = PhCreateHashtable( + sizeof(PH_KNOWNDLL_CACHE_ENTRY), + PhKnownDllsHashtableEqualFunction, + PhKnownDllsHashtableHashFunction, + 100 + ); + + PhInitializeKnownDlls(L"\\KnownDlls"); + PhInitializeKnownDlls(L"\\KnownDlls32"); + + PhEndInitOnce(&PhKnownDllsInitOnce); + } + + return TRUE; +} + +BOOLEAN PhIsKnownDllFileName( + _In_ PPH_STRING FileName + ) +{ + if (PhInitializeKnownDllsTable()) + { + PH_KNOWNDLL_CACHE_ENTRY entry; + + entry.FileName = FileName; + + if (PhFindEntryHashtable(PhKnownDllsHashtable, &entry)) + { + return TRUE; + } + } + + return FALSE; +} diff --git a/ProcessHacker/phlib/secedit.c b/ProcessHacker/phlib/secedit.c index 8d78b78e..0be8bd4f 100644 --- a/ProcessHacker/phlib/secedit.c +++ b/ProcessHacker/phlib/secedit.c @@ -1720,7 +1720,7 @@ PVOID PhpInitializePowerPolicyApi(VOID) if (PhBeginInitOnce(&initOnce)) { - imageBaseAddress = PhLoadLibrarySafe(L"powrprof.dll"); + imageBaseAddress = PhLoadLibrary(L"powrprof.dll"); PhEndInitOnce(&initOnce); } @@ -1858,7 +1858,7 @@ PVOID PhpInitializeRemoteDesktopServiceApi(VOID) if (PhBeginInitOnce(&initOnce)) { - imageBaseAddress = PhLoadLibrarySafe(L"wtsapi32.dll"); + imageBaseAddress = PhLoadLibrary(L"wtsapi32.dll"); PhEndInitOnce(&initOnce); } @@ -1981,8 +1981,8 @@ PVOID PhGetWbemProxDllBase( { if (systemFileName = PhConcatStringRefZ(&systemDirectory->sr, L"\\wbem\\wbemprox.dll")) { - if (!(imageBaseAddress = PhGetLoaderEntryFullDllBase(PhGetString(systemFileName)))) - imageBaseAddress = PhLoadLibrarySafe(PhGetString(systemFileName)); + if (!(imageBaseAddress = PhGetLoaderEntryStringRefDllBase(&systemFileName->sr, NULL))) + imageBaseAddress = PhLoadLibrary(PhGetString(systemFileName)); PhDereferenceObject(systemFileName); } diff --git a/ProcessHacker/phlib/settings.c b/ProcessHacker/phlib/settings.c index ab521395..2d8fdaf1 100644 --- a/ProcessHacker/phlib/settings.c +++ b/ProcessHacker/phlib/settings.c @@ -3,7 +3,7 @@ * settings * * Copyright (C) 2010-2016 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -49,10 +49,6 @@ ULONG NTAPI PhpSettingsHashtableHashFunction( _In_ PVOID Entry ); -ULONG PhpGetCurrentScale( - VOID - ); - VOID PhpFreeSettingValue( _In_ PH_SETTING_TYPE Type, _In_ PPH_SETTING Setting @@ -74,7 +70,7 @@ VOID PhSettingsInitialization( sizeof(PH_SETTING), PhpSettingsHashtableEqualFunction, PhpSettingsHashtableHashFunction, - 256 + 512 ); PhIgnoredSettings = PhCreateList(4); @@ -99,30 +95,14 @@ ULONG NTAPI PhpSettingsHashtableHashFunction( { PPH_SETTING setting = (PPH_SETTING)Entry; - return PhHashBytes((PUCHAR)setting->Name.Buffer, setting->Name.Length); + return PhHashStringRefEx(&setting->Name, FALSE, PH_STRING_HASH_X65599); } static ULONG PhpGetCurrentScale( VOID ) { - static PH_INITONCE initOnce; - static ULONG dpi = 96; - - if (PhBeginInitOnce(&initOnce)) - { - HDC hdc; - - if (hdc = GetDC(NULL)) - { - dpi = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - } - - PhEndInitOnce(&initOnce); - } - - return dpi; + return PhGlobalDpi; } PPH_STRING PhSettingToString( @@ -352,7 +332,7 @@ _May_raise_ ULONG PhGetIntegerSetting( PH_STRINGREF name; ULONG value; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockShared(&PhSettingsLock); @@ -383,7 +363,7 @@ _May_raise_ PH_INTEGER_PAIR PhGetIntegerPairSetting( PH_STRINGREF name; PH_INTEGER_PAIR value; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockShared(&PhSettingsLock); @@ -415,7 +395,7 @@ _May_raise_ PH_SCALABLE_INTEGER_PAIR PhGetScalableIntegerPairSetting( PH_STRINGREF name; PH_SCALABLE_INTEGER_PAIR value; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockShared(&PhSettingsLock); @@ -460,7 +440,7 @@ _May_raise_ PPH_STRING PhGetStringSetting( PH_STRINGREF name; PPH_STRING value; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockShared(&PhSettingsLock); @@ -518,7 +498,7 @@ _May_raise_ VOID PhSetIntegerSetting( PPH_SETTING setting; PH_STRINGREF name; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockExclusive(&PhSettingsLock); @@ -543,7 +523,7 @@ _May_raise_ VOID PhSetIntegerPairSetting( PPH_SETTING setting; PH_STRINGREF name; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockExclusive(&PhSettingsLock); @@ -568,7 +548,7 @@ _May_raise_ VOID PhSetScalableIntegerPairSetting( PPH_SETTING setting; PH_STRINGREF name; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockExclusive(&PhSettingsLock); @@ -606,7 +586,7 @@ _May_raise_ VOID PhSetStringSetting( PPH_SETTING setting; PH_STRINGREF name; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockExclusive(&PhSettingsLock); @@ -632,7 +612,7 @@ _May_raise_ VOID PhSetStringSetting2( PPH_SETTING setting; PH_STRINGREF name; - PhInitializeStringRef(&name, Name); + PhInitializeStringRefLongHint(&name, Name); PhAcquireQueuedLockExclusive(&PhSettingsLock); @@ -765,7 +745,7 @@ NTSTATUS PhLoadSettings( if (settingName = PhGetXmlNodeAttributeText(currentNode, "name")) { - PPH_STRING settingValue = PhGetOpaqueXmlNodeText(currentNode); + PPH_STRING settingValue = PhGetXmlNodeOpaqueText(currentNode); PhAcquireQueuedLockExclusive(&PhSettingsLock); diff --git a/ProcessHacker/phlib/svcsup.c b/ProcessHacker/phlib/svcsup.c index 9aa296ed..c64b6c8b 100644 --- a/ProcessHacker/phlib/svcsup.c +++ b/ProcessHacker/phlib/svcsup.c @@ -196,68 +196,62 @@ PVOID PhEnumServices( return buffer; } -SC_HANDLE PhOpenService( - _In_ PWSTR ServiceName, - _In_ ACCESS_MASK DesiredAccess +SC_HANDLE PhGetServiceManagerHandle( + VOID ) { - SC_HANDLE scManagerHandle; - SC_HANDLE serviceHandle; + static SC_HANDLE cachedServiceManagerHandle = NULL; + SC_HANDLE serviceManagerHandle; + SC_HANDLE newServiceManagerHandle; - scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + // Use the cached value if possible. - if (!scManagerHandle) - return NULL; + serviceManagerHandle = InterlockedCompareExchangePointer(&cachedServiceManagerHandle, NULL, NULL); - serviceHandle = OpenService(scManagerHandle, ServiceName, DesiredAccess); - CloseServiceHandle(scManagerHandle); + // If there is no cached handle, open one. - return serviceHandle; + if (!serviceManagerHandle) + { + if (newServiceManagerHandle = OpenSCManager( + NULL, + NULL, + SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE + )) + { + // We succeeded in opening a policy handle, and since we did not have a cached handle + // before, we will now store it. + serviceManagerHandle = InterlockedCompareExchangePointer( + &cachedServiceManagerHandle, + newServiceManagerHandle, + NULL + ); + + if (!serviceManagerHandle) + { + // Success. Use our handle. + serviceManagerHandle = newServiceManagerHandle; + } + else + { + // Someone already placed a handle in the cache. Close our handle and use their handle. + CloseServiceHandle(newServiceManagerHandle); + } + } + } + + return serviceManagerHandle; } -NTSTATUS PhOpenServiceEx( +SC_HANDLE PhOpenService( _In_ PWSTR ServiceName, - _In_ ACCESS_MASK DesiredAccess, - _In_opt_ SC_HANDLE ScManagerHandle, - _Out_ SC_HANDLE* ServiceHandle + _In_ ACCESS_MASK DesiredAccess ) { SC_HANDLE serviceHandle; - if (ScManagerHandle) - { - if (serviceHandle = OpenService(ScManagerHandle, ServiceName, DesiredAccess)) - { - *ServiceHandle = serviceHandle; - return STATUS_SUCCESS; - } - - return PhGetLastWin32ErrorAsNtStatus(); - } - else - { - NTSTATUS status; - SC_HANDLE scManagerHandle; - - if (!(scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT))) - { - return PhGetLastWin32ErrorAsNtStatus(); - } - - if (serviceHandle = OpenService(ScManagerHandle, ServiceName, DesiredAccess)) - { - *ServiceHandle = serviceHandle; - status = STATUS_SUCCESS; - } - else - { - status = PhGetLastWin32ErrorAsNtStatus(); - } - - CloseServiceHandle(scManagerHandle); + serviceHandle = OpenService(PhGetServiceManagerHandle(), ServiceName, DesiredAccess); - return status; - } + return serviceHandle; } PVOID PhGetServiceConfig( @@ -596,10 +590,10 @@ NTSTATUS PhGetThreadServiceTag( if (!ProcessHandle) { - if (!NT_SUCCESS(status = PhOpenThreadProcess( - ThreadHandle, + if (!NT_SUCCESS(status = PhOpenProcess( + &ProcessHandle, PROCESS_VM_READ, - &ProcessHandle + basicInfo.ClientId.UniqueProcess ))) return status; diff --git a/ProcessHacker/phlib/symprv.c b/ProcessHacker/phlib/symprv.c index 8eb84059..1b3b50a5 100644 --- a/ProcessHacker/phlib/symprv.c +++ b/ProcessHacker/phlib/symprv.c @@ -293,19 +293,19 @@ VOID PhpSymbolProviderCompleteInitialization( #endif if (dbgcoreName = PhConcatStringRef2(&winsdkPath->sr, &dbgcoreFileName)) { - dbgcoreHandle = PhLoadLibrarySafe(dbgcoreName->Buffer); + dbgcoreHandle = PhLoadLibrary(dbgcoreName->Buffer); PhDereferenceObject(dbgcoreName); } if (dbghelpName = PhConcatStringRef2(&winsdkPath->sr, &dbghelpFileName)) { - dbghelpHandle = PhLoadLibrarySafe(dbghelpName->Buffer); + dbghelpHandle = PhLoadLibrary(dbghelpName->Buffer); PhDereferenceObject(dbghelpName); } if (symsrvName = PhConcatStringRef2(&winsdkPath->sr, &symsrvFileName)) { - symsrvHandle = PhLoadLibrarySafe(symsrvName->Buffer); + symsrvHandle = PhLoadLibrary(symsrvName->Buffer); PhDereferenceObject(symsrvName); } @@ -313,11 +313,11 @@ VOID PhpSymbolProviderCompleteInitialization( } if (!dbgcoreHandle) - dbgcoreHandle = PhLoadLibrarySafe(L"dbgcore.dll"); + dbgcoreHandle = PhLoadLibrary(L"dbgcore.dll"); if (!dbghelpHandle) - dbghelpHandle = PhLoadLibrarySafe(L"dbghelp.dll"); + dbghelpHandle = PhLoadLibrary(L"dbghelp.dll"); if (!symsrvHandle) - symsrvHandle = PhLoadLibrarySafe(L"symsrv.dll"); + symsrvHandle = PhLoadLibrary(L"symsrv.dll"); if (dbghelpHandle) { diff --git a/ProcessHacker/phlib/theme.c b/ProcessHacker/phlib/theme.c index 2f26f6ce..1e5d73ed 100644 --- a/ProcessHacker/phlib/theme.c +++ b/ProcessHacker/phlib/theme.c @@ -46,7 +46,20 @@ typedef struct _PHP_THEME_WINDOW_HEADER_CONTEXT typedef struct _PHP_THEME_WINDOW_STATUSBAR_CONTEXT { WNDPROC DefaultWindowProc; - BOOLEAN MouseActive; + + struct + { + BOOLEAN Flags; + union + { + BOOLEAN NonMouseActive : 1; + BOOLEAN MouseActive : 1; + BOOLEAN HotTrack : 1; + BOOLEAN Hot : 1; + BOOLEAN Spare : 4; + }; + }; + HTHEME StatusThemeData; } PHP_THEME_WINDOW_STATUSBAR_CONTEXT, *PPHP_THEME_WINDOW_STATUSBAR_CONTEXT; @@ -114,6 +127,27 @@ LRESULT CALLBACK PhpThemeWindowStaticControlSubclassProc( _In_ LPARAM lParam ); +LRESULT CALLBACK PhpThemeWindowListBoxControlSubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + +LRESULT CALLBACK PhpThemeWindowComboBoxControlSubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + +LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + // Win10-RS5 (uxtheme.dll ordinal 132) BOOL (WINAPI *ShouldAppsUseDarkMode_I)( VOID @@ -156,13 +190,6 @@ BOOL (WINAPI *IsDarkModeAllowedForApp_I)( _In_ HWND WindowHandle ) = NULL; -HRESULT (WINAPI* DwmSetWindowAttribute_I)( - _In_ HWND WindowHandle, - _In_ ULONG AttributeId, - _In_reads_bytes_(AttributeLength) PVOID Attribute, - _In_ ULONG AttributeLength - ); - //HRESULT (WINAPI* DwmGetColorizationColor_I)( // _Out_ PULONG Colorization, // _Out_ PBOOL OpaqueBlend @@ -174,14 +201,10 @@ BOOLEAN PhpThemeBorderEnable = TRUE; HBRUSH PhMenuBackgroundBrush = NULL; COLORREF PhThemeWindowForegroundColor = RGB(28, 28, 28); COLORREF PhThemeWindowBackgroundColor = RGB(43, 43, 43); -COLORREF PhpThemeWindowTextColor = RGB(0xff, 0xff, 0xff); -HFONT PhpTabControlFontHandle = NULL; -HFONT PhpToolBarFontHandle = NULL; -HFONT PhpHeaderFontHandle = NULL; +COLORREF PhThemeWindowTextColor = RGB(0xff, 0xff, 0xff); HFONT PhpListViewFontHandle = NULL; HFONT PhpMenuFontHandle = NULL; HFONT PhpGroupboxFontHandle = NULL; -HFONT PhpStatusBarFontHandle = NULL; VOID PhInitializeWindowTheme( _In_ HWND WindowHandle, @@ -200,14 +223,9 @@ VOID PhInitializeWindowTheme( { PVOID module; - if (module = PhLoadLibrarySafe(L"dwmapi.dll")) - { - DwmSetWindowAttribute_I = PhGetDllBaseProcedureAddress(module, "DwmSetWindowAttribute", 0); - } - if (WindowsVersion >= WINDOWS_10_19H2) { - if (module = PhLoadLibrarySafe(L"uxtheme.dll")) + if (module = PhLoadLibrary(L"uxtheme.dll")) { AllowDarkModeForWindow_I = PhGetDllBaseProcedureAddress(module, NULL, 133); SetPreferredAppMode_I = PhGetDllBaseProcedureAddress(module, NULL, 135); @@ -242,7 +260,7 @@ VOID PhInitializeWindowTheme( case 0: // New colors { HBRUSH brush = PhMenuBackgroundBrush; - PhMenuBackgroundBrush = CreateSolidBrush(PhpThemeWindowTextColor); + PhMenuBackgroundBrush = CreateSolidBrush(PhThemeWindowTextColor); if (brush) DeleteBrush(brush); } break; @@ -278,7 +296,7 @@ VOID PhInitializeWindowTheme( } else { - EnableThemeDialogTexture(WindowHandle, ETDT_ENABLETAB); + //EnableThemeDialogTexture(WindowHandle, ETDT_ENABLETAB); } } @@ -325,7 +343,7 @@ VOID PhReInitializeWindowTheme( case 0: // New colors { HBRUSH brush = PhMenuBackgroundBrush; - PhMenuBackgroundBrush = CreateSolidBrush(PhpThemeWindowTextColor); + PhMenuBackgroundBrush = CreateSolidBrush(PhThemeWindowTextColor); if (brush) DeleteBrush(brush); } break; @@ -384,6 +402,39 @@ VOID PhReInitializeWindowTheme( InvalidateRect(WindowHandle, NULL, FALSE); } +HRESULT PhSetWindowThemeAttribute( + _In_ HWND WindowHandle, + _In_ ULONG AttributeId, + _In_reads_bytes_(AttributeLength) PVOID Attribute, + _In_ ULONG AttributeLength + ) +{ + static PH_INITONCE initOnce = PH_INITONCE_INIT; + static HRESULT (WINAPI* DwmSetWindowAttribute_I)( + _In_ HWND WindowHandle, + _In_ ULONG AttributeId, + _In_reads_bytes_(AttributeLength) PVOID Attribute, + _In_ ULONG AttributeLength + ); + + if (PhBeginInitOnce(&initOnce)) + { + PVOID baseAddress; + + if (baseAddress = PhLoadLibrary(L"dwmapi.dll")) + { + DwmSetWindowAttribute_I = PhGetDllBaseProcedureAddress(baseAddress, "DwmSetWindowAttribute", 0); + } + + PhEndInitOnce(&initOnce); + } + + if (!DwmSetWindowAttribute_I) + return HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); + + return DwmSetWindowAttribute_I(WindowHandle, AttributeId, Attribute, AttributeLength); +} + VOID PhInitializeThemeWindowFrame( _In_ HWND WindowHandle ) @@ -395,45 +446,134 @@ VOID PhInitializeThemeWindowFrame( #ifndef DWMWA_CAPTION_COLOR #define DWMWA_CAPTION_COLOR 35 #endif - - if (WindowsVersion >= WINDOWS_10_RS5 && DwmSetWindowAttribute_I) +#ifndef DWMWA_SYSTEMBACKDROP_TYPE +#define DWMWA_SYSTEMBACKDROP_TYPE 38 +#endif + + if (WindowsVersion >= WINDOWS_10_RS5) { - switch (PhpThemeColorMode) + if (PhpThemeEnable) { - case 0: // New colors + switch (PhpThemeColorMode) { - if (FAILED(DwmSetWindowAttribute_I(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &(BOOL){ FALSE }, sizeof(BOOL)))) + case 0: // New colors { - DwmSetWindowAttribute_I(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &(BOOL){ FALSE }, sizeof(BOOL)); + if (FAILED(PhSetWindowThemeAttribute(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &(BOOL){ FALSE }, sizeof(BOOL)))) + { + PhSetWindowThemeAttribute(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &(BOOL){ FALSE }, sizeof(BOOL)); + } + + //if (WindowsVersion > WINDOWS_11) + //{ + // PhSetWindowThemeAttribute(WindowHandle, DWMWA_CAPTION_COLOR, NULL, 0); + //} } + break; + case 1: // Old colors + { + if (FAILED(PhSetWindowThemeAttribute(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &(BOOL){ TRUE }, sizeof(BOOL)))) + { + PhSetWindowThemeAttribute(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &(BOOL){ TRUE }, sizeof(BOOL)); + } - //if (WindowsVersion > WINDOWS_11) - //{ - // DwmSetWindowAttribute_I(WindowHandle, DWMWA_CAPTION_COLOR, NULL, 0); - //} + if (WindowsVersion >= WINDOWS_11) + { + PhSetWindowThemeAttribute(WindowHandle, DWMWA_CAPTION_COLOR, &PhThemeWindowBackgroundColor, sizeof(COLORREF)); + } + } + break; } - break; - case 1: // Old colors + } + + if (WindowsVersion >= WINDOWS_11_22H1) + { + PhSetWindowThemeAttribute(WindowHandle, DWMWA_SYSTEMBACKDROP_TYPE, &(ULONG){ 1 }, sizeof(ULONG)); + } + } +} + +HBRUSH PhWindowThemeControlColor( + _In_ HWND WindowHandle, + _In_ HDC Hdc, + _In_ HWND ChildWindowHandle, + _In_ INT Type + ) +{ + SetBkMode(Hdc, TRANSPARENT); + + switch (Type) + { + case CTLCOLOR_EDIT: + { + if (PhpThemeEnable) { - if (FAILED(DwmSetWindowAttribute_I(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &(BOOL){ TRUE }, sizeof(BOOL)))) + switch (PhpThemeColorMode) { - DwmSetWindowAttribute_I(WindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, &(BOOL){ TRUE }, sizeof(BOOL)); + case 0: // New colors + SetTextColor(Hdc, RGB(0x0, 0x0, 0x0)); + SetDCBrushColor(Hdc, PhThemeWindowTextColor); + break; + case 1: // Old colors + SetTextColor(Hdc, PhThemeWindowTextColor); + SetDCBrushColor(Hdc, RGB(60, 60, 60)); + break; } + } + else + { + SetTextColor(Hdc, GetSysColor(COLOR_WINDOWTEXT)); + SetDCBrushColor(Hdc, GetSysColor(COLOR_WINDOW)); + } - if (WindowsVersion >= WINDOWS_11) + return GetStockBrush(DC_BRUSH); + } + break; + case CTLCOLOR_SCROLLBAR: + { + if (PhpThemeEnable) + { + SetDCBrushColor(Hdc, RGB(23, 23, 23)); + } + else + { + SetDCBrushColor(Hdc, GetSysColor(COLOR_SCROLLBAR)); + } + + return GetStockBrush(DC_BRUSH); + } + break; + case CTLCOLOR_MSGBOX: + case CTLCOLOR_LISTBOX: + case CTLCOLOR_BTN: + case CTLCOLOR_DLG: + case CTLCOLOR_STATIC: + { + if (PhpThemeEnable) + { + switch (PhpThemeColorMode) { - DwmSetWindowAttribute_I(WindowHandle, DWMWA_CAPTION_COLOR, &PhThemeWindowBackgroundColor, sizeof(COLORREF)); + case 0: // New colors + SetTextColor(Hdc, RGB(0x00, 0x00, 0x00)); + SetDCBrushColor(Hdc, PhThemeWindowTextColor); + break; + case 1: // Old colors + SetTextColor(Hdc, PhThemeWindowTextColor); + SetDCBrushColor(Hdc, PhThemeWindowBackgroundColor); + break; } } - break; + else + { + SetTextColor(Hdc, GetSysColor(COLOR_WINDOWTEXT)); + SetDCBrushColor(Hdc, GetSysColor(COLOR_WINDOW)); + } + + return GetStockBrush(DC_BRUSH); } + break; } - //WINDOWCOMPOSITIONATTRIBDATA data; - //data.Attrib = WCA_USEDARKMODECOLORS; - //data.pvData = &(BOOL){ TRUE }; - //data.cbData = sizeof(BOOL); - //SetWindowCompositionAttribute(WindowHandle, &data); + return NULL; } VOID PhInitializeThemeWindowHeader( @@ -442,6 +582,23 @@ VOID PhInitializeThemeWindowHeader( { PPHP_THEME_WINDOW_HEADER_CONTEXT context; + //if (PhGetWindowContext(HeaderWindow, LONG_MAX)) + // return; + + if (PhGetWindowContext(HeaderWindow, 0xF)) + { + HANDLE parentWindow; + LONG_PTR windowStyle; + + if (parentWindow = GetParent(HeaderWindow)) + { + windowStyle = PhGetWindowStyle(parentWindow); + + if (windowStyle & TN_STYLE_CUSTOM_HEADERDRAW) + return; + } + } + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_HEADER_CONTEXT)); context->DefaultWindowProc = (WNDPROC)GetWindowLongPtr(HeaderWindow, GWLP_WNDPROC); @@ -457,9 +614,6 @@ VOID PhInitializeThemeWindowTabControl( { PPHP_THEME_WINDOW_TAB_CONTEXT context; - if (!PhpTabControlFontHandle) - PhpTabControlFontHandle = PhDuplicateFontWithNewHeight(PhApplicationFont, 15); - context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_TAB_CONTEXT)); context->DefaultWindowProc = (WNDPROC)GetWindowLongPtr(TabControlWindow, GWLP_WNDPROC); @@ -468,8 +622,6 @@ VOID PhInitializeThemeWindowTabControl( PhSetWindowStyle(TabControlWindow, TCS_OWNERDRAWFIXED, TCS_OWNERDRAWFIXED); - SetWindowFont(TabControlWindow, PhpTabControlFontHandle, FALSE); - InvalidateRect(TabControlWindow, NULL, FALSE); } @@ -510,7 +662,7 @@ VOID PhInitializeThemeWindowEditControl( // HACK: The searchbox control does its own themed drawing and it uses the // same window context value so we know when to ignore theming. - if (PhGetWindowContext(EditControlHandle, LONG_MAX)) + if (PhGetWindowContext(EditControlHandle, SHRT_MAX)) return; editControlWindowProc = (WNDPROC)GetWindowLongPtr(EditControlHandle, GWLP_WNDPROC); @@ -569,6 +721,42 @@ VOID PhInitializeWindowThemeStaticControl( InvalidateRect(StaticControl, NULL, FALSE); } +VOID PhInitializeWindowThemeListboxControl( + _In_ HWND ListBoxControl + ) +{ + PPHP_THEME_WINDOW_STATUSBAR_CONTEXT context; + + context = PhAllocateZero(sizeof(PHP_THEME_WINDOW_STATUSBAR_CONTEXT)); + context->DefaultWindowProc = (WNDPROC)GetWindowLongPtr(ListBoxControl, GWLP_WNDPROC); + + PhSetWindowContext(ListBoxControl, LONG_MAX, context); + SetWindowLongPtr(ListBoxControl, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowListBoxControlSubclassProc); + + InvalidateRect(ListBoxControl, NULL, FALSE); + SetWindowPos(ListBoxControl, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); +} + +VOID PhInitializeWindowThemeComboboxControl( + _In_ HWND ComboBoxControl + ) +{ + PhSetWindowContext(ComboBoxControl, LONG_MAX, (PVOID)GetWindowLongPtr(ComboBoxControl, GWLP_WNDPROC)); + SetWindowLongPtr(ComboBoxControl, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowComboBoxControlSubclassProc); + + InvalidateRect(ComboBoxControl, NULL, FALSE); +} + +VOID PhInitializeWindowThemeACLUI( + _In_ HWND ACLUIControl +) +{ + PhSetWindowContext(ACLUIControl, LONG_MAX, (PVOID)GetWindowLongPtr(ACLUIControl, GWLP_WNDPROC)); + SetWindowLongPtr(ACLUIControl, GWLP_WNDPROC, (LONG_PTR)PhpThemeWindowACLUISubclassProc); + + InvalidateRect(ACLUIControl, NULL, FALSE); +} + BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( _In_ HWND WindowHandle, _In_opt_ PVOID Context @@ -673,9 +861,9 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( ListView_SetTextColor(WindowHandle, RGB(0x0, 0x0, 0x0)); break; case 1: // Old colors - ListView_SetBkColor(WindowHandle, RGB(30, 30, 30)); - ListView_SetTextBkColor(WindowHandle, RGB(30, 30, 30)); - ListView_SetTextColor(WindowHandle, PhpThemeWindowTextColor); + ListView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) + ListView_SetTextBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) + ListView_SetTextColor(WindowHandle, PhThemeWindowTextColor); break; } @@ -705,9 +893,9 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( case 0: // New colors break; case 1: // Old colors - TreeView_SetBkColor(WindowHandle, RGB(30, 30, 30)); + TreeView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor);// RGB(30, 30, 30)); //TreeView_SetTextBkColor(WindowHandle, RGB(30, 30, 30)); - TreeView_SetTextColor(WindowHandle, PhpThemeWindowTextColor); + TreeView_SetTextColor(WindowHandle, PhThemeWindowTextColor); break; } @@ -722,7 +910,7 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( SetWindowPos(WindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); -#define EM_SETBKGNDCOLOR (WM_USER + 67) + #define EM_SETBKGNDCOLOR (WM_USER + 67) switch (PhpThemeColorMode) { case 0: // New colors @@ -733,6 +921,8 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( break; } + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + //InvalidateRect(WindowHandle, NULL, FALSE); } else if (PhEqualStringZ(windowClassName, L"PhTreeNew", FALSE)) @@ -745,9 +935,11 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( { case 0: // New colors PhSetControlTheme(tooltipWindow, L""); + PhSetControlTheme(WindowHandle, L""); break; case 1: // Old colors PhSetControlTheme(tooltipWindow, L"DarkMode_Explorer"); + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); break; } } @@ -771,6 +963,65 @@ BOOLEAN CALLBACK PhpThemeWindowEnumChildWindows( //InvalidateRect(WindowHandle, NULL, TRUE); } + else if ( + PhEqualStringZ(windowClassName, WC_LISTBOX, FALSE) || + PhEqualStringZ(windowClassName, L"ComboLBox", FALSE) + ) + { + if (WindowsVersion >= WINDOWS_10_RS5) + { + switch (PhpThemeColorMode) + { + case 0: // New colors + PhSetControlTheme(WindowHandle, L"explorer"); + break; + case 1: // Old colors + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + break; + } + } + + PhInitializeWindowThemeListboxControl(WindowHandle); + } + else if (PhEqualStringZ(windowClassName, WC_COMBOBOX, FALSE)) + { + COMBOBOXINFO info = { sizeof(COMBOBOXINFO) }; + + if (SendMessage(WindowHandle, CB_GETCOMBOBOXINFO, 0, (LPARAM)&info)) + { + //if (info.hwndItem) + //{ + // SendMessage(info.hwndItem, EM_SETMARGINS, EC_LEFTMARGIN, MAKELPARAM(0, 0)); + //} + + if (info.hwndList) + { + PhSetControlTheme(info.hwndList, L"DarkMode_Explorer"); + } + } + + //if ((PhGetWindowStyle(WindowHandle) & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST) + { + PhInitializeWindowThemeComboboxControl(WindowHandle); + } + } + else if (PhEqualStringZ(windowClassName, L"CHECKLIST_ACLUI", FALSE)) + { + if (WindowsVersion >= WINDOWS_10_RS5) + { + switch (PhpThemeColorMode) + { + case 0: // New colors + PhSetControlTheme(WindowHandle, L"explorer"); + break; + case 1: // Old colors + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); + break; + } + } + + PhInitializeWindowThemeACLUI(WindowHandle); + } return TRUE; } @@ -817,9 +1068,9 @@ BOOLEAN CALLBACK PhpReInitializeThemeWindowEnumChildWindows( ListView_SetTextColor(WindowHandle, RGB(0x0, 0x0, 0x0)); break; case 1: // Old colors - ListView_SetBkColor(WindowHandle, RGB(30, 30, 30)); - ListView_SetTextBkColor(WindowHandle, RGB(30, 30, 30)); - ListView_SetTextColor(WindowHandle, PhpThemeWindowTextColor); + ListView_SetBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) + ListView_SetTextBkColor(WindowHandle, PhThemeWindowBackgroundColor); // RGB(30, 30, 30) + ListView_SetTextColor(WindowHandle, PhThemeWindowTextColor); break; } } @@ -844,9 +1095,11 @@ BOOLEAN CALLBACK PhpReInitializeThemeWindowEnumChildWindows( { case 0: // New colors TreeNew_ThemeSupport(WindowHandle, FALSE); + PhSetControlTheme(WindowHandle, L""); break; case 1: // Old colors TreeNew_ThemeSupport(WindowHandle, TRUE); + PhSetControlTheme(WindowHandle, L"DarkMode_Explorer"); break; } } @@ -883,39 +1136,19 @@ BOOLEAN PhThemeWindowDrawItem( case ODT_STATIC: break; case ODT_HEADER: - { - HDITEM headerItem; - WCHAR headerText[MAX_PATH]; - - SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetDCBrushColor(DrawInfo->hDC, RGB(30, 30, 30)); - - FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - DrawEdge(DrawInfo->hDC, &DrawInfo->rcItem, BDR_RAISEDOUTER, BF_RIGHT); - - memset(headerText, 0, sizeof(headerText)); - memset(&headerItem, 0, sizeof(HDITEM)); - headerItem.mask = HDI_TEXT; - headerItem.cchTextMax = RTL_NUMBER_OF(headerText); - headerItem.pszText = headerText; - - if (Header_GetItem(DrawInfo->hwndItem, DrawInfo->itemID, &headerItem)) - { - DrawText( - DrawInfo->hDC, - headerText, - (UINT)PhCountStringZ(headerText), - &DrawInfo->rcItem, - DT_LEFT | DT_END_ELLIPSIS | DT_SINGLELINE //DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX | DT_NOCLIP - ); - } - } - return TRUE; + break; case ODT_MENU: { PPH_EMENU_ITEM menuItemInfo = (PPH_EMENU_ITEM)DrawInfo->itemData; + RECT rect = DrawInfo->rcItem; + ULONG drawTextFlags = DT_SINGLELINE | DT_NOCLIP; HFONT oldFont = NULL; + if (DrawInfo->itemState & ODS_NOACCEL) + { + drawTextFlags |= DT_HIDEPREFIX; + } + if (PhpMenuFontHandle) { oldFont = SelectFont(DrawInfo->hDC, PhpMenuFontHandle); @@ -928,20 +1161,16 @@ BOOLEAN PhThemeWindowDrawItem( // ); //SetTextColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); - if (isDisabled) + if (DrawInfo->itemState & ODS_HOTLIGHT) { - switch (PhpThemeColorMode) - { - case 0: // New colors - SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_GRAYTEXT)); - SetDCBrushColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); - break; - case 1: // Old colors - SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_GRAYTEXT)); - SetDCBrushColor(DrawInfo->hDC, RGB(28, 28, 28)); - break; - } - + SetTextColor(DrawInfo->hDC, PhThemeWindowTextColor); + SetDCBrushColor(DrawInfo->hDC, RGB(128, 128, 128)); + FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); + } + else if (isDisabled) + { + SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_GRAYTEXT)); + SetDCBrushColor(DrawInfo->hDC, PhThemeWindowBackgroundColor); FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); } else if (isSelected) @@ -949,11 +1178,11 @@ BOOLEAN PhThemeWindowDrawItem( switch (PhpThemeColorMode) { case 0: // New colors - SetTextColor(DrawInfo->hDC, PhpThemeWindowTextColor); + SetTextColor(DrawInfo->hDC, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->hDC, PhThemeWindowBackgroundColor); break; case 1: // Old colors - SetTextColor(DrawInfo->hDC, PhpThemeWindowTextColor); + SetTextColor(DrawInfo->hDC, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->hDC, RGB(128, 128, 128)); break; } @@ -962,19 +1191,17 @@ BOOLEAN PhThemeWindowDrawItem( } else { - switch (PhpThemeColorMode) - { - case 0: // New colors - SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_WINDOWTEXT)); - SetDCBrushColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); - FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - break; - case 1: // Old colors - SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetDCBrushColor(DrawInfo->hDC, PhThemeWindowBackgroundColor); // RGB(28, 28, 28) - FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - break; - } + //switch (PhpThemeColorMode) + //{ + //case 0: // New colors + // SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_WINDOWTEXT)); + // SetDCBrushColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); + // FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); + // break; + + SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetDCBrushColor(DrawInfo->hDC, PhThemeWindowBackgroundColor); + FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); } if (isChecked) @@ -1002,9 +1229,7 @@ BOOLEAN PhThemeWindowDrawItem( oldTextColor = SetTextColor(DrawInfo->hDC, GetSysColor(COLOR_WINDOWTEXT)); break; case 1: // Old colors - oldTextColor = SetTextColor(DrawInfo->hDC, PhpThemeWindowTextColor); - //FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - //SetTextColor(DrawInfo->hDC, PhpThemeWindowTextColor); + oldTextColor = SetTextColor(DrawInfo->hDC, PhThemeWindowTextColor); break; } @@ -1032,7 +1257,7 @@ BOOLEAN PhThemeWindowDrawItem( FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); break; case 1: // Old colors - SetDCBrushColor(DrawInfo->hDC, RGB(28, 28, 28)); + SetDCBrushColor(DrawInfo->hDC, PhThemeWindowBackgroundColor); // RGB(28, 28, 28) FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); break; } @@ -1041,25 +1266,33 @@ BOOLEAN PhThemeWindowDrawItem( //DrawInfo->rcItem.bottom -= 2; //DrawFocusRect(drawInfo->hDC, &drawInfo->rcItem); - SetRect( - &DrawInfo->rcItem, - DrawInfo->rcItem.left + 25, - DrawInfo->rcItem.top + 2, - DrawInfo->rcItem.right, - DrawInfo->rcItem.bottom - 2 - ); + // +5 font margin, +1 extra padding + //INT cxMenuCheck = GetSystemMetrics(SM_CXMENUCHECK) + (GetSystemMetrics(SM_CXEDGE) * 2) + 5 + 1; + INT cyEdge = GetSystemMetrics(SM_CYEDGE); + // + //SetRect( + // &DrawInfo->rcItem, + // DrawInfo->rcItem.left + cxMenuCheck, // 25 + // DrawInfo->rcItem.top + cyEdge, + // DrawInfo->rcItem.right, + // DrawInfo->rcItem.bottom - cyEdge + // ); - switch (PhpThemeColorMode) - { - case 0: // New colors - SetDCBrushColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); - FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - break; - case 1: // Old colors - SetDCBrushColor(DrawInfo->hDC, RGB(78, 78, 78)); - FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); - break; - } + SetDCBrushColor(DrawInfo->hDC, RGB(0x5f, 0x5f, 0x5f)); + SelectBrush(DrawInfo->hDC, GetStockBrush(DC_BRUSH)); + PatBlt(DrawInfo->hDC, DrawInfo->rcItem.left, DrawInfo->rcItem.top + cyEdge, DrawInfo->rcItem.right - DrawInfo->rcItem.left, 1, PATCOPY); + + //switch (PhpThemeColorMode) + //{ + //case 0: // New colors + // SetDCBrushColor(DrawInfo->hDC, RGB(0xff, 0xff, 0xff)); + // FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); + // break; + //case 1: // Old colors + // SetDCBrushColor(DrawInfo->hDC, RGB(78, 78, 78)); + // FillRect(DrawInfo->hDC, &DrawInfo->rcItem, GetStockBrush(DC_BRUSH)); + // break; + //} //DrawEdge(drawInfo->hDC, &drawInfo->rcItem, BDR_RAISEDINNER, BF_TOP); } @@ -1069,7 +1302,7 @@ BOOLEAN PhThemeWindowDrawItem( PH_STRINGREF firstPart; PH_STRINGREF secondPart; - PhInitializeStringRef(&part, menuItemInfo->Text); + PhInitializeStringRefLongHint(&part, menuItemInfo->Text); PhSplitStringRefAtLastChar(&part, L'\b', &firstPart, &secondPart); //SetDCBrushColor(DrawInfo->hDC, RGB(28, 28, 28)); @@ -1077,7 +1310,7 @@ BOOLEAN PhThemeWindowDrawItem( if (menuItemInfo->Bitmap) { - HDC hdcMem; + HDC bufferDc; BLENDFUNCTION blendFunction; blendFunction.BlendOp = AC_SRC_OVER; @@ -1085,8 +1318,8 @@ BOOLEAN PhThemeWindowDrawItem( blendFunction.SourceConstantAlpha = 255; blendFunction.AlphaFormat = AC_SRC_ALPHA; - hdcMem = CreateCompatibleDC(DrawInfo->hDC); - SelectBitmap(hdcMem, menuItemInfo->Bitmap); + bufferDc = CreateCompatibleDC(DrawInfo->hDC); + SelectBitmap(bufferDc, menuItemInfo->Bitmap); GdiAlphaBlend( DrawInfo->hDC, @@ -1094,7 +1327,7 @@ BOOLEAN PhThemeWindowDrawItem( DrawInfo->rcItem.top + 4, 16, 16, - hdcMem, + bufferDc, 0, 0, 16, @@ -1102,7 +1335,7 @@ BOOLEAN PhThemeWindowDrawItem( blendFunction ); - DeleteDC(hdcMem); + DeleteDC(bufferDc); } DrawInfo->rcItem.left += 25; @@ -1115,7 +1348,7 @@ BOOLEAN PhThemeWindowDrawItem( firstPart.Buffer, (UINT)firstPart.Length / sizeof(WCHAR), &DrawInfo->rcItem, - DT_LEFT | DT_CENTER | DT_SINGLELINE | DT_HIDEPREFIX | DT_NOCLIP + DT_LEFT | DT_SINGLELINE | DT_CENTER | DT_VCENTER | drawTextFlags ); } else @@ -1125,7 +1358,7 @@ BOOLEAN PhThemeWindowDrawItem( firstPart.Buffer, (UINT)firstPart.Length / sizeof(WCHAR), &DrawInfo->rcItem, - DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX | DT_NOCLIP + DT_LEFT | DT_VCENTER | drawTextFlags ); } @@ -1135,7 +1368,7 @@ BOOLEAN PhThemeWindowDrawItem( secondPart.Buffer, (UINT)secondPart.Length / sizeof(WCHAR), &DrawInfo->rcItem, - DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX | DT_NOCLIP + DT_RIGHT | DT_VCENTER | drawTextFlags ); } @@ -1144,6 +1377,21 @@ BOOLEAN PhThemeWindowDrawItem( SelectFont(DrawInfo->hDC, oldFont); } + if (menuItemInfo->Items && menuItemInfo->Items->Count && (menuItemInfo->Flags & PH_EMENU_MAINMENU) != PH_EMENU_MAINMENU) + { + static HTHEME menuThemeHandle = NULL; + + if (!menuThemeHandle) + { + menuThemeHandle = OpenThemeData(NULL, L"Menu"); + } + + rect.left = rect.right - 25; + DrawThemeBackground(menuThemeHandle, DrawInfo->hDC, MENU_POPUPSUBMENU, isDisabled ? MSM_DISABLED : MSM_NORMAL, &rect, NULL); + } + + ExcludeClipRect(DrawInfo->hDC, rect.left, rect.top, rect.right, rect.bottom); + return TRUE; } case ODT_COMBOBOX: @@ -1192,7 +1440,7 @@ BOOLEAN PhThemeWindowMeasureItem( PPH_EMENU_ITEM menuItemInfo = (PPH_EMENU_ITEM)DrawInfo->itemData; DrawInfo->itemWidth = 150; - DrawInfo->itemHeight = 30; + DrawInfo->itemHeight = 100; if ((menuItemInfo->Flags & PH_EMENU_SEPARATOR) == PH_EMENU_SEPARATOR) { @@ -1277,7 +1525,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( case CDDS_PREPAINT: { PPH_STRING buttonText; - ULONG_PTR buttonStyle; + LONG_PTR buttonStyle; HFONT oldFont; buttonText = PhGetWindowText(DrawInfo->hdr.hwndFrom); @@ -1318,11 +1566,11 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( switch (PhpThemeColorMode) { case 0: // New colors - //SetTextColor(DrawInfo->hdc, PhpThemeWindowTextColor); - SetDCBrushColor(DrawInfo->hdc, PhpThemeWindowTextColor); + //SetTextColor(DrawInfo->hdc, PhThemeWindowTextColor); + SetDCBrushColor(DrawInfo->hdc, PhThemeWindowTextColor); break; case 1: // Old colors - SetTextColor(DrawInfo->hdc, PhpThemeWindowTextColor); + SetTextColor(DrawInfo->hdc, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->hdc, RGB(42, 42, 42)); // WindowForegroundColor break; } @@ -1395,8 +1643,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( } } else if ((buttonStyle & BS_CHECKBOX) == BS_CHECKBOX) - { - + { if (Button_GetCheck(DrawInfo->hdr.hwndFrom) == BST_CHECKED) { HFONT newFont = PhDuplicateFontWithNewHeight(PhApplicationFont, 16); @@ -1405,7 +1652,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( DrawText( DrawInfo->hdc, L"\u2611", - -1, + 1, &DrawInfo->rc, DT_LEFT | DT_SINGLELINE | DT_VCENTER ); @@ -1420,7 +1667,7 @@ LRESULT CALLBACK PhpThemeWindowDrawButton( DrawText( DrawInfo->hdc, L"\u2610", - -1, + 1, &DrawInfo->rc, DT_LEFT | DT_SINGLELINE | DT_VCENTER ); @@ -1502,7 +1749,7 @@ LRESULT CALLBACK PhThemeWindowDrawRebar( //REBARBANDINFO bandinfo = { sizeof(REBARBANDINFO), RBBIM_CHILD | RBBIM_STYLE | RBBIM_CHEVRONLOCATION | RBBIM_CHEVRONSTATE }; //BOOL havebandinfo = (BOOL)SendMessage(DrawInfo->hdr.hwndFrom, RB_GETBANDINFO, DrawInfo->dwItemSpec, (LPARAM)&bandinfo); - SetTextColor(DrawInfo->hdc, PhpThemeWindowTextColor); + SetTextColor(DrawInfo->hdc, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->hdc, PhThemeWindowBackgroundColor); FillRect(DrawInfo->hdc, &DrawInfo->rc, GetStockBrush(DC_BRUSH)); @@ -1525,7 +1772,7 @@ LRESULT CALLBACK PhThemeWindowDrawRebar( return CDRF_NOTIFYITEMDRAW; case CDDS_ITEMPREPAINT: { - /*SetTextColor(DrawInfo->hdc, PhpThemeWindowTextColor); + /*SetTextColor(DrawInfo->hdc, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->hdc, PhThemeWindowBackgroundColor); FillRect(DrawInfo->hdc, &DrawInfo->rc, GetStockBrush(DC_BRUSH));*/ @@ -1538,7 +1785,7 @@ LRESULT CALLBACK PhThemeWindowDrawRebar( } case 1: // Old colors { - //SetTextColor(DrawInfo->hdc, PhpThemeWindowTextColor); + //SetTextColor(DrawInfo->hdc, PhThemeWindowTextColor); //SetDCBrushColor(DrawInfo->hdc, RGB(65, 65, 65)); } break; @@ -1586,6 +1833,12 @@ LRESULT CALLBACK PhThemeWindowDrawToolbar( DrawInfo->nmcd.dwItemSpec, 0 ) == 0; + BOOLEAN isEnabled = SendMessage( + DrawInfo->nmcd.hdr.hwndFrom, + TB_ISBUTTONENABLED, + DrawInfo->nmcd.dwItemSpec, + 0 + ) != 0; if (SendMessage( DrawInfo->nmcd.hdr.hwndFrom, @@ -1599,7 +1852,7 @@ LRESULT CALLBACK PhThemeWindowDrawToolbar( //if (isMouseDown) //{ - // SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + // SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // SetDCBrushColor(DrawInfo->nmcd.hdc, RGB(0xff, 0xff, 0xff)); // FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); //} @@ -1641,18 +1894,18 @@ LRESULT CALLBACK PhThemeWindowDrawToolbar( //switch (PhpThemeColorMode) //{ //case 0: // New colors - // SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + // SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // SetDCBrushColor(DrawInfo->nmcd.hdc, PhThemeWindowBackgroundColor); // FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); // break; //case 1: // Old colors - // SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + // SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // SetDCBrushColor(DrawInfo->nmcd.hdc, RGB(128, 128, 128)); // FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); // break; //} - SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); SetDCBrushColor(DrawInfo->nmcd.hdc, RGB(128, 128, 128)); FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); } @@ -1661,33 +1914,23 @@ LRESULT CALLBACK PhThemeWindowDrawToolbar( //switch (PhpThemeColorMode) //{ //case 0: // New colors - // SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); // RGB(0x0, 0x0, 0x0)); + // SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // RGB(0x0, 0x0, 0x0)); // SetDCBrushColor(DrawInfo->nmcd.hdc, PhThemeWindowBackgroundColor); // GetSysColor(COLOR_3DFACE));// RGB(0xff, 0xff, 0xff)); // FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); // break; //case 1: // Old colors - // SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + // SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // SetDCBrushColor(DrawInfo->nmcd.hdc, PhThemeWindowBackgroundColor); //RGB(65, 65, 65)); //RGB(28, 28, 28)); // RGB(65, 65, 65)); // FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); // break; //} - SetTextColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); // RGB(0x0, 0x0, 0x0)); + SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // RGB(0x0, 0x0, 0x0)); SetDCBrushColor(DrawInfo->nmcd.hdc, PhThemeWindowBackgroundColor); // GetSysColor(COLOR_3DFACE));// RGB(0xff, 0xff, 0xff)); FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); } - if (!PhpToolBarFontHandle) - { - NONCLIENTMETRICS metrics = { sizeof(NONCLIENTMETRICS) }; - - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) - { - PhpToolBarFontHandle = CreateFontIndirect(&metrics.lfMessageFont); - } - } - - SelectFont(DrawInfo->nmcd.hdc, PhpToolBarFontHandle); + SelectFont(DrawInfo->nmcd.hdc, GetWindowFont(DrawInfo->nmcd.hdr.hwndFrom)); if (buttonInfo.iImage != -1) { @@ -1700,15 +1943,30 @@ LRESULT CALLBACK PhThemeWindowDrawToolbar( 0 )) { - DrawInfo->nmcd.rc.left += 5; + LONG x; + LONG y; + + if (buttonInfo.fsStyle & BTNS_SHOWTEXT) + { + DrawInfo->nmcd.rc.left += 5; + + x = DrawInfo->nmcd.rc.left;// + ((DrawInfo->nmcd.rc.right - DrawInfo->nmcd.rc.left) - PhSmallIconSize.X) / 2; + y = DrawInfo->nmcd.rc.top + ((DrawInfo->nmcd.rc.bottom - DrawInfo->nmcd.rc.top) - PhSmallIconSize.Y) / 2; + } + else + { + x = DrawInfo->nmcd.rc.left + ((DrawInfo->nmcd.rc.right - DrawInfo->nmcd.rc.left) - PhSmallIconSize.X) / 2; + y = DrawInfo->nmcd.rc.top + ((DrawInfo->nmcd.rc.bottom - DrawInfo->nmcd.rc.top) - PhSmallIconSize.Y) / 2; + } PhImageListDrawIcon( toolbarImageList, buttonInfo.iImage, DrawInfo->nmcd.hdc, - DrawInfo->nmcd.rc.left, - DrawInfo->nmcd.rc.top + 3, - ILD_NORMAL + x, + y, + ILD_NORMAL, + !isEnabled ); } } @@ -1757,7 +2015,7 @@ LRESULT CALLBACK PhpThemeWindowDrawListViewGroup( { case 0: // New colors SetTextColor(DrawInfo->nmcd.hdc, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor(DrawInfo->nmcd.hdc, PhpThemeWindowTextColor); + SetDCBrushColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); //FillRect(DrawInfo->nmcd.hdc, &DrawInfo->nmcd.rc, GetStockBrush(DC_BRUSH)); break; case 1: // Old colors @@ -1793,7 +2051,7 @@ LRESULT CALLBACK PhpThemeWindowDrawListViewGroup( break; } - SetTextColor(DrawInfo->nmcd.hdc, RGB(255, 69, 0)); + SetTextColor(DrawInfo->nmcd.hdc, PhThemeWindowTextColor); // RGB(255, 69, 0) SetDCBrushColor(DrawInfo->nmcd.hdc, RGB(65, 65, 65)); DrawInfo->rcText.top += 2; @@ -1890,10 +2148,10 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( { case 0: // New colors SetTextColor((HDC)wParam, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor((HDC)wParam, PhpThemeWindowTextColor); + SetDCBrushColor((HDC)wParam, PhThemeWindowTextColor); return (INT_PTR)GetStockBrush(DC_BRUSH); case 1: // Old colors - SetTextColor((HDC)wParam, PhpThemeWindowTextColor); + SetTextColor((HDC)wParam, PhThemeWindowTextColor); SetDCBrushColor((HDC)wParam, RGB(60, 60, 60)); return (INT_PTR)GetStockBrush(DC_BRUSH); } @@ -1905,7 +2163,7 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( case WM_CTLCOLORLISTBOX: { SetBkMode((HDC)wParam, TRANSPARENT); - SetTextColor((HDC)wParam, PhpThemeWindowTextColor); + SetTextColor((HDC)wParam, PhThemeWindowTextColor); SetDCBrushColor((HDC)wParam, PhThemeWindowBackgroundColor); return (INT_PTR)GetStockBrush(DC_BRUSH); } @@ -1918,6 +2176,39 @@ LRESULT CALLBACK PhpThemeWindowSubclassProc( if (PhThemeWindowDrawItem((LPDRAWITEMSTRUCT)lParam)) return TRUE; break; + case WM_NCPAINT: + case WM_NCACTIVATE: + { + LRESULT result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); + + if (GetMenu(hWnd)) + { + RECT clientRect; + RECT windowRect; + HDC hdc; + + GetClientRect(hWnd, &clientRect); + GetWindowRect(hWnd, &windowRect); + + MapWindowPoints(hWnd, NULL, (PPOINT)&clientRect, 2); + PhOffsetRect(&clientRect, -windowRect.left, -windowRect.top); + + // the rcBar is offset by the window rect (thanks to adzm) (dmex) + RECT rcAnnoyingLine = clientRect; + rcAnnoyingLine.bottom = rcAnnoyingLine.top; + rcAnnoyingLine.top--; + + if (hdc = GetWindowDC(hWnd)) + { + SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); + FillRect(hdc, &rcAnnoyingLine, GetStockBrush(DC_BRUSH)); + ReleaseDC(hWnd, hdc); + } + } + + return result; + } + break; } return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); @@ -2007,27 +2298,27 @@ LRESULT CALLBACK PhpThemeWindowGroupBoxSubclassProc( textRect.right = clientRect.right; textRect.bottom = nameSize.cy; - SetTextColor(hdc, RGB(255, 69, 0)); + SetTextColor(hdc, PhThemeWindowTextColor); // RGB(255, 69, 0) SetDCBrushColor(hdc, RGB(65, 65, 65)); FillRect(hdc, &textRect, GetStockBrush(DC_BRUSH)); - switch (PhpThemeColorMode) - { - case 0: // New colors - SetTextColor(hdc, RGB(255, 69, 0)); - SetDCBrushColor(hdc, RGB(65, 65, 65)); - //SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - //SetDCBrushColor(hdc, PhpThemeWindowTextColor); - //FrameRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); - break; - case 1: // Old colors - SetTextColor(hdc, RGB(255, 69, 0)); - SetDCBrushColor(hdc, RGB(65, 65, 65)); - //SetTextColor(hdc, PhpThemeWindowTextColor); - //SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - //FrameRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); - break; - } + //switch (PhpThemeColorMode) + //{ + //case 0: // New colors + // //SetTextColor(hdc, RGB(255, 69, 0)); + // //SetDCBrushColor(hdc, RGB(65, 65, 65)); + // //SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); + // //SetDCBrushColor(hdc, PhThemeWindowTextColor); + // //FrameRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + // break; + //case 1: // Old colors + // //SetTextColor(hdc, RGB(255, 69, 0)); + // //SetDCBrushColor(hdc, RGB(65, 65, 65)); + // //SetTextColor(hdc, PhThemeWindowTextColor); + // //SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); + // //FrameRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + // break; + //} textRect.left += 10; DrawText( @@ -2090,7 +2381,7 @@ LRESULT CALLBACK PhpThemeWindowEditSubclassProc( if (hdc = GetDCEx(WindowHandle, updateRegion, flags)) { GetWindowRect(WindowHandle, &windowRect); - OffsetRect(&windowRect, -windowRect.left, -windowRect.top); + PhOffsetRect(&windowRect, -windowRect.left, -windowRect.top); if (GetFocus() == WindowHandle) { @@ -2145,29 +2436,29 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( return TRUE; case WM_MOUSEMOVE: { - POINT pt; - INT count; - INT i; - - GetCursorPos(&pt); - MapWindowPoints(NULL, WindowHandle, &pt, 1); - - count = TabCtrl_GetItemCount(WindowHandle); - - for (i = 0; i < count; i++) - { - RECT rect = { 0, 0, 0, 0 }; - TCITEM entry = - { - TCIF_STATE, - 0, - TCIS_HIGHLIGHTED - }; - - TabCtrl_GetItemRect(WindowHandle, i, &rect); - entry.dwState = PtInRect(&rect, pt) ? TCIS_HIGHLIGHTED : 0; - TabCtrl_SetItem(WindowHandle, i, &entry); - } + //POINT pt; + //INT count; + //INT i; + // + //GetCursorPos(&pt); + //MapWindowPoints(NULL, WindowHandle, &pt, 1); + // + //count = TabCtrl_GetItemCount(WindowHandle); + // + //for (i = 0; i < count; i++) + //{ + // RECT rect = { 0, 0, 0, 0 }; + // TCITEM entry = + // { + // TCIF_STATE, + // 0, + // TCIS_HIGHLIGHTED + // }; + // + // TabCtrl_GetItemRect(WindowHandle, i, &rect); + // entry.dwState = PtInRect(&rect, pt) ? TCIS_HIGHLIGHTED : 0; + // TabCtrl_SetItem(WindowHandle, i, &entry); + //} if (!context->MouseActive) { @@ -2188,42 +2479,46 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( break; case WM_MOUSELEAVE: { - INT count; - INT i; - - count = TabCtrl_GetItemCount(WindowHandle); - - for (i = 0; i < count; i++) - { - TCITEM entry = - { - TCIF_STATE, - 0, - TCIS_HIGHLIGHTED - }; - - TabCtrl_SetItem(WindowHandle, i, &entry); - } + //INT count; + //INT i; + // + //count = TabCtrl_GetItemCount(WindowHandle); + // + //for (i = 0; i < count; i++) + //{ + // TCITEM entry = + // { + // TCIF_STATE, + // 0, + // TCIS_HIGHLIGHTED + // }; + // + // TabCtrl_SetItem(WindowHandle, i, &entry); + //} - InvalidateRect(WindowHandle, NULL, FALSE); context->MouseActive = FALSE; + InvalidateRect(WindowHandle, NULL, FALSE); } break; case WM_PAINT: { - RECT itemRect; RECT windowRect; RECT clientRect; - PAINTSTRUCT ps; - - if (!BeginPaint(WindowHandle, &ps)) - break; + HDC hdc; + HDC bufferDc; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; GetWindowRect(WindowHandle, &windowRect); GetClientRect(WindowHandle, &clientRect); + hdc = GetDC(WindowHandle); + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + TabCtrl_AdjustRect(WindowHandle, FALSE, &clientRect); // Make sure we don't paint in the client area. - ExcludeClipRect(ps.hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom); + ExcludeClipRect(bufferDc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom); windowRect.right -= windowRect.left; windowRect.bottom -= windowRect.top; @@ -2235,17 +2530,12 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( clientRect.right = windowRect.right; clientRect.bottom = windowRect.bottom; - HDC hdc = CreateCompatibleDC(ps.hdc); - HDC hdcTab = CreateCompatibleDC(hdc); - HBITMAP hbm = CreateCompatibleBitmap(ps.hdc, clientRect.right, clientRect.bottom); - SelectBitmap(hdc, hbm); + SetBkMode(bufferDc, TRANSPARENT); + SelectFont(bufferDc, GetWindowFont(WindowHandle)); - SetBkMode(hdc, TRANSPARENT); - SelectFont(hdc, PhpTabControlFontHandle); - - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); //switch (PhpThemeColorMode) //{ @@ -2267,11 +2557,11 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( //{ //case 0: // New colors // //SetTextColor(hdc, RGB(0x0, 0xff, 0x0)); - // SetDCBrushColor(hdc, GetSysColor(COLOR_3DFACE));// PhpThemeWindowTextColor); + // SetDCBrushColor(hdc, GetSysColor(COLOR_3DFACE));// PhThemeWindowTextColor); // FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); // break; //case 1: // Old colors - // //SetTextColor(hdc, PhpThemeWindowTextColor); + // //SetTextColor(hdc, PhThemeWindowTextColor); // SetDCBrushColor(hdc, RGB(65, 65, 65)); //WindowForegroundColor); // RGB(65, 65, 65)); // FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); // break; @@ -2281,77 +2571,81 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( GetCursorPos(&pt); MapWindowPoints(NULL, WindowHandle, &pt, 1); + INT currentSelection = TabCtrl_GetCurSel(WindowHandle); INT count = TabCtrl_GetItemCount(WindowHandle); + for (INT i = 0; i < count; i++) { + RECT itemRect; + TabCtrl_GetItemRect(WindowHandle, i, &itemRect); if (PtInRect(&itemRect, pt)) { - OffsetRect(&itemRect, 2, 2); + PhOffsetRect(&itemRect, 2, 2); switch (PhpThemeColorMode) { case 0: // New colors { - if (TabCtrl_GetCurSel(WindowHandle) == i) + if (currentSelection == i) { - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(128, 128, 128)); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); + SetDCBrushColor(bufferDc, RGB(128, 128, 128)); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } else { - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } } break; case 1: // Old colors - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, RGB(128, 128, 128)); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, RGB(128, 128, 128)); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); break; } - //FrameRect(hdc, &itemRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + //FrameRect(bufferDc, &itemRect, GetSysColorBrush(COLOR_HIGHLIGHT)); } else { - OffsetRect(&itemRect, 2, 2); + PhOffsetRect(&itemRect, 2, 2); switch (PhpThemeColorMode) { case 0: // New colors { - if (TabCtrl_GetCurSel(WindowHandle) == i) + if (currentSelection == i) { - SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor(hdc, RGB(0xff, 0xff, 0xff)); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, RGB(0x0, 0x0, 0x0)); + SetDCBrushColor(bufferDc, RGB(0xff, 0xff, 0xff)); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } else { - SetTextColor(hdc, RGB(0, 0, 0)); - SetDCBrushColor(hdc, GetSysColor(COLOR_3DFACE));// PhpThemeWindowTextColor); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, RGB(0, 0, 0)); + SetDCBrushColor(bufferDc, GetSysColor(COLOR_3DFACE));// PhThemeWindowTextColor); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } } break; case 1: // Old colors { - if (TabCtrl_GetCurSel(WindowHandle) == i) + if (currentSelection == i) { - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowForegroundColor); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowForegroundColor); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } else { - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &itemRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &itemRect, GetStockBrush(DC_BRUSH)); } } break; @@ -2373,7 +2667,7 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( if (TabCtrl_GetItem(WindowHandle, i, &tabItem)) { DrawText( - hdc, + bufferDc, tabItem.pszText, (UINT)PhCountStringZ(tabItem.pszText), &itemRect, @@ -2383,20 +2677,16 @@ LRESULT CALLBACK PhpThemeWindowTabControlWndSubclassProc( } } - BitBlt(ps.hdc, 0, 0, clientRect.right, clientRect.bottom, hdc, 0, 0, SRCCOPY); - - DeleteDC(hdcTab); - DeleteDC(hdc); - DeleteBitmap(hbm); - EndPaint(WindowHandle, &ps); + BitBlt(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + ReleaseDC(WindowHandle, hdc); } - goto DefaultWndProc; + return DefWindowProc(WindowHandle, uMsg, wParam, lParam); } return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); - -DefaultWndProc: - return DefWindowProc(WindowHandle, uMsg, wParam, lParam); } LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( @@ -2428,20 +2718,8 @@ LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( // return 1; case WM_MOUSEMOVE: { - //POINT pt; - //RECT rcItem; - //TCITEM tcItem; - //tcItem.mask = TCIF_STATE; - //tcItem.dwStateMask = TCIS_HIGHLIGHTED; - //GetCursorPos(&pt); - //MapWindowPoints(NULL, WindowHandle, &pt, 1); - //int nCount = TabCtrl_GetItemCount(WindowHandle); - //for (int i = 0; i < nCount; i++) - //{ - // TabCtrl_GetItemRect(WindowHandle, i, &rcItem); - // tcItem.dwState = PtInRect(&rcItem, pt) ? TCIS_HIGHLIGHTED : 0; - // TabCtrl_SetItem(WindowHandle, i, &tcItem); - //} + if (GetCapture() == WindowHandle) + break; if (!context->MouseActive) { @@ -2482,46 +2760,39 @@ LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( break; case WM_PAINT: { - //HTHEME hTheme = OpenThemeData(WindowHandle, L"HEADER"); - WCHAR headerText[MAX_PATH]; - RECT clientRect; + WCHAR headerText[0x100] = { 0 }; HDITEM headerItem; - PAINTSTRUCT ps; + RECT clientRect; + HDC hdc; + HDC bufferDc; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; - //InvalidateRect(WindowHandle, NULL, FALSE); - BeginPaint(WindowHandle, &ps); GetClientRect(WindowHandle, &clientRect); - HDC hdc = CreateCompatibleDC(ps.hdc); - HDC hdcTab = CreateCompatibleDC(hdc); - HBITMAP hbm = CreateCompatibleBitmap(ps.hdc, clientRect.right, clientRect.bottom); - SelectBitmap(hdc, hbm); + hdc = GetDC(WindowHandle); + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); - if (!PhpHeaderFontHandle) - { - NONCLIENTMETRICS metrics = { sizeof(metrics) }; - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) - { - PhpHeaderFontHandle = CreateFontIndirect(&metrics.lfMessageFont); - } - } - SelectFont(hdc, PhpHeaderFontHandle); - SetBkMode(hdc, TRANSPARENT); + SelectFont(bufferDc, GetWindowFont(WindowHandle)); - switch (PhpThemeColorMode) - { - case 0: // New colors - SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor(hdc, PhpThemeWindowTextColor); - FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); - break; - case 1: // Old colors - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, RGB(65, 65, 65)); //WindowForegroundColor); // RGB(65, 65, 65)); - FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); - break; - } + SetBkMode(bufferDc, TRANSPARENT); + + //switch (PhpThemeColorMode) + //{ + //case 0: // New colors + //SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); + //SetDCBrushColor(hdc, PhThemeWindowTextColor); + //FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + //break; + //case 1: // Old colors + // //SetTextColor(hdc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); //WindowForegroundColor); // RGB(65, 65, 65)); + FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); + // break; + //} INT headerItemCount = Header_GetItemCount(WindowHandle); POINT pt; @@ -2541,14 +2812,14 @@ LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( switch (PhpThemeColorMode) { case 0: // New colors - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &headerRect, GetStockBrush(DC_BRUSH)); break; case 1: // Old colors - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, RGB(128, 128, 128)); - FillRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, RGB(128, 128, 128)); + FillRect(bufferDc, &headerRect, GetStockBrush(DC_BRUSH)); break; } @@ -2556,34 +2827,37 @@ LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( } else { - switch (PhpThemeColorMode) - { - case 0: // New colors - SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor(hdc, PhpThemeWindowTextColor); - FillRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); - break; - case 1: // Old colors - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); - break; - } + //switch (PhpThemeColorMode) + // { + // case 0: // New colors + + //SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); + //SetDCBrushColor(hdc, PhThemeWindowTextColor); + //FillRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); + // break; + //case 1: // Old colors + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &headerRect, GetStockBrush(DC_BRUSH)); + // break; + //} //FrameRect(hdc, &headerRect, GetSysColorBrush(COLOR_HIGHLIGHT)); //SetDCPenColor(hdc, RGB(0, 255, 0)); //SetDCBrushColor(hdc, RGB(0, 255, 0)); //DrawEdge(hdc, &headerRect, BDR_RAISEDOUTER | BF_FLAT, BF_RIGHT); - RECT frameRect; - - frameRect.bottom = headerRect.bottom; - frameRect.left = headerRect.right - 1; - frameRect.right = headerRect.right; - frameRect.top = headerRect.top; - - SetDCBrushColor(hdc, RGB(68, 68, 68)); // RGB(0x77, 0x77, 0x77)); - FrameRect(hdc, &frameRect, GetStockBrush(DC_BRUSH)); + //RECT frameRect; + //frameRect.bottom = headerRect.bottom - 2; + //frameRect.left = headerRect.right - 1; + //frameRect.right = headerRect.right; + //frameRect.top = headerRect.top; + //SetDCBrushColor(hdc, RGB(68, 68, 68)); // RGB(0x77, 0x77, 0x77)); + //FrameRect(hdc, &headerRect, GetStockBrush(DC_BRUSH)); + + //PatBlt(DrawInfo->hDC, DrawInfo->rcItem.right - 1, DrawInfo->rcItem.top, 1, DrawInfo->rcItem.bottom - DrawInfo->rcItem.top, PATCOPY); + //PatBlt(DrawInfo->hDC, DrawInfo->rcItem.left, DrawInfo->rcItem.bottom - 1, DrawInfo->rcItem.right - DrawInfo->rcItem.left, 1, PATCOPY); + DrawEdge(bufferDc, &headerRect, BDR_RAISEDOUTER, BF_RIGHT); } ZeroMemory(&headerItem, sizeof(HDITEM)); @@ -2602,20 +2876,19 @@ LRESULT CALLBACK PhpThemeWindowHeaderSubclassProc( headerRect.left += 4; headerRect.right -= 8; DrawText( - hdc, + bufferDc, headerText, - -1, + (UINT)PhCountStringZ(headerText), &headerRect, drawTextFlags ); } - BitBlt(ps.hdc, 0, 0, clientRect.right, clientRect.bottom, hdc, 0, 0, SRCCOPY); - - DeleteDC(hdcTab); - DeleteDC(hdc); - DeleteBitmap(hbm); - EndPaint(WindowHandle, &ps); + BitBlt(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + ReleaseDC(WindowHandle, hdc); } goto DefaultWndProc; } @@ -2674,123 +2947,121 @@ LRESULT CALLBACK PhpThemeWindowStatusbarWndSubclassProc( break; case WM_MOUSELEAVE: { - InvalidateRect(WindowHandle, NULL, FALSE); context->MouseActive = FALSE; + InvalidateRect(WindowHandle, NULL, FALSE); } break; case WM_PAINT: { RECT clientRect; - PAINTSTRUCT ps; - INT blockCoord[128]; - INT blockCount = (INT)SendMessage(WindowHandle, (UINT)SB_GETPARTS, (WPARAM)ARRAYSIZE(blockCoord), (WPARAM)blockCoord); + HDC hdc; + HDC bufferDc; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; - // InvalidateRect(WindowHandle, NULL, FALSE); GetClientRect(WindowHandle, &clientRect); - if (!BeginPaint(WindowHandle, &ps)) - break; - - SetBkMode(ps.hdc, TRANSPARENT); - HDC hdc = CreateCompatibleDC(ps.hdc); - SetBkMode(hdc, TRANSPARENT); - - HBITMAP hbm = CreateCompatibleBitmap(ps.hdc, clientRect.right, clientRect.bottom); - SelectBitmap(hdc, hbm); - - if (!PhpStatusBarFontHandle) - { - NONCLIENTMETRICS metrics = { sizeof(NONCLIENTMETRICS) }; - - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) - { - PhpStatusBarFontHandle = CreateFontIndirect(&metrics.lfMessageFont); - } - } + hdc = GetDC(WindowHandle); + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); - SelectFont(hdc, PhpStatusBarFontHandle); - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + SetBkMode(bufferDc, TRANSPARENT); + SelectFont(bufferDc, GetWindowFont(WindowHandle)); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); //switch (PhpThemeColorMode) //{ //case 0: // New colors - // SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - // SetDCBrushColor(hdc, GetSysColor(COLOR_3DFACE)); // RGB(0xff, 0xff, 0xff)); - // FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + // SetTextColor(bufferDc, RGB(0x0, 0x0, 0x0)); + // SetDCBrushColor(bufferDc, GetSysColor(COLOR_3DFACE)); // RGB(0xff, 0xff, 0xff)); + // FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); // break; //case 1: // Old colors - // SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - // SetDCBrushColor(hdc, RGB(65, 65, 65)); //RGB(28, 28, 28)); // RGB(65, 65, 65)); - // FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + // SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); + // SetDCBrushColor(bufferDc, RGB(65, 65, 65)); //RGB(28, 28, 28)); // RGB(65, 65, 65)); + // FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); // break; //} - for (INT i = 0; i < blockCount; i++) + POINT windowPoint; + GetCursorPos(&windowPoint); + MapWindowPoints(NULL, WindowHandle, &windowPoint, 1); + + UINT blockCount = (UINT)CallWindowProc(oldWndProc, WindowHandle, SB_GETPARTS, 0, 0); + + for (UINT i = 0; i < blockCount; i++) { - RECT blockRect = { 0, 0, 0, 0 }; - WCHAR buffer[MAX_PATH] = L""; + RECT blockRect = { 0 }; + WCHAR buffer[0x100] = { 0 }; - if (!SendMessage(WindowHandle, SB_GETRECT, (WPARAM)i, (WPARAM)&blockRect)) + if (!CallWindowProc(oldWndProc, WindowHandle, SB_GETRECT, (WPARAM)i, (WPARAM)&blockRect)) continue; - if (!SendMessage(WindowHandle, SB_GETTEXT, (WPARAM)i, (LPARAM)buffer)) + if (!RectVisible(hdc, &blockRect)) + continue; + if (CallWindowProc(oldWndProc, WindowHandle, SB_GETTEXTLENGTH, (WPARAM)i, 0) >= RTL_NUMBER_OF(buffer)) + continue; + if (!CallWindowProc(oldWndProc, WindowHandle, SB_GETTEXT, (WPARAM)i, (LPARAM)buffer)) continue; - POINT pt; - GetCursorPos(&pt); - MapWindowPoints(NULL, WindowHandle, &pt, 1); - - if (PtInRect(&blockRect, pt)) + if (PtInRect(&blockRect, windowPoint)) { switch (PhpThemeColorMode) { case 0: // New colors - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(64, 64, 64)); - FillRect(hdc, &blockRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); + SetDCBrushColor(bufferDc, RGB(64, 64, 64)); + FillRect(bufferDc, &blockRect, GetStockBrush(DC_BRUSH)); break; case 1: // Old colors - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(128, 128, 128)); - FillRect(hdc, &blockRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); + SetDCBrushColor(bufferDc, RGB(128, 128, 128)); + FillRect(bufferDc, &blockRect, GetStockBrush(DC_BRUSH)); break; } - //FrameRect(hdc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); } else { - SetTextColor(hdc, PhpThemeWindowTextColor); - SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - FillRect(hdc, &blockRect, GetStockBrush(DC_BRUSH)); + SetTextColor(bufferDc, PhThemeWindowTextColor); + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &blockRect, GetStockBrush(DC_BRUSH)); //switch (PhpThemeColorMode) //{ //case 0: // New colors - // SetTextColor(hdc, PhpThemeWindowTextColor); - // SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); - // //SetTextColor(hdc, RGB(0x0, 0x0, 0x0)); - // //SetDCBrushColor(hdc, GetSysColor(COLOR_3DFACE)); // RGB(0xff, 0xff, 0xff)); - // FillRect(hdc, &blockRect, GetStockBrush(DC_BRUSH)); + // SetTextColor(bufferDc, PhThemeWindowTextColor); + // SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + // //SetTextColor(bufferDc, RGB(0x0, 0x0, 0x0)); + // //SetDCBrushColor(bufferDc, GetSysColor(COLOR_3DFACE)); // RGB(0xff, 0xff, 0xff)); + // FillRect(bufferDc, &blockRect, GetStockBrush(DC_BRUSH)); // break; //case 1: // Old colors - // SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - // SetDCBrushColor(hdc, RGB(64, 64, 64)); - // FillRect(hdc, &blockRect, GetStockBrush(DC_BRUSH)); + // SetTextColor(bufferDc, RGB(0xff, 0xff, 0xff)); + // SetDCBrushColor(bufferDc, RGB(64, 64, 64)); + // FillRect(bufferDc, &blockRect, GetStockBrush(DC_BRUSH)); // break; //} // - //FrameRect(hdc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + //FrameRect(bufferDc, &blockRect, GetSysColorBrush(COLOR_HIGHLIGHT)); } + blockRect.left += 2; DrawText( - hdc, + bufferDc, buffer, - -1, + (UINT)PhCountStringZ(buffer), &blockRect, - DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX + DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_HIDEPREFIX ); + blockRect.left -= 2; + + //SetDCBrushColor(bufferDc, RGB(0x5f, 0x5f, 0x5f)); + //SelectBrush(bufferDc, GetStockBrush(DC_BRUSH)); + //PatBlt(bufferDc, blockRect.right - 1, blockRect.top, 1, blockRect.bottom - blockRect.top, PATCOPY); + //DrawEdge(bufferDc, &blockRect, BDR_RAISEDOUTER, BF_RIGHT); } { @@ -2802,24 +3073,21 @@ LRESULT CALLBACK PhpThemeWindowStatusbarWndSubclassProc( sizeGripRect.bottom = clientRect.bottom; if (context->StatusThemeData) - DrawThemeBackground(context->StatusThemeData, hdc, SP_GRIPPER, 0, &sizeGripRect, &sizeGripRect); + DrawThemeBackground(context->StatusThemeData, bufferDc, SP_GRIPPER, 0, &sizeGripRect, &sizeGripRect); else - DrawFrameControl(hdc, &sizeGripRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP); + DrawFrameControl(bufferDc, &sizeGripRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP); } - BitBlt(ps.hdc, 0, 0, clientRect.right, clientRect.bottom, hdc, 0, 0, SRCCOPY); - - DeleteDC(hdc); - DeleteBitmap(hbm); - EndPaint(WindowHandle, &ps); + BitBlt(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + ReleaseDC(WindowHandle, hdc); } - goto DefaultWndProc; + return DefWindowProc(WindowHandle, uMsg, wParam, lParam); } return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); - -DefaultWndProc: - return DefWindowProc(WindowHandle, uMsg, wParam, lParam); } LRESULT CALLBACK PhpThemeWindowRebarToolbarSubclassProc( @@ -2855,10 +3123,10 @@ LRESULT CALLBACK PhpThemeWindowRebarToolbarSubclassProc( { case 0: // New colors SetTextColor((HDC)wParam, RGB(0x0, 0x0, 0x0)); - SetDCBrushColor((HDC)wParam, PhpThemeWindowTextColor); + SetDCBrushColor((HDC)wParam, PhThemeWindowTextColor); return (INT_PTR)GetStockBrush(DC_BRUSH); case 1: // Old colors - SetTextColor((HDC)wParam, PhpThemeWindowTextColor); + SetTextColor((HDC)wParam, PhThemeWindowTextColor); SetDCBrushColor((HDC)wParam, RGB(60, 60, 60)); return (INT_PTR)GetStockBrush(DC_BRUSH); } @@ -2931,3 +3199,319 @@ LRESULT CALLBACK PhpThemeWindowStaticControlSubclassProc( return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); } + +LRESULT CALLBACK PhpThemeWindowListBoxControlSubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + PPHP_THEME_WINDOW_STATUSBAR_CONTEXT context; + WNDPROC oldWndProc; + + if (!(context = PhGetWindowContext(WindowHandle, LONG_MAX))) + return FALSE; + + oldWndProc = context->DefaultWindowProc; + + switch (uMsg) + { + case WM_NCDESTROY: + { + PhRemoveWindowContext(WindowHandle, LONG_MAX); + SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)oldWndProc); + } + break; + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + { + POINT windowPoint; + RECT windowRect; + + GetCursorPos(&windowPoint); + GetWindowRect(WindowHandle, &windowRect); + context->Hot = PtInRect(&windowRect, windowPoint); + + if (!context->HotTrack) + { + TRACKMOUSEEVENT trackMouseEvent; + trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); + trackMouseEvent.dwFlags = TME_LEAVE | TME_NONCLIENT; + trackMouseEvent.hwndTrack = WindowHandle; + trackMouseEvent.dwHoverTime = 0; + + context->HotTrack = TRUE; + + TrackMouseEvent(&trackMouseEvent); + } + + RedrawWindow(WindowHandle, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + } + break; + case WM_MOUSELEAVE: + case WM_NCMOUSELEAVE: + { + POINT windowPoint; + RECT windowRect; + + context->HotTrack = FALSE; + + GetCursorPos(&windowPoint); + GetWindowRect(WindowHandle, &windowRect); + context->Hot = PtInRect(&windowRect, windowPoint); + + RedrawWindow(WindowHandle, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + } + break; + case WM_CAPTURECHANGED: + { + POINT windowPoint; + RECT windowRect; + + GetCursorPos(&windowPoint); + GetWindowRect(WindowHandle, &windowRect); + context->Hot = PtInRect(&windowRect, windowPoint); + + RedrawWindow(WindowHandle, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + } + break; + case WM_NCCALCSIZE: + { + LPNCCALCSIZE_PARAMS ncCalcSize = (NCCALCSIZE_PARAMS*)lParam; + + CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); + + PhInflateRect(&ncCalcSize->rgrc[0], 1, 1); + } + return 0; + case WM_NCPAINT: + { + HDC hdc; + ULONG flags; + RECT clientRect; + RECT windowRect; + HRGN updateRegion; + INT cxEdge = GetSystemMetrics(SM_CXEDGE); + INT cyEdge = GetSystemMetrics(SM_CYEDGE); + + updateRegion = (HRGN)wParam; + + GetWindowRect(WindowHandle, &windowRect); + + // draw the scrollbar without the border. + { + HRGN rectregion = CreateRectRgn( + windowRect.left + cxEdge, + windowRect.top + cyEdge, + windowRect.right - cxEdge, + windowRect.bottom - cyEdge + ); + + if (updateRegion != (HRGN)1) + CombineRgn(rectregion, rectregion, updateRegion, RGN_AND); + DefWindowProc(WindowHandle, WM_NCPAINT, (WPARAM)rectregion, 0); + DeleteObject(rectregion); + } + + if (updateRegion == (HRGN)1) // HRGN_FULL + updateRegion = NULL; + + flags = DCX_WINDOW | DCX_LOCKWINDOWUPDATE | DCX_USESTYLE; + + if (updateRegion) + flags |= DCX_INTERSECTRGN | DCX_NODELETERGN; + + if (hdc = GetDCEx(WindowHandle, updateRegion, flags)) + { + PhOffsetRect(&windowRect, -windowRect.left, -windowRect.top); + clientRect = windowRect; + clientRect.left += cxEdge; + clientRect.top += cyEdge; + clientRect.right -= cxEdge; + clientRect.bottom -= cyEdge; + + { + SCROLLBARINFO scrollInfo = { sizeof(SCROLLBARINFO) }; + + if (GetScrollBarInfo(WindowHandle, OBJID_VSCROLL, &scrollInfo)) + { + if ((scrollInfo.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0) + { + clientRect.right -= GetSystemMetrics(SM_CXVSCROLL); + } + } + } + + ExcludeClipRect(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom); + + if (context->Hot) + { + SetDCBrushColor(hdc, RGB(0x8f, 0x8f, 0x8f));// GetSysColor(COLOR_HOTLIGHT)); + FrameRect(hdc, &windowRect, GetStockBrush(DC_BRUSH)); + //windowRect.left += 1; + //windowRect.top += 1; + //windowRect.right -= 1; + //windowRect.bottom -= 1; + //FrameRect(hdc, &windowRect, GetStockBrush(DC_BRUSH)); + } + else + { + SetDCBrushColor(hdc, RGB(65, 65, 65)); + FrameRect(hdc, &windowRect, GetSysColorBrush(COLOR_WINDOWFRAME)); + //windowRect.left += 1; + //windowRect.top += 1; + //windowRect.right -= 1; + //windowRect.bottom -= 1; + //FrameRect(hdc, &windowRect, GetSysColorBrush(COLOR_WINDOWFRAME)); + } + + ReleaseDC(WindowHandle, hdc); + return TRUE; + } + } + break; + } + + return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); +} + +LRESULT CALLBACK PhpThemeWindowComboBoxControlSubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + WNDPROC oldWndProc; + + if (!(oldWndProc = PhGetWindowContext(WindowHandle, LONG_MAX))) + return FALSE; + + switch (uMsg) + { + case WM_NCDESTROY: + { + PhRemoveWindowContext(WindowHandle, LONG_MAX); + SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)oldWndProc); + } + break; + case WM_PAINT: + { + HDC hdc; + + if (hdc = GetDC(WindowHandle)) + { + BOOLEAN isFocused = GetFocus() == WindowHandle; + BOOLEAN isMouseover = FALSE; + RECT clientRect; + + GetClientRect(WindowHandle, &clientRect); + + SetBkMode(hdc, TRANSPARENT); + + LONG_PTR windowStyle = PhGetWindowStyle(WindowHandle); + + if ((windowStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST) + { + COMBOBOXINFO info = { sizeof(COMBOBOXINFO) }; + + if (CallWindowProc(oldWndProc, WindowHandle, CB_GETCOMBOBOXINFO, 0, (LPARAM)&info)) + { + ExcludeClipRect(hdc, info.rcItem.left + 1, info.rcItem.top + 1, info.rcItem.right + 1, info.rcItem.bottom + 1); + } + } + + POINT clientPoint; + GetCursorPos(&clientPoint); + MapWindowPoints(NULL, WindowHandle, &clientPoint, 1); + + if (PtInRect(&clientRect, clientPoint)) + { + isMouseover = TRUE; + } + + SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); + FillRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + + SelectFont(hdc, CallWindowProc(oldWndProc, WindowHandle, WM_GETFONT, 0, 0)); + SetTextColor(hdc, PhThemeWindowTextColor); + SetDCBrushColor(hdc, isMouseover ? RGB(0x8f, 0x8f, 0x8f) : GetSysColor(COLOR_WINDOWFRAME));// RGB(0, 120, 212) : RGB(68, 68, 68)); + FrameRect(hdc, &clientRect, GetStockBrush(DC_BRUSH)); + + //{ + // static HTHEME themeHandle = NULL; + // if (!themeHandle) + // themeHandle = OpenThemeData(NULL, L"ComboBox"); + // + // RECT themeRect = clientRect; + // themeRect.left = themeRect.right - GetSystemMetrics(SM_CYHSCROLL); + // + // DrawThemeBackground(themeHandle, hdc, CP_DROPDOWNBUTTONRIGHT, CBXSR_NORMAL, &themeRect, NULL); + //} + + UINT index = ComboBox_GetCurSel(WindowHandle); + if (index != CB_ERR) + { + WCHAR text[MAX_PATH]; + + ComboBox_GetLBText(WindowHandle, index, text); + + clientRect.left += 5; + DrawText( + hdc, + text, + (UINT)PhCountStringZ(text), + &clientRect, + DT_EDITCONTROL | DT_LEFT | DT_VCENTER | DT_SINGLELINE + ); + clientRect.left -= 5; + } + + ReleaseDC(WindowHandle, hdc); + } + } + return DefWindowProc(WindowHandle, uMsg, wParam, lParam); + } + + return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); +} + +LRESULT CALLBACK PhpThemeWindowACLUISubclassProc( + _In_ HWND WindowHandle, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam +) +{ + WNDPROC oldWndProc; + + if (!(oldWndProc = PhGetWindowContext(WindowHandle, LONG_MAX))) + return FALSE; + + switch (uMsg) + { + case WM_NCDESTROY: + { + PhRemoveWindowContext(WindowHandle, LONG_MAX); + SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)oldWndProc); + } + break; + case WM_ERASEBKGND: + { + RECT rc; + GetClientRect(WindowHandle, &rc); + FillRect((HDC)wParam, &rc, PhMenuBackgroundBrush); + return 1; + } + case WM_CTLCOLORSTATIC: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, PhThemeWindowTextColor); + SetDCBrushColor((HDC)wParam, PhThemeWindowBackgroundColor); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + } + + return CallWindowProc(oldWndProc, WindowHandle, uMsg, wParam, lParam); +} diff --git a/ProcessHacker/phlib/treenew.c b/ProcessHacker/phlib/treenew.c index b2e8ab9d..3407ed0d 100644 --- a/ProcessHacker/phlib/treenew.c +++ b/ProcessHacker/phlib/treenew.c @@ -92,12 +92,12 @@ LRESULT CALLBACK PhTnpWndProc( { PPH_TREENEW_CONTEXT context; - context = (PPH_TREENEW_CONTEXT)GetWindowLongPtr(hwnd, 0); + context = PhGetWindowContext(hwnd, MAXCHAR); if (uMsg == WM_CREATE) { PhTnpCreateTreeNewContext(&context); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)context); + PhSetWindowContext(hwnd, MAXCHAR, context); } if (!context) @@ -123,7 +123,7 @@ LRESULT CALLBACK PhTnpWndProc( { context->Callback(hwnd, TreeNewDestroying, NULL, NULL, context->CallbackContext); PhTnpDestroyTreeNewContext(context); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)NULL); + PhRemoveWindowContext(hwnd, MAXCHAR); } return 0; case WM_SIZE: @@ -302,6 +302,14 @@ LRESULT CALLBACK PhTnpWndProc( if (context->ThemeSupport && PhThemeWindowDrawItem((LPDRAWITEMSTRUCT)lParam)) return TRUE; break; + case WM_CTLCOLORSCROLLBAR: + if (context->ThemeSupport) + return HANDLE_WM_CTLCOLORSCROLLBAR(hwnd, wParam, lParam, PhWindowThemeControlColor); + break; + case WM_CTLCOLORSTATIC: + if (context->ThemeSupport) + return HANDLE_WM_CTLCOLORSTATIC(hwnd, wParam, lParam, PhWindowThemeControlColor); + break; } if (uMsg >= TNM_FIRST && uMsg <= TNM_LAST) @@ -407,6 +415,12 @@ VOID PhTnpDestroyTreeNewContext( if (Context->SuspendUpdateRegion) DeleteRgn(Context->SuspendUpdateRegion); + if (Context->HeaderThemeHandle) + CloseThemeData(Context->HeaderThemeHandle); + + if (Context->HeaderBoldFontHandle) + DeleteFont(Context->HeaderBoldFontHandle); + PhFree(Context); } @@ -450,6 +464,10 @@ BOOLEAN PhTnpOnCreate( Context->CustomSelectedColor = GetSysColor(COLOR_HIGHLIGHT); } + // TODO: HeaderCustomDraw doesn't support classic theme on Windows 7 (dmex) + if (Context->Style & TN_STYLE_CUSTOM_HEADERDRAW && WindowsVersion > WINDOWS_7) + Context->HeaderCustomDraw = TRUE; + if (!(Context->FixedHeaderHandle = CreateWindow( WC_HEADER, NULL, @@ -878,6 +896,15 @@ VOID PhTnpOnMouseLeave( SetTimer(Context->Handle, TNP_TIMER_ANIMATE_DIVIDER, TNP_ANIMATE_DIVIDER_INTERVAL, NULL); } } + + if (Context->TooltipIndex != ULONG_MAX || Context->TooltipId != ULONG_MAX) + { + // Hide the tooltip when the mouse leaves the window or we lose focus. This fixes a certain tooltip bug + // when hovering over an item to show the tooltip while alt-tabbing causes the tooltip to remain stuck + // on screen. There's also a similar issue when a window steals focus just as the tooltip becomes visible + // and also causes the tooltip to remain stuck on screen. Popping here fixes both issues. (dmex) + PhTnpPopTooltip(Context); + } } VOID PhTnpOnXxxButtonXxx( @@ -1132,7 +1159,7 @@ VOID PhTnpOnXxxButtonXxx( clickMessage = -1; - if (Message == WM_LBUTTONDOWN || Message == WM_RBUTTONDOWN) + if (Message == WM_LBUTTONDOWN || Message == WM_RBUTTONDOWN || Message == WM_MBUTTONDOWN) { if (Context->MouseDownLast != 0 && Context->MouseDownLast != Message) { @@ -1141,23 +1168,27 @@ VOID PhTnpOnXxxButtonXxx( if (Context->MouseDownLast == WM_LBUTTONDOWN) clickMessage = TreeNewLeftClick; - else + else if (Context->MouseDownLast == WM_RBUTTONDOWN) clickMessage = TreeNewRightClick; + else + clickMessage = TreeNewMiddleClick; } Context->MouseDownLast = Message; Context->MouseDownLocation.x = CursorX; Context->MouseDownLocation.y = CursorY; } - else if (Message == WM_LBUTTONUP || Message == WM_RBUTTONUP) + else if (Message == WM_LBUTTONUP || Message == WM_RBUTTONUP || Message == WM_MBUTTONUP) { if (Context->MouseDownLast != 0 && Context->MouseDownLocation.x == CursorX && Context->MouseDownLocation.y == CursorY) { if (Context->MouseDownLast == WM_LBUTTONDOWN) clickMessage = TreeNewLeftClick; - else + else if (Context->MouseDownLast == WM_RBUTTONDOWN) clickMessage = TreeNewRightClick; + else + clickMessage = TreeNewMiddleClick; } Context->MouseDownLast = 0; @@ -2243,14 +2274,44 @@ VOID PhTnpLayoutHeader( if (!(Context->Style & TN_STYLE_NO_COLUMN_HEADER)) { + LONG headerHeight = 0; + + if (Context->HeaderCustomDraw) + { + // HACK: Use the row height instead of querying the font. (dmex) + if (Context->RowHeight) + { + headerHeight = Context->RowHeight + 1; + } + else + { + TEXTMETRIC textMetrics; + HDC hdc; + + if (hdc = GetDC(Context->FixedHeaderHandle)) + { + SelectFont(hdc, GetWindowFont(Context->FixedHeaderHandle)); + GetTextMetrics(hdc, &textMetrics); + + // Below we try to match the height as calculated by the header, even if it + // involves magic numbers. On Vista and above there seems to be extra padding. + + headerHeight = textMetrics.tmHeight; + ReleaseDC(Context->FixedHeaderHandle, hdc); + } + + headerHeight += 5; // Add magic padding + } + } + // Fixed portion header control rect.left = 0; rect.top = 0; rect.right = Context->NormalLeft; rect.bottom = Context->ClientRect.bottom; Header_Layout(Context->FixedHeaderHandle, &hdl); - SetWindowPos(Context->FixedHeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy, windowPos.flags); - Context->HeaderHeight = windowPos.cy; + SetWindowPos(Context->FixedHeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy + headerHeight, windowPos.flags); + Context->HeaderHeight = windowPos.cy + headerHeight; // Normal portion header control rect.left = Context->NormalLeft - Context->HScrollPosition; @@ -2258,7 +2319,7 @@ VOID PhTnpLayoutHeader( rect.right = Context->ClientRect.right - (Context->VScrollVisible ? Context->VScrollWidth : 0); rect.bottom = Context->ClientRect.bottom; Header_Layout(Context->HeaderHandle, &hdl); - SetWindowPos(Context->HeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy, windowPos.flags); + SetWindowPos(Context->HeaderHandle, NULL, windowPos.x, windowPos.y, windowPos.cx, windowPos.cy + headerHeight, windowPos.flags); } else { @@ -5023,7 +5084,7 @@ VOID PhTnpPaint( vScrollPosition = Context->VScrollPosition; hScrollPosition = Context->HScrollPosition; - // Calculate the indicies of the first and last rows that need painting. These indicies are + // Calculate the indices of the first and last rows that need painting. These indices are // relative to the top of the view area. firstRowToUpdate = (PaintRect->top - Context->HeaderHeight) / Context->RowHeight; @@ -5037,7 +5098,7 @@ VOID PhTnpPaint( rowRect.right = Context->NormalLeft + Context->TotalViewX - Context->HScrollPosition; rowRect.bottom = rowRect.top + Context->RowHeight; - // Change the indicies to absolute row indicies. + // Change the indices to absolute row indices. firstRowToUpdate += vScrollPosition; lastRowToUpdate += vScrollPosition; @@ -5108,8 +5169,8 @@ VOID PhTnpPaint( RECT tempRect; BLENDFUNCTION blendFunction; - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(30, 30, 30)); + SetTextColor(hdc, PhThemeWindowTextColor); + SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); FillRect(hdc, &rowRect, GetStockBrush(DC_BRUSH)); if (tempDc = CreateCompatibleDC(hdc)) @@ -5143,7 +5204,7 @@ VOID PhTnpPaint( } else { - SetDCBrushColor(tempDc, RGB(30, 30, 30)); + SetDCBrushColor(tempDc, PhThemeWindowBackgroundColor); FillRect(tempDc, &tempRect, GetStockBrush(DC_BRUSH)); } @@ -5316,8 +5377,8 @@ VOID PhTnpPaint( if (Context->ThemeSupport) { - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(30, 30, 30)); + SetTextColor(hdc, PhThemeWindowTextColor); + SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); FillRect(hdc, &rowRect, GetStockBrush(DC_BRUSH)); } else @@ -5336,8 +5397,8 @@ VOID PhTnpPaint( if (Context->ThemeSupport) { - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); - SetDCBrushColor(hdc, RGB(30, 30, 30)); + SetTextColor(hdc, PhThemeWindowTextColor); + SetDCBrushColor(hdc, PhThemeWindowBackgroundColor); FillRect(hdc, &rowRect, GetStockBrush(DC_BRUSH)); } else @@ -5357,7 +5418,7 @@ VOID PhTnpPaint( if (Context->ThemeSupport) { - SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); + SetTextColor(hdc, PhThemeWindowTextColor); } else { @@ -5382,6 +5443,25 @@ VOID PhTnpPaint( { PhTnpDrawSelectionRectangle(Context, hdc, &Context->DragRect); } + + if (Context->HeaderCustomDraw) + { + //if (Context->FixedColumnVisible && Context->FixedHeaderHandle) + //{ + // InvalidateRect(Context->FixedHeaderHandle, NULL, FALSE); + //} + + // TODO: + // 1) PhTickProcessNodes excludes the header when invalidating the treelist. + // 2) This invalidates the whole header even when nothing changes. + // We can add a callback similar to TreeNewGetHeaderText that returns TRUE + // for headers that have custom text and need invalidating? (dmex) + + if (Context->HeaderHandle && GetCapture() != Context->HeaderHandle) // HACK (dmex) + { + InvalidateRect(Context->HeaderHandle, NULL, FALSE); + } + } } VOID PhTnpPrepareRowForDraw( @@ -5558,6 +5638,8 @@ VOID PhTnpDrawCell( themeRect.left = textRect.left; themeRect.right = themeRect.left + SmallIconWidth; + //themeRect.left = textRect.right; + //themeRect.right = textRect.right - SmallIconWidth; themeRect.top = textRect.top; themeRect.bottom = themeRect.top + SmallIconHeight; @@ -5591,6 +5673,8 @@ VOID PhTnpDrawCell( glyphRect.left = textRect.left + (SmallIconWidth - glyphWidth) / 2; glyphRect.right = glyphRect.left + glyphWidth; + //glyphRect.left = textRect.right + (SmallIconWidth - glyphWidth) / 2; + //glyphRect.right = glyphRect.left - glyphWidth; glyphRect.top = textRect.top + (SmallIconHeight - glyphHeight) / 2; glyphRect.bottom = glyphRect.top + glyphHeight; @@ -5605,6 +5689,11 @@ VOID PhTnpDrawCell( if (Context->ImageListSupport) { + //LONG right = textRect.right; + //textRect.right = textRect.left + SmallIconWidth; + //FillRect(hdc, &textRect, GetSysColorBrush(COLOR_HOTLIGHT)); + //textRect.right = right; + PhImageListDrawEx( Context->ImageListHandle, (ULONG)(ULONG_PTR)Node->Icon, // HACK (dmex) @@ -5615,7 +5704,8 @@ VOID PhTnpDrawCell( SmallIconHeight, CLR_DEFAULT, CLR_NONE, - ILD_NORMAL | ILD_TRANSPARENT + ILD_NORMAL | ILD_TRANSPARENT, + ILS_NORMAL ); textRect.left += SmallIconWidth + TNP_ICON_RIGHT_PADDING; @@ -6011,6 +6101,12 @@ VOID PhTnpInitializeTooltips( PhSetWindowContext(Context->HeaderHandle, 0xF, Context); PhSetWindowContext(Context->FixedHeaderHandle, 0xF, Context); + if (Context->HeaderCustomDraw) + { + Context->HeaderHotColumn = ULONG_MAX; + Context->HeaderThemeHandle = OpenThemeData(Context->HeaderHandle, VSCLASS_HEADER); + } + SetWindowLongPtr(Context->FixedHeaderHandle, GWLP_WNDPROC, (LONG_PTR)PhTnpHeaderHookWndProc); SetWindowLongPtr(Context->HeaderHandle, GWLP_WNDPROC, (LONG_PTR)PhTnpHeaderHookWndProc); @@ -6299,6 +6395,46 @@ VOID PhTnpGetHeaderTooltipText( SendMessage(Context->TooltipsHandle, TTM_SETMAXTIPWIDTH, 0, TNP_TOOLTIPS_DEFAULT_MAXIMUM_WIDTH); } +BOOLEAN PhTnpGetColumnHeaderText( + _In_ PPH_TREENEW_CONTEXT Context, + _In_ PPH_TREENEW_COLUMN Column, + _In_ PWSTR TextCache, + _In_ ULONG TextCacheSize, + _Out_ PPH_STRINGREF Text + ) +{ + PH_TREENEW_GET_HEADER_TEXT getHeaderText; + + //if (Id < Column->TextCacheSize && Column->TextCache[Id].Buffer) + //{ + // *Text = Column->TextCache[Id]; + // return TRUE; + //} + + PhInitializeEmptyStringRef(&getHeaderText.Text); + getHeaderText.Column = Column; + getHeaderText.TextCache = TextCache; + getHeaderText.TextCacheSize = TextCacheSize; + + if (Context->Callback( + Context->Handle, + TreeNewGetHeaderText, + &getHeaderText, + NULL, + Context->CallbackContext + ) && getHeaderText.Text.Buffer) + { + *Text = getHeaderText.Text; + + //if ((getHeaderText.Flags & TN_CACHE) && Id < Column->TextCacheSize) + // Column->TextCache[Id] = getHeaderText.Text; + + return TRUE; + } + + return FALSE; +} + LRESULT CALLBACK PhTnpHeaderHookWndProc( _In_ HWND hwnd, _In_ UINT uMsg, @@ -6386,9 +6522,9 @@ LRESULT CALLBACK PhTnpHeaderHookWndProc( switch (uMsg) { - case WM_MOUSEMOVE: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: + //case WM_MOUSEMOVE: + //case WM_LBUTTONDOWN: + //case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: @@ -6406,6 +6542,450 @@ LRESULT CALLBACK PhTnpHeaderHookWndProc( } } break; + case WM_SETFONT: + { + HFONT fontHandle = (HFONT)wParam; + LOGFONT logFont; + + if (!context->HeaderCustomDraw) + break; + + if (context->HeaderBoldFontHandle) + { + DeleteFont(context->HeaderBoldFontHandle); + context->HeaderBoldFontHandle = NULL; + } + + if (GetObject(fontHandle, sizeof(LOGFONT), &logFont)) + { + logFont.lfHeight -= PhMultiplyDivideSigned(3, PhGlobalDpi, 96); + context->HeaderBoldFontHandle = CreateFontIndirect(&logFont); + //context->HeaderBoldFontHandle = PhDuplicateFontWithNewHeight(fontHandle, -14); + } + } + break; + case WM_MOUSEMOVE: + { + BOOLEAN redraw = FALSE; + ULONG hitcolumn; + POINT point; + PPH_TREENEW_COLUMN column; + + if (context->TooltipsHandle) + { + MSG message; + + message.hwnd = hwnd; + message.message = uMsg; + message.wParam = wParam; + message.lParam = lParam; + SendMessage(context->TooltipsHandle, TTM_RELAYEVENT, 0, (LPARAM)&message); + } + + if (!context->HeaderCustomDraw) + break; + //if (GetCapture() == WindowHandle) + // break; + + point.x = GET_X_LPARAM(lParam); + point.y = GET_Y_LPARAM(lParam); + column = PhTnpHitTestHeader(context, hwnd == context->FixedHeaderHandle, &point, NULL); + + hitcolumn = column ? column->Id : ULONG_MAX; + + if (context->HeaderHotColumn != hitcolumn) + { + context->HeaderHotColumn = hitcolumn; + //redraw = TRUE; + } + + if (!context->HeaderMouseActive) + { + TRACKMOUSEEVENT trackEvent = + { + sizeof(TRACKMOUSEEVENT), + TME_LEAVE, + hwnd, + 0 + }; + + TrackMouseEvent(&trackEvent); + context->HeaderMouseActive = TRUE; + + redraw = TRUE; + } + + if (redraw) + { + InvalidateRect(hwnd, NULL, FALSE); + } + } + break; + case WM_CONTEXTMENU: + { + LRESULT result; + + if (!context->HeaderCustomDraw) + break; + + result = CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); + InvalidateRect(hwnd, NULL, FALSE); + return result; + } + break; + case WM_LBUTTONDOWN: + { + LRESULT result; + + if (context->TooltipsHandle) + { + MSG message; + + message.hwnd = hwnd; + message.message = uMsg; + message.wParam = wParam; + message.lParam = lParam; + SendMessage(context->TooltipsHandle, TTM_RELAYEVENT, 0, (LPARAM)&message); + } + + if (!context->HeaderCustomDraw) + break; + + result = CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); + context->HeaderDragging = TRUE; + return result; + } + break; + case WM_LBUTTONUP: + { + LRESULT result; + + if (context->TooltipsHandle) + { + MSG message; + + message.hwnd = hwnd; + message.message = uMsg; + message.wParam = wParam; + message.lParam = lParam; + SendMessage(context->TooltipsHandle, TTM_RELAYEVENT, 0, (LPARAM)&message); + } + + if (!context->HeaderCustomDraw) + break; + + result = CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); + context->HeaderDragging = FALSE; + return result; + } + break; + case WM_MOUSELEAVE: + { + LRESULT result; + + if (context->TooltipsHandle) + { + MSG message; + + message.hwnd = hwnd; + message.message = uMsg; + message.wParam = wParam; + message.lParam = lParam; + SendMessage(context->TooltipsHandle, TTM_RELAYEVENT, 0, (LPARAM)&message); + } + + if (!context->HeaderCustomDraw) + break; + + result = CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); + context->HeaderMouseActive = FALSE; + context->HeaderHotColumn = ULONG_MAX; + + if (GetCapture() != hwnd) + { + InvalidateRect(hwnd, NULL, FALSE); + } + + return result; + } + break; + case WM_PAINT: + { + RECT clientRect; + HDC hdc; + HDC bufferDc; + RECT bufferRect; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; + PH_STRINGREF headerString; + WCHAR headerText[0x50]; + + // TODO: This drawing code works most of the time but has some issues when dragging columns, + // we should probably switch to a custom header control that draws both lines. (dmex) + if (!context->HeaderCustomDraw) + break; + + GetClientRect(hwnd, &clientRect); + bufferRect.left = 0; + bufferRect.top = 0; + bufferRect.right = clientRect.right - clientRect.left; + bufferRect.bottom = clientRect.bottom - clientRect.top; + + hdc = GetDC(hwnd); + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, bufferRect.right, bufferRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + + SetBkMode(bufferDc, TRANSPARENT); + + if (context->ThemeSupport) + { + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); + } + else + { + //if (context->HeaderThemeHandle) + //{ + // DrawThemeBackground( + // context->HeaderThemeHandle, + // bufferDc, + // HP_HEADERITEM, + // HIS_NORMAL, + // &clientRect, + // NULL + // ); + //} + //else + { + FillRect(bufferDc, &clientRect, GetSysColorBrush(COLOR_WINDOW)); + } + } + + UINT32 headerItemCount = (UINT32)CallWindowProc(oldWndProc, hwnd, HDM_GETITEMCOUNT, 0, 0); + + for (UINT32 i = 0; i < headerItemCount; i++) + { + HDITEM headerItem; + RECT headerRect; + PPH_TREENEW_COLUMN column; + + if (!CallWindowProc(oldWndProc, hwnd, HDM_GETITEMRECT, (WPARAM)i, (LPARAM)&headerRect)) + continue; + if (!RectVisible(bufferDc, &headerRect)) + continue; + + headerItem.mask = HDI_LPARAM | HDI_FORMAT; + + if (!CallWindowProc(oldWndProc, hwnd, HDM_GETITEM, (WPARAM)i, (LPARAM)&headerItem)) + continue; + if (!(column = (PPH_TREENEW_COLUMN)headerItem.lParam)) + continue; + + if (context->HeaderHotColumn != ULONG_MAX && context->HeaderHotColumn == column->Id) + { + if (context->ThemeSupport) + { + SetDCBrushColor(bufferDc, RGB(128, 128, 128)); + FillRect(bufferDc, &headerRect, GetStockBrush(DC_BRUSH)); + + if (context->HeaderDragging && context->HeaderHotColumn != -1 && context->HeaderHotColumn == column->Id) + { + SetDCBrushColor(bufferDc, RGB(0, 0, 229)); + SelectBrush(bufferDc, GetStockBrush(DC_BRUSH)); + PatBlt(bufferDc, headerRect.right - 2, headerRect.top, 2, headerRect.bottom - headerRect.top, PATCOPY); + } + else + { + SetDCBrushColor(bufferDc, context->ThemeSupport ? RGB(0x5f, 0x5f, 0x5f) : RGB(229, 229, 229)); + SelectBrush(bufferDc, GetStockBrush(DC_BRUSH)); + PatBlt(bufferDc, headerRect.right - 1, headerRect.top, 1, headerRect.bottom - headerRect.top, PATCOPY); + //PatBlt(bufferDc, headerRect.left, headerRect.bottom - 1, headerRect.right - headerRect.left, 1, PATCOPY); + } + } + else if (context->HeaderThemeHandle) + { + DrawThemeBackground( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERITEM, + HIS_HOT, + &headerRect, + NULL + ); + } + else + { + FillRect(bufferDc, &headerRect, GetSysColorBrush(COLOR_HIGHLIGHT)); + } + } + else + { + if (context->ThemeSupport) + { + SetDCBrushColor(bufferDc, PhThemeWindowBackgroundColor); + FillRect(bufferDc, &headerRect, GetStockBrush(DC_BRUSH)); + + if (context->HeaderDragging && context->HeaderHotColumn != -1 && context->HeaderHotColumn == column->Id) + { + SetDCBrushColor(bufferDc, RGB(0, 0, 229)); + SelectBrush(bufferDc, GetStockBrush(DC_BRUSH)); + PatBlt(bufferDc, headerRect.right - 2, headerRect.top, 2, headerRect.bottom - headerRect.top, PATCOPY); + } + else + { + SetDCBrushColor(bufferDc, context->ThemeSupport ? RGB(0x5f, 0x5f, 0x5f) : RGB(229, 229, 229)); + SelectBrush(bufferDc, GetStockBrush(DC_BRUSH)); + PatBlt(bufferDc, headerRect.right - 1, headerRect.top, 1, headerRect.bottom - headerRect.top, PATCOPY); + //PatBlt(bufferDc, headerRect.left, headerRect.bottom - 1, headerRect.right - headerRect.left, 1, PATCOPY); + } + } + else if (context->HeaderThemeHandle) + { + DrawThemeBackground( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERITEM, + HIS_NORMAL, + &headerRect, + NULL + ); + } + else + { + FillRect(bufferDc, &headerRect, GetSysColorBrush(COLOR_WINDOW)); + } + } + + if (column->Text) + { + PWSTR textBuffer; + UINT textLength; + RECT textRect; + HFONT oldFont; + + textBuffer = column->Text; + textLength = (UINT)PhCountStringZ(column->Text); + + textRect = headerRect; + textRect.left += 5; + textRect.right -= 5; + textRect.bottom -= 5; + textRect.top += 2; + + SetTextColor(bufferDc, context->ThemeSupport ? RGB(0x8f, 0x8f, 0x8f) : RGB(97, 116, 139)); // RGB(178, 178, 178) + oldFont = SelectFont(bufferDc, context->Font); + if (headerItem.fmt & HDF_RIGHT) + { + DrawText( + bufferDc, + textBuffer, + textLength, + &textRect, + DT_SINGLELINE | DT_HIDEPREFIX | DT_WORD_ELLIPSIS | DT_BOTTOM | DT_RIGHT + ); + } + else + { + DrawText( + bufferDc, + textBuffer, + textLength, + &textRect, + DT_SINGLELINE | DT_HIDEPREFIX | DT_WORD_ELLIPSIS | DT_BOTTOM | DT_LEFT + ); + } + SelectFont(bufferDc, oldFont); + + if (PhTnpGetColumnHeaderText( + context, + column, + headerText, + sizeof(headerText), + &headerString + )) + { + SetTextColor(bufferDc, context->ThemeSupport ? RGB(0xff, 0xff, 0xff) : RGB(0, 0, 0)); + + oldFont = SelectFont(bufferDc, context->HeaderBoldFontHandle); + DrawText( + bufferDc, + headerString.Buffer, + (UINT)headerString.Length / sizeof(WCHAR), + &textRect, + DT_SINGLELINE | DT_HIDEPREFIX | DT_WORD_ELLIPSIS | DT_TOP | DT_RIGHT + ); + SelectFont(bufferDc, oldFont); + } + + if (headerItem.fmt & HDF_SORTDOWN) + { + if (context->HeaderThemeHandle) + { + SIZE sortArrowSize; + + if (GetThemePartSize( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERSORTARROW, + HSAS_SORTEDDOWN, + NULL, + TS_TRUE, + &sortArrowSize + ) == S_OK) + { + headerRect.bottom = sortArrowSize.cy; + } + + DrawThemeBackground( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERSORTARROW, + HSAS_SORTEDDOWN, + &headerRect, + NULL + ); + } + } + else if (headerItem.fmt & HDF_SORTUP) + { + if (context->HeaderThemeHandle) + { + SIZE sortArrowSize; + + if (GetThemePartSize( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERSORTARROW, + HSAS_SORTEDUP, + NULL, + TS_TRUE, + &sortArrowSize + ) == S_OK) + { + headerRect.bottom = sortArrowSize.cy; + } + + DrawThemeBackground( + context->HeaderThemeHandle, + bufferDc, + HP_HEADERSORTARROW, + HSAS_SORTEDUP, + &headerRect, + NULL + ); + } + } + } + } + + BitBlt(hdc, bufferRect.left, bufferRect.top, bufferRect.right, bufferRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + ReleaseDC(hwnd, hdc); + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); } return CallWindowProc(oldWndProc, hwnd, uMsg, wParam, lParam); diff --git a/ProcessHacker/phlib/util.c b/ProcessHacker/phlib/util.c index c30127ad..307fd0d3 100644 --- a/ProcessHacker/phlib/util.c +++ b/ProcessHacker/phlib/util.c @@ -3,7 +3,7 @@ * general support functions * * Copyright (C) 2009-2016 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -39,6 +39,7 @@ DECLSPEC_SELECTANY WCHAR *PhSizeUnitNames[7] = { L"B", L"kB", L"MB", L"GB", L"TB", L"PB", L"EB" }; DECLSPEC_SELECTANY ULONG PhMaxSizeUnit = ULONG_MAX; +DECLSPEC_SELECTANY USHORT PhMaxPrecisionUnit = 2; /** * Ensures a rectangle is positioned within the specified bounds. @@ -169,9 +170,6 @@ VOID PhCenterWindow( } } -// NLS support -// TODO: Move to seperate file. (dmex) - // rev from GetSystemDefaultLCID LCID PhGetSystemDefaultLCID( VOID @@ -426,13 +424,11 @@ PPH_STRING PhGetMessage( return NULL; if (messageEntry->Flags & MESSAGE_RESOURCE_UNICODE) - { return PhCreateStringEx((PWCHAR)messageEntry->Text, messageEntry->Length); - } + else if (messageEntry->Flags & MESSAGE_RESOURCE_UTF8) + return PhConvertUtf8ToUtf16Ex((PCHAR)messageEntry->Text, messageEntry->Length); else - { return PhConvertMultiByteToUtf16Ex((PCHAR)messageEntry->Text, messageEntry->Length); - } } /** @@ -604,6 +600,10 @@ PPH_STRING PhGetStatusMessage( { Win32Result = WIN32_FROM_NTSTATUS(Status); } + else if (NT_FACILITY(Status) == FACILTIY_MUI_ERROR_CODE) + { + Win32Result = Status; // needed by PhGetLastWin32ErrorAsNtStatus(CERT_E_REVOKED) (dmex) + } } if (!Win32Result) @@ -646,7 +646,7 @@ VOID PhShowStatus( { if (Message) { - PhShowError(hWnd, L"%s.", Message); + PhShowError(hWnd, L"%s", Message); } else { @@ -1822,7 +1822,7 @@ PVOID PhGetFileVersionInfoValue( _Success_(return) BOOLEAN PhGetFileVersionInfoKey( _In_ PVS_VERSION_INFO_STRUCT32 VersionInfo, - _In_ ULONG KeyLength, + _In_ SIZE_T KeyLength, _In_ PWSTR Key, _Out_opt_ PVOID* Buffer ) @@ -1837,7 +1837,7 @@ BOOLEAN PhGetFileVersionInfoKey( valueOffset = VersionInfo->ValueLength * (VersionInfo->Type ? sizeof(WCHAR) : sizeof(BYTE)); child = PTR_ADD_OFFSET(value, ALIGN_UP(valueOffset, ULONG)); - while ((ULONG_PTR)child < (ULONG_PTR)VersionInfo + VersionInfo->Length) + while ((ULONG_PTR)child < (ULONG_PTR)PTR_ADD_OFFSET(VersionInfo, VersionInfo->Length)) { if (_wcsnicmp(child->Key, Key, KeyLength) == 0 && child->Key[KeyLength] == UNICODE_NULL) { @@ -1870,14 +1870,14 @@ BOOLEAN PhGetFileVersionVarFileInfoValue( if (PhGetFileVersionInfoKey( VersionInfo, - (ULONG)varfileBlockName.Length / sizeof(WCHAR), + varfileBlockName.Length / sizeof(WCHAR), varfileBlockName.Buffer, &varfileBlockInfo )) { if (PhGetFileVersionInfoKey( varfileBlockInfo, - (ULONG)KeyName->Length / sizeof(WCHAR), + KeyName->Length / sizeof(WCHAR), KeyName->Buffer, &varfileBlockValue )) @@ -2002,7 +2002,7 @@ PPH_STRING PhGetFileVersionInfoString2( if (!PhGetFileVersionInfoKey( VersionInfo, - (ULONG)blockInfoName.Length / sizeof(WCHAR), + blockInfoName.Length / sizeof(WCHAR), blockInfoName.Buffer, &blockStringInfo )) @@ -2019,7 +2019,7 @@ PPH_STRING PhGetFileVersionInfoString2( if (!PhGetFileVersionInfoKey( blockStringInfo, - (ULONG)returnLength / sizeof(WCHAR) - sizeof(ANSI_NULL), // ANSI_NULL required (dmex) + returnLength / sizeof(WCHAR) - sizeof(ANSI_NULL), // ANSI_NULL required (dmex) langNameString, &blockLangInfo )) @@ -2029,7 +2029,7 @@ PPH_STRING PhGetFileVersionInfoString2( if (!PhGetFileVersionInfoKey( blockLangInfo, - (ULONG)KeyName->Length / sizeof(WCHAR), + KeyName->Length / sizeof(WCHAR), KeyName->Buffer, &stringNameBlockInfo )) @@ -2043,7 +2043,7 @@ PPH_STRING PhGetFileVersionInfoString2( return NULL; string = PhCreateStringEx( - (PWCHAR)stringNameBlockValue, + stringNameBlockValue, stringNameBlockInfo->ValueLength * sizeof(WCHAR) ); PhTrimToNullTerminatorString(string); // length may include the null terminator. @@ -2364,7 +2364,7 @@ static ULONG PhpImageVersionInfoCacheHashtableHashFunction( { PPH_FILE_VERSIONINFO_CACHE_ENTRY entry = Entry; - return PhHashStringRef(&entry->FileName->sr, TRUE); + return PhHashStringRefEx(&entry->FileName->sr, TRUE, PH_STRING_HASH_X65599); } _Success_(return) @@ -2998,7 +2998,7 @@ NTSTATUS PhWaitForMultipleObjectsAndPump( * the console of the parent process. * \param ParentProcessHandle The process from which the new process will inherit attributes. * Specify NULL for the current process. - * \param ClientId A variable which recieves the identifier of the initial thread. + * \param ClientId A variable which receives the identifier of the initial thread. * \param ProcessHandle A variable which receives a handle to the process. * \param ThreadHandle A variable which receives a handle to the initial thread. */ @@ -3207,7 +3207,7 @@ FORCEINLINE VOID PhpConvertProcessInformation( * \param StartupInfo A STARTUPINFO structure containing additional parameters for the process. * \param Flags See PhCreateProcess(). * \param TokenHandle The token of the process. Specify NULL for the token of the parent process. - * \param ClientId A variable which recieves the identifier of the initial thread. + * \param ClientId A variable which receives the identifier of the initial thread. * \param ProcessHandle A variable which receives a handle to the process. * \param ThreadHandle A variable which receives a handle to the initial thread. */ @@ -3375,7 +3375,7 @@ NTSTATUS PhCreateProcessWin32Ex( * the process to be elevated or unelevated depending on the specified options. * \li \c PH_CREATE_PROCESS_SET_SESSION_ID \a SessionId is specified in \a Information. * \li \c PH_CREATE_PROCESS_WITH_PROFILE Load the user profile, if supported. - * \param ClientId A variable which recieves the identifier of the initial thread. + * \param ClientId A variable which receives the identifier of the initial thread. * \param ProcessHandle A variable which receives a handle to the process. * \param ThreadHandle A variable which receives a handle to the initial thread. */ @@ -6034,9 +6034,9 @@ NTSTATUS PhAccessResource( PVOID baseAddress; if (LDR_IS_DATAFILE(DllBase)) - baseAddress = (PVOID)((ULONG_PTR)DllBase & ~1); + baseAddress = LDR_DATAFILE_TO_MAPPEDVIEW(DllBase); else if (LDR_IS_IMAGEMAPPING(DllBase)) - baseAddress = (PVOID)((ULONG_PTR)DllBase & ~2); + baseAddress = LDR_IMAGEMAPPING_TO_MAPPEDVIEW(DllBase); else baseAddress = DllBase; @@ -6318,8 +6318,8 @@ PLDR_DATA_TABLE_ENTRY PhFindLoaderEntry( if ( (!DllBase || entry->DllBase == DllBase) && - (!FullDllName || PhEqualStringRef(&fullDllName, FullDllName, TRUE)) && - (!BaseDllName || PhEqualStringRef(&baseDllName, BaseDllName, TRUE)) + (!FullDllName || PhStartsWithStringRef(&fullDllName, FullDllName, TRUE)) && + (!BaseDllName || PhStartsWithStringRef(&baseDllName, BaseDllName, TRUE)) ) { result = entry; @@ -6413,17 +6413,15 @@ PPH_STRING PhGetDllFileName( return fileName; } -PVOID PhGetLoaderEntryDllBase( - _In_ PWSTR BaseDllName +PVOID PhGetLoaderEntryStringRefDllBase( + _In_opt_ PPH_STRINGREF FullDllName, + _In_opt_ PPH_STRINGREF BaseDllName ) { - PH_STRINGREF entryNameSr; PLDR_DATA_TABLE_ENTRY ldrEntry; - PhInitializeStringRefLongHint(&entryNameSr, BaseDllName); - RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock); - ldrEntry = PhFindLoaderEntry(NULL, NULL, &entryNameSr); + ldrEntry = PhFindLoaderEntry(NULL, FullDllName, BaseDllName); RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); if (ldrEntry) @@ -6432,17 +6430,17 @@ PVOID PhGetLoaderEntryDllBase( return NULL; } -PVOID PhGetLoaderEntryFullDllBase( - _In_ PWSTR FullDllName +PVOID PhGetLoaderEntryDllBase( + _In_ PWSTR BaseDllName ) { PH_STRINGREF entryNameSr; PLDR_DATA_TABLE_ENTRY ldrEntry; - PhInitializeStringRefLongHint(&entryNameSr, FullDllName); + PhInitializeStringRefLongHint(&entryNameSr, BaseDllName); RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock); - ldrEntry = PhFindLoaderEntry(NULL, &entryNameSr, NULL); + ldrEntry = PhFindLoaderEntry(NULL, NULL, &entryNameSr); RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock); if (ldrEntry) @@ -6566,6 +6564,33 @@ NTSTATUS PhGetLoaderEntryImageDirectory( directory = &ImageNtHeader->OptionalHeader.DataDirectory[ImageDirectoryIndex]; + //if (ImageNtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) + //{ + // PIMAGE_OPTIONAL_HEADER32 optionalHeader; + // + // optionalHeader = &((PIMAGE_NT_HEADERS32)ImageNtHeader)->OptionalHeader; + // + // if (ImageDirectoryIndex >= optionalHeader->NumberOfRvaAndSizes) + // return STATUS_INVALID_FILE_FOR_SECTION; + // + // directory = &optionalHeader->DataDirectory[ImageDirectoryIndex]; + //} + //else if (ImageNtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) + //{ + // PIMAGE_OPTIONAL_HEADER64 optionalHeader; + // + // optionalHeader = &((PIMAGE_NT_HEADERS64)ImageNtHeader)->OptionalHeader; + // + // if (ImageDirectoryIndex >= optionalHeader->NumberOfRvaAndSizes) + // return STATUS_INVALID_FILE_FOR_SECTION; + // + // directory = &optionalHeader->DataDirectory[ImageDirectoryIndex]; + //} + //else + //{ + // return STATUS_INVALID_FILE_FOR_SECTION; + //} + if (directory->VirtualAddress == 0 || directory->Size == 0) return STATUS_INVALID_FILE_FOR_SECTION; @@ -6688,6 +6713,47 @@ NTSTATUS PhLoaderEntryImageRvaToVa( return STATUS_SUCCESS; } +static ULONG PhpLookupLoaderEntryImageExportFunctionIndex( + _In_ PVOID BaseAddress, + _In_ PIMAGE_EXPORT_DIRECTORY ExportDirectory, + _In_ PULONG ExportNameTable, + _In_ PSTR ExportName + ) +{ + LONG low; + LONG high; + LONG i; + + if (ExportDirectory->NumberOfNames == 0) + return ULONG_MAX; + + low = 0; + high = ExportDirectory->NumberOfNames - 1; + + do + { + PSTR name; + INT comparison; + + i = (low + high) / 2; + name = PTR_ADD_OFFSET(BaseAddress, ExportNameTable[i]); + + if (!name) + return ULONG_MAX; + + comparison = strcmp(ExportName, name); + + if (comparison == 0) + return i; + else if (comparison < 0) + high = i - 1; + else + low = i + 1; + } while (low <= high); + + return ULONG_MAX; +} + PVOID PhGetLoaderEntryImageExportFunction( _In_ PVOID BaseAddress, _In_ PIMAGE_DATA_DIRECTORY DataDirectory, @@ -6714,14 +6780,28 @@ PVOID PhGetLoaderEntryImageExportFunction( } else if (ExportName) { - for (ULONG i = 0; i < ExportDirectory->NumberOfNames; i++) - { - if (PhEqualBytesZ(ExportName, PTR_ADD_OFFSET(BaseAddress, exportNameTable[i]), FALSE)) - { - exportAddress = PTR_ADD_OFFSET(BaseAddress, exportAddressTable[exportOrdinalTable[i]]); - break; - } - } + ULONG exportIndex; + + exportIndex = PhpLookupLoaderEntryImageExportFunctionIndex( + BaseAddress, + ExportDirectory, + exportNameTable, + ExportName + ); + + if (exportIndex == ULONG_MAX) + return NULL; + + exportAddress = PTR_ADD_OFFSET(BaseAddress, exportAddressTable[exportOrdinalTable[exportIndex]]); + + //for (exportIndex = 0; exportIndex < ExportDirectory->NumberOfNames; exportIndex++) + //{ + // if (PhEqualBytesZ(ExportName, PTR_ADD_OFFSET(BaseAddress, exportNameTable[exportIndex]), FALSE)) + // { + // exportAddress = PTR_ADD_OFFSET(BaseAddress, exportAddressTable[exportOrdinalTable[exportIndex]]); + // break; + // } + //} } if (!exportAddress) @@ -6742,15 +6822,23 @@ PVOID PhGetLoaderEntryImageExportFunction( if (PhSplitStringRefAtChar(&dllForwarderString->sr, L'.', &dllNameRef, &dllProcedureRef)) { - PPH_STRING libraryNameString; - PPH_BYTES libraryFunctionString; - PVOID libraryModule; + PVOID libraryDllBase; - libraryNameString = PhCreateStringEx(dllNameRef.Buffer, dllNameRef.Length); - libraryFunctionString = PhConvertUtf16ToUtf8Ex(dllProcedureRef.Buffer, dllProcedureRef.Length); + if (!(libraryDllBase = PhGetLoaderEntryStringRefDllBase(NULL, &dllNameRef))) + { + PPH_STRING libraryName; - if (libraryModule = PhLoadLibrarySafe(libraryNameString->Buffer)) + libraryName = PhCreateString2(&dllNameRef); + libraryDllBase = PhLoadLibrary(libraryName->Buffer); + PhDereferenceObject(libraryName); + } + + if (libraryDllBase) { + PPH_BYTES libraryFunctionString; + + libraryFunctionString = PhConvertUtf16ToUtf8Ex(dllProcedureRef.Buffer, dllProcedureRef.Length); + if (libraryFunctionString->Buffer[0] == L'#') // This is a forwarder RVA with an ordinal import. { LONG64 importOrdinal; @@ -6758,18 +6846,17 @@ PVOID PhGetLoaderEntryImageExportFunction( PhSkipStringRef(&dllProcedureRef, sizeof(L'#')); if (PhStringToInteger64(&dllProcedureRef, 10, &importOrdinal)) - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, NULL, (USHORT)importOrdinal); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, NULL, (USHORT)importOrdinal); else - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, libraryFunctionString->Buffer, 0); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, libraryFunctionString->Buffer, 0); } else { - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, libraryFunctionString->Buffer, 0); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, libraryFunctionString->Buffer, 0); } - } - PhDereferenceObject(libraryFunctionString); - PhDereferenceObject(libraryNameString); + PhDereferenceObject(libraryFunctionString); + } } PhDereferenceObject(dllForwarderString); @@ -6835,15 +6922,23 @@ PVOID PhGetDllBaseProcedureAddressWithHint( if (PhSplitStringRefAtChar(&dllForwarderString->sr, L'.', &dllNameRef, &dllProcedureRef)) { - PPH_STRING libraryNameString; - PPH_BYTES libraryFunctionString; - PVOID libraryModule; + PVOID libraryDllBase; - libraryNameString = PhCreateStringEx(dllNameRef.Buffer, dllNameRef.Length); - libraryFunctionString = PhConvertUtf16ToUtf8Ex(dllProcedureRef.Buffer, dllProcedureRef.Length); + if (!(libraryDllBase = PhGetLoaderEntryStringRefDllBase(NULL, &dllNameRef))) + { + PPH_STRING libraryName; + + libraryName = PhCreateString2(&dllNameRef); + libraryDllBase = PhLoadLibrary(libraryName->Buffer); + PhDereferenceObject(libraryName); + } - if (libraryModule = PhLoadLibrarySafe(libraryNameString->Buffer)) + if (libraryDllBase) { + PPH_BYTES libraryFunctionString; + + libraryFunctionString = PhConvertUtf16ToUtf8Ex(dllProcedureRef.Buffer, dllProcedureRef.Length); + if (libraryFunctionString->Buffer[0] == L'#') // This is a forwarder RVA with an ordinal import. { LONG64 importOrdinal; @@ -6851,18 +6946,17 @@ PVOID PhGetDllBaseProcedureAddressWithHint( PhSkipStringRef(&dllProcedureRef, sizeof(L'#')); if (PhStringToInteger64(&dllProcedureRef, 10, &importOrdinal)) - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, NULL, (USHORT)importOrdinal); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, NULL, (USHORT)importOrdinal); else - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, libraryFunctionString->Buffer, 0); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, libraryFunctionString->Buffer, 0); } else { - exportAddress = PhGetDllBaseProcedureAddress(libraryModule, libraryFunctionString->Buffer, 0); + exportAddress = PhGetDllBaseProcedureAddress(libraryDllBase, libraryFunctionString->Buffer, 0); } - } - PhDereferenceObject(libraryFunctionString); - PhDereferenceObject(libraryNameString); + PhDereferenceObject(libraryFunctionString); + } } PhDereferenceObject(dllForwarderString); @@ -6943,9 +7037,9 @@ static NTSTATUS PhpFixupLoaderEntryImageImports( importNameSr = PhZeroExtendToUtf16(importName); - if (!(importBaseAddress = PhGetLoaderEntryDllBase(importNameSr->Buffer))) + if (!(importBaseAddress = PhGetLoaderEntryStringRefDllBase(NULL, &importNameSr->sr))) { - if (importBaseAddress = PhLoadLibrarySafe(importNameSr->Buffer)) + if (importBaseAddress = PhLoadLibrary(importNameSr->Buffer)) status = STATUS_SUCCESS; else status = PhGetLastWin32ErrorAsNtStatus(); @@ -7141,9 +7235,9 @@ static NTSTATUS PhpFixupLoaderEntryImageDelayImports( importNameSr = PhZeroExtendToUtf16(importName); - if (!(importBaseAddress = PhGetLoaderEntryDllBase(importNameSr->Buffer))) + if (!(importBaseAddress = PhGetLoaderEntryStringRefDllBase(NULL, &importNameSr->sr))) { - if (importBaseAddress = PhLoadLibrarySafe(importNameSr->Buffer)) + if (importBaseAddress = PhLoadLibrary(importNameSr->Buffer)) { importNeedsFree = TRUE; status = STATUS_SUCCESS; @@ -7397,9 +7491,9 @@ NTSTATUS PhLoaderEntryLoadDll( PVOID imageBaseAddress; SIZE_T imageBaseOffset; - status = PhCreateFile( + status = PhCreateFileWin32( &fileHandle, - FileName, + FileName->Buffer, FILE_READ_DATA | FILE_EXECUTE | SYNCHRONIZE, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, @@ -7446,7 +7540,7 @@ NTSTATUS PhLoaderEntryLoadDll( 0, NULL, &imageBaseOffset, - ViewUnmap, + ViewShare, 0, PAGE_EXECUTE ); @@ -7574,13 +7668,8 @@ NTSTATUS PhLoadPluginImage( &imageBaseAddress ); - //NTSTATUS status; - //PVOID imageBaseAddress; - //PIMAGE_NT_HEADERS imageNtHeaders; - //PLDR_INIT_ROUTINE imageEntryRoutine; - //status = PhLoaderEntryLoadDll( - // FileName->Buffer, + // FileName, // &imageBaseAddress // ); @@ -7609,6 +7698,7 @@ NTSTATUS PhLoadPluginImage( imageNtHeaders, "ProcessHacker.exe" ); + if (!NT_SUCCESS(status)) goto CleanupExit; @@ -7832,7 +7922,7 @@ HRESULT PhGetClassObject( if (!(baseAddress = PhGetLoaderEntryDllBase(DllName))) { - if (!(baseAddress = PhLoadLibrarySafe(DllName))) + if (!(baseAddress = PhLoadLibrary(DllName))) return HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND); } @@ -7840,7 +7930,7 @@ HRESULT PhGetClassObject( } /*! - @brief PhLoadLibrarySafe prevents the loader from searching in an unsafe + @brief PhLoadLibrary prevents the loader from searching in an unsafe order by first requiring the loader try to load and resolve through System32. Then upping the loading flags until the library is loaded. @@ -7848,33 +7938,36 @@ HRESULT PhGetClassObject( @return HMODULE to the library on success, null on failure. */ -_Ret_maybenull_ -PVOID -PhLoadLibrarySafe( +PVOID PhLoadLibrary( _In_ PCWSTR LibFileName ) { PVOID baseAddress; - // // Force LOAD_LIBRARY_SEARCH_SYSTEM32. If the library file name is a fully // qualified path this will succeed. - // - baseAddress = LoadLibraryExW(LibFileName, - NULL, - LOAD_LIBRARY_SEARCH_SYSTEM32); - if (baseAddress) + + if (baseAddress = LoadLibraryEx( + LibFileName, + NULL, + LOAD_LIBRARY_SEARCH_SYSTEM32 + )) { return baseAddress; } - // // Include the application directory now. - // - return LoadLibraryExW(LibFileName, - NULL, - LOAD_LIBRARY_SEARCH_SYSTEM32 | - LOAD_LIBRARY_SEARCH_APPLICATION_DIR); + + if (baseAddress = LoadLibraryEx( + LibFileName, + NULL, + LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_APPLICATION_DIR + )) + { + return baseAddress; + } + + return NULL; } // rev from LoadLibraryEx with LOAD_LIBRARY_AS_IMAGE_RESOURCE @@ -8007,3 +8100,123 @@ NTSTATUS PhDelayExecution( return PhDelayExecutionEx(FALSE, &interval); } } + +ULONGLONG PhReadTimeStampCounter( + VOID + ) +{ +#if (_M_IX86 || _M_AMD64) + return ReadTimeStampCounter(); +#elif _M_ARM + return __rdpmccntr64(); +#elif _M_ARM64 + // The ReadTimeStampCounter() macro uses PMCCNTR on ARM64 instead of CNTVCT? (dmex) + return _ReadStatusReg(ARM64_CNTVCT); +#endif +} + +VOID PhQueryPerformanceCounter( + _Out_ PLARGE_INTEGER PerformanceCounter, + _Out_opt_ PLARGE_INTEGER PerformanceFrequency + ) +{ + if (PerformanceFrequency) + { + RtlQueryPerformanceFrequency(PerformanceFrequency); + } + + RtlQueryPerformanceCounter(PerformanceCounter); + + //if (RtlQueryPerformanceCounter(PerformanceCounter)) + //{ + // if (PerformanceFrequency) + // { + // if (RtlQueryPerformanceFrequency(PerformanceFrequency)) + // return TRUE; + // } + // else + // { + // return TRUE; + // } + //} + // + //return NT_SUCCESS(NtQueryPerformanceCounter(PerformanceCounter, PerformanceFrequency)); +} + +VOID PhQueryPerformanceFrequency( + _Out_ PLARGE_INTEGER PerformanceFrequency + ) +{ + RtlQueryPerformanceFrequency(PerformanceFrequency); + + //if (RtlQueryPerformanceFrequency(PerformanceFrequency)) + //{ + // return TRUE; + //} + //else + //{ + // LARGE_INTEGER performanceCounter; + // + // return NT_SUCCESS(NtQueryPerformanceCounter(&performanceCounter, PerformanceFrequency)); + //} +} + +PPH_STRING PhApiSetResolveToHost( + _In_ PPH_STRINGREF ApiSetName + ) +{ + PAPI_SET_NAMESPACE apisetMap; + PAPI_SET_NAMESPACE_ENTRY apisetMapEntry; + + if (ApiSetName->Length >= 8) + { + ULONGLONG apisetNameBufferPrefix = ((PULONGLONG)ApiSetName->Buffer)[0] & 0xFFFFFFDFFFDFFFDF; + + if (apisetNameBufferPrefix != 0x2D004900500041ULL && // L"api-" + apisetNameBufferPrefix != 0x2D005400580045ULL) // L"ext-" + { + return NULL; + } + } + else + { + return NULL; + } + + apisetMap = NtCurrentPeb()->ApiSetMap; + apisetMapEntry = PTR_ADD_OFFSET(apisetMap->EntryOffset, apisetMap); + + if (apisetMap->Version != 6) + return NULL; + + for (ULONG i = 0; i < apisetMap->Count; i++) + { + PAPI_SET_VALUE_ENTRY apisetMapValue = PTR_ADD_OFFSET(apisetMap, apisetMapEntry->ValueOffset); + PH_STRINGREF nameStringRef; + + nameStringRef.Length = apisetMapEntry->HashedLength; // NameLength + nameStringRef.Buffer = PTR_ADD_OFFSET(apisetMap, apisetMapEntry->NameOffset); + + if (PhStartsWithStringRef(ApiSetName, &nameStringRef, TRUE)) + { + for (ULONG ii = 0; ii < apisetMapEntry->ValueCount; ii++) + { + if (apisetMapValue->ValueLength) + { + PH_STRINGREF valueStringRef; + + valueStringRef.Length = apisetMapValue->ValueLength; + valueStringRef.Buffer = PTR_ADD_OFFSET(apisetMap, apisetMapValue->ValueOffset); + + return PhCreateString2(&valueStringRef); + } + + apisetMapValue++; + } + } + + apisetMapEntry++; + } + + return NULL; +} diff --git a/ProcessHacker/phlib/verify.c b/ProcessHacker/phlib/verify.c index 913aa35b..76479605 100644 --- a/ProcessHacker/phlib/verify.c +++ b/ProcessHacker/phlib/verify.c @@ -45,9 +45,8 @@ _CertFreeCertificateContext CertFreeCertificateContext_I; static PH_INITONCE PhpVerifyInitOnce = PH_INITONCE_INIT; static GUID WinTrustActionGenericVerifyV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2; static GUID DriverActionVerify = DRIVER_ACTION_VERIFY; - #ifdef PH_ENABLE_VERIFY_CACHE -static PH_AVL_TREE PhpVerifyCacheSet = PH_AVL_TREE_INIT(PhpVerifyCacheCompareFunction); +static PPH_HASHTABLE PhpVerifyCacheHashTable = NULL; static PH_QUEUED_LOCK PhpVerifyCacheLock = PH_QUEUED_LOCK_INIT; #endif @@ -58,8 +57,8 @@ static VOID PhpVerifyInitialization( PVOID wintrust; PVOID crypt32; - wintrust = PhLoadLibrarySafe(L"wintrust.dll"); - crypt32 = PhLoadLibrarySafe(L"crypt32.dll"); + wintrust = PhLoadLibrary(L"wintrust.dll"); + crypt32 = PhLoadLibrary(L"crypt32.dll"); if (wintrust) { @@ -82,6 +81,29 @@ static VOID PhpVerifyInitialization( CertDuplicateCertificateContext_I = PhGetDllBaseProcedureAddress(crypt32, "CertDuplicateCertificateContext", 0); CertFreeCertificateContext_I = PhGetDllBaseProcedureAddress(crypt32, "CertFreeCertificateContext", 0); } + + if ( + CryptCATAdminCalcHashFromFileHandle && + CryptCATAdminAcquireContext && + CryptCATAdminEnumCatalogFromHash && + CryptCATCatalogInfoFromContext && + CryptCATAdminReleaseCatalogContext && + CryptCATAdminReleaseContext && + WTHelperProvDataFromStateData_I && + WTHelperGetProvSignerFromChain_I && + WinVerifyTrust_I && + CertNameToStr_I && + CertDuplicateCertificateContext_I && + CertFreeCertificateContext_I + ) + { + PhpVerifyCacheHashTable = PhCreateHashtable( + sizeof(PH_VERIFY_CACHE_ENTRY), + PhpVerifyCacheHashtableEqualFunction, + PhpVerifyCacheHashtableHashFunction, + 100 + ); + } } VERIFY_RESULT PhpStatusToVerifyResult( @@ -180,7 +202,7 @@ VOID PhpViewSignerInfo( { HMODULE cryptui; - if (cryptui = PhLoadLibrarySafe(L"cryptui.dll")) + if (cryptui = PhLoadLibrary(L"cryptui.dll")) { cryptUIDlgViewSignerInfo = PhGetDllBaseProcedureAddress(cryptui, "CryptUIDlgViewSignerInfoW", 0); } @@ -218,8 +240,9 @@ VERIFY_RESULT PhpVerifyFile( ) { LONG status; - WINTRUST_DATA trustData = { 0 }; + WINTRUST_DATA trustData; + memset(&trustData, 0, sizeof(WINTRUST_DATA)); trustData.cbStruct = sizeof(WINTRUST_DATA); trustData.pPolicyCallbackData = PolicyCallbackData; trustData.dwUIChoice = WTD_UI_NONE; @@ -255,7 +278,7 @@ VERIFY_RESULT PhpVerifyFile( _Success_(return) BOOLEAN PhpCalculateFileHash( _In_ HANDLE FileHandle, - _In_ PWSTR HashAlgorithm, + _In_opt_ PWSTR HashAlgorithm, _Out_ PUCHAR *FileHash, _Out_ PULONG FileHashLength, _Out_ HANDLE *CatAdminHandle @@ -328,7 +351,7 @@ VERIFY_RESULT PhpVerifyFileFromCatalog( VERIFY_RESULT verifyResult = VrNoSignature; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; - WINTRUST_CATALOG_INFO catalogInfo = { 0 }; + WINTRUST_CATALOG_INFO catalogInfo; LARGE_INTEGER fileSize; ULONG fileSizeLimit; PUCHAR fileHash; @@ -374,7 +397,7 @@ VERIFY_RESULT PhpVerifyFileFromCatalog( if (catInfoHandle) { - CATALOG_INFO ci = { 0 }; + CATALOG_INFO ci = { sizeof(CATALOG_INFO) }; DRIVER_VER_INFO verInfo = { 0 }; if (CryptCATCatalogInfoFromContext(catInfoHandle, &ci, 0)) @@ -382,9 +405,10 @@ VERIFY_RESULT PhpVerifyFileFromCatalog( // Disable OS version checking by passing in a DRIVER_VER_INFO structure. verInfo.cbStruct = sizeof(DRIVER_VER_INFO); + memset(&catalogInfo, 0, sizeof(catalogInfo)); catalogInfo.cbStruct = sizeof(catalogInfo); catalogInfo.pcwszCatalogFilePath = ci.wszCatalogFile; - catalogInfo.pcwszMemberFilePath = Information->FileName; + catalogInfo.pcwszMemberFilePath = NULL; // Information->FileName catalogInfo.hMemberFile = FileHandle; catalogInfo.pcwszMemberTag = fileHashTag->Buffer; catalogInfo.pbCalculatedFileHash = fileHash; @@ -406,9 +430,10 @@ VERIFY_RESULT PhpVerifyFileFromCatalog( { PhFreeVerifySignatures(signatures, numberOfSignatures); + memset(&catalogInfo, 0, sizeof(catalogInfo)); catalogInfo.cbStruct = sizeof(catalogInfo); catalogInfo.pcwszCatalogFilePath = Information->CatalogFileNames[i]; - catalogInfo.pcwszMemberFilePath = Information->FileName; + catalogInfo.pcwszMemberFilePath = NULL; // Information->FileName catalogInfo.hMemberFile = FileHandle; catalogInfo.pcwszMemberTag = fileHashTag->Buffer; catalogInfo.pbCalculatedFileHash = fileHash; @@ -439,12 +464,10 @@ NTSTATUS PhVerifyFileEx( _Out_opt_ PULONG NumberOfSignatures ) { - NTSTATUS status; - HANDLE fileHandle; VERIFY_RESULT verifyResult; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; - WINTRUST_FILE_INFO fileInfo = { 0 }; + WINTRUST_FILE_INFO fileInfo; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { @@ -452,52 +475,49 @@ NTSTATUS PhVerifyFileEx( PhEndInitOnce(&PhpVerifyInitOnce); } - // Make sure we have successfully imported the required functions. - if ( - !CryptCATAdminCalcHashFromFileHandle || - !CryptCATAdminAcquireContext || - !CryptCATAdminEnumCatalogFromHash || - !CryptCATCatalogInfoFromContext || - !CryptCATAdminReleaseCatalogContext || - !CryptCATAdminReleaseContext || - !WinVerifyTrust_I || - !WTHelperProvDataFromStateData_I || - !WTHelperGetProvSignerFromChain_I || - !CertNameToStr_I || - !CertDuplicateCertificateContext_I || - !CertFreeCertificateContext_I - ) + if (!PhpVerifyCacheHashTable) return STATUS_NOT_SUPPORTED; - if (!NT_SUCCESS(status = PhCreateFileWin32( - &fileHandle, - Information->FileName, - FILE_GENERIC_READ, - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT - ))) - return status; - + memset(&fileInfo, 0, sizeof(WINTRUST_FILE_INFO)); fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); - fileInfo.pcwszFilePath = Information->FileName; - fileInfo.hFile = fileHandle; + fileInfo.hFile = Information->FileHandle; - verifyResult = PhpVerifyFile(Information, WTD_CHOICE_FILE, &fileInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures); + verifyResult = PhpVerifyFile( + Information, + WTD_CHOICE_FILE, + &fileInfo, + &WinTrustActionGenericVerifyV2, + NULL, + &signatures, + &numberOfSignatures + ); if (verifyResult == VrNoSignature) { if (CryptCATAdminAcquireContext2 && CryptCATAdminCalcHashFromFileHandle2) { PhFreeVerifySignatures(signatures, numberOfSignatures); - verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, BCRYPT_SHA256_ALGORITHM, &signatures, &numberOfSignatures); + + verifyResult = PhpVerifyFileFromCatalog( + Information, + Information->FileHandle, + BCRYPT_SHA256_ALGORITHM, + &signatures, + &numberOfSignatures + ); } if (verifyResult != VrTrusted) { PhFreeVerifySignatures(signatures, numberOfSignatures); - verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, NULL, &signatures, &numberOfSignatures); + + verifyResult = PhpVerifyFileFromCatalog( + Information, + Information->FileHandle, + NULL, + &signatures, + &numberOfSignatures + ); } } @@ -511,8 +531,6 @@ NTSTATUS PhVerifyFileEx( if (NumberOfSignatures) *NumberOfSignatures = numberOfSignatures; - NtClose(fileHandle); - return STATUS_SUCCESS; } @@ -659,12 +677,29 @@ VERIFY_RESULT PhVerifyFile( ) { PH_VERIFY_FILE_INFO info = { 0 }; + HANDLE fileHandle; VERIFY_RESULT verifyResult; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; - info.FileName = FileName; + if (!NT_SUCCESS(PhCreateFileWin32( + &fileHandle, + FileName, + FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + ))) + { + if (SignerName) + *SignerName = NULL; + + return VrNoSignature; + } + info.Flags = PH_VERIFY_PREVENT_NETWORK_ACCESS; + info.FileHandle = fileHandle; if (NT_SUCCESS(PhVerifyFileEx(&info, &verifyResult, &signatures, &numberOfSignatures))) { @@ -677,6 +712,9 @@ VERIFY_RESULT PhVerifyFile( } PhFreeVerifySignatures(signatures, numberOfSignatures); + + NtClose(fileHandle); + return verifyResult; } else @@ -684,19 +722,63 @@ VERIFY_RESULT PhVerifyFile( if (SignerName) *SignerName = NULL; + NtClose(fileHandle); + return VrNoSignature; } } -INT NTAPI PhpVerifyCacheCompareFunction( - _In_ PPH_AVL_LINKS Links1, - _In_ PPH_AVL_LINKS Links2 +BOOLEAN PhpVerifyCacheHashtableEqualFunction( + _In_ PVOID Entry1, + _In_ PVOID Entry2 + ) +{ + PPH_VERIFY_CACHE_ENTRY entry1 = Entry1; + PPH_VERIFY_CACHE_ENTRY entry2 = Entry2; + + return entry1->SequenceNumber == entry2->SequenceNumber && PhEqualString(entry1->FileName, entry2->FileName, TRUE); +} + +ULONG PhpVerifyCacheHashtableHashFunction( + _In_ PVOID Entry + ) +{ + PPH_VERIFY_CACHE_ENTRY entry = Entry; + + return PhHashInt64(entry->SequenceNumber) ^ PhHashStringRefEx(&entry->FileName->sr, TRUE, PH_STRING_HASH_X65599); +} + +VOID PhFlushVerifyCache( + VOID ) { - PPH_VERIFY_CACHE_ENTRY entry1 = CONTAINING_RECORD(Links1, PH_VERIFY_CACHE_ENTRY, Links); - PPH_VERIFY_CACHE_ENTRY entry2 = CONTAINING_RECORD(Links2, PH_VERIFY_CACHE_ENTRY, Links); + PH_HASHTABLE_ENUM_CONTEXT enumContext; + PPH_VERIFY_CACHE_ENTRY entry; + + if (!PhpVerifyCacheHashTable) + return; + + PhAcquireQueuedLockExclusive(&PhpVerifyCacheLock); + + PhBeginEnumHashtable(PhpVerifyCacheHashTable, &enumContext); + + while (entry = PhNextEnumHashtable(&enumContext)) + { + if (entry->FileName) + PhDereferenceObject(entry->FileName); + if (entry->VerifySignerName) + PhDereferenceObject(entry->VerifySignerName); + } + + PhDereferenceObject(PhpVerifyCacheHashTable); + PhpVerifyCacheHashTable = PhCreateHashtable( + sizeof(PH_VERIFY_CACHE_ENTRY), + PhpVerifyCacheHashtableEqualFunction, + PhpVerifyCacheHashtableHashFunction, + 100 + ); - return PhCompareString(entry1->FileName, entry2->FileName, TRUE); + PhReleaseQueuedLockExclusive(&PhpVerifyCacheLock); } VERIFY_RESULT PhVerifyFileWithAdditionalCatalog( @@ -706,7 +788,6 @@ VERIFY_RESULT PhVerifyFileWithAdditionalCatalog( ) { static PH_STRINGREF codeIntegrityFileName = PH_STRINGREF_INIT(L"\\AppxMetadata\\CodeIntegrity.cat"); - VERIFY_RESULT result; PPH_STRING additionalCatalogFileName = NULL; PCERT_CONTEXT *signatures; @@ -768,27 +849,79 @@ VERIFY_RESULT PhVerifyFileCached( _In_ PPH_STRING FileName, _In_opt_ PPH_STRING PackageFullName, _Out_opt_ PPH_STRING *SignerName, + _In_ BOOLEAN NativeFileName, _In_ BOOLEAN CachedOnly ) { #ifdef PH_ENABLE_VERIFY_CACHE - PPH_AVL_LINKS links; + HANDLE fileHandle; + LONGLONG sequenceNumber = 0; PPH_VERIFY_CACHE_ENTRY entry; - PH_VERIFY_CACHE_ENTRY lookupEntry; - lookupEntry.FileName = FileName; + if (PhBeginInitOnce(&PhpVerifyInitOnce)) + { + PhpVerifyInitialization(); + PhEndInitOnce(&PhpVerifyInitOnce); + } + + if (!PhpVerifyCacheHashTable) + { + if (SignerName) *SignerName = NULL; + return VrNoSignature; + } - PhAcquireQueuedLockShared(&PhpVerifyCacheLock); - links = PhFindElementAvlTree(&PhpVerifyCacheSet, &lookupEntry.Links); - PhReleaseQueuedLockShared(&PhpVerifyCacheLock); + if (NativeFileName) + { + if (!NT_SUCCESS(PhCreateFile( + &fileHandle, + FileName, + FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + ))) + { + if (SignerName) *SignerName = NULL; + return VrNoSignature; + } + } + else + { + if (!NT_SUCCESS(PhCreateFileWin32( + &fileHandle, + FileName->Buffer, + FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + ))) + { + if (SignerName) *SignerName = NULL; + return VrNoSignature; + } + } - if (links) { - entry = CONTAINING_RECORD(links, PH_VERIFY_CACHE_ENTRY, Links); + PH_VERIFY_CACHE_ENTRY lookupEntry; + + PhGetFileUsn(fileHandle, &sequenceNumber); + lookupEntry.FileName = FileName; + lookupEntry.SequenceNumber = sequenceNumber; + PhAcquireQueuedLockShared(&PhpVerifyCacheLock); + entry = PhFindEntryHashtable(PhpVerifyCacheHashTable, &lookupEntry); + PhReleaseQueuedLockShared(&PhpVerifyCacheLock); + } + + if (entry) + { if (SignerName) PhSetReference(SignerName, entry->VerifySignerName); + NtClose(fileHandle); + return entry->VerifyResult; } else @@ -801,8 +934,8 @@ VERIFY_RESULT PhVerifyFileCached( PH_VERIFY_FILE_INFO info; memset(&info, 0, sizeof(PH_VERIFY_FILE_INFO)); - info.FileName = FileName->Buffer; info.Flags = PH_VERIFY_PREVENT_NETWORK_ACCESS; + info.FileHandle = fileHandle; result = PhVerifyFileWithAdditionalCatalog(&info, PackageFullName, &signerName); if (result != VrTrusted) @@ -816,29 +949,25 @@ VERIFY_RESULT PhVerifyFileCached( if (result != VrUnknown) { - entry = PhAllocate(sizeof(PH_VERIFY_CACHE_ENTRY)); - entry->FileName = FileName; - entry->VerifyResult = result; - entry->VerifySignerName = signerName; + PH_VERIFY_CACHE_ENTRY newEntry; + + newEntry.FileName = FileName; + newEntry.SequenceNumber = sequenceNumber; + newEntry.VerifyResult = result; + newEntry.VerifySignerName = signerName; PhAcquireQueuedLockExclusive(&PhpVerifyCacheLock); - links = PhAddElementAvlTree(&PhpVerifyCacheSet, &entry->Links); - PhReleaseQueuedLockExclusive(&PhpVerifyCacheLock); - if (!links) + if (PhAddEntryHashtable(PhpVerifyCacheHashTable, &newEntry)) { // We successfully added the cache entry. Add references. + PhReferenceObject(FileName); - PhReferenceObject(entry->FileName); - - if (entry->VerifySignerName) - PhReferenceObject(entry->VerifySignerName); - } - else - { - // Entry already exists. - PhFree(entry); + if (signerName) + PhReferenceObject(signerName); } + + PhReleaseQueuedLockExclusive(&PhpVerifyCacheLock); } if (SignerName) @@ -851,6 +980,8 @@ VERIFY_RESULT PhVerifyFileCached( PhDereferenceObject(signerName); } + NtClose(fileHandle); + return result; } #else @@ -926,7 +1057,7 @@ VERIFY_RESULT PhVerifyFileSignatureInfo( { PVOID wintrust; - if (wintrust = PhLoadLibrarySafe(L"wintrust.dll")) + if (wintrust = PhLoadLibrary(L"wintrust.dll")) { WTGetSignatureInfo_I = PhGetDllBaseProcedureAddress(wintrust, "WTGetSignatureInfo", 0); } diff --git a/ProcessHacker/phlib/wslsup.c b/ProcessHacker/phlib/wslsup.c index a2269cc8..51cd396c 100644 --- a/ProcessHacker/phlib/wslsup.c +++ b/ProcessHacker/phlib/wslsup.c @@ -2,7 +2,7 @@ * Process Hacker - * LXSS support helpers * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -26,11 +26,10 @@ BOOLEAN NTAPI PhpWslDistributionNamesCallback( _In_ HANDLE RootDirectory, _In_ PKEY_BASIC_INFORMATION Information, - _In_opt_ PVOID Context + _In_ PVOID Context ) { - if (Context) - PhAddItemList(Context, PhCreateStringEx(Information->Name, Information->NameLength)); + PhAddItemList(Context, PhCreateStringEx(Information->Name, Information->NameLength)); return TRUE; } @@ -199,11 +198,32 @@ BOOLEAN PhInitializeLxssImageVersionInfo( &lxssFileName->sr )); - if (PhCreateProcessLxss( + if (!PhCreateProcessLxss( lxssDistroName, lxssCommandLine, &lxssCommandResult )) + { + // The dpkg metadata for some packages doesn't contain /usr for + // /usr/bin/ paths. Try lookup the package again without /usr. (dmex) + if (PhStartsWithString2(lxssFileName, L"/usr", TRUE)) + { + PhSkipStringRef(&lxssFileName->sr, 4 * sizeof(WCHAR)); + + PhMoveReference(&lxssCommandLine, PhConcatStringRef2( + &lxssDpkgCommandLine, + &lxssFileName->sr + )); + + PhCreateProcessLxss( + lxssDistroName, + lxssCommandLine, + &lxssCommandResult + ); + } + } + + if (!PhIsNullOrEmptyString(lxssCommandResult)) { PH_STRINGREF remainingPart; PH_STRINGREF packagePart; @@ -278,15 +298,15 @@ BOOLEAN PhCreateProcessLxss( _Out_ PPH_STRING *Result ) { - NTSTATUS status; - PPH_STRING lxssOutputString; + BOOLEAN result = FALSE; + PPH_STRING lxssOutputString = NULL; PPH_STRING lxssCommandLine; PPH_STRING systemDirectory; HANDLE processHandle; - HANDLE outputReadHandle, outputWriteHandle; - HANDLE inputReadHandle, inputWriteHandle; + HANDLE outputReadHandle = NULL, outputWriteHandle = NULL; + HANDLE inputReadHandle = NULL, inputWriteHandle = NULL; + STARTUPINFOEX startupInfo = { 0 }; PROCESS_BASIC_INFORMATION basicInfo; - STARTUPINFO startupInfo; PH_FORMAT format[4]; // "wsl.exe -u root -d %s -e %s" @@ -313,91 +333,118 @@ BOOLEAN PhCreateProcessLxss( PhDereferenceObject(systemDirectory); } - status = PhCreatePipeEx( + if (!NT_SUCCESS(PhCreatePipeEx( &outputReadHandle, &outputWriteHandle, TRUE, NULL - ); - - if (!NT_SUCCESS(status)) - return FALSE; + ))) + { + goto CleanupExit; + } - status = PhCreatePipeEx( + if (!NT_SUCCESS(PhCreatePipeEx( &inputReadHandle, &inputWriteHandle, TRUE, NULL - ); - - if (!NT_SUCCESS(status)) + ))) { - NtClose(outputWriteHandle); - NtClose(outputReadHandle); - return FALSE; + goto CleanupExit; } - memset(&startupInfo, 0, sizeof(STARTUPINFO)); - startupInfo.cb = sizeof(STARTUPINFO); - startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES; - startupInfo.wShowWindow = SW_HIDE; - startupInfo.hStdInput = inputReadHandle; - startupInfo.hStdOutput = outputWriteHandle; - startupInfo.hStdError = outputWriteHandle; + memset(&startupInfo, 0, sizeof(STARTUPINFOEX)); + startupInfo.StartupInfo.cb = sizeof(STARTUPINFOEX); + startupInfo.StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES; + startupInfo.StartupInfo.wShowWindow = SW_HIDE; + startupInfo.StartupInfo.hStdInput = inputReadHandle; + startupInfo.StartupInfo.hStdOutput = outputWriteHandle; + startupInfo.StartupInfo.hStdError = outputWriteHandle; + +#if (PHNT_VERSION >= PHNT_WIN7) + { + SIZE_T attributeListLength = 0; + + if (!InitializeProcThreadAttributeList(NULL, 1, 0, &attributeListLength) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto CleanupExit; + + startupInfo.lpAttributeList = PhAllocate(attributeListLength); + + if (!InitializeProcThreadAttributeList(startupInfo.lpAttributeList, 1, 0, &attributeListLength)) + goto CleanupExit; + + if (!UpdateProcThreadAttribute( + startupInfo.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + &(HANDLE[2]){ inputReadHandle, outputWriteHandle }, + sizeof(HANDLE[2]), + NULL, + NULL + )) + { + goto CleanupExit; + } + } +#endif - status = PhCreateProcessWin32Ex( + if (!NT_SUCCESS(PhCreateProcessWin32Ex( NULL, PhGetString(lxssCommandLine), NULL, NULL, - &startupInfo, - PH_CREATE_PROCESS_INHERIT_HANDLES | PH_CREATE_PROCESS_NEW_CONSOLE | PH_CREATE_PROCESS_DEFAULT_ERROR_MODE, + &startupInfo.StartupInfo, + PH_CREATE_PROCESS_INHERIT_HANDLES | PH_CREATE_PROCESS_NEW_CONSOLE | + PH_CREATE_PROCESS_DEFAULT_ERROR_MODE | PH_CREATE_PROCESS_EXTENDED_STARTUPINFO, NULL, NULL, &processHandle, NULL - ); - - if (!NT_SUCCESS(status)) + ))) { - NtClose(outputWriteHandle); - NtClose(outputReadHandle); - NtClose(inputReadHandle); - NtClose(inputWriteHandle); - return FALSE; + goto CleanupExit; } - // Note: Close the write handles or the child process - // won't exit and ReadFile will block indefinitely. (dmex) - NtClose(inputReadHandle); - NtClose(outputWriteHandle); + // Close the handles. (dmex) + NtClose(inputReadHandle); inputReadHandle = NULL; + NtClose(outputWriteHandle); outputWriteHandle = NULL; // Read the pipe data. (dmex) lxssOutputString = PhGetFileText(outputReadHandle, TRUE); // Get the exit code after we finish reading the data from the pipe. (dmex) - if (NT_SUCCESS(status = PhGetProcessBasicInformation(processHandle, &basicInfo))) + if (NT_SUCCESS(PhGetProcessBasicInformation(processHandle, &basicInfo))) { - status = basicInfo.ExitStatus; + if (basicInfo.ExitStatus == 0) + { + *Result = PhReferenceObject(lxssOutputString); + result = TRUE; + } } - // Note: Don't use NTSTATUS now that we have the lxss exit code. (dmex) - if (status == 0) - { - if (Result) *Result = lxssOutputString; - if (processHandle) NtClose(processHandle); - if (outputReadHandle) NtClose(outputReadHandle); - if (inputWriteHandle) NtClose(inputWriteHandle); + NtClose(processHandle); - return TRUE; - } - else - { - if (lxssOutputString) PhDereferenceObject(lxssOutputString); - if (processHandle) NtClose(processHandle); - if (outputReadHandle) NtClose(outputReadHandle); - if (inputWriteHandle) NtClose(inputWriteHandle); +CleanupExit: - return FALSE; + if (lxssOutputString) + PhDereferenceObject(lxssOutputString); + if (lxssCommandLine) + PhDereferenceObject(lxssCommandLine); + + if (outputWriteHandle) + NtClose(outputWriteHandle); + if (outputReadHandle) + NtClose(outputReadHandle); + if (inputReadHandle) + NtClose(inputReadHandle); + if (inputWriteHandle) + NtClose(inputWriteHandle); + + if (startupInfo.lpAttributeList) + { + DeleteProcThreadAttributeList(startupInfo.lpAttributeList); + PhFree(startupInfo.lpAttributeList); } + + return result; } diff --git a/ProcessHacker/phnt/include/ntexapi.h b/ProcessHacker/phnt/include/ntexapi.h index 465ec044..b5baee2c 100644 --- a/ProcessHacker/phnt/include/ntexapi.h +++ b/ProcessHacker/phnt/include/ntexapi.h @@ -459,6 +459,14 @@ NtSetHighWaitLowEventPair( // Mutant +#ifndef MUTANT_QUERY_STATE +#define MUTANT_QUERY_STATE 0x0001 +#endif + +#ifndef MUTANT_ALL_ACCESS +#define MUTANT_ALL_ACCESS (MUTANT_QUERY_STATE|STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE) +#endif + typedef enum _MUTANT_INFORMATION_CLASS { MutantBasicInformation, // MUTANT_BASIC_INFORMATION @@ -521,6 +529,14 @@ NtQueryMutant( #define SEMAPHORE_QUERY_STATE 0x0001 #endif +#ifndef SEMAPHORE_MODIFY_STATE +#define SEMAPHORE_MODIFY_STATE 0x0002 +#endif + +#ifndef SEMAPHORE_ALL_ACCESS +#define SEMAPHORE_ALL_ACCESS (SEMAPHORE_QUERY_STATE|SEMAPHORE_MODIFY_STATE|STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE) +#endif + typedef enum _SEMAPHORE_INFORMATION_CLASS { SemaphoreBasicInformation @@ -574,6 +590,18 @@ NtQuerySemaphore( // Timer +#ifndef TIMER_QUERY_STATE +#define TIMER_QUERY_STATE 0x0001 +#endif + +#ifndef TIMER_MODIFY_STATE +#define TIMER_MODIFY_STATE 0x0002 +#endif + +#ifndef TIMER_ALL_ACCESS +#define TIMER_ALL_ACCESS (TIMER_QUERY_STATE|TIMER_MODIFY_STATE|STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE) +#endif + typedef enum _TIMER_INFORMATION_CLASS { TimerBasicInformation // TIMER_BASIC_INFORMATION @@ -712,7 +740,7 @@ NTAPI NtCreateTimer2( _Out_ PHANDLE TimerHandle, _In_opt_ PVOID Reserved1, - _In_opt_ PVOID Reserved2, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ ULONG Attributes, _In_ ACCESS_MASK DesiredAccess ); @@ -894,7 +922,8 @@ typedef enum _WNF_DATA_SCOPE WnfDataScopeSession, WnfDataScopeUser, WnfDataScopeProcess, - WnfDataScopeMachine // REDSTONE3 + WnfDataScopeMachine, // REDSTONE3 + WnfDataScopePhysicalMachine, // WIN11 } WNF_DATA_SCOPE; typedef struct _WNF_TYPE_ID @@ -1266,7 +1295,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemProcessInformation, // q: SYSTEM_PROCESS_INFORMATION SystemCallCountInformation, // q: SYSTEM_CALL_COUNT_INFORMATION SystemDeviceInformation, // q: SYSTEM_DEVICE_INFORMATION - SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION + SystemProcessorPerformanceInformation, // q: SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION (EX in: USHORT ProcessorGroup) SystemFlagsInformation, // q: SYSTEM_FLAGS_INFORMATION SystemCallTimeInformation, // not implemented // SYSTEM_CALL_TIME_INFORMATION // 10 SystemModuleInformation, // q: RTL_PROCESS_MODULES @@ -1488,8 +1517,15 @@ typedef enum _SYSTEM_INFORMATION_CLASS SystemPoolZeroingInformation, // SYSTEM_POOL_ZEROING_INFORMATION SystemDpcWatchdogInformation, SystemDpcWatchdogInformation2, - SystemSupportedProcessorArchitectures2,// q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230 + SystemSupportedProcessorArchitectures2, // q: in opt: HANDLE, out: SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION[] // NtQuerySystemInformationEx // 230 SystemSingleProcessorRelationshipInformation, + SystemXfgCheckFailureInformation, + SystemIommuStateInformation, // SYSTEM_IOMMU_STATE_INFORMATION // since 22H1 + SystemHypervisorMinrootInformation, // SYSTEM_HYPERVISOR_MINROOT_INFORMATION + SystemHypervisorBootPagesInformation, // SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION + SystemPointerAuthInformation, // SYSTEM_POINTER_AUTH_INFORMATION + SystemSecureKernelDebuggerInformation, + SystemOriginalImageFeatureInformation, MaxSystemInfoClass } SYSTEM_INFORMATION_CLASS; @@ -3426,14 +3462,13 @@ typedef struct _PROCESS_DISK_COUNTERS // private typedef union _ENERGY_STATE_DURATION { - union + ULONGLONG Value; + struct { - ULONGLONG Value; ULONG LastChangeTime; + ULONG Duration : 31; + ULONG IsInState : 1; }; - - ULONG Duration : 31; - ULONG IsInState : 1; } ENERGY_STATE_DURATION, *PENERGY_STATE_DURATION; typedef struct _PROCESS_ENERGY_VALUES @@ -3462,11 +3497,14 @@ typedef struct _PROCESS_ENERGY_VALUES ULONGLONG WorkOnBehalfCycles[4][2]; } PROCESS_ENERGY_VALUES, *PPROCESS_ENERGY_VALUES; -typedef struct _TIMELINE_BITMAP +typedef union _TIMELINE_BITMAP { ULONGLONG Value; - ULONG EndTime; - ULONG Bitmap; + struct + { + ULONG EndTime; + ULONG Bitmap; + }; } TIMELINE_BITMAP, *PTIMELINE_BITMAP; typedef struct _PROCESS_ENERGY_VALUES_EXTENSION @@ -4151,6 +4189,76 @@ typedef struct _SYSTEM_POOL_LIMIT_INFORMATION // BOOLEAN PoolZeroingSupportPresent; //} SYSTEM_POOL_ZEROING_INFORMATION, *PSYSTEM_POOL_ZEROING_INFORMATION; +// private +typedef struct _HV_MINROOT_NUMA_LPS +{ + ULONG NodeIndex; + ULONG_PTR Mask[16]; +} HV_MINROOT_NUMA_LPS, *PHV_MINROOT_NUMA_LPS; + +// private +typedef enum _SYSTEM_IOMMU_STATE +{ + IommuStateBlock, + IommuStateUnblock +} SYSTEM_IOMMU_STATE; + +// private +typedef struct _SYSTEM_IOMMU_STATE_INFORMATION +{ + SYSTEM_IOMMU_STATE State; + PVOID Pdo; +} SYSTEM_IOMMU_STATE_INFORMATION, *PSYSTEM_IOMMU_STATE_INFORMATION; + +// private +typedef struct _SYSTEM_HYPERVISOR_MINROOT_INFORMATION +{ + ULONG NumProc; + ULONG RootProc; + ULONG RootProcNumaNodesSpecified; + USHORT RootProcNumaNodes[64]; + ULONG RootProcPerCore; + ULONG RootProcPerNode; + ULONG RootProcNumaNodesLpsSpecified; + HV_MINROOT_NUMA_LPS RootProcNumaNodeLps[64]; +} SYSTEM_HYPERVISOR_MINROOT_INFORMATION, *PSYSTEM_HYPERVISOR_MINROOT_INFORMATION; + +// private +typedef struct _SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION +{ + ULONG RangeCount; + ULONG_PTR RangeArray[1]; +} SYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION, *PSYSTEM_HYPERVISOR_BOOT_PAGES_INFORMATION; + +// private +typedef struct _SYSTEM_POINTER_AUTH_INFORMATION +{ + union + { + USHORT SupportedFlags; + struct + { + USHORT AddressAuthSupported : 1; + USHORT AddressAuthQarma : 1; + USHORT GenericAuthSupported : 1; + USHORT GenericAuthQarma : 1; + USHORT SupportedReserved : 12; + }; + }; + union + { + USHORT EnabledFlags; + struct + { + USHORT UserPerProcessIpAuthEnabled : 1; + USHORT UserGlobalIpAuthEnabled : 1; + USHORT UserEnabledReserved : 6; + USHORT KernelIpAuthEnabled : 1; + USHORT KernelEnabledReserved : 7; + }; + }; +} SYSTEM_POINTER_AUTH_INFORMATION, *PSYSTEM_POINTER_AUTH_INFORMATION; + #if (PHNT_MODE != PHNT_MODE_KERNEL) NTSYSCALLAPI @@ -4612,6 +4720,8 @@ C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, NumberOfPhysicalPages) == 0x2e8); C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SafeBootMode) == 0x2ec); C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCount) == 0x320); C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountQuad) == 0x320); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveProcessorCount) == 0x3c0); +C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, ActiveGroupCount) == 0x3c4); C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, XState) == 0x3d8); //C_ASSERT(sizeof(KUSER_SHARED_DATA) == 0x70C); // VS2019 has some weird issue with this. diff --git a/ProcessHacker/phnt/include/ntioapi.h b/ProcessHacker/phnt/include/ntioapi.h index 2c0a326b..d66290fd 100644 --- a/ProcessHacker/phnt/include/ntioapi.h +++ b/ProcessHacker/phnt/include/ntioapi.h @@ -131,6 +131,8 @@ #define FILE_CHARACTERISTIC_CSV 0x00010000 #define FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL 0x00020000 #define FILE_PORTABLE_DEVICE 0x00040000 +#define FILE_REMOTE_DEVICE_VSMB 0x00080000 +#define FILE_DEVICE_REQUIRE_SECURITY_CHECK 0x00100000 // Named pipe values @@ -258,7 +260,7 @@ typedef enum _FILE_INFORMATION_CLASS FileIdInformation, // FILE_ID_INFORMATION FileIdExtdDirectoryInformation, // FILE_ID_EXTD_DIR_INFORMATION // 60 FileReplaceCompletionInformation, // FILE_COMPLETION_INFORMATION // since WINBLUE - FileHardLinkFullIdInformation, // FILE_LINK_ENTRY_FULL_ID_INFORMATION + FileHardLinkFullIdInformation, // FILE_LINK_ENTRY_FULL_ID_INFORMATION // FILE_LINKS_FULL_ID_INFORMATION FileIdExtdBothDirectoryInformation, // FILE_ID_EXTD_BOTH_DIR_INFORMATION // since THRESHOLD FileDispositionInformationEx, // FILE_DISPOSITION_INFO_EX // since REDSTONE FileRenameInformationEx, // FILE_RENAME_INFORMATION_EX @@ -272,6 +274,7 @@ typedef enum _FILE_INFORMATION_CLASS FileLinkInformationExBypassAccessCheck, // (kernel-mode only); FILE_LINK_INFORMATION_EX FileStorageReserveIdInformation, // FILE_SET_STORAGE_RESERVE_ID_INFORMATION FileCaseSensitiveInformationForceAccessCheck, // FILE_CASE_SENSITIVE_INFORMATION + FileKnownFolderInformation, // FILE_KNOWN_FOLDER_INFORMATION // since WIN11 FileMaximumInformation } FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; @@ -397,22 +400,31 @@ typedef struct _FILE_END_OF_FILE_INFORMATION LARGE_INTEGER EndOfFile; } FILE_END_OF_FILE_INFORMATION, *PFILE_END_OF_FILE_INFORMATION; +//#if (PHNT_VERSION >= PHNT_REDSTONE5) +#define FLAGS_END_OF_FILE_INFO_EX_EXTEND_PAGING 0x00000001 +#define FLAGS_END_OF_FILE_INFO_EX_NO_EXTRA_PAGING_EXTEND 0x00000002 +#define FLAGS_END_OF_FILE_INFO_EX_TIME_CONSTRAINED 0x00000004 +#define FLAGS_DELAY_REASONS_LOG_FILE_FULL 0x00000001 +#define FLAGS_DELAY_REASONS_BITMAP_SCANNED 0x00000002 + +typedef struct _FILE_END_OF_FILE_INFORMATION_EX +{ + LARGE_INTEGER EndOfFile; + LARGE_INTEGER PagingFileSizeInMM; + LARGE_INTEGER PagingFileMaxSize; + ULONG Flags; +} FILE_END_OF_FILE_INFORMATION_EX, *PFILE_END_OF_FILE_INFORMATION_EX; +//#endif + typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION { LARGE_INTEGER ValidDataLength; } FILE_VALID_DATA_LENGTH_INFORMATION, *PFILE_VALID_DATA_LENGTH_INFORMATION; -typedef struct _FILE_LINK_INFORMATION -{ - BOOLEAN ReplaceIfExists; - HANDLE RootDirectory; - ULONG FileNameLength; - WCHAR FileName[1]; -} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; - #if (PHNT_VERSION >= PHNT_REDSTONE5) #define FILE_LINK_REPLACE_IF_EXISTS 0x00000001 #define FILE_LINK_POSIX_SEMANTICS 0x00000002 + #define FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE 0x00000008 #define FILE_LINK_NO_INCREASE_AVAILABLE_SPACE 0x00000010 #define FILE_LINK_NO_DECREASE_AVAILABLE_SPACE 0x00000020 @@ -426,6 +438,22 @@ typedef struct _FILE_LINK_INFORMATION #define FILE_LINK_FORCE_RESIZE_SR 0x00000180 #endif +typedef struct _FILE_LINK_INFORMATION +{ +#if (PHNT_VERSION >= PHNT_REDSTONE5) + union + { + BOOLEAN ReplaceIfExists; // FileLinkInformation + ULONG Flags; // FileLinkInformationEx + }; +#else + BOOLEAN ReplaceIfExists; +#endif + HANDLE RootDirectory; + ULONG FileNameLength; + WCHAR FileName[1]; +} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION; + typedef struct _FILE_LINK_INFORMATION_EX { ULONG Flags; @@ -647,21 +675,23 @@ typedef struct _FILE_IOSTATUSBLOCK_RANGE_INFORMATION ULONG Length; } FILE_IOSTATUSBLOCK_RANGE_INFORMATION, *PFILE_IOSTATUSBLOCK_RANGE_INFORMATION; +// Win32 FILE_REMOTE_PROTOCOL_INFO typedef struct _FILE_REMOTE_PROTOCOL_INFORMATION { - USHORT StructureVersion; // 1 - USHORT StructureSize; + // Structure Version + USHORT StructureVersion; // 1 for Win7, 2 for Win8 SMB3, 3 for Blue SMB3, 4 for RS5 + USHORT StructureSize; // sizeof(FILE_REMOTE_PROTOCOL_INFORMATION) - ULONG Protocol; // WNNC_NET_* + ULONG Protocol; // Protocol (WNNC_NET_*) defined in winnetwk.h or ntifs.h. + // Protocol Version & Type USHORT ProtocolMajorVersion; USHORT ProtocolMinorVersion; USHORT ProtocolRevision; USHORT Reserved; - // Generic information - + // Protocol-Generic Information ULONG Flags; struct @@ -669,14 +699,16 @@ typedef struct _FILE_REMOTE_PROTOCOL_INFORMATION ULONG Reserved[8]; } GenericReserved; - // Specific information + // Protocol specific information -#if (PHNT_VERSION < PHNT_WIN8) +#if (_WIN32_WINNT < PHNT_WIN8) struct { ULONG Reserved[16]; } ProtocolSpecificReserved; -#else +#endif + +#if (PHNT_VERSION >= PHNT_WIN8) union { struct @@ -688,7 +720,16 @@ typedef struct _FILE_REMOTE_PROTOCOL_INFORMATION struct { ULONG Capabilities; +#if (PHNT_VERSION >= PHNT_21H1) + ULONG ShareFlags; +#else ULONG CachingFlags; +#endif +#if (PHNT_VERSION >= PHNT_REDSTONE5) + UCHAR ShareType; + UCHAR Reserved0[3]; + ULONG Reserved1; +#endif } Share; } Smb2; ULONG Reserved[16]; @@ -744,6 +785,13 @@ typedef struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION WCHAR FileName[1]; } FILE_LINK_ENTRY_FULL_ID_INFORMATION, *PFILE_LINK_ENTRY_FULL_ID_INFORMATION; +typedef struct _FILE_LINKS_FULL_ID_INFORMATION +{ + ULONG BytesNeeded; + ULONG EntriesReturned; + FILE_LINK_ENTRY_FULL_ID_INFORMATION Entry; +} FILE_LINKS_FULL_ID_INFORMATION, *PFILE_LINKS_FULL_ID_INFORMATION; + typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATION { ULONG NextEntryOffset; @@ -777,7 +825,7 @@ typedef struct _FILE_STAT_INFORMATION ULONG FileAttributes; ULONG ReparseTag; ULONG NumberOfLinks; - ULONG EffectiveAccess; + ACCESS_MASK EffectiveAccess; } FILE_STAT_INFORMATION, *PFILE_STAT_INFORMATION; // private @@ -795,6 +843,13 @@ typedef struct _FILE_MEMORY_PARTITION_INFORMATION } Flags; } FILE_MEMORY_PARTITION_INFORMATION, *PFILE_MEMORY_PARTITION_INFORMATION; +// LxFlags +#define LX_FILE_METADATA_HAS_UID 0x1 +#define LX_FILE_METADATA_HAS_GID 0x2 +#define LX_FILE_METADATA_HAS_MODE 0x4 +#define LX_FILE_METADATA_HAS_DEVICE_ID 0x8 +#define LX_FILE_CASE_SENSITIVE_DIR 0x10 + // private typedef struct _FILE_STAT_LX_INFORMATION { @@ -808,7 +863,7 @@ typedef struct _FILE_STAT_LX_INFORMATION ULONG FileAttributes; ULONG ReparseTag; ULONG NumberOfLinks; - ULONG EffectiveAccess; + ACCESS_MASK EffectiveAccess; ULONG LxFlags; ULONG LxUid; ULONG LxGid; @@ -817,12 +872,34 @@ typedef struct _FILE_STAT_LX_INFORMATION ULONG LxDeviceIdMinor; } FILE_STAT_LX_INFORMATION, *PFILE_STAT_LX_INFORMATION; +#define FILE_CS_FLAG_CASE_SENSITIVE_DIR 0x00000001 + // private typedef struct _FILE_CASE_SENSITIVE_INFORMATION { ULONG Flags; } FILE_CASE_SENSITIVE_INFORMATION, *PFILE_CASE_SENSITIVE_INFORMATION; +// private +typedef enum _FILE_KNOWN_FOLDER_TYPE +{ + KnownFolderNone, + KnownFolderDesktop, + KnownFolderDocuments, + KnownFolderDownloads, + KnownFolderMusic, + KnownFolderPictures, + KnownFolderVideos, + KnownFolderOther, + KnownFolderMax = 7 +} FILE_KNOWN_FOLDER_TYPE; + +// private +typedef struct _FILE_KNOWN_FOLDER_INFORMATION +{ + FILE_KNOWN_FOLDER_TYPE Type; +} FILE_KNOWN_FOLDER_INFORMATION, *PFILE_KNOWN_FOLDER_INFORMATION; + // NtQueryDirectoryFile types typedef struct _FILE_DIRECTORY_INFORMATION @@ -1041,6 +1118,20 @@ typedef struct _FILE_FS_SIZE_INFORMATION ULONG BytesPerSector; } FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION; +// FileSystemControlFlags +#define FILE_VC_QUOTA_NONE 0x00000000 +#define FILE_VC_QUOTA_TRACK 0x00000001 +#define FILE_VC_QUOTA_ENFORCE 0x00000002 +#define FILE_VC_QUOTA_MASK 0x00000003 +#define FILE_VC_CONTENT_INDEX_DISABLED 0x00000008 +#define FILE_VC_LOG_QUOTA_THRESHOLD 0x00000010 +#define FILE_VC_LOG_QUOTA_LIMIT 0x00000020 +#define FILE_VC_LOG_VOLUME_THRESHOLD 0x00000040 +#define FILE_VC_LOG_VOLUME_LIMIT 0x00000080 +#define FILE_VC_QUOTAS_INCOMPLETE 0x00000100 +#define FILE_VC_QUOTAS_REBUILDING 0x00000200 +#define FILE_VC_VALID_MASK 0x000003ff + // private typedef struct _FILE_FS_CONTROL_INFORMATION { @@ -1298,6 +1389,15 @@ NtQueryDirectoryFile( ); #if (PHNT_VERSION >= PHNT_REDSTONE3) +// QueryFlags values for NtQueryDirectoryFileEx +#define FILE_QUERY_RESTART_SCAN 0x00000001 +#define FILE_QUERY_RETURN_SINGLE_ENTRY 0x00000002 +#define FILE_QUERY_INDEX_SPECIFIED 0x00000004 +#define FILE_QUERY_RETURN_ON_DISK_ENTRIES_ONLY 0x00000008 +#if (PHNT_VERSION >= PHNT_REDSTONE5) +#define FILE_QUERY_NO_CURSOR_UPDATE 0x00000010 +#endif + NTSYSCALLAPI NTSTATUS NTAPI @@ -1612,6 +1712,14 @@ NtUnloadDriver( #define IO_COMPLETION_QUERY_STATE 0x0001 #endif +#ifndef IO_COMPLETION_MODIFY_STATE +#define IO_COMPLETION_MODIFY_STATE 0x0002 +#endif + +#ifndef IO_COMPLETION_ALL_ACCESS +#define IO_COMPLETION_ALL_ACCESS (IO_COMPLETION_QUERY_STATE|IO_COMPLETION_MODIFY_STATE|STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE) +#endif + typedef enum _IO_COMPLETION_INFORMATION_CLASS { IoCompletionBasicInformation @@ -1867,13 +1975,20 @@ typedef enum _BUS_DATA_TYPE // Reparse structure for FSCTL_SET_REPARSE_POINT, FSCTL_GET_REPARSE_POINT, FSCTL_DELETE_REPARSE_POINT -#define SYMLINK_FLAG_RELATIVE 1 +#define SYMLINK_FLAG_RELATIVE 0x00000001 + +#if (PHNT_VERSION >= PHNT_REDSTONE4) +#define SYMLINK_DIRECTORY 0x80000000 // If set then this is a directory symlink +#define SYMLINK_FILE 0x40000000 // If set then this is a file symlink +#endif typedef struct _REPARSE_DATA_BUFFER { ULONG ReparseTag; USHORT ReparseDataLength; USHORT Reserved; + + _Field_size_bytes_(ReparseDataLength) union { struct @@ -1900,6 +2015,8 @@ typedef struct _REPARSE_DATA_BUFFER }; } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +#define REPARSE_DATA_BUFFER_HEADER_SIZE UFIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer) + // Named pipe FS control definitions #define DEVICE_NAMED_PIPE L"\\Device\\NamedPipe\\" @@ -1925,6 +2042,7 @@ typedef struct _REPARSE_DATA_BUFFER #define FSCTL_PIPE_SILO_ARRIVAL CTL_CODE(FILE_DEVICE_NAMED_PIPE, 18, METHOD_BUFFERED, FILE_WRITE_DATA) #define FSCTL_PIPE_CREATE_SYMLINK CTL_CODE(FILE_DEVICE_NAMED_PIPE, 19, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) #define FSCTL_PIPE_DELETE_SYMLINK CTL_CODE(FILE_DEVICE_NAMED_PIPE, 20, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) +#define FSCTL_PIPE_QUERY_CLIENT_PROCESS_V2 CTL_CODE(FILE_DEVICE_NAMED_PIPE, 21, METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSCTL_PIPE_INTERNAL_READ CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2045, METHOD_BUFFERED, FILE_READ_DATA) #define FSCTL_PIPE_INTERNAL_WRITE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2046, METHOD_BUFFERED, FILE_WRITE_DATA) @@ -1984,6 +2102,18 @@ typedef struct _FILE_PIPE_CLIENT_PROCESS_BUFFER #endif } FILE_PIPE_CLIENT_PROCESS_BUFFER, *PFILE_PIPE_CLIENT_PROCESS_BUFFER; +// Control structure for FSCTL_PIPE_QUERY_CLIENT_PROCESS_V2 + +typedef struct _FILE_PIPE_CLIENT_PROCESS_BUFFER_V2 +{ + ULONGLONG ClientSession; +#if !defined(BUILD_WOW6432) + PVOID ClientProcess; +#else + ULONGLONG ClientProcess; +#endif +} FILE_PIPE_CLIENT_PROCESS_BUFFER_V2, *PFILE_PIPE_CLIENT_PROCESS_BUFFER_V2; + #define FILE_PIPE_COMPUTER_NAME_LENGTH 15 // Input for FSCTL_PIPE_SET_CLIENT_PROCESS, Output for FSCTL_PIPE_QUERY_CLIENT_PROCESS diff --git a/ProcessHacker/phnt/include/ntkeapi.h b/ProcessHacker/phnt/include/ntkeapi.h index 38d8633a..225aac3e 100644 --- a/ProcessHacker/phnt/include/ntkeapi.h +++ b/ProcessHacker/phnt/include/ntkeapi.h @@ -103,6 +103,8 @@ typedef enum _KWAIT_REASON WrAlertByThreadId, WrDeferredPreempt, WrPhysicalFault, + WrIoRing, + WrMdlCache, MaximumWaitReason } KWAIT_REASON, *PKWAIT_REASON; diff --git a/ProcessHacker/phnt/include/ntldr.h b/ProcessHacker/phnt/include/ntldr.h index 3964618a..a7ebcf32 100644 --- a/ProcessHacker/phnt/include/ntldr.h +++ b/ProcessHacker/phnt/include/ntldr.h @@ -102,39 +102,54 @@ typedef enum _LDR_DLL_LOAD_REASON LoadReasonDynamicLoad, LoadReasonAsImageLoad, LoadReasonAsDataLoad, - LoadReasonEnclavePrimary, // REDSTONE3 + LoadReasonEnclavePrimary, // since REDSTONE3 LoadReasonEnclaveDependency, + LoadReasonPatchImage, // since WIN11 LoadReasonUnknown = -1 } LDR_DLL_LOAD_REASON, *PLDR_DLL_LOAD_REASON; +typedef enum _LDR_HOT_PATCH_STATE +{ + LdrHotPatchBaseImage, + LdrHotPatchNotApplied, + LdrHotPatchAppliedReverse, + LdrHotPatchAppliedForward, + LdrHotPatchFailedToPatch, + LdrHotPatchStateMax, +} LDR_HOT_PATCH_STATE, *PLDR_HOT_PATCH_STATE; + +// LDR_DATA_TABLE_ENTRY->Flags #define LDRP_PACKAGED_BINARY 0x00000001 -#define LDRP_STATIC_LINK 0x00000002 +#define LDRP_MARKED_FOR_REMOVAL 0x00000002 #define LDRP_IMAGE_DLL 0x00000004 +#define LDRP_LOAD_NOTIFICATIONS_SENT 0x00000008 +#define LDRP_TELEMETRY_ENTRY_PROCESSED 0x00000010 +#define LDRP_PROCESS_STATIC_IMPORT 0x00000020 +#define LDRP_IN_LEGACY_LISTS 0x00000040 +#define LDRP_IN_INDEXES 0x00000080 +#define LDRP_SHIM_DLL 0x00000100 +#define LDRP_IN_EXCEPTION_TABLE 0x00000200 #define LDRP_LOAD_IN_PROGRESS 0x00001000 -#define LDRP_UNLOAD_IN_PROGRESS 0x00002000 +#define LDRP_LOAD_CONFIG_PROCESSED 0x00002000 #define LDRP_ENTRY_PROCESSED 0x00004000 -#define LDRP_ENTRY_INSERTED 0x00008000 -#define LDRP_CURRENT_LOAD 0x00010000 -#define LDRP_FAILED_BUILTIN_LOAD 0x00020000 +#define LDRP_PROTECT_DELAY_LOAD 0x00008000 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 -#define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 -#define LDRP_IMAGE_NOT_AT_BASE 0x00200000 // Vista and below +#define LDRP_PROCESS_ATTACH_FAILED 0x00100000 +#define LDRP_COR_DEFERRED_VALIDATE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 -#define LDRP_DONT_RELOCATE 0x00800000 // LDR_COR_OWNS_UNMAP -#define LDRP_SYSTEM_MAPPED 0x01000000 -#define LDRP_IMAGE_VERIFYING 0x02000000 -#define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 -#define LDRP_ENTRY_NATIVE 0x08000000 +#define LDRP_DONT_RELOCATE 0x00800000 +#define LDRP_COR_IL_ONLY 0x01000000 +#define LDRP_CHPE_IMAGE 0x02000000 +#define LDRP_CHPE_EMULATOR_IMAGE 0x04000000 #define LDRP_REDIRECTED 0x10000000 -#define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 -#define LDRP_MM_LOADED 0x40000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 #define LDR_DATA_TABLE_ENTRY_SIZE_WINXP FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, DdagNode) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN7 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, BaseNameHashValue) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN8 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, ImplicitPathOptions) -#define LDR_DATA_TABLE_ENTRY_SIZE_WIN10 sizeof(LDR_DATA_TABLE_ENTRY) +#define LDR_DATA_TABLE_ENTRY_SIZE_WIN10 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, SigningLevel) +#define LDR_DATA_TABLE_ENTRY_SIZE_WIN11 sizeof(LDR_DATA_TABLE_ENTRY) // symbols typedef struct _LDR_DATA_TABLE_ENTRY @@ -181,7 +196,8 @@ typedef struct _LDR_DATA_TABLE_ENTRY ULONG DontRelocate : 1; ULONG CorILOnly : 1; ULONG ChpeImage : 1; - ULONG ReservedFlags5 : 2; + ULONG ChpeEmulatorImage : 1; + ULONG ReservedFlags5 : 1; ULONG Redirected : 1; ULONG ReservedFlags6 : 2; ULONG CompatDatabaseProcessed : 1; @@ -203,11 +219,14 @@ typedef struct _LDR_DATA_TABLE_ENTRY ULONG_PTR OriginalBase; LARGE_INTEGER LoadTime; ULONG BaseNameHashValue; - LDR_DLL_LOAD_REASON LoadReason; + LDR_DLL_LOAD_REASON LoadReason; // since WIN8 ULONG ImplicitPathOptions; - ULONG ReferenceCount; + ULONG ReferenceCount; // since WIN10 ULONG DependentLoadFlags; UCHAR SigningLevel; // since REDSTONE2 + ULONG CheckSum; // since 22H1 + PVOID ActivePatchImageBase; + LDR_HOT_PATCH_STATE HotPatchState; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; #define LDR_IS_DATAFILE(DllHandle) (((ULONG_PTR)(DllHandle)) & (ULONG_PTR)1) @@ -256,7 +275,7 @@ LdrGetDllHandleEx( _In_opt_ PWSTR DllPath, _In_opt_ PULONG DllCharacteristics, _In_ PUNICODE_STRING DllName, - _Out_opt_ PVOID *DllHandle + _Out_ PVOID *DllHandle ); #if (PHNT_VERSION >= PHNT_WIN7) diff --git a/ProcessHacker/phnt/include/ntmmapi.h b/ProcessHacker/phnt/include/ntmmapi.h index 70b5e621..2260652e 100644 --- a/ProcessHacker/phnt/include/ntmmapi.h +++ b/ProcessHacker/phnt/include/ntmmapi.h @@ -65,7 +65,17 @@ #define MEM_LARGE_PAGES 0x20000000 #define MEM_DOS_LIM 0x40000000 #define MEM_4MB_PAGES 0x80000000 +#define MEM_64K_PAGES (MEM_LARGE_PAGES | MEM_PHYSICAL) +#define MEM_UNMAP_WITH_TRANSIENT_BOOST 0x00000001 +#define MEM_COALESCE_PLACEHOLDERS 0x00000001 +#define MEM_PRESERVE_PLACEHOLDER 0x00000002 +#define MEM_REPLACE_PLACEHOLDER 0x00004000 +#define MEM_RESERVE_PLACEHOLDER 0x00040000 + +#define SEC_HUGE_PAGES 0x00020000 +#define SEC_PARTITION_OWNER_HANDLE 0x00040000 +#define SEC_64K_PAGES 0x00080000 #define SEC_BASED 0x00200000 #define SEC_NO_CHANGE 0x00400000 #define SEC_FILE 0x00800000 @@ -98,6 +108,8 @@ typedef enum _MEMORY_INFORMATION_CLASS MemoryEnclaveImageInformation, // MEMORY_ENCLAVE_IMAGE_INFORMATION // since REDSTONE3 MemoryBasicInformationCapped, // 10 MemoryPhysicalContiguityInformation, // MEMORY_PHYSICAL_CONTIGUITY_INFORMATION // since 20H1 + MemoryBadInformation, // since WIN11 + MemoryBadInformationAllProcesses, // since 22H1 MaxMemoryInfoClass } MEMORY_INFORMATION_CLASS; #else @@ -113,6 +125,8 @@ typedef enum _MEMORY_INFORMATION_CLASS #define MemoryEnclaveImageInformation 0x9 #define MemoryBasicInformationCapped 0xA #define MemoryPhysicalContiguityInformation 0xB +#define MemoryBadInformation 0xC +#define MemoryBadInformationAllProcesses 0xD #endif typedef struct _MEMORY_WORKING_SET_BLOCK @@ -421,7 +435,7 @@ typedef enum _SECTION_INFORMATION_CLASS { SectionBasicInformation, // q; SECTION_BASIC_INFORMATION SectionImageInformation, // q; SECTION_IMAGE_INFORMATION - SectionRelocationInformation, // name:wow64:whNtQuerySection_SectionRelocationInformation + SectionRelocationInformation, // q; PVOID RelocationAddress // name:wow64:whNtQuerySection_SectionRelocationInformation SectionOriginalBaseInformation, // PVOID BaseAddress SectionInternalImageInformation, // SECTION_INTERNAL_IMAGE_INFORMATION // since REDSTONE2 MaxSectionInfoClass @@ -513,8 +527,8 @@ typedef enum _SECTION_INHERIT } SECTION_INHERIT; #endif -#define MEM_EXECUTE_OPTION_DISABLE 0x1 -#define MEM_EXECUTE_OPTION_ENABLE 0x2 +#define MEM_EXECUTE_OPTION_ENABLE 0x1 +#define MEM_EXECUTE_OPTION_DISABLE 0x2 #define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x4 #define MEM_EXECUTE_OPTION_PERMANENT 0x8 #define MEM_EXECUTE_OPTION_EXECUTE_DISPATCH_ENABLE 0x10 @@ -573,6 +587,21 @@ NtReadVirtualMemory( _Out_opt_ PSIZE_T NumberOfBytesRead ); +#if (PHNT_VERSION >= PHNT_WIN11) +// rev +NTSYSAPI +NTSTATUS +NTAPI +NtReadVirtualMemoryEx( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress, + _Out_writes_bytes_(BufferSize) PVOID Buffer, + _In_ SIZE_T BufferSize, + _Out_opt_ PSIZE_T NumberOfBytesRead, + _In_ ULONG Flags + ); +#endif + NTSYSCALLAPI NTSTATUS NTAPI @@ -624,7 +653,7 @@ NtFlushVirtualMemory( typedef enum _VIRTUAL_MEMORY_INFORMATION_CLASS { VmPrefetchInformation, // ULONG - VmPagePriorityInformation, + VmPagePriorityInformation, // OFFER_PRIORITY VmCfgCallTargetInformation, // CFG_CALL_TARGET_LIST_INFORMATION // REDSTONE2 VmPageDirtyStateInformation, // REDSTONE3 VmImageHotPatchInformation, // 19H1 @@ -654,7 +683,7 @@ typedef struct _CFG_CALL_TARGET_LIST_INFORMATION #if (PHNT_MODE != PHNT_MODE_KERNEL) -#if (PHNT_VERSION >= PHNT_THRESHOLD) +#if (PHNT_VERSION >= PHNT_WIN8) NTSYSCALLAPI NTSTATUS @@ -843,9 +872,10 @@ typedef enum _PARTITION_INFORMATION_CLASS SystemMemoryPartitionNodeInformation, SystemMemoryPartitionCreateLargePages, SystemMemoryPartitionDedicatedMemoryInformation, - SystemMemoryPartitionOpenDedicatedMemory, + SystemMemoryPartitionOpenDedicatedMemory, // 10 SystemMemoryPartitionMemoryChargeAttributes, SystemMemoryPartitionClearAttributes, + SystemMemoryPartitionSetMemoryThresholds, // since WIN11 SystemMemoryPartitionMax } PARTITION_INFORMATION_CLASS, *PPARTITION_INFORMATION_CLASS; #else @@ -862,7 +892,8 @@ typedef enum _PARTITION_INFORMATION_CLASS #define SystemMemoryPartitionOpenDedicatedMemory 0xA #define SystemMemoryPartitionMemoryChargeAttributes 0xB #define SystemMemoryPartitionClearAttributes 0xC -#define SystemMemoryPartitionMax 0xD +#define SystemMemoryPartitionSetMemoryThresholds 0xD +#define SystemMemoryPartitionMax 0xE #endif // private @@ -884,7 +915,7 @@ typedef struct _MEMORY_PARTITION_CONFIGURATION_INFORMATION ULONG_PTR StandbyPageCountByPriority[8]; // since REDSTONE2 ULONG_PTR RepurposedPagesByPriority[8]; ULONG_PTR MaximumCommitLimit; - ULONG_PTR DonatedPagesToPartitions; + ULONG_PTR Reserved; // DonatedPagesToPartitions ULONG PartitionId; // since REDSTONE3 } MEMORY_PARTITION_CONFIGURATION_INFORMATION, *PMEMORY_PARTITION_CONFIGURATION_INFORMATION; @@ -957,6 +988,7 @@ NTSYSCALLAPI NTSTATUS NTAPI NtCreatePartition( + _In_ HANDLE ParentPartitionHandle, _Out_ PHANDLE PartitionHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, diff --git a/ProcessHacker/phnt/include/ntobapi.h b/ProcessHacker/phnt/include/ntobapi.h index b6c17af7..13798674 100644 --- a/ProcessHacker/phnt/include/ntobapi.h +++ b/ProcessHacker/phnt/include/ntobapi.h @@ -36,7 +36,9 @@ #if (PHNT_MODE != PHNT_MODE_KERNEL) #define SYMBOLIC_LINK_QUERY 0x0001 +#define SYMBOLIC_LINK_SET 0x0002 #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) +#define SYMBOLIC_LINK_ALL_ACCESS_EX (STANDARD_RIGHTS_REQUIRED | 0xFFFF) #endif #ifndef OBJ_PROTECT_CLOSE @@ -330,14 +332,50 @@ NtQueryDirectoryObject( #if (PHNT_VERSION >= PHNT_VISTA) +// private +typedef enum _BOUNDARY_ENTRY_TYPE +{ + OBNS_Invalid, + OBNS_Name, + OBNS_SID, + OBNS_IL +} BOUNDARY_ENTRY_TYPE; + +// private +typedef struct _OBJECT_BOUNDARY_ENTRY +{ + BOUNDARY_ENTRY_TYPE EntryType; + ULONG EntrySize; +} OBJECT_BOUNDARY_ENTRY, *POBJECT_BOUNDARY_ENTRY; + +// rev +#define OBJECT_BOUNDARY_DESCRIPTOR_VERSION 1 + +// private +typedef struct _OBJECT_BOUNDARY_DESCRIPTOR +{ + ULONG Version; + ULONG Items; + ULONG TotalSize; + union + { + ULONG Flags; + struct + { + ULONG AddAppContainerSid : 1; + ULONG Reserved : 31; + }; + }; +} OBJECT_BOUNDARY_DESCRIPTOR, *POBJECT_BOUNDARY_DESCRIPTOR; + NTSYSCALLAPI NTSTATUS NTAPI NtCreatePrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ POBJECT_BOUNDARY_DESCRIPTOR BoundaryDescriptor ); NTSYSCALLAPI @@ -347,7 +385,7 @@ NtOpenPrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_ POBJECT_BOUNDARY_DESCRIPTOR BoundaryDescriptor ); NTSYSCALLAPI @@ -400,6 +438,7 @@ typedef enum _SYMBOLIC_LINK_INFO_CLASS MaxnSymbolicLinkInfoClass } SYMBOLIC_LINK_INFO_CLASS; +#if (PHNT_VERSION >= PHNT_THRESHOLD) NTSYSCALLAPI NTSTATUS NTAPI @@ -409,6 +448,7 @@ NtSetInformationSymbolicLink( _In_reads_bytes_(SymbolicLinkInformationLength) PVOID SymbolicLinkInformation, _In_ ULONG SymbolicLinkInformationLength ); +#endif #endif diff --git a/ProcessHacker/phnt/include/ntpebteb.h b/ProcessHacker/phnt/include/ntpebteb.h index a4544393..a276a9ef 100644 --- a/ProcessHacker/phnt/include/ntpebteb.h +++ b/ProcessHacker/phnt/include/ntpebteb.h @@ -203,7 +203,14 @@ typedef struct _PEB PVOID WerRegistrationData; PVOID WerShipAssertPtr; - PVOID pUnused; // pContextData + + union + { + PVOID pContextData; // WIN7 + PVOID pUnused; // WIN10 + PVOID EcCodeBitMap; // WIN11 + }; + PVOID pImageHeaderHash; union { @@ -430,7 +437,7 @@ typedef struct _TEB USHORT LoadOwner : 1; USHORT LoaderWorker : 1; USHORT SkipLoaderInit : 1; - USHORT SpareSameTebBits : 1; + USHORT SkipFileAPIBrokering : 1; }; }; @@ -443,6 +450,9 @@ typedef struct _TEB PVOID ReservedForWdf; ULONGLONG ReservedForCrt; GUID EffectiveContainerId; + ULONGLONG LastSleepCounter; // Win11 + ULONG SpinCallCount; + ULONGLONG ExtendedFeatureDisableMask; } TEB, *PTEB; #endif diff --git a/ProcessHacker/phnt/include/ntpoapi.h b/ProcessHacker/phnt/include/ntpoapi.h index 8b8fca9f..6f6ee35b 100644 --- a/ProcessHacker/phnt/include/ntpoapi.h +++ b/ProcessHacker/phnt/include/ntpoapi.h @@ -70,7 +70,7 @@ #define PowerRequestCreate 43 // in: COUNTED_REASON_CONTEXT, out: HANDLE #define PowerRequestAction 44 // in: POWER_REQUEST_ACTION #define GetPowerRequestList 45 // out: POWER_REQUEST_LIST -#define ProcessorInformationEx 46 // in: USHORT, out: PROCESSOR_POWER_INFORMATION +#define ProcessorInformationEx 46 // in: USHORT ProcessorGroup, out: PROCESSOR_POWER_INFORMATION #define NotifyUserModeLegacyPowerEvent 47 // (kernel-mode only) #define GroupPark 48 // (debug-mode boot only) #define ProcessorIdleDomains 49 // (kernel-mode only) @@ -120,7 +120,8 @@ #define EnergyTrackerQuery 93 #define UpdateBlackBoxRecorder 94 #define SessionAllowExternalDmaDevices 95 -#define PowerInformationLevelMaximum 96 +#define SendSuspendResumeNotification 96 // since WIN11 +#define PowerInformationLevelMaximum 97 #endif typedef struct _PROCESSOR_POWER_INFORMATION @@ -334,7 +335,7 @@ typedef NTSTATUS (NTAPI *PENTER_STATE_HANDLER)( _In_opt_ PENTER_STATE_SYSTEM_HANDLER SystemHandler, _In_ PVOID SystemContext, _In_ LONG NumberProcessors, - _In_ volatile PLONG Number + _In_ LONG volatile *Number ); typedef struct _POWER_STATE_HANDLER @@ -435,6 +436,27 @@ typedef enum _POWER_INFORMATION_LEVEL_INTERNAL PowerInternalClearConstraints, PowerInternalSoftParkVelocityEnabled, PowerInternalQueryIntelPepCapabilities, + PowerInternalGetSystemIdleLoopEnablement, // since WIN11 + PowerInternalGetVmPerfControlSupport, + PowerInternalGetVmPerfControlConfig, // 70 + PowerInternalSleepDetailedDiagUpdate, + PowerInternalProcessorClassFrequencyBandsStats, + PowerInternalHostGlobalUserPresenceStateUpdate, + PowerInternalCpuNodeIdleIntervalStats, + PowerInternalClassIdleIntervalStats, + PowerInternalCpuNodeConcurrencyStats, + PowerInternalClassConcurrencyStats, + PowerInternalQueryProcMeasurementCapabilities, + PowerInternalQueryProcMeasurementValues, + PowerInternalPrepareForSystemInitiatedReboot, // 80 + PowerInternalGetAdaptiveSessionState, + PowerInternalSetConsoleLockedState, + PowerInternalOverrideSystemInitiatedRebootState, + PowerInternalFanImpactStats, + PowerInternalFanRpmBuckets, + PowerInternalPowerBootAppDiagInfo, + PowerInternalUnregisterShutdownNotification, // since 22H1 + PowerInternalManageTransitionStateRecord, PowerInformationInternalMaximum } POWER_INFORMATION_LEVEL_INTERNAL; @@ -536,12 +558,14 @@ NtSetThreadExecutionState( _Out_ EXECUTION_STATE *PreviousFlags ); +#if (PHNT_VERSION < PHNT_WIN7) NTSYSCALLAPI NTSTATUS NTAPI NtRequestWakeupLatency( _In_ LATENCY_TIME latency ); +#endif NTSYSCALLAPI NTSTATUS diff --git a/ProcessHacker/phnt/include/ntpsapi.h b/ProcessHacker/phnt/include/ntpsapi.h index 3b12164e..f8ea33fe 100644 --- a/ProcessHacker/phnt/include/ntpsapi.h +++ b/ProcessHacker/phnt/include/ntpsapi.h @@ -58,7 +58,8 @@ #define JOB_OBJECT_QUERY 0x0004 #define JOB_OBJECT_TERMINATE 0x0008 #define JOB_OBJECT_SET_SECURITY_ATTRIBUTES 0x0010 -#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1f) +#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3F) +//#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1f) // pre-Vista full access #endif #define GDI_HANDLE_BUFFER_SIZE32 34 @@ -224,6 +225,15 @@ typedef enum _PROCESSINFOCLASS ProcessAltSystemCallInformation, // qs: BOOLEAN (kernel-mode only) // INT2E // since 20H1 // 100 ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION ProcessDynamicEnforcedCetCompatibleRanges, // PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2 + ProcessCreateStateChange, // since WIN11 + ProcessApplyStateChange, + ProcessEnableOptionalXStateFeatures, + ProcessAltPrefetchParam, // since 22H1 + ProcessAssignCpuPartitions, + ProcessPriorityClassEx, + ProcessMembershipInformation, + ProcessEffectiveIoPriority, + ProcessEffectivePagePriority, MaxProcessInfoClass } PROCESSINFOCLASS; #endif @@ -282,6 +292,11 @@ typedef enum _THREADINFOCLASS ThreadManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 ThreadPowerThrottlingState, // POWER_THROTTLING_THREAD_STATE ThreadWorkloadClass, // THREAD_WORKLOAD_CLASS // since REDSTONE5 // 50 + ThreadCreateStateChange, // since WIN11 + ThreadApplyStateChange, + ThreadStrongerBadHandleChecks, // since 22H1 + ThreadEffectiveIoPriority, + ThreadEffectivePagePriority, MaxThreadInfoClass } THREADINFOCLASS; #endif @@ -657,24 +672,19 @@ typedef struct _PROCESS_HANDLE_SNAPSHOT_INFORMATION #if (PHNT_MODE != PHNT_MODE_KERNEL) -typedef struct _PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY_ { +#if !defined(NTDDI_WIN10_CO) || (NTDDI_VERSION < NTDDI_WIN10_CO) +typedef struct _PROCESS_MITIGATION_REDIRECTION_TRUST_POLICY +{ union { - DWORD Flags; + ULONG Flags; struct { - DWORD EnableUserShadowStack : 1; - DWORD AuditUserShadowStack : 1; - DWORD SetContextIpValidation : 1; - DWORD AuditSetContextIpValidation : 1; - DWORD EnableUserShadowStackStrictMode : 1; - DWORD BlockNonCetBinaries : 1; - DWORD BlockNonCetBinariesNonEhcont : 1; - DWORD AuditBlockNonCetBinaries : 1; - DWORD CetDynamicApisOutOfProcOnly : 1; - DWORD SetContextIpValidationRelaxedMode : 1; - DWORD ReservedFlags : 22; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; -} PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY_, * PPROCESS_MITIGATION_USER_SHADOW_STACK_POLICY_; + ULONG EnforceRedirectionTrust : 1; + ULONG AuditRedirectionTrust : 1; + ULONG ReservedFlags : 30; + }; + }; +} PROCESS_MITIGATION_REDIRECTION_TRUST_POLICY, * PPROCESS_MITIGATION_REDIRECTION_TRUST_POLICY; +#endif // private typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION @@ -695,7 +705,8 @@ typedef struct _PROCESS_MITIGATION_POLICY_INFORMATION PROCESS_MITIGATION_PAYLOAD_RESTRICTION_POLICY PayloadRestrictionPolicy; PROCESS_MITIGATION_CHILD_PROCESS_POLICY ChildProcessPolicy; PROCESS_MITIGATION_SIDE_CHANNEL_ISOLATION_POLICY SideChannelIsolationPolicy; - PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY_ UserShadowStackPolicy; + PROCESS_MITIGATION_USER_SHADOW_STACK_POLICY UserShadowStackPolicy; + PROCESS_MITIGATION_REDIRECTION_TRUST_POLICY RedirectionTrustPolicy; }; } PROCESS_MITIGATION_POLICY_INFORMATION, *PPROCESS_MITIGATION_POLICY_INFORMATION; @@ -948,7 +959,7 @@ typedef struct _PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION } PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION, *PPROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION; // private -typedef struct _PROCESS_LOGGING_INFORMATION +typedef union _PROCESS_LOGGING_INFORMATION { ULONG Flags; struct @@ -1201,14 +1212,25 @@ NtCreateProcess( _In_ BOOLEAN InheritObjectTable, _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort + _In_opt_ HANDLE TokenHandle ); -#define PROCESS_CREATE_FLAGS_BREAKAWAY 0x00000001 -#define PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT 0x00000002 -#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES 0x00000004 -#define PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE 0x00000008 -#define PROCESS_CREATE_FLAGS_LARGE_PAGES 0x00000010 +// begin_rev +#define PROCESS_CREATE_FLAGS_BREAKAWAY 0x00000001 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT 0x00000002 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES 0x00000004 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE 0x00000008 // NtCreateProcessEx only +#define PROCESS_CREATE_FLAGS_LARGE_PAGES 0x00000010 // NtCreateProcessEx only, requires SeLockMemory +#define PROCESS_CREATE_FLAGS_LARGE_PAGE_SYSTEM_DLL 0x00000020 // NtCreateProcessEx only, requires SeLockMemory +#define PROCESS_CREATE_FLAGS_PROTECTED_PROCESS 0x00000040 // NtCreateUserProcess only +#define PROCESS_CREATE_FLAGS_CREATE_SESSION 0x00000080 // NtCreateProcessEx & NtCreateUserProcess, requires SeLoadDriver +#define PROCESS_CREATE_FLAGS_INHERIT_FROM_PARENT 0x00000100 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_SUSPENDED 0x00000200 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_FORCE_BREAKAWAY 0x00000400 // NtCreateProcessEx & NtCreateUserProcess, requires SeTcb +#define PROCESS_CREATE_FLAGS_MINIMAL_PROCESS 0x00000800 // NtCreateProcessEx only +#define PROCESS_CREATE_FLAGS_RELEASE_SECTION 0x00001000 // NtCreateProcessEx & NtCreateUserProcess +#define PROCESS_CREATE_FLAGS_AUXILIARY_PROCESS 0x00008000 // NtCreateProcessEx & NtCreateUserProcess, requires SeTcb +// end_rev NTSYSCALLAPI NTSTATUS @@ -1218,11 +1240,11 @@ NtCreateProcessEx( _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ HANDLE ParentProcess, - _In_ ULONG Flags, + _In_ ULONG Flags, // PROCESS_CREATE_FLAGS_* _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort, - _In_ ULONG JobMemberLevel + _In_opt_ HANDLE TokenHandle, + _Reserved_ ULONG Reserved // JobMemberLevel ); NTSYSCALLAPI @@ -1309,7 +1331,7 @@ NTSTATUS NTAPI NtGetNextThread( _In_ HANDLE ProcessHandle, - _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Flags, @@ -1327,11 +1349,74 @@ NtSetInformationProcess( _In_ ULONG ProcessInformationLength ); +#endif + +#define STATECHANGE_SET_ATTRIBUTES 0x0001 + +typedef enum _PROCESS_STATE_CHANGE_TYPE +{ + ProcessStateChangeSuspend, + ProcessStateChangeResume, + ProcessStateChangeMax, +} PROCESS_STATE_CHANGE_TYPE, *PPROCESS_STATE_CHANGE_TYPE; + +#if (PHNT_VERSION >= PHNT_WIN11) + NTSYSCALLAPI NTSTATUS NTAPI -NtQueryPortInformationProcess( - VOID +NtCreateProcessStateChange( + _Out_ PHANDLE ProcessStateChangeHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ProcessHandle, + _In_opt_ ULONG64 Reserved + ); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtChangeProcessState( + _In_ HANDLE ProcessStateChangeHandle, + _In_ HANDLE ProcessHandle, + _In_ PROCESS_STATE_CHANGE_TYPE StateChangeType, + _In_opt_ PVOID ExtendedInformation, + _In_opt_ SIZE_T ExtendedInformationLength, + _In_opt_ ULONG64 Reserved + ); + +#endif + +typedef enum _THREAD_STATE_CHANGE_TYPE +{ + ThreadStateChangeSuspend, + ThreadStateChangeResume, + ThreadStateChangeMax, +} THREAD_STATE_CHANGE_TYPE, *PTHREAD_STATE_CHANGE_TYPE; + +#if (PHNT_VERSION >= PHNT_WIN11) + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtCreateThreadStateChange( + _Out_ PHANDLE ThreadStateChangeHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ThreadHandle, + _In_opt_ ULONG64 Reserved + ); + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtChangeThreadState( + _In_ HANDLE ThreadStateChangeHandle, + _In_ HANDLE ThreadHandle, + _In_ THREAD_STATE_CHANGE_TYPE StateChangeType, + _In_opt_ PVOID ExtendedInformation, + _In_opt_ SIZE_T ExtendedInformationLength, + _In_opt_ ULONG64 Reserved ); #endif @@ -1525,6 +1610,31 @@ NtQueueApcThreadEx( ); #endif +#if (PHNT_VERSION >= PHNT_WIN11) + +#if !defined(NTDDI_WIN10_CO) || (NTDDI_VERSION < NTDDI_WIN10_CO) +typedef enum _QUEUE_USER_APC_FLAGS +{ + QUEUE_USER_APC_FLAGS_NONE = 0x0, + QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC = 0x1, +} QUEUE_USER_APC_FLAGS; +#endif + +NTSYSCALLAPI +NTSTATUS +NTAPI +NtQueueApcThreadEx2( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ReserveHandle, // NtAllocateReserveObject + _In_ QUEUE_USER_APC_FLAGS ApcFlags, + _In_ PPS_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcArgument1, + _In_opt_ PVOID ApcArgument2, + _In_opt_ PVOID ApcArgument3 + ); + +#endif + #if (PHNT_VERSION >= PHNT_WIN8) // rev @@ -1560,6 +1670,68 @@ NtWaitForAlertByThreadId( #define PS_ATTRIBUTE_INPUT 0x00020000 // input only #define PS_ATTRIBUTE_ADDITIVE 0x00040000 // "accumulated" e.g. bitmasks, counters, etc. +// PROC_THREAD_ATTRIBUTE_NUM (Win32 CreateProcess) (dmex) +#define ProcThreadAttributeParentProcess 0 // in HANDLE +#define ProcThreadAttributeExtendedFlags 1 // in ULONG (PROC_EXTENDED_FLAG) +#define ProcThreadAttributeHandleList 2 // in HANDLE[] +#define ProcThreadAttributeGroupAffinity 3 // in GROUP_AFFINITY // since WIN7 +#define ProcThreadAttributePreferredNode 4 // in USHORT +#define ProcThreadAttributeIdealProcessor 5// in PROCESSOR_NUMBER +#define ProcThreadAttributeUmsThread 6 // in UMS_CREATE_THREAD_ATTRIBUTES +#define ProcThreadAttributeMitigationPolicy 7 // in ULONG[] or ULONG64[] +#define ProcThreadAttributePackageName 8 // in WCHAR[] // since WIN8 +#define ProcThreadAttributeSecurityCapabilities 9 // in SECURITY_CAPABILITIES +#define ProcThreadAttributeConsoleReference 10 // BaseGetConsoleReference (kernelbase.dll) +#define ProcThreadAttributeProtectionLevel 11 // in ULONG +#define ProcThreadAttributeJobList 13 // in HANDLE[] // since WIN10 +#define ProcThreadAttributeChildProcessPolicy 14 // in ULONG +#define ProcThreadAttributeAllApplicationPackagesPolicy 15 // in ULONG +#define ProcThreadAttributeWin32kFilter 16 // in PROC_THREAD_WIN32KFILTER_ATTRIBUTE +#define ProcThreadAttributeSafeOpenPromptOriginClaim 17 // since RS1 +#define ProcThreadAttributeDesktopAppPolicy 18 // in ULONG // since RS2 +#define ProcThreadAttributeBnoIsolation 19 // in PROC_THREAD_BNOISOLATION_ATTRIBUTE +#define ProcThreadAttributePseudoConsole 22 // in HANDLE (HPCON) // since RS5 +#define ProcThreadAttributeMitigationAuditPolicy 24 // in ULONG[] or ULONG64[] // since 20H1 +#define ProcThreadAttributeMachineType 25 // in ULONG +#define ProcThreadAttributeComponentFilter 26 // in ULONG +#define ProcThreadAttributeEnableOptionalXStateFeatures 27 // in ULONG // since 20H2 + +#define PROC_EXTENDED_FLAG_LOG_ELEVATION_FAILURE 0x1 +#define PROC_EXTENDED_FLAG_IGNORE_ELEVATION 0x2 +#define PROC_EXTENDED_FLAG_FORCE_JOB_BREAKAWAY 0x4 // (requires SeTcbPrivilege) + +#define WIN32KFILTER_FLAG_ENABLE 0x1 +#define WIN32KFILTER_FLAG_AUDIT 0x2 + +typedef struct _PROC_THREAD_WIN32KFILTER_ATTRIBUTE +{ + ULONG Flags; + ULONG FilterLevel; +} PROC_THREAD_WIN32KFILTER_ATTRIBUTE, *PPROC_THREAD_WIN32KFILTER_ATTRIBUTE; + +typedef struct _PROC_THREAD_BNOISOLATION_ATTRIBUTE +{ + BOOL IsolationEnabled; + WCHAR IsolationPrefix[0x88]; +} PROC_THREAD_BNOISOLATION_ATTRIBUTE, *PPROC_THREAD_BNOISOLATION_ATTRIBUTE; + +#ifndef PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS +#define PROC_THREAD_ATTRIBUTE_EXTENDED_FLAGS \ + ProcThreadAttributeValue(ProcThreadAttributeExtendedFlags, FALSE, TRUE, TRUE) +#endif +#ifndef PROC_THREAD_ATTRIBUTE_CONSOLE_REFERENCE +#define PROC_THREAD_ATTRIBUTE_CONSOLE_REFERENCE \ + ProcThreadAttributeValue(ProcThreadAttributeConsoleReference, FALSE, TRUE, FALSE) +#endif +#ifndef PROC_THREAD_ATTRIBUTE_SAFE_OPEN_PROMPT_ORIGIN_CLAIM +#define PROC_THREAD_ATTRIBUTE_SAFE_OPEN_PROMPT_ORIGIN_CLAIM \ + ProcThreadAttributeValue(ProcThreadAttributeSafeOpenPromptOriginClaim, FALSE, TRUE, FALSE) +#endif +#ifndef PROC_THREAD_ATTRIBUTE_BNO_ISOLATION +#define PROC_THREAD_ATTRIBUTE_BNO_ISOLATION \ + ProcThreadAttributeValue(ProcThreadAttributeBnoIsolation, FALSE, TRUE, FALSE) +#endif + // private typedef enum _PS_ATTRIBUTE_NUM { @@ -1591,6 +1763,9 @@ typedef enum _PS_ATTRIBUTE_NUM PsAttributeDesktopAppPolicy, // in ULONG PsAttributeChpe, // since REDSTONE3 PsAttributeMitigationAuditOptions, // since 21H1 + PsAttributeMachineType, // since WIN11 + PsAttributeComponentFilter, + PsAttributeEnableOptionalXStateFeatures, PsAttributeMax } PS_ATTRIBUTE_NUM; @@ -1757,7 +1932,8 @@ typedef enum _PS_MITIGATION_OPTION PS_MITIGATION_OPTION_CET_USER_SHADOW_STACKS, PS_MITIGATION_OPTION_USER_CET_SET_CONTEXT_IP_VALIDATION, // since 21H1 PS_MITIGATION_OPTION_BLOCK_NON_CET_BINARIES, - PS_MITIGATION_OPTION_CET_DYNAMIC_APIS_OUT_OF_PROC_ONLY + PS_MITIGATION_OPTION_CET_DYNAMIC_APIS_OUT_OF_PROC_ONLY, + PS_MITIGATION_OPTION_REDIRECTION_TRUST, // since 22H1 } PS_MITIGATION_OPTION; // windows-internals-book:"Chapter 5" @@ -1850,21 +2026,6 @@ typedef struct _PS_CREATE_INFO // end_private -// begin_rev -#define PROCESS_CREATE_FLAGS_BREAKAWAY 0x00000001 -#define PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT 0x00000002 -#define PROCESS_CREATE_FLAGS_INHERIT_HANDLES 0x00000004 -#define PROCESS_CREATE_FLAGS_OVERRIDE_ADDRESS_SPACE 0x00000008 -#define PROCESS_CREATE_FLAGS_LARGE_PAGES 0x00000010 -#define PROCESS_CREATE_FLAGS_LARGE_PAGE_SYSTEM_DLL 0x00000020 -// Extended PROCESS_CREATE_FLAGS_* -#define PROCESS_CREATE_FLAGS_PROTECTED_PROCESS 0x00000040 -#define PROCESS_CREATE_FLAGS_CREATE_SESSION 0x00000080 // ? -#define PROCESS_CREATE_FLAGS_INHERIT_FROM_PARENT 0x00000100 -#define PROCESS_CREATE_FLAGS_SUSPENDED 0x00000200 -#define PROCESS_CREATE_FLAGS_EXTENDED_UNKNOWN 0x00000400 -// end_rev - #if (PHNT_VERSION >= PHNT_VISTA) NTSYSCALLAPI NTSTATUS @@ -1885,13 +2046,13 @@ NtCreateUserProcess( #endif // begin_rev -#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 -#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 // ? -#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 -#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010 // ? -#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020 // ? -#define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x00000040 // ? -#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080 +#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001 // NtCreateUserProcess & NtCreateThreadEx +#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002 // NtCreateThreadEx only +#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004 // NtCreateThreadEx only +#define THREAD_CREATE_FLAGS_LOADER_WORKER 0x00000010 // NtCreateThreadEx only +#define THREAD_CREATE_FLAGS_SKIP_LOADER_INIT 0x00000020 // NtCreateThreadEx only +#define THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE 0x00000040 // NtCreateThreadEx only +#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080 // ? // end_rev #if (PHNT_VERSION >= PHNT_VISTA) @@ -1968,7 +2129,9 @@ NtCreateThreadEx( #define JobObjectSiloSystemRoot 45 #define JobObjectEnergyTrackingState 46 // JOBOBJECT_ENERGY_TRACKING_STATE #define JobObjectThreadImpersonationInformation 47 -#define MaxJobObjectInfoClass 48 +#define JobObjectIoPriorityLimit 48 +#define JobObjectPagePriorityLimit 49 +#define MaxJobObjectInfoClass 50 // private typedef struct _JOBOBJECT_EXTENDED_ACCOUNTING_INFORMATION diff --git a/ProcessHacker/phnt/include/ntregapi.h b/ProcessHacker/phnt/include/ntregapi.h index e1f62230..bce73ecb 100644 --- a/ProcessHacker/phnt/include/ntregapi.h +++ b/ProcessHacker/phnt/include/ntregapi.h @@ -242,8 +242,8 @@ typedef struct _KEY_VALUE_PARTIAL_INFORMATION_ALIGN64 // private typedef struct _KEY_VALUE_LAYER_INFORMATION { - ULONG IsTombstone; - ULONG Reserved; + ULONG IsTombstone : 1; + ULONG Reserved : 31; } KEY_VALUE_LAYER_INFORMATION, *PKEY_VALUE_LAYER_INFORMATION; // rev diff --git a/ProcessHacker/phnt/include/ntrtl.h b/ProcessHacker/phnt/include/ntrtl.h index 14d880c4..429e34a4 100644 --- a/ProcessHacker/phnt/include/ntrtl.h +++ b/ProcessHacker/phnt/include/ntrtl.h @@ -1245,6 +1245,20 @@ RtlWakeAddressSingle( // Strings +FORCEINLINE +VOID +NTAPI +RtlInitEmptyAnsiString( + _Out_ PANSI_STRING AnsiString, + _Pre_maybenull_ _Pre_readable_size_(MaximumLength) PCHAR Buffer, + _In_ USHORT MaximumLength + ) +{ + memset(AnsiString, 0, sizeof(ANSI_STRING)); + AnsiString->MaximumLength = MaximumLength; + AnsiString->Buffer = Buffer; +} + #ifndef PHNT_NO_INLINE_INIT_STRING FORCEINLINE VOID RtlInitString( _Out_ PSTRING DestinationString, @@ -1252,7 +1266,7 @@ FORCEINLINE VOID RtlInitString( ) { if (SourceString) - DestinationString->MaximumLength = (DestinationString->Length = (USHORT)strlen(SourceString)) + 1; + DestinationString->MaximumLength = (DestinationString->Length = (USHORT)strlen(SourceString)) + sizeof(ANSI_NULL); else DestinationString->MaximumLength = DestinationString->Length = 0; @@ -1285,7 +1299,7 @@ FORCEINLINE VOID RtlInitAnsiString( ) { if (SourceString) - DestinationString->MaximumLength = (DestinationString->Length = (USHORT)strlen(SourceString)) + 1; + DestinationString->MaximumLength = (DestinationString->Length = (USHORT)strlen(SourceString)) + sizeof(ANSI_NULL); else DestinationString->MaximumLength = DestinationString->Length = 0; @@ -1433,13 +1447,13 @@ VOID NTAPI RtlInitEmptyUnicodeString( _Out_ PUNICODE_STRING DestinationString, - _In_opt_ PWCHAR Buffer, + _Writable_bytes_(MaximumLength) _When_(MaximumLength != 0, _Notnull_) PWCHAR Buffer, _In_ USHORT MaximumLength ) { - DestinationString->Buffer = Buffer; + memset(DestinationString, 0, sizeof(UNICODE_STRING)); DestinationString->MaximumLength = MaximumLength; - DestinationString->Length = 0; + DestinationString->Buffer = Buffer; } #ifndef PHNT_NO_INLINE_INIT_STRING @@ -2843,7 +2857,7 @@ NTSTATUS NTAPI RtlCreateProcessReflection( _In_ HANDLE ProcessHandle, - _In_ ULONG Flags, + _In_ ULONG Flags, // RTL_CLONE_PROCESS_FLAGS _In_opt_ PVOID StartRoutine, _In_opt_ PVOID StartContext, _In_opt_ HANDLE EventHandle, @@ -3979,6 +3993,7 @@ typedef struct _RTL_HEAP_INFORMATION ULONG Reserved[5]; PRTL_HEAP_TAG Tags; PRTL_HEAP_ENTRY Entries; + ULONG64 HeapTag; // Windows 11 > 22000 } RTL_HEAP_INFORMATION, *PRTL_HEAP_INFORMATION; #define RTL_HEAP_SIGNATURE 0xFFEEFFEEUL @@ -4612,7 +4627,7 @@ NTSYSAPI LOGICAL NTAPI RtlSetCurrentTransaction( - _In_ HANDLE TransactionHandle + _In_opt_ HANDLE TransactionHandle ); #endif @@ -4796,7 +4811,7 @@ RtlDeCommitDebugInfo( #define RTL_QUERY_PROCESS_MODULES32 0x00000040 #define RTL_QUERY_PROCESS_VERIFIER_OPTIONS 0x00000080 // rev #define RTL_QUERY_PROCESS_MODULESEX 0x00000100 // rev -#define RTL_QUERY_PROCESS_HEAP_ENTRIES_EX 0x00000200 // ? +#define RTL_QUERY_PROCESS_HEAP_SEGMENTS 0x00000200 #define RTL_QUERY_PROCESS_CS_OWNER 0x00000400 // rev #define RTL_QUERY_PROCESS_NONINVASIVE 0x80000000 @@ -6405,6 +6420,29 @@ RtlSelfRelativeToAbsoluteSD2( // Access masks +#ifndef PHNT_NO_INLINE_ACCESSES_GRANTED +FORCEINLINE +BOOLEAN +NTAPI +RtlAreAllAccessesGranted( + _In_ ACCESS_MASK GrantedAccess, + _In_ ACCESS_MASK DesiredAccess + ) +{ + return (~GrantedAccess & DesiredAccess) == 0; +} + +FORCEINLINE +BOOLEAN +NTAPI +RtlAreAnyAccessesGranted( + _In_ ACCESS_MASK GrantedAccess, + _In_ ACCESS_MASK DesiredAccess + ) +{ + return (GrantedAccess & DesiredAccess) != 0; +} +#else NTSYSAPI BOOLEAN NTAPI @@ -6420,6 +6458,7 @@ RtlAreAnyAccessesGranted( _In_ ACCESS_MASK GrantedAccess, _In_ ACCESS_MASK DesiredAccess ); +#endif NTSYSAPI VOID @@ -6953,10 +6992,15 @@ RtlQueryValidationRunlevel( #if (PHNT_VERSION >= PHNT_VISTA) +// rev +#define BOUNDARY_DESCRIPTOR_ADD_APPCONTAINER_SID 0x0001 + // begin_private +_Ret_maybenull_ +_Success_(return != NULL) NTSYSAPI -HANDLE +POBJECT_BOUNDARY_DESCRIPTOR NTAPI RtlCreateBoundaryDescriptor( _In_ PUNICODE_STRING Name, @@ -6967,14 +7011,14 @@ NTSYSAPI VOID NTAPI RtlDeleteBoundaryDescriptor( - _In_ HANDLE BoundaryDescriptor + _In_ _Post_invalid_ POBJECT_BOUNDARY_DESCRIPTOR BoundaryDescriptor ); NTSYSAPI NTSTATUS NTAPI RtlAddSIDToBoundaryDescriptor( - _Inout_ PHANDLE BoundaryDescriptor, + _Inout_ POBJECT_BOUNDARY_DESCRIPTOR *BoundaryDescriptor, _In_ PSID RequiredSid ); @@ -6984,7 +7028,7 @@ NTSYSAPI NTSTATUS NTAPI RtlAddIntegrityLabelToBoundaryDescriptor( - _Inout_ PHANDLE BoundaryDescriptor, + _Inout_ POBJECT_BOUNDARY_DESCRIPTOR *BoundaryDescriptor, _In_ PSID IntegrityLabel ); #endif @@ -7077,7 +7121,7 @@ NTSTATUS NTAPI RtlDeregisterWaitEx( _In_ HANDLE WaitHandle, - _In_opt_ HANDLE Event + _In_opt_ HANDLE Event // optional: RTL_WAITER_DEREGISTER_WAIT_FOR_COMPLETION ); NTSYSAPI @@ -7182,7 +7226,7 @@ NTAPI RtlDeleteTimer( _In_ HANDLE TimerQueueHandle, _In_ HANDLE TimerToCancel, - _In_opt_ HANDLE Event + _In_opt_ HANDLE Event // optional: RTL_TIMER_DELETE_WAIT_FOR_COMPLETION ); NTSYSAPI @@ -8430,7 +8474,7 @@ RtlCheckBootStatusIntegrity( _In_ HANDLE FileHandle, _Out_ PBOOLEAN Verified ); - + // rev NTSYSAPI NTSTATUS @@ -8627,7 +8671,7 @@ RtlQueryFeatureUsageNotificationSubscriptions( _Inout_ PULONG FeatureConfigurationCount ); -typedef VOID (NTAPI *PRTL_FEATURE_CONFIGURATION_CHANGE_NOTIFICAION)( +typedef VOID (NTAPI *PRTL_FEATURE_CONFIGURATION_CHANGE_NOTIFICATION)( _In_opt_ PVOID Context ); @@ -8636,7 +8680,7 @@ NTSYSAPI NTSTATUS NTAPI RtlRegisterFeatureConfigurationChangeNotification( - _In_ PRTL_FEATURE_CONFIGURATION_CHANGE_NOTIFICAION Callback, + _In_ PRTL_FEATURE_CONFIGURATION_CHANGE_NOTIFICATION Callback, _In_opt_ PVOID Context, _Inout_opt_ PULONGLONG ChangeStamp, _Out_ PHANDLE NotificationHandle diff --git a/ProcessHacker/phnt/include/ntsam.h b/ProcessHacker/phnt/include/ntsam.h index 6a9ad70e..1615ea04 100644 --- a/ProcessHacker/phnt/include/ntsam.h +++ b/ProcessHacker/phnt/include/ntsam.h @@ -208,19 +208,19 @@ SamShutdownSamServer( typedef enum _DOMAIN_INFORMATION_CLASS { - DomainPasswordInformation = 1, - DomainGeneralInformation, - DomainLogoffInformation, - DomainOemInformation, - DomainNameInformation, - DomainReplicationInformation, - DomainServerRoleInformation, - DomainModifiedInformation, - DomainStateInformation, - DomainUasInformation, - DomainGeneralInformation2, - DomainLockoutInformation, - DomainModifiedInformation2 + DomainPasswordInformation = 1, // q; s: DOMAIN_PASSWORD_INFORMATION + DomainGeneralInformation, // q: DOMAIN_GENERAL_INFORMATION + DomainLogoffInformation, // q; s: DOMAIN_LOGOFF_INFORMATION + DomainOemInformation, // q; s: DOMAIN_OEM_INFORMATION + DomainNameInformation, // q: DOMAIN_NAME_INFORMATION + DomainReplicationInformation, // q; s: DOMAIN_REPLICATION_INFORMATION + DomainServerRoleInformation, // q; s: DOMAIN_SERVER_ROLE_INFORMATION + DomainModifiedInformation, // q: DOMAIN_MODIFIED_INFORMATION + DomainStateInformation, // q; s: DOMAIN_STATE_INFORMATION + DomainUasInformation, // q; s: DOMAIN_UAS_INFORMATION + DomainGeneralInformation2, // q: DOMAIN_GENERAL_INFORMATION2 + DomainLockoutInformation, // q; s: DOMAIN_LOCKOUT_INFORMATION + DomainModifiedInformation2 // q: DOMAIN_MODIFIED_INFORMATION2 } DOMAIN_INFORMATION_CLASS; typedef enum _DOMAIN_SERVER_ENABLE_STATE @@ -351,11 +351,11 @@ typedef struct _DOMAIN_LOCKOUT_INFORMATION typedef enum _DOMAIN_DISPLAY_INFORMATION { - DomainDisplayUser = 1, - DomainDisplayMachine, - DomainDisplayGroup, - DomainDisplayOemUser, - DomainDisplayOemGroup, + DomainDisplayUser = 1, // DOMAIN_DISPLAY_USER + DomainDisplayMachine, // DOMAIN_DISPLAY_MACHINE + DomainDisplayGroup, // DOMAIN_DISPLAY_GROUP + DomainDisplayOemUser, // DOMAIN_DISPLAY_OEM_USER + DomainDisplayOemGroup, // DOMAIN_DISPLAY_OEM_GROUP DomainDisplayServer } DOMAIN_DISPLAY_INFORMATION, *PDOMAIN_DISPLAY_INFORMATION; @@ -563,10 +563,10 @@ typedef struct _GROUP_MEMBERSHIP typedef enum _GROUP_INFORMATION_CLASS { - GroupGeneralInformation = 1, - GroupNameInformation, - GroupAttributeInformation, - GroupAdminCommentInformation, + GroupGeneralInformation = 1, // q: GROUP_GENERAL_INFORMATION + GroupNameInformation, // q; s: GROUP_NAME_INFORMATION + GroupAttributeInformation, // q; s: GROUP_ATTRIBUTE_INFORMATION + GroupAdminCommentInformation, // q; s: GROUP_ADM_COMMENT_INFORMATION GroupReplicationInformation } GROUP_INFORMATION_CLASS; @@ -718,9 +718,9 @@ SamSetMemberAttributesOfGroup( typedef enum _ALIAS_INFORMATION_CLASS { - AliasGeneralInformation = 1, - AliasNameInformation, - AliasAdminCommentInformation, + AliasGeneralInformation = 1, // q: ALIAS_GENERAL_INFORMATION + AliasNameInformation, // q; s: ALIAS_NAME_INFORMATION + AliasAdminCommentInformation, // q; s: ALIAS_ADM_COMMENT_INFORMATION AliasReplicationInformation, AliasExtendedInformation, } ALIAS_INFORMATION_CLASS; @@ -1001,26 +1001,26 @@ typedef struct _SR_SECURITY_DESCRIPTOR typedef enum _USER_INFORMATION_CLASS { - UserGeneralInformation = 1, // USER_GENERAL_INFORMATION - UserPreferencesInformation, // USER_PREFERENCES_INFORMATION - UserLogonInformation, // USER_LOGON_INFORMATION - UserLogonHoursInformation, // USER_LOGON_HOURS_INFORMATION - UserAccountInformation, // USER_ACCOUNT_INFORMATION - UserNameInformation, // USER_NAME_INFORMATION - UserAccountNameInformation, // USER_ACCOUNT_NAME_INFORMATION - UserFullNameInformation, // USER_FULL_NAME_INFORMATION - UserPrimaryGroupInformation, // USER_PRIMARY_GROUP_INFORMATION - UserHomeInformation, // USER_HOME_INFORMATION // 10 - UserScriptInformation, // USER_SCRIPT_INFORMATION - UserProfileInformation, // USER_PROFILE_INFORMATION - UserAdminCommentInformation, // USER_ADMIN_COMMENT_INFORMATION - UserWorkStationsInformation, // USER_WORKSTATIONS_INFORMATION - UserSetPasswordInformation, // USER_SET_PASSWORD_INFORMATION - UserControlInformation, // USER_CONTROL_INFORMATION - UserExpiresInformation, // USER_EXPIRES_INFORMATION + UserGeneralInformation = 1, // q: USER_GENERAL_INFORMATION + UserPreferencesInformation, // q; s: USER_PREFERENCES_INFORMATION + UserLogonInformation, // q: USER_LOGON_INFORMATION + UserLogonHoursInformation, // q; s: USER_LOGON_HOURS_INFORMATION + UserAccountInformation, // q: USER_ACCOUNT_INFORMATION + UserNameInformation, // q; s: USER_NAME_INFORMATION + UserAccountNameInformation, // q; s: USER_ACCOUNT_NAME_INFORMATION + UserFullNameInformation, // q; s: USER_FULL_NAME_INFORMATION + UserPrimaryGroupInformation, // q; s: USER_PRIMARY_GROUP_INFORMATION + UserHomeInformation, // q; s: USER_HOME_INFORMATION // 10 + UserScriptInformation, // q; s: USER_SCRIPT_INFORMATION + UserProfileInformation, // q; s: USER_PROFILE_INFORMATION + UserAdminCommentInformation, // q; s: USER_ADMIN_COMMENT_INFORMATION + UserWorkStationsInformation, // q; s: USER_WORKSTATIONS_INFORMATION + UserSetPasswordInformation, // s: USER_SET_PASSWORD_INFORMATION + UserControlInformation, // q; s: USER_CONTROL_INFORMATION + UserExpiresInformation, // q; s: USER_EXPIRES_INFORMATION UserInternal1Information, // USER_INTERNAL1_INFORMATION UserInternal2Information, // USER_INTERNAL2_INFORMATION - UserParametersInformation, // USER_PARAMETERS_INFORMATION // 20 + UserParametersInformation, // q; s: USER_PARAMETERS_INFORMATION // 20 UserAllInformation, // USER_ALL_INFORMATION UserInternal3Information, // USER_INTERNAL3_INFORMATION UserInternal4Information, // USER_INTERNAL4_INFORMATION @@ -1647,7 +1647,7 @@ SamQueryDisplayInformation( _In_ ULONG Index, _In_ ULONG EntryCount, _In_ ULONG PreferredMaximumLength, - _In_ PULONG TotalAvailable, + _Out_ PULONG TotalAvailable, _Out_ PULONG TotalReturned, _Out_ PULONG ReturnedEntryCount, _Outptr_ PVOID *SortedBuffer diff --git a/ProcessHacker/phnt/include/ntseapi.h b/ProcessHacker/phnt/include/ntseapi.h index 031ce1d8..d6c0d3b1 100644 --- a/ProcessHacker/phnt/include/ntseapi.h +++ b/ProcessHacker/phnt/include/ntseapi.h @@ -113,10 +113,10 @@ typedef enum _TOKEN_INFORMATION_CLASS TokenPrivateNameSpace, // q; s: ULONG TokenSingletonAttributes, // q: TOKEN_SECURITY_ATTRIBUTES_INFORMATION TokenBnoIsolation, // q: TOKEN_BNO_ISOLATION_INFORMATION - TokenChildProcessFlags, // q; s: ULONG + TokenChildProcessFlags, // s: ULONG TokenIsLessPrivilegedAppContainer, // q: ULONG TokenIsSandboxed, // q: ULONG - TokenOriginatingProcessTrustLevel, // q: TOKEN_PROCESS_TRUST_LEVEL + TokenIsAppSilo, // TokenOriginatingProcessTrustLevel // q: TOKEN_PROCESS_TRUST_LEVEL MaxTokenInfoClass } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS; #endif diff --git a/ProcessHacker/phnt/include/ntzwapi.h b/ProcessHacker/phnt/include/ntzwapi.h index 6a017a35..3363f55b 100644 --- a/ProcessHacker/phnt/include/ntzwapi.h +++ b/ProcessHacker/phnt/include/ntzwapi.h @@ -665,6 +665,30 @@ ZwCancelWaitCompletionPacket( _In_ BOOLEAN RemoveSignaledPacket ); +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwChangeProcessState( + _In_ HANDLE ProcessStateChangeHandle, + _In_ HANDLE ProcessHandle, + _In_ PROCESS_STATE_CHANGE_TYPE StateChangeType, + _In_opt_ PVOID ExtendedInformation, + _In_opt_ SIZE_T ExtendedInformationLength, + _In_opt_ ULONG64 Reserved + ); + +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwChangeThreadState( + _In_ HANDLE ThreadStateChangeHandle, + _In_ HANDLE ThreadHandle, + _In_ THREAD_STATE_CHANGE_TYPE StateChangeType, + _In_opt_ PVOID ExtendedInformation, + _In_opt_ SIZE_T ExtendedInformationLength, + _In_opt_ ULONG64 Reserved + ); + NTSYSCALLAPI NTSTATUS NTAPI @@ -795,7 +819,7 @@ NTAPI ZwCreateDebugObject( _Out_ PHANDLE DebugObjectHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ ULONG Flags ); @@ -1031,6 +1055,7 @@ NTSYSCALLAPI NTSTATUS NTAPI ZwCreatePartition( + _In_ HANDLE ParentPartitionHandle, _Out_ PHANDLE PartitionHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, @@ -1054,8 +1079,8 @@ NTAPI ZwCreatePrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ POBJECT_BOUNDARY_DESCRIPTOR BoundaryDescriptor ); NTSYSCALLAPI @@ -1069,7 +1094,7 @@ ZwCreateProcess( _In_ BOOLEAN InheritObjectTable, _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort + _In_opt_ HANDLE TokenHandle ); NTSYSCALLAPI @@ -1080,11 +1105,22 @@ ZwCreateProcessEx( _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ HANDLE ParentProcess, - _In_ ULONG Flags, + _In_ ULONG Flags, // PROCESS_CREATE_FLAGS_* _In_opt_ HANDLE SectionHandle, _In_opt_ HANDLE DebugPort, - _In_opt_ HANDLE ExceptionPort, - _In_ ULONG JobMemberLevel + _In_opt_ HANDLE TokenHandle, + _Reserved_ ULONG Reserved // JobMemberLevel + ); + +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwCreateProcessStateChange( + _Out_ PHANDLE ProcessStateChangeHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ProcessHandle, + _In_opt_ ULONG64 Reserved ); NTSYSCALLAPI @@ -1211,6 +1247,17 @@ ZwCreateThreadEx( _In_opt_ PPS_ATTRIBUTE_LIST AttributeList ); +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwCreateThreadStateChange( + _Out_ PHANDLE ThreadStateChangeHandle, + _In_ ACCESS_MASK DesiredAccess, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_ HANDLE ThreadHandle, + _In_opt_ ULONG64 Reserved + ); + NTSYSCALLAPI NTSTATUS NTAPI @@ -1227,7 +1274,7 @@ NTAPI ZwCreateTimer2( _Out_ PHANDLE TimerHandle, _In_opt_ PVOID Reserved1, - _In_opt_ PVOID Reserved2, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ ULONG Attributes, _In_ ACCESS_MASK DesiredAccess ); @@ -1239,7 +1286,7 @@ ZwCreateToken( _Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ TOKEN_TYPE TokenType, + _In_ TOKEN_TYPE Type, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER User, @@ -1248,7 +1295,7 @@ ZwCreateToken( _In_opt_ PTOKEN_OWNER Owner, _In_ PTOKEN_PRIMARY_GROUP PrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl, - _In_ PTOKEN_SOURCE TokenSource + _In_ PTOKEN_SOURCE Source ); NTSYSCALLAPI @@ -1258,7 +1305,7 @@ ZwCreateTokenEx( _Out_ PHANDLE TokenHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ TOKEN_TYPE TokenType, + _In_ TOKEN_TYPE Type, _In_ PLUID AuthenticationId, _In_ PLARGE_INTEGER ExpirationTime, _In_ PTOKEN_USER User, @@ -1267,11 +1314,11 @@ ZwCreateTokenEx( _In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION UserAttributes, _In_opt_ PTOKEN_SECURITY_ATTRIBUTES_INFORMATION DeviceAttributes, _In_opt_ PTOKEN_GROUPS DeviceGroups, - _In_opt_ PTOKEN_MANDATORY_POLICY TokenMandatoryPolicy, + _In_opt_ PTOKEN_MANDATORY_POLICY MandatoryPolicy, _In_opt_ PTOKEN_OWNER Owner, _In_ PTOKEN_PRIMARY_GROUP PrimaryGroup, _In_opt_ PTOKEN_DEFAULT_DACL DefaultDacl, - _In_ PTOKEN_SOURCE TokenSource + _In_ PTOKEN_SOURCE Source ); NTSYSCALLAPI @@ -1525,7 +1572,7 @@ ZwDuplicateToken( _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ BOOLEAN EffectiveOnly, - _In_ TOKEN_TYPE TokenType, + _In_ TOKEN_TYPE Type, _Out_ PHANDLE NewTokenHandle ); @@ -1816,7 +1863,7 @@ NTSYSCALLAPI ULONG NTAPI ZwGetCurrentProcessorNumberEx( - _Out_opt_ PPROCESSOR_NUMBER ProcNumber + _Out_opt_ PPROCESSOR_NUMBER ProcessorNumber ); NTSYSCALLAPI @@ -1852,7 +1899,7 @@ NTSTATUS NTAPI ZwGetNextThread( _In_ HANDLE ProcessHandle, - _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _In_ ULONG Flags, @@ -2036,6 +2083,20 @@ ZwLoadKey2( _In_ ULONG Flags ); +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwLoadKey3( + _In_ POBJECT_ATTRIBUTES TargetKey, + _In_ POBJECT_ATTRIBUTES SourceFile, + _In_ ULONG Flags, + _In_reads_(LoadEntryCount) PKEY_LOAD_ENTRY LoadEntries, + _In_ ULONG LoadEntryCount, + _In_opt_ ACCESS_MASK DesiredAccess, + _Out_opt_ PHANDLE RootHandle, + _Reserved_ PVOID Reserved + ); + NTSYSCALLAPI NTSTATUS NTAPI @@ -2415,7 +2476,7 @@ ZwOpenPrivateNamespace( _Out_ PHANDLE NamespaceHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ PVOID BoundaryDescriptor + _In_ POBJECT_BOUNDARY_DESCRIPTOR BoundaryDescriptor ); NTSYSCALLAPI @@ -2540,8 +2601,8 @@ NTAPI ZwOpenTransaction( _Out_ PHANDLE TransactionHandle, _In_ ACCESS_MASK DesiredAccess, - _In_ POBJECT_ATTRIBUTES ObjectAttributes, - _In_ LPGUID Uow, + _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, + _In_opt_ LPGUID Uow, _In_opt_ HANDLE TmHandle ); @@ -3065,13 +3126,6 @@ ZwQueryPerformanceCounter( _Out_opt_ PLARGE_INTEGER PerformanceFrequency ); -NTSYSCALLAPI -NTSTATUS -NTAPI -ZwQueryPortInformationProcess( - VOID - ); - NTSYSCALLAPI NTSTATUS NTAPI @@ -3159,7 +3213,7 @@ ZwQuerySystemEnvironmentValueEx( _In_ LPGUID VendorGuid, _Out_writes_bytes_opt_(*ValueLength) PVOID Value, _Inout_ PULONG ValueLength, - _Out_opt_ PULONG Attributes + _Out_opt_ PULONG Attributes // EFI_VARIABLE_* ); NTSYSCALLAPI @@ -3292,6 +3346,27 @@ ZwQueueApcThreadEx( _In_opt_ PVOID ApcArgument3 ); +#if !defined(NTDDI_WIN10_CO) || (NTDDI_VERSION < NTDDI_WIN10_CO) +typedef enum _QUEUE_USER_APC_FLAGS +{ + QUEUE_USER_APC_FLAGS_NONE = 0x0, + QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC = 0x1, +} QUEUE_USER_APC_FLAGS; +#endif + +NTSYSCALLAPI +NTSTATUS +NTAPI +ZwQueueApcThreadEx2( + _In_ HANDLE ThreadHandle, + _In_opt_ HANDLE ReserveHandle, // NtAllocateReserveObject + _In_ QUEUE_USER_APC_FLAGS ApcFlags, + _In_ PPS_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcArgument1, + _In_opt_ PVOID ApcArgument2, + _In_opt_ PVOID ApcArgument3 + ); + NTSYSCALLAPI NTSTATUS NTAPI @@ -4075,8 +4150,8 @@ ZwSetSystemEnvironmentValueEx( _In_ PUNICODE_STRING VariableName, _In_ LPGUID VendorGuid, _In_reads_bytes_opt_(ValueLength) PVOID Value, - _In_ ULONG ValueLength, - _In_ ULONG Attributes + _In_ ULONG ValueLength, // 0 = delete variable + _In_ ULONG Attributes // EFI_VARIABLE_* ); NTSYSCALLAPI diff --git a/ProcessHacker/phnt/include/phnt.h b/ProcessHacker/phnt/include/phnt.h index d6e1acf9..d6454232 100644 --- a/ProcessHacker/phnt/include/phnt.h +++ b/ProcessHacker/phnt/include/phnt.h @@ -63,6 +63,8 @@ #define PHNT_20H1 109 #define PHNT_20H2 110 #define PHNT_21H1 111 +#define PHNT_21H2 112 +#define PHNT_WIN11 113 #ifndef PHNT_MODE #define PHNT_MODE PHNT_MODE_USER diff --git a/ProcessHacker/phnt/include/winsta.h b/ProcessHacker/phnt/include/winsta.h index 061cf50b..b74979e0 100644 --- a/ProcessHacker/phnt/include/winsta.h +++ b/ProcessHacker/phnt/include/winsta.h @@ -630,13 +630,17 @@ typedef enum _SHADOWSTATECLASS State_Shadowed // The session is being shadowed by a different session. The current session is referred to as a shadow target. } SHADOWSTATECLASS; +#define PROTOCOL_CONSOLE 0 +#define PROTOCOL_OTHERS 1 +#define PROTOCOL_RDP 2 + // Retrieves the current shadow state of a session. typedef struct _WINSTATIONSHADOW { SHADOWSTATECLASS ShadowState; // Specifies the current state of shadowing. SHADOWCLASS ShadowClass; // Specifies the type of shadowing. ULONG SessionId; // Specifies the session ID of the session. - ULONG ProtocolType; // Specifies the type of protocol on the session. Can be one of the following values. + ULONG ProtocolType; // Specifies the type of protocol on the session. Can be one of PROTOCOL_* values. } WINSTATIONSHADOW, *PWINSTATIONSHADOW; // Retrieves the client product ID and current product ID of the session. @@ -836,7 +840,7 @@ WinStationFreeMemory( HANDLE WINAPI WinStationOpenServerW( - _In_ PWSTR ServerName + _In_opt_ PWSTR ServerName ); // rev diff --git a/ProcessHacker/tools/peview/attributes.c b/ProcessHacker/tools/peview/attributes.c index e45fe30d..4df89c51 100644 --- a/ProcessHacker/tools/peview/attributes.c +++ b/ProcessHacker/tools/peview/attributes.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2018-2021 dmex + * Copyright (C) 2018-2022 dmex * * This file is part of Process Hacker. * @@ -26,7 +26,6 @@ typedef struct _PVP_PE_ATTRIBUTES_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PVP_PE_ATTRIBUTES_CONTEXT, *PPVP_PE_ATTRIBUTES_CONTEXT; @@ -138,6 +137,8 @@ INT_PTR CALLBACK PvpPeExtendedAttributesDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; + context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); @@ -153,8 +154,8 @@ INT_PTR CALLBACK PvpPeExtendedAttributesDlgProc( PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PvEnumerateFileExtendedAttributes(context->ListViewHandle); @@ -165,9 +166,6 @@ INT_PTR CALLBACK PvpPeExtendedAttributesDlgProc( { PhSaveListViewColumnsToSetting(L"ImageAttributesListViewColumns", context->ListViewHandle); - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); PhFree(context); @@ -291,6 +289,17 @@ INT_PTR CALLBACK PvpPeExtendedAttributesDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/cfgprp.c b/ProcessHacker/tools/peview/cfgprp.c index a4735238..cbbe5c0f 100644 --- a/ProcessHacker/tools/peview/cfgprp.c +++ b/ProcessHacker/tools/peview/cfgprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -52,7 +52,7 @@ VOID PvPeAddListViewCfgFunctionEntry( if (!NT_SUCCESS(PhGetMappedImageCfgEntry(CfgConfig, Index, Type, &cfgFunctionEntry))) return; - PhPrintUInt64(value, Count + 1); + PhPrintUInt64(value, Count); lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, value, NULL); PhPrintPointer(value, UlongToPtr(cfgFunctionEntry.Rva)); @@ -268,6 +268,17 @@ INT_PTR CALLBACK PvpPeCgfDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/chcol.c b/ProcessHacker/tools/peview/chcol.c new file mode 100644 index 00000000..a6fd272f --- /dev/null +++ b/ProcessHacker/tools/peview/chcol.c @@ -0,0 +1,749 @@ +/* + * Process Hacker - + * column chooser + * + * Copyright (C) 2010 wj32 + * Copyright (C) 2017-2021 dmex + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +// NOTE: Copied from processhacker\ProcessHacker\chcol.c + +#include +#include + +typedef struct _COLUMNS_DIALOG_CONTEXT +{ + HWND ControlHandle; + HFONT ControlFont; + ULONG Type; + PPH_LIST Columns; + + HBRUSH BrushNormal; + HBRUSH BrushPushed; + HBRUSH BrushHot; + COLORREF TextColor; + + HWND InactiveWindowHandle; + HWND ActiveWindowHandle; + HWND SearchInactiveHandle; + HWND SearchActiveHandle; + PPH_LIST InactiveListArray; + PPH_LIST ActiveListArray; + PPH_STRING InactiveSearchboxText; + PPH_STRING ActiveSearchboxText; +} COLUMNS_DIALOG_CONTEXT, *PCOLUMNS_DIALOG_CONTEXT; + +INT_PTR CALLBACK PvColumnsDlgProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + +VOID PvShowChooseColumnsDialog( + _In_ HWND ParentWindowHandle, + _In_ HWND ControlHandle, + _In_ ULONG Type + ) +{ + COLUMNS_DIALOG_CONTEXT context; + + memset(&context, 0, sizeof(COLUMNS_DIALOG_CONTEXT)); + context.ControlHandle = ControlHandle; + context.Type = Type; + + if (Type == PV_CONTROL_TYPE_TREE_NEW) + context.Columns = PhCreateList(TreeNew_GetColumnCount(ControlHandle)); + else + return; + + DialogBoxParam( + PhInstanceHandle, + MAKEINTRESOURCE(IDD_CHOOSECOLUMNS), + ParentWindowHandle, + PvColumnsDlgProc, + (LPARAM)&context + ); + + PhDereferenceObject(context.Columns); +} + +static int __cdecl PvColumnsCompareDisplayIndexTn( + _In_ const void* Context, + _In_ const void* elem1, + _In_ const void* elem2 + ) +{ + PPH_TREENEW_COLUMN column1 = *(PPH_TREENEW_COLUMN*)elem1; + PPH_TREENEW_COLUMN column2 = *(PPH_TREENEW_COLUMN*)elem2; + + return uintcmp(column1->DisplayIndex, column2->DisplayIndex); +} + +static int __cdecl PvInactiveColumnsCompareNameTn( + _In_ const void* Context, + _In_ const void* elem1, + _In_ const void* elem2 + ) +{ + PWSTR column1 = *(PWSTR*)elem1; + PWSTR column2 = *(PWSTR*)elem2; + + return PhCompareStringZ(column1, column2, FALSE); +} + +_Success_(return != ULONG_MAX) +static ULONG IndexOfStringInList( + _In_ PPH_LIST List, + _In_ PWSTR String + ) +{ + for (ULONG i = 0; i < List->Count; i++) + { + if (PhEqualStringZ(List->Items[i], String, FALSE)) + return i; + } + + return ULONG_MAX; +} + +static HFONT PvColumnsGetCurrentFont( + VOID + ) +{ + NONCLIENTMETRICS metrics = { sizeof(NONCLIENTMETRICS) }; + HFONT font; + + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) + font = CreateFontIndirect(&metrics.lfMessageFont); + else + font = NULL; + + return font; +} + +BOOLEAN PvColumnsWordMatchStringRef( + _In_ PPH_STRING SearchboxText, + _In_ PPH_STRINGREF Text + ) +{ + PH_STRINGREF part; + PH_STRINGREF remainingPart; + + remainingPart = SearchboxText->sr; + + while (remainingPart.Length) + { + PhSplitStringRefAtChar(&remainingPart, L'|', &part, &remainingPart); + + if (part.Length) + { + if (PhFindStringInStringRef(Text, &part, TRUE) != SIZE_MAX) + return TRUE; + } + } + + return FALSE; +} + +VOID PvColumnsResetListBox( + _In_ HWND ListBoxHandle, + _In_ PPH_STRING SearchboxText, + _In_ PPH_LIST Array, + _In_ PVOID CompareFunction + ) +{ + SendMessage(ListBoxHandle, WM_SETREDRAW, FALSE, 0); + + ListBox_ResetContent(ListBoxHandle); + + if (CompareFunction) + qsort_s(Array->Items, Array->Count, sizeof(ULONG_PTR), CompareFunction, NULL); + + if (PhIsNullOrEmptyString(SearchboxText)) + { + for (ULONG i = 0; i < Array->Count; i++) + { + ListBox_InsertString(ListBoxHandle, i, Array->Items[i]); + } + } + else + { + ULONG index = 0; + + for (ULONG i = 0; i < Array->Count; i++) + { + PH_STRINGREF text; + + PhInitializeStringRefLongHint(&text, Array->Items[i]); + + if (PvColumnsWordMatchStringRef(SearchboxText, &text)) + { + ListBox_InsertString(ListBoxHandle, index, Array->Items[i]); + index++; + } + } + } + + SendMessage(ListBoxHandle, WM_SETREDRAW, TRUE, 0); +} + +INT_PTR CALLBACK PvColumnsDlgProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + PCOLUMNS_DIALOG_CONTEXT context = NULL; + + if (uMsg == WM_INITDIALOG) + { + context = (PCOLUMNS_DIALOG_CONTEXT)lParam; + PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); + } + else + { + context = PhGetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); + } + + if (!context) + return FALSE; + + switch (uMsg) + { + case WM_INITDIALOG: + { + ULONG count; + ULONG total; + ULONG i; + PPH_LIST displayOrderList = NULL; + + PhCenterWindow(hwndDlg, GetParent(hwndDlg)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)PvImageSmallIcon); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)PvImageLargeIcon); + + context->InactiveWindowHandle = GetDlgItem(hwndDlg, IDC_INACTIVE); + context->ActiveWindowHandle = GetDlgItem(hwndDlg, IDC_ACTIVE); + context->SearchInactiveHandle = GetDlgItem(hwndDlg, IDC_SEARCH); + context->SearchActiveHandle = GetDlgItem(hwndDlg, IDC_FILTER); + context->InactiveListArray = PhCreateList(1); + context->ActiveListArray = PhCreateList(1); + context->ControlFont = PvColumnsGetCurrentFont(); + context->InactiveSearchboxText = PhReferenceEmptyString(); + context->ActiveSearchboxText = PhReferenceEmptyString(); + + PvCreateSearchControl(context->SearchInactiveHandle, L"Inactive columns..."); + PvCreateSearchControl(context->SearchActiveHandle, L"Active columns..."); + + ListBox_SetItemHeight(context->InactiveWindowHandle, 0, PV_SCALE_DPI(16)); + ListBox_SetItemHeight(context->ActiveWindowHandle, 0, PV_SCALE_DPI(16)); + + Button_Enable(GetDlgItem(hwndDlg, IDC_HIDE), FALSE); + Button_Enable(GetDlgItem(hwndDlg, IDC_SHOW), FALSE); + Button_Enable(GetDlgItem(hwndDlg, IDC_MOVEUP), FALSE); + Button_Enable(GetDlgItem(hwndDlg, IDC_MOVEDOWN), FALSE); + + if (PhGetIntegerSetting(L"EnableThemeSupport")) + { + context->BrushNormal = CreateSolidBrush(RGB(43, 43, 43)); + context->BrushHot = CreateSolidBrush(RGB(128, 128, 128)); + context->BrushPushed = CreateSolidBrush(RGB(153, 209, 255)); + context->TextColor = RGB(0xff, 0xff, 0xff); + } + else + { + context->BrushNormal = GetSysColorBrush(COLOR_WINDOW); + context->BrushHot = CreateSolidBrush(RGB(145, 201, 247)); + context->BrushPushed = CreateSolidBrush(RGB(153, 209, 255)); + context->TextColor = GetSysColor(COLOR_WINDOWTEXT); + } + + if (context->Type == PV_CONTROL_TYPE_TREE_NEW) + { + PH_TREENEW_COLUMN column; + + count = 0; + total = TreeNew_GetColumnCount(context->ControlHandle); + i = 0; + + displayOrderList = PhCreateList(total); + + while (count < total) + { + if (TreeNew_GetColumn(context->ControlHandle, i, &column)) + { + PPH_TREENEW_COLUMN copy; + + if (column.Fixed) + { + i++; + total--; + continue; + } + + copy = PhAllocateCopy(&column, sizeof(PH_TREENEW_COLUMN)); + PhAddItemList(context->Columns, copy); + count++; + + if (column.Visible) + { + PhAddItemList(displayOrderList, copy); + } + else + { + PhAddItemList(context->InactiveListArray, column.Text); + } + } + + i++; + } + + qsort_s(displayOrderList->Items, displayOrderList->Count, sizeof(PVOID), PvColumnsCompareDisplayIndexTn, NULL); + } + + PvColumnsResetListBox( + context->InactiveWindowHandle, + NULL, + context->InactiveListArray, + PvInactiveColumnsCompareNameTn + ); + + if (displayOrderList) + { + for (i = 0; i < displayOrderList->Count; i++) + { + if (context->Type == PV_CONTROL_TYPE_TREE_NEW) + { + PPH_TREENEW_COLUMN copy = displayOrderList->Items[i]; + + PhAddItemList(context->ActiveListArray, copy->Text); + ListBox_InsertItemData(context->ActiveWindowHandle, i, copy->Text); + } + } + + PhDereferenceObject(displayOrderList); + } + + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveWindowHandle); + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveWindowHandle); + + PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); + + PhSetDialogFocus(hwndDlg, GetDlgItem(hwndDlg, IDCANCEL)); + } + break; + case WM_DESTROY: + { + for (ULONG i = 0; i < context->Columns->Count; i++) + PhFree(context->Columns->Items[i]); + + if (context->BrushHot) + DeleteBrush(context->BrushHot); + if (context->BrushPushed) + DeleteBrush(context->BrushPushed); + if (context->ControlFont) + DeleteFont(context->ControlFont); + if (context->InactiveListArray) + PhDereferenceObject(context->InactiveListArray); + if (context->ActiveListArray) + PhDereferenceObject(context->ActiveListArray); + if (context->InactiveSearchboxText) + PhDereferenceObject(context->InactiveSearchboxText); + if (context->ActiveSearchboxText) + PhDereferenceObject(context->ActiveSearchboxText); + + PhRemoveWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); + } + break; + case WM_COMMAND: + { + switch (GET_WM_COMMAND_CMD(wParam, lParam)) + { + case EN_CHANGE: + { + if (GET_WM_COMMAND_HWND(wParam, lParam) == context->SearchInactiveHandle) + { + PPH_STRING newSearchboxText = PH_AUTO(PhGetWindowText(context->SearchInactiveHandle)); + + if (!PhEqualString(context->InactiveSearchboxText, newSearchboxText, FALSE)) + { + PhSwapReference(&context->InactiveSearchboxText, newSearchboxText); + + PvColumnsResetListBox( + context->InactiveWindowHandle, context->InactiveSearchboxText, + context->InactiveListArray, PvInactiveColumnsCompareNameTn); + } + } + else if (GET_WM_COMMAND_HWND(wParam, lParam) == context->SearchActiveHandle) + { + PPH_STRING newSearchboxText = PH_AUTO(PhGetWindowText(context->SearchActiveHandle)); + + if (!PhEqualString(context->ActiveSearchboxText, newSearchboxText, FALSE)) + { + PhSwapReference(&context->ActiveSearchboxText, newSearchboxText); + + PvColumnsResetListBox( + context->ActiveWindowHandle, context->ActiveSearchboxText, + context->ActiveListArray, NULL); + } + } + } + break; + } + + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + case IDOK: + { +#define ORDER_LIMIT 200 + ULONG i; + INT orderArray[ORDER_LIMIT]; + INT maxOrder; + + memset(orderArray, 0, sizeof(orderArray)); + maxOrder = 0; + + if (context->Type == PV_CONTROL_TYPE_TREE_NEW) + { + // Apply visibility settings and build the order array. + + TreeNew_SetRedraw(context->ControlHandle, FALSE); + + for (i = 0; i < context->Columns->Count; i++) + { + PPH_TREENEW_COLUMN column = context->Columns->Items[i]; + ULONG index; + + index = IndexOfStringInList(context->ActiveListArray, column->Text); + column->Visible = index != ULONG_MAX; + + TreeNew_SetColumn(context->ControlHandle, TN_COLUMN_FLAG_VISIBLE, column); + + if (column->Visible && index < ORDER_LIMIT) + { + orderArray[index] = column->Id; + + if ((ULONG)maxOrder < index + 1) + maxOrder = index + 1; + } + } + + // Apply display order. + TreeNew_SetColumnOrderArray(context->ControlHandle, maxOrder, orderArray); + + TreeNew_SetRedraw(context->ControlHandle, TRUE); + + InvalidateRect(context->ControlHandle, NULL, FALSE); + } + + EndDialog(hwndDlg, IDOK); + } + break; + case IDC_INACTIVE: + { + switch (HIWORD(wParam)) + { + case LBN_DBLCLK: + { + SendMessage(hwndDlg, WM_COMMAND, IDC_SHOW, 0); + } + break; + case LBN_SELCHANGE: + { + INT sel = ListBox_GetCurSel(context->InactiveWindowHandle); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW), sel != LB_ERR); + } + break; + } + } + break; + case IDC_ACTIVE: + { + switch (HIWORD(wParam)) + { + case LBN_DBLCLK: + { + SendMessage(hwndDlg, WM_COMMAND, IDC_HIDE, 0); + } + break; + case LBN_SELCHANGE: + { + INT sel = ListBox_GetCurSel(context->ActiveWindowHandle); + INT count = ListBox_GetCount(context->ActiveWindowHandle); + + if (sel != LB_ERR) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_HIDE), sel != 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); + } + } + break; + } + } + break; + case IDC_SHOW: + { + INT sel; + INT count; + PWSTR string; + + sel = ListBox_GetCurSel(context->InactiveWindowHandle); + count = ListBox_GetCount(context->InactiveWindowHandle); + + if (sel != LB_ERR) + { + if (string = (PWSTR)ListBox_GetItemData(context->InactiveWindowHandle, sel)) + { + ULONG index = IndexOfStringInList(context->InactiveListArray, string); + + if (index != ULONG_MAX) + { + PVOID item = context->InactiveListArray->Items[index]; + + PhRemoveItemsList(context->InactiveListArray, index, 1); + PhAddItemList(context->ActiveListArray, item); + + ListBox_DeleteString(context->InactiveWindowHandle, sel); + ListBox_AddItemData(context->ActiveWindowHandle, item); + } + + count--; + + if (sel >= count - 1) + sel = count - 1; + + if (sel != LB_ERR) + { + ListBox_SetCurSel(context->InactiveWindowHandle, sel); + } + } + } + + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveWindowHandle); + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveWindowHandle); + } + break; + case IDC_HIDE: + { + INT sel; + INT count; + PWSTR string; + + sel = ListBox_GetCurSel(context->ActiveWindowHandle); + count = ListBox_GetCount(context->ActiveWindowHandle); + + if (sel != LB_ERR) + { + if (string = (PWSTR)ListBox_GetItemData(context->ActiveWindowHandle, sel)) + { + ULONG index = IndexOfStringInList(context->ActiveListArray, string); + + if (index != ULONG_MAX) + { + PVOID item = context->ActiveListArray->Items[index]; + + // Remove from active array, insert into inactive + PhRemoveItemsList(context->ActiveListArray, index, 1); + PhAddItemList(context->InactiveListArray, item); + + // Sort inactive list with new entry + qsort_s(context->InactiveListArray->Items, context->InactiveListArray->Count, sizeof(ULONG_PTR), PvInactiveColumnsCompareNameTn, NULL); + // Find index of new entry in inactive list + ULONG lb_index = IndexOfStringInList(context->InactiveListArray, item); + + // Delete from active list + ListBox_DeleteString(context->ActiveWindowHandle, sel); + // Add to list in the same position as the inactive list + ListBox_InsertString(context->InactiveWindowHandle, lb_index, item); + + PvColumnsResetListBox(context->InactiveWindowHandle, context->InactiveSearchboxText, context->InactiveListArray, PvInactiveColumnsCompareNameTn); + } + + count--; + + if (sel >= count - 1) + sel = count - 1; + + if (sel != LB_ERR) + { + ListBox_SetCurSel(context->ActiveWindowHandle, sel); + } + } + } + + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveWindowHandle); + SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveWindowHandle); + } + break; + case IDC_MOVEUP: + { + INT sel; + INT count; + PWSTR string; + + sel = ListBox_GetCurSel(context->ActiveWindowHandle); + count = ListBox_GetCount(context->ActiveWindowHandle); + + if (sel != LB_ERR) + { + if (string = (PWSTR)ListBox_GetItemData(context->ActiveWindowHandle, sel)) + { + ULONG index = IndexOfStringInList(context->ActiveListArray, string); + + if (index != ULONG_MAX) + { + PVOID item = context->ActiveListArray->Items[index]; + PhRemoveItemsList(context->ActiveListArray, index, 1); + PhInsertItemList(context->ActiveListArray, index - 1, item); + + ListBox_DeleteString(context->ActiveWindowHandle, sel); + sel -= 1; + ListBox_InsertItemData(context->ActiveWindowHandle, sel, item); + ListBox_SetCurSel(context->ActiveWindowHandle, sel); + + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); + } + } + } + } + break; + case IDC_MOVEDOWN: + { + INT sel; + INT count; + PWSTR string; + + sel = ListBox_GetCurSel(context->ActiveWindowHandle); + count = ListBox_GetCount(context->ActiveWindowHandle); + + if (sel != LB_ERR && sel != count - 1) + { + if (string = (PWSTR)ListBox_GetItemData(context->ActiveWindowHandle, sel)) + { + ULONG index = IndexOfStringInList(context->ActiveListArray, string); + + if (index != ULONG_MAX) + { + PVOID item = context->ActiveListArray->Items[index]; + PhRemoveItemsList(context->ActiveListArray, index, 1); + PhInsertItemList(context->ActiveListArray, index + 1, item); + + ListBox_DeleteString(context->ActiveWindowHandle, sel); + sel += 1; + ListBox_InsertItemData(context->ActiveWindowHandle, sel, item); + ListBox_SetCurSel(context->ActiveWindowHandle, sel); + + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); + EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); + } + } + } + } + break; + } + } + break; + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT drawInfo = (LPDRAWITEMSTRUCT)lParam; + + if ( + drawInfo->hwndItem == context->InactiveWindowHandle || + drawInfo->hwndItem == context->ActiveWindowHandle + ) + { + HDC bufferDc; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; + PWSTR string; + RECT bufferRect = + { + 0, 0, + drawInfo->rcItem.right - drawInfo->rcItem.left, + drawInfo->rcItem.bottom - drawInfo->rcItem.top + }; + BOOLEAN isSelected = (drawInfo->itemState & ODS_SELECTED) == ODS_SELECTED; + BOOLEAN isFocused = (drawInfo->itemState & ODS_FOCUS) == ODS_FOCUS; + + if (drawInfo->itemID == LB_ERR) + break; + + if (!(string = (PWSTR)ListBox_GetItemData(drawInfo->hwndItem, drawInfo->itemID))) + break; + + bufferDc = CreateCompatibleDC(drawInfo->hDC); + bufferBitmap = CreateCompatibleBitmap(drawInfo->hDC, bufferRect.right, bufferRect.bottom); + + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + SelectFont(bufferDc, context->ControlFont); + SetBkMode(bufferDc, TRANSPARENT); + + if (isSelected || isFocused) + { + FillRect(bufferDc, &bufferRect, context->BrushHot); + //FrameRect(bufferDc, &bufferRect, GetStockBrush(BLACK_BRUSH)); + SetTextColor(bufferDc, context->TextColor); + } + else + { + FillRect(bufferDc, &bufferRect, context->BrushNormal); + //FrameRect(bufferDc, &bufferRect, GetSysColorBrush(COLOR_HIGHLIGHTTEXT)); + SetTextColor(bufferDc, context->TextColor); + } + + bufferRect.left += 5; + DrawText( + bufferDc, + string, + -1, + &bufferRect, + DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP + ); + bufferRect.left -= 5; + + BitBlt( + drawInfo->hDC, + drawInfo->rcItem.left, + drawInfo->rcItem.top, + drawInfo->rcItem.right, + drawInfo->rcItem.bottom, + bufferDc, + 0, + 0, + SRCCOPY + ); + + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + + return TRUE; + } + } + break; + } + + return FALSE; +} diff --git a/ProcessHacker/tools/peview/clrprp.c b/ProcessHacker/tools/peview/clrprp.c index b7e35cc4..7e53fd30 100644 --- a/ProcessHacker/tools/peview/clrprp.c +++ b/ProcessHacker/tools/peview/clrprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -22,13 +22,12 @@ */ #include -#include "metahost.h" +#include typedef struct _PVP_PE_CLR_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; PVOID PdbMetadataAddress; @@ -303,7 +302,7 @@ VOID PvpGetClrStrongNameToken( { PPH_STRING clrStrongNameString = NULL; ICLRMetaHost* clrMetaHost = NULL; - ICLRRuntimeInfo* clrRuntimInfo = NULL; + ICLRRuntimeInfo* clrRuntimeInfo = NULL; ICLRStrongName* clrStrongName = NULL; CLRCreateInstanceFnPtr CLRCreateInstance_I = NULL; PVOID mscoreeHandle = NULL; @@ -314,7 +313,7 @@ VOID PvpGetClrStrongNameToken( ULONG size = MAX_PATH; WCHAR version[MAX_PATH] = L""; - if (mscoreeHandle = PhLoadLibrarySafe(L"mscoree.dll")) + if (mscoreeHandle = PhLoadLibrary(L"mscoree.dll")) { if (CLRCreateInstance_I = PhGetDllBaseProcedureAddress(mscoreeHandle, "CLRCreateInstance", 0)) { @@ -351,14 +350,14 @@ VOID PvpGetClrStrongNameToken( clrMetaHost, version, &IID_ICLRRuntimeInfo, - &clrRuntimInfo + &clrRuntimeInfo ))) { goto CleanupExit; } if (!SUCCEEDED(ICLRRuntimeInfo_GetInterface( - clrRuntimInfo, + clrRuntimeInfo, &CLSID_CLRStrongName, &IID_ICLRStrongName, &clrStrongName @@ -408,8 +407,8 @@ VOID PvpGetClrStrongNameToken( ICLRStrongName_Release(clrStrongName); } - if (clrRuntimInfo) - ICLRRuntimeInfo_Release(clrRuntimInfo); + if (clrRuntimeInfo) + ICLRRuntimeInfo_Release(clrRuntimeInfo); if (clrMetaHost) ICLRMetaHost_Release(clrMetaHost); if (mscoreeHandle) @@ -449,6 +448,7 @@ INT_PTR CALLBACK PvpPeClrDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; PSTORAGESIGNATURE clrMetaData; context->WindowHandle = hwndDlg; @@ -472,8 +472,8 @@ INT_PTR CALLBACK PvpPeClrDlgProc( PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_TOKENSTRING), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); if (!context->PdbMetadataAddress) { @@ -506,12 +506,7 @@ INT_PTR CALLBACK PvpPeClrDlgProc( case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"ImageClrListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -550,6 +545,17 @@ INT_PTR CALLBACK PvpPeClrDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/clrtableimportprp.c b/ProcessHacker/tools/peview/clrtableimportprp.c new file mode 100644 index 00000000..e2b0cb90 --- /dev/null +++ b/ProcessHacker/tools/peview/clrtableimportprp.c @@ -0,0 +1,308 @@ +/* + * Process Hacker - + * PE viewer + * + * Copyright (C) 2021-2022 dmex + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +#include +#include + +typedef struct _PVP_PE_CLR_IMPORTS_CONTEXT +{ + HWND WindowHandle; + HWND ListViewHandle; + PH_LAYOUT_MANAGER LayoutManager; + PPV_PROPPAGECONTEXT PropSheetContext; +} PVP_PE_CLR_IMPORTS_CONTEXT, *PPVP_PE_CLR_IMPORTS_CONTEXT; + +EXTERN_GUID(CLSID_CorMetaDataDispenser, 0xe5cb7a31, 0x7512, 0x11d2, 0x89, 0xce, 0x0, 0x80, 0xc7, 0x92, 0xe5, 0xd8); +EXTERN_GUID(IID_IMetaDataDispenser, 0x809c652e, 0x7396, 0x11d2, 0x97, 0x71, 0x00, 0xa0, 0xc9, 0xb4, 0xd5, 0x0c); + +_Success_(return) +BOOLEAN PvpGetMetaDataInterface( + _Out_ PVOID* ClrCoreBaseAddress, + _Out_ PVOID* ClrMetaDataInterface + ) +{ + HRESULT (WINAPI* MetaDataGetDispenser_I)(_In_ REFCLSID rclsid, _In_ REFIID riid, _COM_Outptr_ PVOID* ppv) = NULL; + PVOID clrCoreBaseAddress = NULL; + PVOID clrMetadataInterface = NULL; + + if (!(clrCoreBaseAddress = PhLoadLibrary(L"mscoree.dll"))) + return FALSE; + + if (MetaDataGetDispenser_I = PhGetDllBaseProcedureAddress(clrCoreBaseAddress, "MetaDataGetDispenser", 0)) + { + MetaDataGetDispenser_I(&CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenser, &clrMetadataInterface); + } + + if (!clrMetadataInterface) + { + PhGetClassObjectDllBase(clrCoreBaseAddress, &CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenser, &clrMetadataInterface); + } + + if (!clrMetadataInterface) + { + CLRCreateInstanceFnPtr CLRCreateInstance_I = NULL; + ICLRMetaHost* clrMetaHost = NULL; + ICLRRuntimeInfo* clrRuntimeInfo = NULL; + + if (CLRCreateInstance_I = PhGetDllBaseProcedureAddress(clrCoreBaseAddress, "CLRCreateInstance", 0)) + { + if (SUCCEEDED(CLRCreateInstance_I( + &CLSID_CLRMetaHost, + &IID_ICLRMetaHost, + &clrMetaHost + ))) + { + ULONG size = MAX_PATH; + WCHAR version[MAX_PATH] = L""; + + if (SUCCEEDED(ICLRMetaHost_GetVersionFromFile( + clrMetaHost, + PvFileName->Buffer, + version, + &size + ))) + { + if (SUCCEEDED(ICLRMetaHost_GetRuntime( + clrMetaHost, + version, + &IID_ICLRRuntimeInfo, + &clrRuntimeInfo + ))) + { + ICLRRuntimeInfo_GetInterface( + clrRuntimeInfo, + &CLSID_CorMetaDataDispenser, + &IID_IMetaDataDispenser, + &clrMetadataInterface + ); + + ICLRRuntimeInfo_Release(clrRuntimeInfo); + } + } + + ICLRMetaHost_Release(clrMetaHost); + } + } + } + + if (clrMetadataInterface) + { + *ClrCoreBaseAddress = clrCoreBaseAddress; + *ClrMetaDataInterface = clrMetadataInterface; + return TRUE; + } + + if (clrCoreBaseAddress) + { + FreeLibrary(clrCoreBaseAddress); + } + + return FALSE; +} + +VOID PvpEnumerateClrImports( + _In_ HWND ListViewHandle + ) +{ + PVOID clrCoreBaseAddress = NULL; + PVOID clrMetadataInterface = NULL; + PPH_LIST clrImportsList = NULL; + + if (!PvpGetMetaDataInterface(&clrCoreBaseAddress, &clrMetadataInterface)) + return; + + if (SUCCEEDED(PvGetClrImageImports(clrMetadataInterface, PvFileName->Buffer, &clrImportsList))) + { + ULONG count = 0; + ULONG i; + ULONG j; + + for (i = 0; i < clrImportsList->Count; i++) + { + PPV_CLR_IMAGE_IMPORT_DLL importDll = clrImportsList->Items[i]; + + if (importDll->Functions) + { + if (importDll->ImportName) + { + PPH_STRING importDllName; + + if (importDllName = PhApiSetResolveToHost(&importDll->ImportName->sr)) + { + PhMoveReference(&importDll->ImportName, PhFormatString( + L"%s (%s)", + PhGetString(importDll->ImportName), + PhGetString(importDllName)) + ); + PhDereferenceObject(importDllName); + } + } + + for (j = 0; j < importDll->Functions->Count; j++) + { + PPV_CLR_IMAGE_IMPORT_FUNCTION importFunction = importDll->Functions->Items[j]; + INT lvItemIndex; + WCHAR value[PH_INT64_STR_LEN_1]; + + PhPrintUInt32(value, ++count); + lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, value, NULL); + + PhPrintPointer(value, importFunction->Offset); + PhSetListViewSubItem(ListViewHandle, lvItemIndex, 1, value); + PhSetListViewSubItem(ListViewHandle, lvItemIndex, 2, PhGetString(importDll->ImportName)); + PhSetListViewSubItem(ListViewHandle, lvItemIndex, 3, PhGetString(importFunction->FunctionName)); + if (importFunction->Flags) + PhSetListViewSubItem(ListViewHandle, lvItemIndex, 4, PH_AUTO_T(PH_STRING, PvClrImportFlagsToString(importFunction->Flags))->Buffer); + + PhClearReference(&importFunction->FunctionName); + PhFree(importFunction); + } + + PhDereferenceObject(importDll->Functions); + } + + PhClearReference(&importDll->ImportName); + PhFree(importDll); + } + + PhDereferenceObject(clrImportsList); + } + + if (clrCoreBaseAddress) + { + FreeLibrary(clrCoreBaseAddress); + } +} + +INT_PTR CALLBACK PvpPeClrImportsDlgProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + PPVP_PE_CLR_IMPORTS_CONTEXT context; + + if (uMsg == WM_INITDIALOG) + { + context = PhAllocateZero(sizeof(PVP_PE_CLR_IMPORTS_CONTEXT)); + PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); + + if (lParam) + { + LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; + context->PropSheetContext = (PPV_PROPPAGECONTEXT)propSheetPage->lParam; + } + } + else + { + context = PhGetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); + } + + if (!context) + return FALSE; + + switch (uMsg) + { + case WM_INITDIALOG: + { + context->WindowHandle = hwndDlg; + context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); + + PhSetListViewStyle(context->ListViewHandle, TRUE, TRUE); + PhSetControlTheme(context->ListViewHandle, L"explorer"); + PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 40, L"#"); + PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 250, L"RVA"); + PhAddListViewColumn(context->ListViewHandle, 2, 2, 2, LVCFMT_LEFT, 100, L"DLL"); + PhAddListViewColumn(context->ListViewHandle, 3, 3, 3, LVCFMT_LEFT, 250, L"Name"); + PhAddListViewColumn(context->ListViewHandle, 4, 4, 4, LVCFMT_LEFT, 80, L"Flags"); + PhSetExtendedListView(context->ListViewHandle); + PhLoadListViewColumnsFromSetting(L"ImageClrImportsListViewColumns", context->ListViewHandle); + PvConfigTreeBorders(context->ListViewHandle); + + PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); + PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); + + PvpEnumerateClrImports(context->ListViewHandle); + + PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); + } + break; + case WM_DESTROY: + { + PhSaveListViewColumnsToSetting(L"ImageClrImportsListViewColumns", context->ListViewHandle); + + PhDeleteLayoutManager(&context->LayoutManager); + + PhFree(context); + } + break; + case WM_SHOWWINDOW: + { + if (context->PropSheetContext && !context->PropSheetContext->LayoutInitialized) + { + PvAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); + PvDoPropPageLayout(hwndDlg); + + context->PropSheetContext->LayoutInitialized = TRUE; + } + } + break; + case WM_SIZE: + { + PhLayoutManagerLayout(&context->LayoutManager); + } + break; + case WM_NOTIFY: + { + LPNMHDR header = (LPNMHDR)lParam; + + switch (header->code) + { + case PSN_QUERYINITIALFOCUS: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)context->ListViewHandle); + return TRUE; + } + + PvHandleListViewNotifyForCopy(lParam, context->ListViewHandle); + } + break; + case WM_CONTEXTMENU: + { + PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); + } + break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; + } + + return FALSE; +} diff --git a/ProcessHacker/tools/peview/clrtableimports.cpp b/ProcessHacker/tools/peview/clrtableimports.cpp new file mode 100644 index 00000000..1cfb0904 --- /dev/null +++ b/ProcessHacker/tools/peview/clrtableimports.cpp @@ -0,0 +1,267 @@ +/* + * Process Hacker - + * PE viewer + * + * Copyright (C) 2021 dmex + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +#include +#include +#include + +// metamodelpub.h +#define TBL_Method 6UL +#define TBL_ModuleRef 26UL +#define TBL_ImplMap 28UL +// ModuleRefRec +#define ModuleRefRec_COL_Name 0UL +// ImplMapRec +#define ImplMapRec_COL_MappingFlags 0UL +#define ImplMapRec_COL_MemberForwarded 1UL // mdField or mdMethod +#define ImplMapRec_COL_ImportName 2UL +#define ImplMapRec_COL_ImportScope 3UL // mdModuleRef + +EXTERN_C +PPH_STRING PvClrImportFlagsToString( + _In_ ULONG Flags + ) +{ + PH_STRING_BUILDER stringBuilder; + WCHAR pointer[PH_PTR_STR_LEN_1]; + + PhInitializeStringBuilder(&stringBuilder, 10); + + if (IsPmNoMangle(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"No mangle, ")); + if (IsPmCharSetAnsi(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Ansi charset, ")); + if (IsPmCharSetUnicode(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Unicode charset, ")); + if (IsPmCharSetAuto(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Auto charset, ")); + if (IsPmSupportsLastError(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Supports last error, ")); + if (IsPmCallConvWinapi(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Winapi, ")); + if (IsPmCallConvCdecl(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Cdecl, ")); + if (IsPmCallConvStdcall(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Stdcall, ")); + if (IsPmCallConvThiscall(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Thiscall, ")); + if (IsPmCallConvFastcall(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Fastcall, ")); + if (IsPmBestFitEnabled(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Bestfit enabled, ")); + if (IsPmBestFitDisabled(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Bestfit disabled, ")); + if (IsPmBestFitUseAssem(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"Bestfit assembly, ")); + if (IsPmThrowOnUnmappableCharEnabled(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"ThrowOnUnmappableChar enabled, ")); + if (IsPmThrowOnUnmappableCharDisabled(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"ThrowOnUnmappableChar disabled, ")); + if (IsPmThrowOnUnmappableCharUseAssem(Flags)) + PhAppendStringBuilder2(&stringBuilder, const_cast(L"ThrowOnUnmappableChar assembly, ")); + + if (PhEndsWithString2(stringBuilder.String, const_cast(L", "), FALSE)) + PhRemoveEndStringBuilder(&stringBuilder, 2); + + PhPrintPointer(pointer, UlongToPtr(Flags)); + PhAppendFormatStringBuilder(&stringBuilder, const_cast(L" (%s)"), pointer); + + return PhFinalStringBuilderString(&stringBuilder); +} + +// TODO: Add support for dynamic imports by enumerating the types. (dmex) +EXTERN_C HRESULT PvGetClrImageImports( + _In_ PVOID ClrMetaDataDispenser, + _In_ PWSTR FileName, + _Out_ PPH_LIST* ClrImportsList + ) +{ + IMetaDataDispenser* metaDataDispenser = reinterpret_cast(ClrMetaDataDispenser); + IMetaDataImport* metaDataImport = nullptr; + IMetaDataTables* metaDataTables = nullptr; + PPH_LIST clrImportsList = nullptr; + HRESULT status = E_FAIL; + ULONG rowModuleCount = 0; + ULONG rowModuleColumns = 0; + ULONG rowImportCount = 0; + ULONG rowImportColumns = 0; + + status = metaDataDispenser->OpenScopeOnMemory( + PvMappedImage.ViewBase, + static_cast(PvMappedImage.Size), + ofReadOnly, + IID_IMetaDataImport, + reinterpret_cast(&metaDataImport) + ); + + if (!SUCCEEDED(status)) + { + status = metaDataDispenser->OpenScope( + FileName, + ofReadOnly, + IID_IMetaDataImport, + reinterpret_cast(&metaDataImport) + ); + } + + if (!SUCCEEDED(status)) + { + metaDataDispenser->Release(); + return status; + } + + status = metaDataImport->QueryInterface( + IID_IMetaDataTables, + reinterpret_cast(&metaDataTables) + ); + + if (!SUCCEEDED(status)) + { + metaDataImport->Release(); + metaDataDispenser->Release(); + return status; + } + + clrImportsList = PhCreateList(64); + + // dummy unknown entry at index 0 + { + PPV_CLR_IMAGE_IMPORT_DLL importDll; + + importDll = static_cast(PhAllocateZero(sizeof(PV_CLR_IMAGE_IMPORT_DLL))); + importDll->ImportName = PhCreateString(const_cast(L"Unknown")); + importDll->ImportToken = ULONG_MAX; + + PhAddItemList(clrImportsList, importDll); + } + + if (SUCCEEDED(metaDataTables->GetTableInfo(TBL_ModuleRef, nullptr, &rowModuleCount, &rowModuleColumns, nullptr, nullptr))) + { + for (ULONG i = 1; i <= rowModuleCount; i++) + { + ULONG moduleNameValue = 0; + const char* moduleName = nullptr; + + if (SUCCEEDED(metaDataTables->GetColumn(TBL_ModuleRef, ModuleRefRec_COL_Name, i, &moduleNameValue))) + { + if (SUCCEEDED(metaDataTables->GetString(moduleNameValue, &moduleName))) + { + PPV_CLR_IMAGE_IMPORT_DLL importDll; + + importDll = static_cast(PhAllocateZero(sizeof(PV_CLR_IMAGE_IMPORT_DLL))); + importDll->ImportName = PhConvertUtf8ToUtf16(const_cast(moduleName)); + importDll->ImportToken = TokenFromRid(i, mdtModuleRef); + + PhAddItemList(clrImportsList, importDll); + } + } + } + } + + if (SUCCEEDED(metaDataTables->GetTableInfo(TBL_ImplMap, nullptr, &rowImportCount, &rowImportColumns, nullptr, nullptr))) + { + for (ULONG i = 1; i <= rowImportCount; i++) + { + bool found = false; + ULONG importFlagsValue = 0; + ULONG importNameValue = 0; + ULONG moduleTokenValue = 0; + PVOID importRowValue = 0; + PVOID importOffsetValue = 0; + const char* importName = nullptr; + + metaDataTables->GetColumn(TBL_ImplMap, ImplMapRec_COL_MappingFlags, i, &importFlagsValue); + + if (SUCCEEDED(metaDataTables->GetColumn(TBL_ImplMap, ImplMapRec_COL_ImportName, i, &importNameValue))) + { + metaDataTables->GetString(importNameValue, &importName); + } + + if (!SUCCEEDED(metaDataTables->GetColumn(TBL_ImplMap, ImplMapRec_COL_ImportScope, i, &moduleTokenValue))) + { + moduleTokenValue = ULONG_MAX; + } + + if (SUCCEEDED(metaDataTables->GetRow(TBL_ImplMap, i, &importRowValue))) + { + importOffsetValue = PTR_SUB_OFFSET(importRowValue, PvMappedImage.ViewBase); + } + + for (ULONG i = 0; i < clrImportsList->Count; i++) + { + PPV_CLR_IMAGE_IMPORT_DLL importDll = static_cast(clrImportsList->Items[i]); + + if (importDll->ImportToken == moduleTokenValue) + { + if (!importDll->Functions) + importDll->Functions = PhCreateList(1); + if (!importName) + importName = "Unknown"; + + if (importDll->Functions) + { + PPV_CLR_IMAGE_IMPORT_FUNCTION importFunction; + + importFunction = static_cast(PhAllocateZero(sizeof(PV_CLR_IMAGE_IMPORT_FUNCTION))); + importFunction->FunctionName = PhConvertUtf8ToUtf16(const_cast(importName)); + importFunction->Flags = importFlagsValue; + importFunction->Offset = importOffsetValue; + + PhAddItemList(importDll->Functions, importFunction); + } + + found = true; + break; + } + } + + if (!found) + { + PPV_CLR_IMAGE_IMPORT_DLL unknownImportDll = static_cast(clrImportsList->Items[0]); + + if (!unknownImportDll->Functions) + unknownImportDll->Functions = PhCreateList(1); + if (!importName) + importName = "Unknown"; + + if (unknownImportDll->Functions) + { + PPV_CLR_IMAGE_IMPORT_FUNCTION importFunction; + + importFunction = static_cast(PhAllocateZero(sizeof(PV_CLR_IMAGE_IMPORT_FUNCTION))); + importFunction->FunctionName = PhConvertUtf8ToUtf16(const_cast(importName)); + importFunction->Flags = importFlagsValue; + importFunction->Offset = importOffsetValue; + + PhAddItemList(unknownImportDll->Functions, importFunction); + } + } + } + } + + metaDataTables->Release(); + metaDataImport->Release(); + metaDataDispenser->Release(); + + *ClrImportsList = clrImportsList; + return S_OK; +} diff --git a/ProcessHacker/tools/peview/colmgr.c b/ProcessHacker/tools/peview/colmgr.c index 42b13bfe..f00ce87b 100644 --- a/ProcessHacker/tools/peview/colmgr.c +++ b/ProcessHacker/tools/peview/colmgr.c @@ -349,7 +349,7 @@ BOOLEAN PhCmLoadSettingsEx( if (!setColumn.Fixed) { - // For compatibility reasons, normal columns have their display indicies stored + // For compatibility reasons, normal columns have their display indices stored // one higher than usual (so they start from 1, not 0). Fix that here. if (hasFixedColumn && (*columnPtr)->DisplayIndex != 0) (*columnPtr)->DisplayIndex--; diff --git a/ProcessHacker/tools/peview/debugprp.c b/ProcessHacker/tools/peview/debugprp.c index d6fe83f1..7a6105b4 100644 --- a/ProcessHacker/tools/peview/debugprp.c +++ b/ProcessHacker/tools/peview/debugprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -26,7 +26,6 @@ typedef struct _PVP_PE_DEBUG_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PVP_PE_DEBUG_CONTEXT, *PPVP_PE_DEBUG_CONTEXT; @@ -115,6 +114,7 @@ INT_PTR CALLBACK PvpPeDebugDlgProc( { PH_MAPPED_IMAGE_DEBUG debug; PH_IMAGE_DEBUG_ENTRY entry; + HIMAGELIST listViewImageList; ULONG count = 0; ULONG i; INT lvItemIndex; @@ -137,8 +137,8 @@ INT_PTR CALLBACK PvpPeDebugDlgProc( PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); if (NT_SUCCESS(PhGetMappedImageDebug(&PvMappedImage, &debug))) { @@ -200,12 +200,7 @@ INT_PTR CALLBACK PvpPeDebugDlgProc( case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"ImageDebugListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -235,6 +230,17 @@ INT_PTR CALLBACK PvpPeDebugDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/ehcontprp.c b/ProcessHacker/tools/peview/ehcontprp.c index 626fcfb5..2fba1796 100644 --- a/ProcessHacker/tools/peview/ehcontprp.c +++ b/ProcessHacker/tools/peview/ehcontprp.c @@ -2,7 +2,7 @@ * PE viewer - * EH continuation support * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -216,6 +216,17 @@ INT_PTR CALLBACK PvpPeEhContDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/exlfprp.c b/ProcessHacker/tools/peview/exlfprp.c index 858be5fa..d6e2ff33 100644 --- a/ProcessHacker/tools/peview/exlfprp.c +++ b/ProcessHacker/tools/peview/exlfprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -139,7 +139,7 @@ VOID PvExlfProperties( // Imports newPage = PvCreatePropPageContext( - MAKEINTRESOURCE(IDD_PELOADCONFIG), + MAKEINTRESOURCE(IDD_ELFIMPORTS), PvpExlfImportsDlgProc, NULL ); @@ -147,7 +147,7 @@ VOID PvExlfProperties( // Exports newPage = PvCreatePropPageContext( - MAKEINTRESOURCE(IDD_PELOADCONFIG), + MAKEINTRESOURCE(IDD_ELFEXPORTS), PvpExlfExportsDlgProc, NULL ); diff --git a/ProcessHacker/tools/peview/expprp.c b/ProcessHacker/tools/peview/expprp.c index df6a4d7c..7b81114a 100644 --- a/ProcessHacker/tools/peview/expprp.c +++ b/ProcessHacker/tools/peview/expprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -61,7 +61,6 @@ typedef struct _PV_EXPORT_CONTEXT HWND SearchHandle; HWND TreeNewHandle; HWND ParentWindowHandle; - HANDLE UpdateTimerHandle; PPH_STRING SearchboxText; PPH_STRING TreeText; @@ -154,19 +153,6 @@ VOID PvAddPendingExportNodes( TreeNew_SetRedraw(Context->TreeNewHandle, TRUE); } -VOID CALLBACK PvExportTreeUpdateCallback( - _In_ PPV_EXPORT_CONTEXT Context, - _In_ BOOLEAN TimerOrWaitFired - ) -{ - if (!Context->UpdateTimerHandle) - return; - - PvAddPendingExportNodes(Context); - - RtlUpdateTimer(PhGetGlobalTimerQueue(), Context->UpdateTimerHandle, 1000, INFINITE); -} - NTSTATUS PvpPeExportsEnumerateThread( _In_ PPV_EXPORT_CONTEXT Context ) @@ -206,7 +192,7 @@ NTSTATUS PvpPeExportsEnumerateThread( { PPH_STRING forwardName; - forwardName = PhZeroExtendToUtf16(exportFunction.ForwardedName); + forwardName = PhConvertUtf8ToUtf16(exportFunction.ForwardedName); if (forwardName->Buffer[0] == L'?') { @@ -220,15 +206,18 @@ NTSTATUS PvpPeExportsEnumerateThread( } else { - PhPrintPointer(value, exportFunction.Function); - exportNode->AddressString = PhCreateString(value); + if (exportFunction.Function) + { + PhPrintPointer(value, exportFunction.Function); + exportNode->AddressString = PhCreateString(value); + } } if (exportEntry.Name) { PPH_STRING exportName; - exportName = PhZeroExtendToUtf16(exportEntry.Name); + exportName = PhConvertUtf8ToUtf16(exportEntry.Name); if (exportName->Buffer[0] == L'?') { @@ -271,11 +260,12 @@ NTSTATUS PvpPeExportsEnumerateThread( ); } - if (exportSymbolName) + if (!PhIsNullOrEmptyString(exportSymbolName)) { exportNode->NameString = PhConcatStringRefZ(&exportSymbolName->sr, L" (unnamed)"); } - + + PhClearReference(&exportSymbolName); PhClearReference(&exportSymbol); } } @@ -344,27 +334,11 @@ INT_PTR CALLBACK PvPeExportsDlgProc( PhCreateThread2(PvpPeExportsEnumerateThread, context); - RtlCreateTimer( - PhGetGlobalTimerQueue(), - &context->UpdateTimerHandle, - PvExportTreeUpdateCallback, - context, - 0, - 1000, - 0 - ); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); } break; case WM_DESTROY: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PhSaveSettingsExportList(context); PvDeleteExportTree(context); } @@ -426,12 +400,6 @@ INT_PTR CALLBACK PvPeExportsDlgProc( break; case WM_PV_SEARCH_FINISHED: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PvAddPendingExportNodes(context); TreeNew_SetEmptyText(context->TreeNewHandle, &EmptyExportsText, 0); @@ -485,6 +453,17 @@ INT_PTR CALLBACK PvPeExportsDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; @@ -771,12 +750,7 @@ BOOLEAN NTAPI PvExportTreeNewCallback( getCellText->Text = PhGetStringRef(node->AddressString); break; case PV_EXPORT_TREE_COLUMN_ITEM_NAME: - { - if (node->NameString) - getCellText->Text = PhGetStringRef(node->NameString); - else - PhInitializeStringRefLongHint(&getCellText->Text, L"(unnamed)"); - } + getCellText->Text = PhGetStringRef(node->NameString); break; case PV_EXPORT_TREE_COLUMN_ITEM_ORDINAL: getCellText->Text = PhGetStringRef(node->OrdinalString); diff --git a/ProcessHacker/tools/peview/hashprp.c b/ProcessHacker/tools/peview/hashprp.c index 28fd4deb..4b888ead 100644 --- a/ProcessHacker/tools/peview/hashprp.c +++ b/ProcessHacker/tools/peview/hashprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -28,14 +28,12 @@ typedef struct _PV_PE_HASH_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PV_PE_HASH_CONTEXT, *PPV_PE_HASH_CONTEXT; typedef struct _PVP_HASH_CONTEXT { - BCRYPT_ALG_HANDLE SignAlgHandle; BCRYPT_ALG_HANDLE HashAlgHandle; BCRYPT_KEY_HANDLE KeyHandle; BCRYPT_HASH_HANDLE HashHandle; @@ -169,9 +167,6 @@ VOID PvpDestroyHashHandle( if (Context->HashAlgHandle) BCryptCloseAlgorithmProvider(Context->HashAlgHandle, 0); - if (Context->SignAlgHandle) - BCryptCloseAlgorithmProvider(Context->SignAlgHandle, 0); - if (Context->HashHandle) BCryptDestroyHash(Context->HashHandle); @@ -954,6 +949,8 @@ INT_PTR CALLBACK PvpPeHashesDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; + context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); PhSetListViewStyle(context->ListViewHandle, TRUE, TRUE); @@ -968,8 +965,8 @@ INT_PTR CALLBACK PvpPeHashesDlgProc( PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PvpPeEnumFileHashes(context->ListViewHandle); @@ -979,12 +976,7 @@ INT_PTR CALLBACK PvpPeHashesDlgProc( case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"ImageHashesListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -1014,6 +1006,17 @@ INT_PTR CALLBACK PvpPeHashesDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/impprp.c b/ProcessHacker/tools/peview/impprp.c index 04c1dab7..7a512e08 100644 --- a/ProcessHacker/tools/peview/impprp.c +++ b/ProcessHacker/tools/peview/impprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -59,7 +59,6 @@ typedef struct _PV_IMPORT_CONTEXT HWND SearchHandle; HWND TreeNewHandle; HWND ParentWindowHandle; - HANDLE UpdateTimerHandle; PPH_STRING SearchboxText; PPH_STRING TreeText; @@ -152,19 +151,6 @@ VOID PvAddPendingImportNodes( TreeNew_SetRedraw(Context->TreeNewHandle, TRUE); } -VOID CALLBACK PvImportTreeUpdateCallback( - _In_ PPV_IMPORT_CONTEXT Context, - _In_ BOOLEAN TimerOrWaitFired - ) -{ - if (!Context->UpdateTimerHandle) - return; - - PvAddPendingImportNodes(Context); - - RtlUpdateTimer(PhGetGlobalTimerQueue(), Context->UpdateTimerHandle, 1000, INFINITE); -} - PPH_STRING PvpQueryModuleOrdinalName( _In_ PPH_STRING FileName, _In_ USHORT Ordinal @@ -193,7 +179,7 @@ PPH_STRING PvpQueryModuleOrdinalName( { if (exportEntry.Name) { - exportName = PhZeroExtendToUtf16(exportEntry.Name); + exportName = PhConvertUtf8ToUtf16(exportEntry.Name); if (exportName->Buffer[0] == L'?') { @@ -209,7 +195,7 @@ PPH_STRING PvpQueryModuleOrdinalName( { PPH_STRING forwardName; - forwardName = PhZeroExtendToUtf16(exportFunction.ForwardedName); + forwardName = PhConvertUtf8ToUtf16(exportFunction.ForwardedName); if (forwardName->Buffer[0] == L'?') { @@ -226,23 +212,36 @@ PPH_STRING PvpQueryModuleOrdinalName( { PPH_STRING exportSymbol = NULL; PPH_STRING exportSymbolName = NULL; + PPH_STRING exportFileName; - if (PhLoadModuleSymbolProvider( - PvSymbolProvider, - FileName->Buffer, - (ULONG64)mappedImage.ViewBase, - (ULONG)mappedImage.Size - )) + if (NT_SUCCESS(PhGetProcessMappedFileName(NtCurrentProcess(), (PVOID)mappedImage.ViewBase, &exportFileName))) { - // Try find the export name using symbols. - exportSymbol = PhGetSymbolFromAddress( - PvSymbolProvider, - (ULONG64)PTR_ADD_OFFSET(mappedImage.ViewBase, exportFunction.Function), - NULL, - NULL, - &exportSymbolName, - NULL - ); + PPH_SYMBOL_PROVIDER moduleSymbolProvider = NULL; + + if (PvpLoadDbgHelp(&moduleSymbolProvider)) + { + if (PhLoadModuleSymbolProvider( + moduleSymbolProvider, + exportFileName->Buffer, + (ULONG64)mappedImage.ViewBase, + (ULONG)mappedImage.Size + )) + { + // Try find the export name using symbols. + exportSymbol = PhGetSymbolFromAddress( + moduleSymbolProvider, + (ULONG64)PTR_ADD_OFFSET(mappedImage.ViewBase, exportFunction.Function), + NULL, + NULL, + &exportSymbolName, + NULL + ); + } + + PhDereferenceObject(moduleSymbolProvider); + } + + PhDereferenceObject(exportFileName); } if (exportSymbolName) @@ -300,16 +299,34 @@ VOID PvpProcessImports( importNode->HintString = PhFormatUInt64(importEntry.NameHint, FALSE); } + if (importNode->DllString = PhConvertUtf8ToUtf16(importDll.Name)) + { + PPH_STRING importDllName; + + if (importDllName = PhApiSetResolveToHost(&importNode->DllString->sr)) + { + PhMoveReference(&importNode->DllString, PhFormatString( + L"%s (%s)", + PhGetString(importNode->DllString), + PhGetString(importDllName)) + ); + PhDereferenceObject(importDllName); + } + } + if (DelayImports) - importNode->DllString = PhFormatString(L"%S (Delay)", importDll.Name); - else - importNode->DllString = PhZeroExtendToUtf16(importDll.Name); + { + PhMoveReference(&importNode->DllString, PhFormatString( + L"%s (Delay)", + PhGetString(importNode->DllString)) + ); + } if (importEntry.Name) { PPH_STRING importName; - importName = PhZeroExtendToUtf16(importEntry.Name); + importName = PhConvertUtf8ToUtf16(importEntry.Name); if (importName->Buffer[0] == L'?') { @@ -329,8 +346,13 @@ VOID PvpProcessImports( if (exportDllName = PhConvertUtf8ToUtf16(importDll.Name)) { PPH_STRING filePath; + PPH_STRING importDllName; + + if (importDllName = PhApiSetResolveToHost(&exportDllName->sr)) + { + PhMoveReference(&exportDllName, importDllName); + } - // TODO: Implement ApiSet mappings for exportDllName. (dmex) // TODO: Add DLL directory to PhSearchFilePath for locating non-system images. (dmex) if (filePath = PhSearchFilePath(exportDllName->Buffer, L".dll")) @@ -486,27 +508,11 @@ INT_PTR CALLBACK PvPeImportsDlgProc( PhCreateThread2(PvpPeImportsEnumerateThread, context); - RtlCreateTimer( - PhGetGlobalTimerQueue(), - &context->UpdateTimerHandle, - PvImportTreeUpdateCallback, - context, - 0, - 1000, - 0 - ); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); } break; case WM_DESTROY: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PhSaveSettingsImportList(context); PvDeleteImportTree(context); } @@ -568,12 +574,6 @@ INT_PTR CALLBACK PvPeImportsDlgProc( break; case WM_PV_SEARCH_FINISHED: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PvAddPendingImportNodes(context); TreeNew_SetEmptyText(context->TreeNewHandle, &EmptyImportsText, 0); @@ -627,6 +627,17 @@ INT_PTR CALLBACK PvPeImportsDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/include/prpsh.h b/ProcessHacker/tools/peview/include/prpsh.h index 796cd175..ca339c0e 100644 --- a/ProcessHacker/tools/peview/include/prpsh.h +++ b/ProcessHacker/tools/peview/include/prpsh.h @@ -20,7 +20,7 @@ * along with Process Hacker. If not, see . */ -// NOTE: Copied from processhacker2\ProcessHacker\procprp.h +// NOTE: Copied from processhacker\ProcessHacker\procprp.h #ifndef PV_PRP_H #define PV_PRP_H diff --git a/ProcessHacker/tools/peview/layout.c b/ProcessHacker/tools/peview/layout.c index e2291fa6..70ef07be 100644 --- a/ProcessHacker/tools/peview/layout.c +++ b/ProcessHacker/tools/peview/layout.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -1426,6 +1426,17 @@ INT_PTR CALLBACK PvpPeLayoutDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/ldprp.c b/ProcessHacker/tools/peview/ldprp.c index 2d1b7f57..f3d6e06b 100644 --- a/ProcessHacker/tools/peview/ldprp.c +++ b/ProcessHacker/tools/peview/ldprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -408,11 +408,28 @@ INT_PTR CALLBACK PvPeLoadConfigDlgProc( } \ } + #define ADD_VALUES2(Type, Config) \ + { \ + if (RTL_CONTAINS_FIELD((Config), (Config)->Size, GuardXFGCheckFunctionPointer)) \ + { \ + ADD_VALUE(L"XFG check-function pointer", PhaFormatString(L"0x%Ix", (Config)->GuardXFGCheckFunctionPointer)->Buffer); \ + ADD_VALUE(L"XFG dispatch-function pointer", PhaFormatString(L"0x%Ix", (Config)->GuardXFGDispatchFunctionPointer)->Buffer); \ + ADD_VALUE(L"XFG table dispatch-function pointer", PhaFormatString(L"0x%Ix", (Config)->GuardXFGTableDispatchFunctionPointer)->Buffer); \ + } \ + if (RTL_CONTAINS_FIELD((Config), (Config)->Size, CastGuardOsDeterminedFailureMode)) \ + { \ + ADD_VALUE(L"Cast guard failure mode", PhaFormatString(L"0x%Ix", (Config)->CastGuardOsDeterminedFailureMode)->Buffer); \ + } \ + } + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { if (NT_SUCCESS(PhGetMappedImageLoadConfig32(&PvMappedImage, &config32))) { ADD_VALUES(IMAGE_LOAD_CONFIG_DIRECTORY32, config32); + #if defined(NTDDI_WIN10_CO) && (NTDDI_VERSION >= NTDDI_WIN10_CO) + ADD_VALUES2(IMAGE_LOAD_CONFIG_DIRECTORY32, config32); + #endif PvpAddPeEnclaveConfig(config32, context->ListViewHandle); } } @@ -421,6 +438,9 @@ INT_PTR CALLBACK PvPeLoadConfigDlgProc( if (NT_SUCCESS(PhGetMappedImageLoadConfig64(&PvMappedImage, &config64))) { ADD_VALUES(IMAGE_LOAD_CONFIG_DIRECTORY64, config64); + #if defined(NTDDI_WIN10_CO) && (NTDDI_VERSION >= NTDDI_WIN10_CO) + ADD_VALUES2(IMAGE_LOAD_CONFIG_DIRECTORY32, config64); + #endif PvpAddPeEnclaveConfig(config64, context->ListViewHandle); } } @@ -459,6 +479,17 @@ INT_PTR CALLBACK PvPeLoadConfigDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/links.c b/ProcessHacker/tools/peview/links.c index 518a1779..826cda63 100644 --- a/ProcessHacker/tools/peview/links.c +++ b/ProcessHacker/tools/peview/links.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -26,7 +26,6 @@ typedef struct _PVP_PE_LINKS_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PVP_PE_LINKS_CONTEXT, *PPVP_PE_LINKS_CONTEXT; @@ -248,6 +247,17 @@ INT_PTR CALLBACK PvpPeLinksDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/main.c b/ProcessHacker/tools/peview/main.c index 0ecc3fa7..fae80f54 100644 --- a/ProcessHacker/tools/peview/main.c +++ b/ProcessHacker/tools/peview/main.c @@ -25,6 +25,10 @@ PPH_STRING PvFileName = NULL; +BOOLEAN PvInitializeExceptionPolicy( + VOID + ); + BOOLEAN NTAPI PvpCommandLineCallback( _In_opt_ PPH_COMMAND_LINE_OPTION Option, _In_opt_ PPH_STRING Value, @@ -52,6 +56,8 @@ INT WINAPI wWinMain( if (!NT_SUCCESS(PhInitializePhLibEx(L"PE Viewer", ULONG_MAX, hInstance, 0, 0))) return 1; + if (!PvInitializeExceptionPolicy()) + return 1; // Create a mutant for the installer. { @@ -281,3 +287,56 @@ INT WINAPI wWinMain( return 0; } + +#ifndef DEBUG +ULONG CALLBACK PvUnhandledExceptionCallback( + _In_ PEXCEPTION_POINTERS ExceptionInfo + ) +{ + PPH_STRING errorMessage; + PPH_STRING message; + + if (NT_NTWIN32(ExceptionInfo->ExceptionRecord->ExceptionCode)) + errorMessage = PhGetStatusMessage(0, WIN32_FROM_NTSTATUS(ExceptionInfo->ExceptionRecord->ExceptionCode)); + else + errorMessage = PhGetStatusMessage(ExceptionInfo->ExceptionRecord->ExceptionCode, 0); + + message = PhFormatString( + L"0x%08X (%s)", + ExceptionInfo->ExceptionRecord->ExceptionCode, + PhGetStringOrEmpty(errorMessage) + ); + + PhShowMessage( + NULL, + MB_OK | MB_ICONWARNING, + L"PE Viewer has crashed :(\r\n\r\n%s", + PhGetStringOrEmpty(message) + ); + + PhExitApplication(ExceptionInfo->ExceptionRecord->ExceptionCode); + + PhDereferenceObject(message); + PhDereferenceObject(errorMessage); + + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + +BOOLEAN PvInitializeExceptionPolicy( + VOID + ) +{ +#ifndef DEBUG + ULONG errorMode; + + if (NT_SUCCESS(PhGetProcessErrorMode(NtCurrentProcess(), &errorMode))) + { + errorMode &= ~(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + PhSetProcessErrorMode(NtCurrentProcess(), errorMode); + } + + RtlSetUnhandledExceptionFilter(PvUnhandledExceptionCallback); +#endif + return TRUE; +} diff --git a/ProcessHacker/tools/peview/options.c b/ProcessHacker/tools/peview/options.c index a8947d95..6f0cdba6 100644 --- a/ProcessHacker/tools/peview/options.c +++ b/ProcessHacker/tools/peview/options.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -35,7 +35,6 @@ typedef struct _PVP_PE_OPTIONS_CONTEXT HWND WindowHandle; HWND ListViewHandle; HWND ComboHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; } PVP_PE_OPTIONS_CONTEXT, *PPVP_PE_OPTIONS_CONTEXT; @@ -236,13 +235,14 @@ INT_PTR CALLBACK PvOptionsWndProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; HICON smallIcon; HICON largeIcon; context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_SETTINGS); context->ComboHandle = GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT); - context->ListViewImageList = PhImageListCreate(1, PV_SCALE_DPI(22), ILC_MASK | ILC_COLOR, 1, 1); + listViewImageList = PhImageListCreate(1, PV_SCALE_DPI(22), ILC_MASK | ILC_COLOR, 1, 1); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); @@ -260,7 +260,7 @@ INT_PTR CALLBACK PvOptionsWndProc( PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); ListView_SetExtendedListViewStyleEx(context->ListViewHandle, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PhSetControlTheme(context->ListViewHandle, L"explorer"); for (ULONG i = 0; i < RTL_NUMBER_OF(PhSizeUnitNames); i++) @@ -278,8 +278,7 @@ INT_PTR CALLBACK PvOptionsWndProc( break; case WM_DESTROY: { - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); + NOTHING; } break; case WM_COMMAND: @@ -370,6 +369,17 @@ INT_PTR CALLBACK PvOptionsWndProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/pdb.c b/ProcessHacker/tools/peview/pdb.c index aa5dd936..eb31ac51 100644 --- a/ProcessHacker/tools/peview/pdb.c +++ b/ProcessHacker/tools/peview/pdb.c @@ -2,7 +2,7 @@ * PE viewer - * pdb support * - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -172,32 +172,32 @@ VOID PrintVariant( _In_ PPH_STRING_BUILDER StringBuilder, _In_ VARIANT var) { - switch (var.vt) + switch (V_VT(&var)) { case VT_UI1: case VT_I1: - PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", var.bVal); + PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", V_UI1(&var)); break; case VT_I2: case VT_UI2: case VT_BOOL: - PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", var.iVal); + PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", V_I2(&var)); break; case VT_I4: case VT_UI4: case VT_INT: case VT_UINT: case VT_ERROR: - PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", var.lVal); + PhAppendFormatStringBuilder(StringBuilder, L" 0x%X", V_I4(&var)); break; case VT_R4: - PhAppendFormatStringBuilder(StringBuilder, L" %g", var.fltVal); + PhAppendFormatStringBuilder(StringBuilder, L" %g", V_R4(&var)); break; case VT_R8: - PhAppendFormatStringBuilder(StringBuilder, L" %g", var.dblVal); + PhAppendFormatStringBuilder(StringBuilder, L" %g", V_R8(&var)); break; case VT_BSTR: - PhAppendFormatStringBuilder(StringBuilder, L" \"%s\"", var.bstrVal); + PhAppendFormatStringBuilder(StringBuilder, L" \"%s\"", V_BSTR(&var)); break; default: PhAppendStringBuilder2(StringBuilder, L" ??"); @@ -1248,6 +1248,12 @@ NTSTATUS PeDumpFileSymbols( &size ); + if (!NT_SUCCESS(status)) + { + PhShowStatus(NULL, L"Unable to load the file.", status, 0); + return status; + } + if (PvpLoadDbgHelp(&PvSymbolProvider)) { if (PhLoadModuleSymbolProvider( diff --git a/ProcessHacker/tools/peview/pdbprp.c b/ProcessHacker/tools/peview/pdbprp.c index 2c4cea45..2311a742 100644 --- a/ProcessHacker/tools/peview/pdbprp.c +++ b/ProcessHacker/tools/peview/pdbprp.c @@ -2,7 +2,7 @@ * PE viewer - * pdb support * - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -187,13 +187,13 @@ END_SORT_FUNCTION BEGIN_SORT_FUNCTION(Symbol) { - sortResult = PhCompareStringWithNull(node1->Name, node2->Name, FALSE); + sortResult = PhCompareStringWithNull(node1->Name, node2->Name, TRUE); } END_SORT_FUNCTION BEGIN_SORT_FUNCTION(Data) { - sortResult = PhCompareStringWithNull(node1->Data, node2->Data, FALSE); + sortResult = PhCompareStringWithNull(node1->Data, node2->Data, TRUE); } END_SORT_FUNCTION diff --git a/ProcessHacker/tools/peview/pedirprp.c b/ProcessHacker/tools/peview/pedirprp.c index 3d4bfa98..9c3ebc52 100644 --- a/ProcessHacker/tools/peview/pedirprp.c +++ b/ProcessHacker/tools/peview/pedirprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -80,7 +80,6 @@ typedef struct _PV_DIRECTORY_CONTEXT HWND SearchHandle; HWND TreeNewHandle; HWND ParentWindowHandle; - HANDLE UpdateTimerHandle; PPH_STRING SearchboxText; PPH_STRING TreeText; @@ -173,19 +172,6 @@ VOID PvAddPendingDirectoryNodes( TreeNew_SetRedraw(Context->TreeNewHandle, TRUE); } -VOID CALLBACK PvDirectoryTreeUpdateCallback( - _In_ PPV_DIRECTORY_CONTEXT Context, - _In_ BOOLEAN TimerOrWaitFired - ) -{ - if (!Context->UpdateTimerHandle) - return; - - PvAddPendingDirectoryNodes(Context); - - RtlUpdateTimer(PhGetGlobalTimerQueue(), Context->UpdateTimerHandle, 1000, INFINITE); -} - VOID PvpPeEnumerateImageDataDirectory( _In_ PPV_DIRECTORY_CONTEXT Context, _In_ ULONG Index, @@ -449,27 +435,11 @@ INT_PTR CALLBACK PvPeDirectoryDlgProc( PhCreateThread2(PvpPeDirectoryEnumerateThread, context); - RtlCreateTimer( - PhGetGlobalTimerQueue(), - &context->UpdateTimerHandle, - PvDirectoryTreeUpdateCallback, - context, - 0, - 1000, - 0 - ); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); } break; case WM_DESTROY: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PhSaveSettingsDirectoryList(context); PvDeleteDirectoryTree(context); } @@ -531,12 +501,6 @@ INT_PTR CALLBACK PvPeDirectoryDlgProc( break; case WM_PV_SEARCH_FINISHED: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PvAddPendingDirectoryNodes(context); TreeNew_SetEmptyText(context->TreeNewHandle, &EmptyDirectoriesText, 0); @@ -590,6 +554,17 @@ INT_PTR CALLBACK PvPeDirectoryDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/peexceptprp.c b/ProcessHacker/tools/peview/peexceptprp.c index 8298b11e..2bdb126c 100644 --- a/ProcessHacker/tools/peview/peexceptprp.c +++ b/ProcessHacker/tools/peview/peexceptprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -115,14 +115,14 @@ VOID PvEnumerateExceptionEntries( { for (ULONG i = 0; i < exceptions.NumberOfEntries; i++) { - PIMAGE_RUNTIME_FUNCTION_ENTRY entry = PTR_ADD_OFFSET(exceptions.ExceptionDirectory, i * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)); + PPH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64 entry = PTR_ADD_OFFSET(exceptions.ExceptionDirectory, i * sizeof(PH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64)); INT lvItemIndex; PPH_STRING symbol; PPH_STRING symbolName = NULL; WCHAR value[PH_INT64_STR_LEN_1]; PhPrintUInt64(value, ++count); - lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, value, NULL); + lvItemIndex = PhAddListViewItem(ListViewHandle, MAXINT, value, entry); PhPrintPointer(value, UlongToPtr(entry->BeginAddress)); PhSetListViewSubItem(ListViewHandle, lvItemIndex, 1, value); @@ -175,11 +175,27 @@ VOID PvEnumerateExceptionEntries( } } } + else if (imageMachine == IMAGE_FILE_MACHINE_ARM64) + { + /* Todo */ + } //ExtendedListView_SortItems(ListViewHandle); ExtendedListView_SetRedraw(ListViewHandle, TRUE); } +INT NTAPI PvpPeExceptionSizeCompareFunctionAmd64( + _In_ PVOID Item1, + _In_ PVOID Item2, + _In_ PVOID Context + ) +{ + PPH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64 entry1 = Item1; + PPH_IMAGE_RUNTIME_FUNCTION_ENTRY_AMD64 entry2 = Item2; + + return uintptrcmp((ULONG_PTR)entry1->EndAddress - entry1->BeginAddress, (ULONG_PTR)entry2->EndAddress - entry2->BeginAddress); +} + INT_PTR CALLBACK PvpPeExceptionDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, @@ -233,7 +249,7 @@ INT_PTR CALLBACK PvpPeExceptionDlgProc( PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"SEH Handler"); PhAddListViewColumn(context->ListViewHandle, 2, 2, 2, LVCFMT_LEFT, 200, L"Symbol"); PhAddListViewColumn(context->ListViewHandle, 3, 3, 3, LVCFMT_LEFT, 100, L"Section"); - PhLoadListViewColumnsFromSetting(L"ImageExceptions32ListViewColumns", context->ListViewHandle); + PhLoadListViewColumnsFromSetting(L"ImageExceptionsIa32ListViewColumns", context->ListViewHandle); } else if (imageMachine == IMAGE_FILE_MACHINE_AMD64) { @@ -243,7 +259,13 @@ INT_PTR CALLBACK PvpPeExceptionDlgProc( PhAddListViewColumn(context->ListViewHandle, 4, 4, 4, LVCFMT_LEFT, 100, L"Size"); PhAddListViewColumn(context->ListViewHandle, 5, 5, 5, LVCFMT_LEFT, 200, L"Symbol"); PhAddListViewColumn(context->ListViewHandle, 6, 6, 6, LVCFMT_LEFT, 100, L"Section"); - PhLoadListViewColumnsFromSetting(L"ImageExceptions64ListViewColumns", context->ListViewHandle); + PhLoadListViewColumnsFromSetting(L"ImageExceptionsAmd64ListViewColumns", context->ListViewHandle); + + ExtendedListView_SetCompareFunction(context->ListViewHandle, 4, PvpPeExceptionSizeCompareFunctionAmd64); + } + else if (imageMachine == IMAGE_FILE_MACHINE_ARM64) + { + /* Todo */ } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); @@ -265,11 +287,15 @@ INT_PTR CALLBACK PvpPeExceptionDlgProc( if (imageMachine == IMAGE_FILE_MACHINE_I386) { - PhSaveListViewColumnsToSetting(L"ImageExceptions32ListViewColumns", context->ListViewHandle); + PhSaveListViewColumnsToSetting(L"ImageExceptionsIa32ListViewColumns", context->ListViewHandle); } else if (imageMachine == IMAGE_FILE_MACHINE_AMD64) { - PhSaveListViewColumnsToSetting(L"ImageExceptions64ListViewColumns", context->ListViewHandle); + PhSaveListViewColumnsToSetting(L"ImageExceptionsAmd64ListViewColumns", context->ListViewHandle); + } + else if (imageMachine == IMAGE_FILE_MACHINE_ARM64) + { + /* Todo */ } PhDeleteLayoutManager(&context->LayoutManager); @@ -303,6 +329,17 @@ INT_PTR CALLBACK PvpPeExceptionDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/peheaderprp.c b/ProcessHacker/tools/peview/peheaderprp.c new file mode 100644 index 00000000..b1efbe66 --- /dev/null +++ b/ProcessHacker/tools/peview/peheaderprp.c @@ -0,0 +1,1003 @@ +/* + * Process Hacker - + * PE viewer + * + * Copyright (C) 2021 dmex + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +#include + +typedef struct _PVP_PE_HEADER_CONTEXT +{ + HWND WindowHandle; + HWND ListViewHandle; + PH_LAYOUT_MANAGER LayoutManager; + PPV_PROPPAGECONTEXT PropSheetContext; +} PVP_PE_HEADER_CONTEXT, *PPVP_PE_HEADER_CONTEXT; + +typedef enum _PVP_IMAGE_HEADER_CATEGORY +{ + PVP_IMAGE_HEADER_CATEGORY_DOSHDR, + PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, + PVP_IMAGE_HEADER_CATEGORY_FILEHDR, + PVP_IMAGE_HEADER_CATEGORY_OPTHDR, + PVP_IMAGE_HEADER_CATEGORY_OVERLAY, + PVP_IMAGE_HEADER_CATEGORY_MAXIMUM +} PVP_IMAGE_HEADER_CATEGORY; + +typedef enum _PVP_IMAGE_HEADER_INDEX +{ + PVP_IMAGE_HEADER_INDEX_DOS_MAGIC, + PVP_IMAGE_HEADER_INDEX_DOS_BYTES, + PVP_IMAGE_HEADER_INDEX_DOS_PAGES, + PVP_IMAGE_HEADER_INDEX_DOS_RELOCATIONS, + PVP_IMAGE_HEADER_INDEX_DOS_PARAGRAPH, + PVP_IMAGE_HEADER_INDEX_DOS_MINPARA, + PVP_IMAGE_HEADER_INDEX_DOS_MAXPARA, + PVP_IMAGE_HEADER_INDEX_DOS_INITRELSS, + PVP_IMAGE_HEADER_INDEX_DOS_INITRELSP, + PVP_IMAGE_HEADER_INDEX_DOS_CHECKSUM, + PVP_IMAGE_HEADER_INDEX_DOS_INITIP, + PVP_IMAGE_HEADER_INDEX_DOS_INITCS, + PVP_IMAGE_HEADER_INDEX_DOS_RELOCADDR, + PVP_IMAGE_HEADER_INDEX_DOS_OVERLAY, + //PVP_IMAGE_HEADER_INDEX_DOS_RESERVED1, + PVP_IMAGE_HEADER_INDEX_DOS_OEMID, + PVP_IMAGE_HEADER_INDEX_DOS_OEMINFO, + //PVP_IMAGE_HEADER_INDEX_DOS_RESERVED2, + PVP_IMAGE_HEADER_INDEX_DOS_EXEHDRADDR, + PVP_IMAGE_HEADER_INDEX_DOS_STUBSIZE, + PVP_IMAGE_HEADER_INDEX_DOS_STUBENTROPY, + PVP_IMAGE_HEADER_INDEX_DOS_STUBHASH, + PVP_IMAGE_HEADER_INDEX_DOS_RICHSIZE, + PVP_IMAGE_HEADER_INDEX_DOS_RICHENTROPY, + PVP_IMAGE_HEADER_INDEX_DOS_RICHHASH, + PVP_IMAGE_HEADER_INDEX_DOS_SIZE, + PVP_IMAGE_HEADER_INDEX_DOS_ENTROPY, + PVP_IMAGE_HEADER_INDEX_DOS_HASH, + PVP_IMAGE_HEADER_INDEX_FILE_NTSIG, + PVP_IMAGE_HEADER_INDEX_FILE_MACHINE, + PVP_IMAGE_HEADER_INDEX_FILE_SECTIONS, + PVP_IMAGE_HEADER_INDEX_FILE_TIMESTAMP, + PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLEADDR, + PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLECOUNT, + PVP_IMAGE_HEADER_INDEX_FILE_OPTHDRSIZE, + PVP_IMAGE_HEADER_INDEX_FILE_CHARACTERISTICS, + PVP_IMAGE_HEADER_INDEX_OPT_MAGIC, + PVP_IMAGE_HEADER_INDEX_OPT_LINKERVERSION, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFCODE, + PVP_IMAGE_HEADER_INDEX_OPT_INITSIZE, + PVP_IMAGE_HEADER_INDEX_OPT_UNINITSIZE, + PVP_IMAGE_HEADER_INDEX_OPT_ENTRYPOINT, + PVP_IMAGE_HEADER_INDEX_OPT_BASEOFCODE, + PVP_IMAGE_HEADER_INDEX_OPT_BASEOFDATA, + PVP_IMAGE_HEADER_INDEX_OPT_IMAGEBASE, + PVP_IMAGE_HEADER_INDEX_OPT_SECTIONALIGN, + PVP_IMAGE_HEADER_INDEX_OPT_FILEALIGN, + PVP_IMAGE_HEADER_INDEX_OPT_OSVERSION, + PVP_IMAGE_HEADER_INDEX_OPT_IMGVERSION, + PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEMVERSION, + PVP_IMAGE_HEADER_INDEX_OPT_WIN32VERSION, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFIMAGE, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEADERS, + PVP_IMAGE_HEADER_INDEX_OPT_CHECKSUM, + PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEM, + PVP_IMAGE_HEADER_INDEX_OPT_DLLCHARACTERISTICS, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKRESERVE, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKCOMMIT, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPRESERVE, + PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPCOMMIT, + PVP_IMAGE_HEADER_INDEX_OPT_LOADERFLAGS, + PVP_IMAGE_HEADER_INDEX_OPT_NUMBEROFRVA, + PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_SIZE, + PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_ENTROPY, + PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_HASH, + PVP_IMAGE_HEADER_INDEX_MAXIMUM +} PVP_IMAGE_HEADER_INDEX; + +VOID PvSetPeImageDosHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + PIMAGE_DOS_HEADER imageDosHeader = PvMappedImage.ViewBase; + WCHAR value[PH_PTR_STR_LEN_1]; + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_magic)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_MAGIC, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_cblp)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_BYTES, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_cp)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_PAGES, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_crlc)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RELOCATIONS, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_cparhdr)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_PARAGRAPH, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_minalloc)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_MINPARA, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_maxalloc)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_MAXPARA, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_ss)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_INITRELSS, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_sp)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_INITRELSP, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_csum)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_CHECKSUM, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_ip)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_INITIP, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_cs)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_INITCS, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_lfarlc)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RELOCADDR, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_ovno)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_OVERLAY, 1, value); + + //PPH_STRING reserved1 = PhBufferToHexString((PUCHAR)imageDosHeader->e_res, sizeof(imageDosHeader->e_res)); + //PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RESERVED1, 1, PhGetString(reserved1)); + //PhDereferenceObject(reserved1); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_oemid)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_OEMID, 1, value); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_oeminfo)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_OEMINFO, 1, value); + + //PPH_STRING reserved2 = PhBufferToHexString((PUCHAR)imageDosHeader->e_res2, sizeof(imageDosHeader->e_res2)); + //PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RESERVED2, 1, PhGetString(reserved2)); + //PhDereferenceObject(reserved2); + + PhPrintPointer(value, UlongToPtr(imageDosHeader->e_lfanew)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_EXEHDRADDR, 1, value); +} + +VOID PvSetPeImageDosStubHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + PIMAGE_DOS_HEADER imageDosHeader = PvMappedImage.ViewBase; + ULONG imageDosStubDataLength = imageDosHeader->e_lfanew - RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew); + PVOID imageDosStubData = PTR_ADD_OFFSET(PvMappedImage.ViewBase, RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew)); + ULONG imageDosStubRichStart; + ULONG imageDosStubRichEnd; + ULONG imageDosStubRichLength = 0; + ULONG imageDosStubActualDataLength = 0; + PVOID imageDosStubRichData = NULL; + WCHAR value[PH_PTR_STR_LEN_1]; + WCHAR size[PH_PTR_STR_LEN_1]; + PPH_STRING string; + + if (imageDosStubDataLength == 0) + return; + + if (NT_SUCCESS(PhGetMappedImageProdIdExtents(&PvMappedImage, &imageDosStubRichStart, &imageDosStubRichEnd))) + { + imageDosStubRichData = PTR_ADD_OFFSET(PvMappedImage.ViewBase, imageDosStubRichStart); + imageDosStubRichLength = imageDosStubRichEnd - imageDosStubRichStart; + imageDosStubActualDataLength = imageDosStubDataLength - imageDosStubRichLength; + } + + if (imageDosStubActualDataLength) + { + PhPrintPointer(value, UlongToPtr(RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew))); + PhPrintPointer(size, PTR_ADD_OFFSET(RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew), imageDosStubActualDataLength)); + string = PhaFormatString(L"%s-%s", value, size); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_STUBSIZE, 1, PhaFormatString( + L"%s (%s)", + PhGetString(string), + PhaFormatSize(imageDosStubActualDataLength, ULONG_MAX)->Buffer + )->Buffer); + + __try + { + DOUBLE imageDosStubEntropy; + DOUBLE imageDosStubMean = 0; + PPH_STRING entropyString; + PPH_STRING stringEntropy; + PPH_STRING stringMean; + + imageDosStubEntropy = PvCalculateEntropyBuffer( + imageDosStubData, + imageDosStubActualDataLength, + &imageDosStubMean + ); + + stringEntropy = PvFormatDoubleCropZero(imageDosStubEntropy, 6); + stringMean = PvFormatDoubleCropZero(imageDosStubMean, 4); + entropyString = PhFormatString( + L"%s S (%s X)", + PhGetStringOrEmpty(stringEntropy), + PhGetStringOrEmpty(stringMean) + ); + + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_STUBENTROPY, 1, PhGetStringOrEmpty(entropyString)); + + PhDereferenceObject(entropyString); + PhDereferenceObject(stringMean); + PhDereferenceObject(stringEntropy); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_STUBENTROPY, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + + __try + { + PH_HASH_CONTEXT hashContext; + PPH_STRING hashString; + UCHAR hash[32]; + + PhInitializeHash(&hashContext, Md5HashAlgorithm); // PhGetIntegerSetting(L"HashAlgorithm") + PhUpdateHash(&hashContext, imageDosStubData, imageDosStubActualDataLength); + + if (PhFinalHash(&hashContext, hash, 16, NULL)) + { + if (hashString = PhBufferToHexString(hash, 16)) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_STUBHASH, 1, PhGetString(hashString)); + PhDereferenceObject(hashString); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_STUBHASH, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + } + + if (imageDosStubRichLength) + { + PhPrintPointer(value, UlongToPtr(imageDosStubRichStart)); + PhPrintPointer(size, PTR_ADD_OFFSET(imageDosStubRichStart, imageDosStubRichLength)); + string = PhaFormatString(L"%s-%s", value, size); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RICHSIZE, 1, PhaFormatString( + L"%s (%s)", + PhGetString(string), + PhaFormatSize(imageDosStubRichLength, ULONG_MAX)->Buffer + )->Buffer); + + __try + { + DOUBLE imageDosStubEntropy; + DOUBLE imageDosStubMean = 0; + PPH_STRING entropyString; + PPH_STRING stringEntropy; + PPH_STRING stringMean; + + imageDosStubEntropy = PvCalculateEntropyBuffer( + imageDosStubRichData, + imageDosStubRichLength, + &imageDosStubMean + ); + + stringEntropy = PvFormatDoubleCropZero(imageDosStubEntropy, 6); + stringMean = PvFormatDoubleCropZero(imageDosStubMean, 4); + entropyString = PhFormatString( + L"%s S (%s X)", + PhGetStringOrEmpty(stringEntropy), + PhGetStringOrEmpty(stringMean) + ); + + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RICHENTROPY, 1, PhGetStringOrEmpty(entropyString)); + + PhDereferenceObject(entropyString); + PhDereferenceObject(stringMean); + PhDereferenceObject(stringEntropy); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RICHENTROPY, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + + __try + { + PH_HASH_CONTEXT hashContext; + PPH_STRING hashString; + UCHAR hash[32]; + + PhInitializeHash(&hashContext, Md5HashAlgorithm); // PhGetIntegerSetting(L"HashAlgorithm") + PhUpdateHash(&hashContext, imageDosStubRichData, imageDosStubRichLength); + + if (PhFinalHash(&hashContext, hash, 16, NULL)) + { + if (hashString = PhBufferToHexString(hash, 16)) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RICHHASH, 1, PhGetString(hashString)); + PhDereferenceObject(hashString); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_RICHHASH, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + } + + if (imageDosStubDataLength) + { + PhPrintPointer(value, UlongToPtr(RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew))); + PhPrintPointer(size, PTR_ADD_OFFSET(RTL_SIZEOF_THROUGH_FIELD(IMAGE_DOS_HEADER, e_lfanew), imageDosStubDataLength)); + string = PhaFormatString(L"%s-%s", value, size); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_SIZE, 1, PhaFormatString( + L"%s (%s)", + PhGetString(string), + PhaFormatSize(imageDosStubDataLength, ULONG_MAX)->Buffer + )->Buffer); + + __try + { + DOUBLE imageDosStubEntropy; + DOUBLE imageDosStubMean = 0; + PPH_STRING entropyString; + PPH_STRING stringEntropy; + PPH_STRING stringMean; + + imageDosStubEntropy = PvCalculateEntropyBuffer( + imageDosStubData, + imageDosStubDataLength, + &imageDosStubMean + ); + + stringEntropy = PvFormatDoubleCropZero(imageDosStubEntropy, 6); + stringMean = PvFormatDoubleCropZero(imageDosStubMean, 4); + entropyString = PhFormatString( + L"%s S (%s X)", + PhGetStringOrEmpty(stringEntropy), + PhGetStringOrEmpty(stringMean) + ); + + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_ENTROPY, 1, PhGetStringOrEmpty(entropyString)); + + PhDereferenceObject(entropyString); + PhDereferenceObject(stringMean); + PhDereferenceObject(stringEntropy); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_ENTROPY, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + + __try + { + PH_HASH_CONTEXT hashContext; + PPH_STRING hashString; + UCHAR hash[32]; + + PhInitializeHash(&hashContext, Md5HashAlgorithm); // PhGetIntegerSetting(L"HashAlgorithm") + PhUpdateHash(&hashContext, imageDosStubData, imageDosStubDataLength); + + if (PhFinalHash(&hashContext, hash, 16, NULL)) + { + if (hashString = PhBufferToHexString(hash, 16)) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_HASH, 1, PhGetString(hashString)); + PhDereferenceObject(hashString); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_DOS_HASH, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + } +} + +VOID PvSetPeImageFileHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + PIMAGE_NT_HEADERS imageNtHeader = PvMappedImage.NtHeaders; + WCHAR value[PH_PTR_STR_LEN_1]; + PPH_STRING string; + + PhPrintPointer(value, UlongToPtr(imageNtHeader->Signature)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_NTSIG, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->FileHeader.Machine)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_MACHINE, 1, value); + + PhPrintUInt32(value, imageNtHeader->FileHeader.NumberOfSections); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_SECTIONS, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->FileHeader.TimeDateStamp)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_TIMESTAMP, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->FileHeader.PointerToSymbolTable)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLEADDR, 1, value); + + PhPrintUInt32(value, imageNtHeader->FileHeader.NumberOfSymbols); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLECOUNT, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->FileHeader.SizeOfOptionalHeader)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->FileHeader.SizeOfOptionalHeader, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_OPTHDRSIZE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->FileHeader.Characteristics)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_FILE_CHARACTERISTICS, 1, value); +} + +VOID PvSetPeImageOptionalHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + PIMAGE_NT_HEADERS32 imageNtHeader = PvMappedImage.NtHeaders32; + WCHAR value[PH_PTR_STR_LEN_1]; + PPH_STRING string; + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.Magic)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_MAGIC, 1, value); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorLinkerVersion, imageNtHeader->OptionalHeader.MinorLinkerVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_LINKERVERSION, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfCode)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfCode, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFCODE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfInitializedData)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfInitializedData, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_INITSIZE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfUninitializedData)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfUninitializedData, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_UNINITSIZE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.AddressOfEntryPoint)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_ENTRYPOINT, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.BaseOfCode)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFCODE, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.BaseOfData)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFDATA, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.ImageBase)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_IMAGEBASE, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SectionAlignment)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SECTIONALIGN, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.FileAlignment)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_FILEALIGN, 1, value); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorOperatingSystemVersion, imageNtHeader->OptionalHeader.MinorOperatingSystemVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_OSVERSION, 1, PhGetString(string)); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorImageVersion, imageNtHeader->OptionalHeader.MinorImageVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_IMGVERSION, 1, PhGetString(string)); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorSubsystemVersion, imageNtHeader->OptionalHeader.MinorSubsystemVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEMVERSION, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.Win32VersionValue)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_WIN32VERSION, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfImage)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfImage, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFIMAGE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfHeaders)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeaders, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEADERS, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.CheckSum)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_CHECKSUM, 1, value); + + PhPrintUInt32(value, imageNtHeader->OptionalHeader.Subsystem); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEM, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.DllCharacteristics)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_DLLCHARACTERISTICS, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfStackReserve)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKRESERVE, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfStackCommit)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKCOMMIT, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfHeapReserve)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeapReserve, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPRESERVE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfHeapCommit)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeapCommit, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPCOMMIT, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.LoaderFlags)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_LOADERFLAGS, 1, value); + + PhPrintUInt32(value, imageNtHeader->OptionalHeader.NumberOfRvaAndSizes); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_NUMBEROFRVA, 1, value); + } + else + { + PIMAGE_NT_HEADERS imageNtHeader = PvMappedImage.NtHeaders; + WCHAR value[PH_PTR_STR_LEN_1]; + PPH_STRING string; + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.Magic)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_MAGIC, 1, value); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorLinkerVersion, imageNtHeader->OptionalHeader.MinorLinkerVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_LINKERVERSION, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfCode)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfCode, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFCODE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfInitializedData)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfInitializedData, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_INITSIZE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfUninitializedData)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfUninitializedData, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_UNINITSIZE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.AddressOfEntryPoint)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_ENTRYPOINT, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.BaseOfCode)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFCODE, 1, value); + + //PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.BaseOfData)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFDATA, 1, L"N/A"); + + PhPrintPointer(value, (PVOID)imageNtHeader->OptionalHeader.ImageBase); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_IMAGEBASE, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SectionAlignment)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SectionAlignment, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SECTIONALIGN, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.FileAlignment)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.FileAlignment, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_FILEALIGN, 1, PhGetString(string)); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorOperatingSystemVersion, imageNtHeader->OptionalHeader.MinorOperatingSystemVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_OSVERSION, 1, PhGetString(string)); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorImageVersion, imageNtHeader->OptionalHeader.MinorImageVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_IMGVERSION, 1, PhGetString(string)); + + string = PhaFormatString(L"%lu.%lu", imageNtHeader->OptionalHeader.MajorSubsystemVersion, imageNtHeader->OptionalHeader.MinorSubsystemVersion); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEMVERSION, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.Win32VersionValue)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_WIN32VERSION, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfImage)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfImage, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFIMAGE, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.SizeOfHeaders)); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeaders, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEADERS, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.CheckSum)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_CHECKSUM, 1, value); + + PhPrintUInt32(value, imageNtHeader->OptionalHeader.Subsystem); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEM, 1, value); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.DllCharacteristics)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_DLLCHARACTERISTICS, 1, value); + + PhPrintPointer(value, (PVOID)imageNtHeader->OptionalHeader.SizeOfStackReserve); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfStackReserve, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKRESERVE, 1, PhGetString(string)); + + PhPrintPointer(value, (PVOID)imageNtHeader->OptionalHeader.SizeOfStackCommit); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfStackCommit, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKCOMMIT, 1, PhGetString(string)); + + PhPrintPointer(value, (PVOID)imageNtHeader->OptionalHeader.SizeOfHeapReserve); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeapReserve, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPRESERVE, 1, PhGetString(string)); + + PhPrintPointer(value, (PVOID)imageNtHeader->OptionalHeader.SizeOfHeapCommit); + string = PhaFormatString(L"%s (%s)", value, PhaFormatSize(imageNtHeader->OptionalHeader.SizeOfHeapCommit, ULONG_MAX)->Buffer); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPCOMMIT, 1, PhGetString(string)); + + PhPrintPointer(value, UlongToPtr(imageNtHeader->OptionalHeader.LoaderFlags)); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_LOADERFLAGS, 1, value); + + PhPrintUInt32(value, imageNtHeader->OptionalHeader.NumberOfRvaAndSizes); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_OPT_NUMBEROFRVA, 1, value); + } +} + +VOID PvSetPeImageOverlayHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + ULONG lastRawDataAddress = 0; + ULONG64 lastRawDataOffset = 0; + + for (ULONG i = 0; i < PvMappedImage.NumberOfSections; i++) + { + if (PvMappedImage.Sections[i].PointerToRawData > lastRawDataAddress) + { + lastRawDataAddress = PvMappedImage.Sections[i].PointerToRawData; + lastRawDataOffset = (ULONG64)PTR_ADD_OFFSET(lastRawDataAddress, PvMappedImage.Sections[i].SizeOfRawData); + } + } + + if (PvMappedImage.Size != lastRawDataOffset) + { + PIMAGE_DATA_DIRECTORY dataDirectory; + ULONG64 imageOverlayDataLength; + PVOID imageOverlayData; + WCHAR value[PH_PTR_STR_LEN_1]; + WCHAR size[PH_PTR_STR_LEN_1]; + PPH_STRING string; + + if (NT_SUCCESS(PhGetMappedImageDataEntry( + &PvMappedImage, + IMAGE_DIRECTORY_ENTRY_SECURITY, + &dataDirectory + ))) + { + if ( + dataDirectory->VirtualAddress && + (lastRawDataOffset + dataDirectory->Size == PvMappedImage.Size) && + (lastRawDataOffset == dataDirectory->VirtualAddress) + ) + { + return; + } + } + + imageOverlayDataLength = PvMappedImage.Size - lastRawDataOffset; + imageOverlayData = PTR_ADD_OFFSET(PvMappedImage.ViewBase, lastRawDataOffset); + + PhPrintPointer(value, (PVOID)lastRawDataOffset); + PhPrintPointer(size, PTR_ADD_OFFSET(lastRawDataOffset, imageOverlayDataLength)); + string = PhaFormatString(L"%s-%s", value, size); + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_SIZE, 1, PhaFormatString( + L"%s (%s)", + PhGetString(string), + PhaFormatSize(imageOverlayDataLength, ULONG_MAX)->Buffer + )->Buffer); + + __try + { + DOUBLE imageDosStubEntropy; + DOUBLE imageDosStubMean = 0; + PPH_STRING entropyString; + PPH_STRING stringEntropy; + PPH_STRING stringMean; + + imageDosStubEntropy = PvCalculateEntropyBuffer( + imageOverlayData, + (ULONG)imageOverlayDataLength, + &imageDosStubMean + ); + + stringEntropy = PvFormatDoubleCropZero(imageDosStubEntropy, 6); + stringMean = PvFormatDoubleCropZero(imageDosStubMean, 4); + entropyString = PhFormatString( + L"%s S (%s X)", + PhGetStringOrEmpty(stringEntropy), + PhGetStringOrEmpty(stringMean) + ); + + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_ENTROPY, 1, PhGetStringOrEmpty(entropyString)); + + PhDereferenceObject(entropyString); + PhDereferenceObject(stringMean); + PhDereferenceObject(stringEntropy); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_ENTROPY, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + + __try + { + PH_HASH_CONTEXT hashContext; + PPH_STRING hashString; + UCHAR hash[32]; + + PhInitializeHash(&hashContext, Md5HashAlgorithm); // PhGetIntegerSetting(L"HashAlgorithm") + PhUpdateHash(&hashContext, imageOverlayData, (ULONG)imageOverlayDataLength); + + if (PhFinalHash(&hashContext, hash, 16, NULL)) + { + if (hashString = PhBufferToHexString(hash, 16)) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_HASH, 1, PhGetString(hashString)); + PhDereferenceObject(hashString); + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + PPH_STRING message; + + if (message = PhGetWin32Message(RtlNtStatusToDosError(GetExceptionCode()))) + { + PhSetListViewSubItem(Context->ListViewHandle, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_HASH, 1, PhGetString(message)); + PhDereferenceObject(message); + } + } + } +} + +VOID PvPeUpdateImageHeaderProperties( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + ExtendedListView_SetRedraw(Context->ListViewHandle, FALSE); + ListView_DeleteAllItems(Context->ListViewHandle); + + // DOS Headers + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_MAGIC, L"Magic number", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_BYTES, L"Bytes on last page of file", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_PAGES, L"Pages in file", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_RELOCATIONS, L"Relocations", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_PARAGRAPH, L"Size of header in paragraphs", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_MINPARA, L"Minimum extra paragraphs needed", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_MAXPARA, L"Maximum extra paragraphs needed", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_INITRELSS, L"Initial (relative) SS value", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_INITRELSP, L"Initial SP value", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_CHECKSUM, L"Checksum", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_INITIP, L"Initial IP value", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_INITCS, L"Initial (relative) CS value", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_RELOCADDR, L"File address of relocation table", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_OVERLAY, L"Overlay number", NULL); + //PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_RESERVED1, L"Reserved words", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_OEMID, L"OEM identifier (for e_oeminfo)", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_OEMINFO, L"OEM information (e_oemid specific)", NULL); + //PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_RESERVED2, L"Reserved words", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, PVP_IMAGE_HEADER_INDEX_DOS_EXEHDRADDR, L"File address of new exe header", NULL); + // DOS Stub + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_STUBSIZE, L"Stub size", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_STUBENTROPY, L"Stub entropy", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_STUBHASH, L"Stub hash", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_RICHSIZE, L"Rich size", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_RICHENTROPY, L"Rich entropy", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_RICHHASH, L"Rich hash", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_SIZE, L"Total size", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_ENTROPY, L"Total entropy", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, PVP_IMAGE_HEADER_INDEX_DOS_HASH, L"Total hash", NULL); + // File Headers + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_NTSIG, L"Signature", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_MACHINE, L"Machine", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_SECTIONS, L"NumberOfSections", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_TIMESTAMP, L"Timestamp", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLEADDR, L"PointerToSymbolTable", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_SYMTABLECOUNT, L"NumberOfSymbols", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_OPTHDRSIZE, L"SizeOfOptionalHeader", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, PVP_IMAGE_HEADER_INDEX_FILE_CHARACTERISTICS, L"Characteristics", NULL); + // Optional Headers + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_MAGIC, L"Magic", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_LINKERVERSION, L"LinkerVersion", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFCODE, L"SizeOfCode", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_INITSIZE, L"SizeOfInitializedData", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_UNINITSIZE, L"SizeOfUninitializedData", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_ENTRYPOINT, L"AddressOfEntryPoint", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFCODE, L"BaseOfCode", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_BASEOFDATA, L"BaseOfData", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_IMAGEBASE, L"ImageBase", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SECTIONALIGN, L"SectionAlignment", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_FILEALIGN, L"FileAlignment", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_OSVERSION, L"OperatingSystemVersion", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_IMGVERSION, L"ImageVersion", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEMVERSION, L"SubsystemVersion", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_WIN32VERSION, L"Win32VersionValue", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFIMAGE, L"SizeOfImage", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEADERS, L"SizeOfHeaders", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_CHECKSUM, L"CheckSum", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SUBSYSTEM, L"Subsystem", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_DLLCHARACTERISTICS, L"DllCharacteristics", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKRESERVE, L"SizeOfStackReserve", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFSTACKCOMMIT, L"SizeOfStackCommit", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPRESERVE, L"SizeOfHeapReserve", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_SIZEOFHEAPCOMMIT, L"SizeOfHeapCommit", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_LOADERFLAGS, L"LoaderFlags", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, PVP_IMAGE_HEADER_INDEX_OPT_NUMBEROFRVA, L"NumberOfRvaAndSizes", NULL); + // Overlay Data + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OVERLAY, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_SIZE, L"Data size", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OVERLAY, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_ENTROPY, L"Data entropy", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OVERLAY, PVP_IMAGE_HEADER_INDEX_PE_OVERLAY_HASH, L"Data hash", NULL); + + // DOS Headers + PvSetPeImageDosHeaderProperties(Context); + // DOS Stub + PvSetPeImageDosStubHeaderProperties(Context); + // File Headers + PvSetPeImageFileHeaderProperties(Context); + // Optional Headers + PvSetPeImageOptionalHeaderProperties(Context); + // Overlay Data + PvSetPeImageOverlayHeaderProperties(Context); + + ExtendedListView_SetRedraw(Context->ListViewHandle, TRUE); +} + +VOID PvPeAddImageHeaderGroups( + _In_ PPVP_PE_HEADER_CONTEXT Context + ) +{ + ExtendedListView_SetRedraw(Context->ListViewHandle, FALSE); + + ListView_EnableGroupView(Context->ListViewHandle, TRUE); + PhAddListViewGroup(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSHDR, L"DOS Header"); + PhAddListViewGroup(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_DOSSTUB, L"DOS Stub"); + PhAddListViewGroup(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_FILEHDR, L"File Header"); + PhAddListViewGroup(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OPTHDR, L"Optional Header"); + PhAddListViewGroup(Context->ListViewHandle, PVP_IMAGE_HEADER_CATEGORY_OVERLAY, L"Overlay Stub"); + + ExtendedListView_SetRedraw(Context->ListViewHandle, TRUE); +} + +INT_PTR CALLBACK PvPeHeadersDlgProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + PPVP_PE_HEADER_CONTEXT context; + + if (uMsg == WM_INITDIALOG) + { + context = PhAllocateZero(sizeof(PVP_PE_HEADER_CONTEXT)); + PhSetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT, context); + + if (lParam) + { + LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; + context->PropSheetContext = (PPV_PROPPAGECONTEXT)propSheetPage->lParam; + } + } + else + { + context = PhGetWindowContext(hwndDlg, PH_WINDOW_CONTEXT_DEFAULT); + } + + if (!context) + return FALSE; + + switch (uMsg) + { + case WM_INITDIALOG: + { + context->WindowHandle = hwndDlg; + context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); + + PhSetListViewStyle(context->ListViewHandle, FALSE, TRUE); + PhSetControlTheme(context->ListViewHandle, L"explorer"); + PhAddListViewColumn(context->ListViewHandle, 0, 0, 0, LVCFMT_LEFT, 220, L"Name"); + PhAddListViewColumn(context->ListViewHandle, 1, 1, 1, LVCFMT_LEFT, 170, L"Value"); + PhSetExtendedListView(context->ListViewHandle); + PvPeAddImageHeaderGroups(context); + PhLoadListViewColumnsFromSetting(L"ImageHeadersListViewColumns", context->ListViewHandle); + PhLoadListViewGroupStatesFromSetting(L"ImageHeadersListViewGroupStates", context->ListViewHandle); + PvConfigTreeBorders(context->ListViewHandle); + + PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); + PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); + + PvPeUpdateImageHeaderProperties(context); + + PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); + } + break; + case WM_DESTROY: + { + PhSaveListViewGroupStatesToSetting(L"ImageHeadersListViewGroupStates", context->ListViewHandle); + PhSaveListViewColumnsToSetting(L"ImageHeadersListViewColumns", context->ListViewHandle); + } + break; + case WM_SHOWWINDOW: + { + if (context->PropSheetContext && !context->PropSheetContext->LayoutInitialized) + { + PvAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); + PvDoPropPageLayout(hwndDlg); + + context->PropSheetContext->LayoutInitialized = TRUE; + } + } + break; + case WM_SIZE: + { + PhLayoutManagerLayout(&context->LayoutManager); + } + break; + case WM_NOTIFY: + { + PvHandleListViewNotifyForCopy(lParam, context->ListViewHandle); + } + break; + case WM_CONTEXTMENU: + { + PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); + } + break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; + } + + return FALSE; +} diff --git a/ProcessHacker/tools/peview/pepogoprp.c b/ProcessHacker/tools/peview/pepogoprp.c index f76fdf51..0fc5a821 100644 --- a/ProcessHacker/tools/peview/pepogoprp.c +++ b/ProcessHacker/tools/peview/pepogoprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -298,6 +298,17 @@ INT_PTR CALLBACK PvpPeDebugPogoDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; @@ -551,6 +562,17 @@ INT_PTR CALLBACK PvpPeDebugCrtDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/peprp.c b/ProcessHacker/tools/peview/peprp.c index 5aebf130..a8672ddf 100644 --- a/ProcessHacker/tools/peview/peprp.c +++ b/ProcessHacker/tools/peview/peprp.c @@ -3,7 +3,7 @@ * PE viewer * * Copyright (C) 2010-2011 wj32 - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -63,6 +63,7 @@ typedef enum _PVP_IMAGE_GENERAL_INDEX PVP_IMAGE_GENERAL_INDEX_FILEINDEX, PVP_IMAGE_GENERAL_INDEX_FILEID, PVP_IMAGE_GENERAL_INDEX_FILEOBJECTID, + PVP_IMAGE_GENERAL_INDEX_FILEUSN, PVP_IMAGE_GENERAL_INDEX_DEBUGPDB, PVP_IMAGE_GENERAL_INDEX_DEBUGIMAGE, @@ -76,7 +77,6 @@ typedef struct _PVP_PE_GENERAL_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; ULONG ListViewRowCache[PVP_IMAGE_GENERAL_INDEX_MAXIMUM]; @@ -124,26 +124,30 @@ VOID PvPeProperties( if (PvpLoadDbgHelp(&PvSymbolProvider)) { - // Load current PE pdb - // TODO: Move into seperate thread. + PPH_STRING fileName; - if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) - { - PhLoadModuleSymbolProvider( - PvSymbolProvider, - PvFileName->Buffer, - (ULONG64)PvMappedImage.NtHeaders32->OptionalHeader.ImageBase, - PvMappedImage.NtHeaders32->OptionalHeader.SizeOfImage - ); - } - else + if (NT_SUCCESS(PhGetProcessMappedFileName(NtCurrentProcess(), PvMappedImage.ViewBase, &fileName))) { - PhLoadModuleSymbolProvider( - PvSymbolProvider, - PvFileName->Buffer, - (ULONG64)PvMappedImage.NtHeaders->OptionalHeader.ImageBase, - PvMappedImage.NtHeaders->OptionalHeader.SizeOfImage - ); + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + PhLoadModuleSymbolProvider( + PvSymbolProvider, + fileName->Buffer, + (ULONG64)PvMappedImage.NtHeaders32->OptionalHeader.ImageBase, + PvMappedImage.NtHeaders32->OptionalHeader.SizeOfImage + ); + } + else + { + PhLoadModuleSymbolProvider( + PvSymbolProvider, + fileName->Buffer, + (ULONG64)PvMappedImage.NtHeaders->OptionalHeader.ImageBase, + PvMappedImage.NtHeaders->OptionalHeader.SizeOfImage + ); + } + + PhDereferenceObject(fileName); } PhLoadModulesForProcessSymbolProvider(PvSymbolProvider, NtCurrentProcessId()); @@ -579,6 +583,8 @@ VERIFY_RESULT PvpVerifyFileWithAdditionalCatalog( { static PH_STRINGREF codeIntegrityFileName = PH_STRINGREF_INIT(L"\\AppxMetadata\\CodeIntegrity.cat"); static PH_STRINGREF windowsAppsPathSr = PH_STRINGREF_INIT(L"%ProgramFiles%\\WindowsApps\\"); + NTSTATUS status; + HANDLE fileHandle; VERIFY_RESULT result; PH_VERIFY_FILE_INFO info; PPH_STRING windowsAppsPath; @@ -586,8 +592,25 @@ VERIFY_RESULT PvpVerifyFileWithAdditionalCatalog( PCERT_CONTEXT *signatures; ULONG numberOfSignatures; + status = PhCreateFileWin32( + &fileHandle, + FileName->Buffer, + FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + ); + + if (!NT_SUCCESS(status)) + { + signatures = NULL; + numberOfSignatures = 0; + return VrNoSignature; + } + memset(&info, 0, sizeof(PH_VERIFY_FILE_INFO)); - info.FileName = FileName->Buffer; + info.FileHandle = fileHandle; info.Flags = Flags; info.hWnd = hWnd; @@ -640,6 +663,8 @@ VERIFY_RESULT PvpVerifyFileWithAdditionalCatalog( PhFreeVerifySignatures(signatures, numberOfSignatures); + NtClose(fileHandle); + return result; } @@ -1095,21 +1120,77 @@ VOID PvpSetPeImageEntropy( PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), PvpEntropyImageThreadStart, WindowHandle); } -VOID PvpSetPeImageEntryPoint( - _In_ HWND ListViewHandle +static NTSTATUS PvpEntryPointImageThreadStart( + _In_ PVOID Parameter ) { ULONG addressOfEntryPoint; PPH_STRING string; + PPH_STRING symbol = NULL; + PPH_STRING symbolName = NULL; + PH_SYMBOL_RESOLVE_LEVEL symbolResolveLevel = PhsrlInvalid; if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) addressOfEntryPoint = PvMappedImage.NtHeaders32->OptionalHeader.AddressOfEntryPoint; else addressOfEntryPoint = PvMappedImage.NtHeaders->OptionalHeader.AddressOfEntryPoint; - string = PhFormatString(L"0x%I32x", addressOfEntryPoint); - PhSetListViewSubItem(ListViewHandle, PVP_IMAGE_GENERAL_INDEX_ENTRYPOINT, 1, string->Buffer); - PhDereferenceObject(string); + if (addressOfEntryPoint) + { + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + symbol = PhGetSymbolFromAddress( + PvSymbolProvider, + (ULONG64)PTR_ADD_OFFSET(PvMappedImage.NtHeaders32->OptionalHeader.ImageBase, addressOfEntryPoint), + &symbolResolveLevel, + NULL, + &symbolName, + NULL + ); + } + else + { + symbol = PhGetSymbolFromAddress( + PvSymbolProvider, + (ULONG64)PTR_ADD_OFFSET(PvMappedImage.NtHeaders->OptionalHeader.ImageBase, addressOfEntryPoint), + &symbolResolveLevel, + NULL, + &symbolName, + NULL + ); + } + } + + if ( + !PhIsNullOrEmptyString(symbolName) && ( + symbolResolveLevel == PhsrlFunction || + symbolResolveLevel == PhsrlModule || + symbolResolveLevel == PhsrlAddress + )) + { + string = PhFormatString(L"0x%I32x (%s)", addressOfEntryPoint, PhGetStringOrEmpty(symbolName)); + PhSetListViewSubItem(Parameter, PVP_IMAGE_GENERAL_INDEX_ENTRYPOINT, 1, string->Buffer); + PhDereferenceObject(string); + } + else + { + string = PhFormatString(L"0x%I32x", addressOfEntryPoint); + PhSetListViewSubItem(Parameter, PVP_IMAGE_GENERAL_INDEX_ENTRYPOINT, 1, string->Buffer); + PhDereferenceObject(string); + } + + PhClearReference(&symbolName); + PhClearReference(&symbol); + return STATUS_SUCCESS; +} + +VOID PvpSetPeImageEntryPoint( + _In_ HWND ListViewHandle + ) +{ + PhSetListViewSubItem(ListViewHandle, PVP_IMAGE_GENERAL_INDEX_ENTRYPOINT, 1, L"Resolving..."); + + PhQueueItemWorkQueue(PhGetGlobalWorkQueue(), PvpEntryPointImageThreadStart, ListViewHandle); } VOID PvpSetPeImageCheckSum( @@ -1522,6 +1603,15 @@ VOID PvpSetPeImageFileProperties( PhDereferenceObject(string); } + { + LONGLONG fileUsn; + + if (NT_SUCCESS(PhGetFileUsn(fileHandle, &fileUsn))) + { + PhSetListViewSubItem(ListViewHandle, PVP_IMAGE_GENERAL_INDEX_FILEUSN, 1, PhaFormatUInt64(fileUsn, FALSE)->Buffer); + } + } + NtClose(fileHandle); } } @@ -1721,6 +1811,7 @@ VOID PvpSetPeImageProperties( PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_GENERAL_CATEGORY_EXTRAINFO, PVP_IMAGE_GENERAL_INDEX_FILEINDEX, L"File index", NULL); PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_GENERAL_CATEGORY_EXTRAINFO, PVP_IMAGE_GENERAL_INDEX_FILEID, L"File identifier", NULL); PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_GENERAL_CATEGORY_EXTRAINFO, PVP_IMAGE_GENERAL_INDEX_FILEOBJECTID, L"File object identifier", NULL); + PhAddListViewGroupItem(Context->ListViewHandle, PVP_IMAGE_GENERAL_CATEGORY_EXTRAINFO, PVP_IMAGE_GENERAL_INDEX_FILEUSN, L"File last USN", NULL); PvpSetPeImageMachineType(Context->ListViewHandle); PvpSetPeImageTimeStamp(Context->ListViewHandle); @@ -1908,6 +1999,8 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; + context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); @@ -1921,8 +2014,8 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( PvPeAddImagePropertiesGroups(context); PhLoadListViewGroupStatesFromSetting(L"ImageGeneralPropertiesListViewGroupStates", context->ListViewHandle); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_FILE), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); @@ -1937,8 +2030,10 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( ExtendedListView_SetColumnWidth(context->ListViewHandle, 1, ELVSCW_AUTOSIZE_REMAININGSPACE); if (PeEnableThemeSupport) + { PhInitializeWindowThemeStaticControl(GetDlgItem(hwndDlg, IDC_FILEICON)); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); + PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); + } } break; case WM_DESTROY: @@ -1946,12 +2041,7 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( PhSaveListViewGroupStatesToSetting(L"ImageGeneralPropertiesListViewGroupStates", context->ListViewHandle); //PhSaveListViewSortColumnsToSetting(L"ImageGeneralPropertiesListViewSort", context->ListViewHandle); //PhSaveListViewColumnsToSetting(L"ImageGeneralPropertiesListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -2084,6 +2174,17 @@ INT_PTR CALLBACK PvPeGeneralDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } if (context) diff --git a/ProcessHacker/tools/peview/peprpwnd.c b/ProcessHacker/tools/peview/peprpwnd.c new file mode 100644 index 00000000..d7f13c30 --- /dev/null +++ b/ProcessHacker/tools/peview/peprpwnd.c @@ -0,0 +1,1018 @@ +/* + * Process Hacker - + * PE viewer + + * Copyright (C) 2021 dmex + * + * This file is part of Process Hacker. + * + * Process Hacker is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Process Hacker is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Process Hacker. If not, see . + */ + +#include +#include + +typedef struct _PV_WINDOW_SECTION +{ + PH_STRINGREF Name; + + PVOID Instance; + PWSTR Template; + DLGPROC DialogProc; + PVOID Parameter; + + HWND DialogHandle; + HTREEITEM TreeItemHandle; +} PV_WINDOW_SECTION, *PPV_WINDOW_SECTION; + +INT_PTR CALLBACK PvTabWindowDialogProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ); + +#define SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER (SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER) +#define SWP_SHOWWINDOW_ONLY (SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER | SWP_SHOWWINDOW) +#define SWP_HIDEWINDOW_ONLY (SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER | SWP_HIDEWINDOW) + +VOID PvDestroyTabSection( + _In_ PPV_WINDOW_SECTION Section + ); + +VOID PvEnterTabSectionView( + _In_ PPV_WINDOW_SECTION NewSection + ); + +VOID PvLayoutTabSectionView( + VOID + ); + +VOID PvEnterTabSectionViewInner( + _In_ PPV_WINDOW_SECTION Section, + _Inout_ HDWP *ContainerDeferHandle + ); + +VOID PvCreateTabSectionDialog( + _In_ PPV_WINDOW_SECTION Section + ); + +VOID PvTabWindowOnSize( + VOID + ); + +PPV_WINDOW_SECTION PvFindTabSectionByName( + _In_ PPH_STRINGREF Name + ); + +PPV_WINDOW_SECTION PvGetSelectedTabSection( + _In_opt_ PVOID TreeItemHandle + ); + +PPV_WINDOW_SECTION PvCreateTabSection( + _In_ PWSTR Name, + _In_ PVOID Instance, + _In_ PWSTR Template, + _In_ DLGPROC DialogProc, + _In_opt_ PVOID Parameter + ); + +static HWND PvPropertiesWindowHandle = NULL; +static HWND PvTabTreeControl = NULL; +static HWND PvTabContainerControl = NULL; +static INT PvPropertiesWindowShowCommand = SW_SHOW; +static HIMAGELIST PvTabTreeImageList = NULL; +static PH_LAYOUT_MANAGER PvTabWindowLayoutManager; +static PPH_LIST PvTabSectionList = NULL; +static PPV_WINDOW_SECTION PvTabCurrentSection = NULL; + +VOID PvShowPePropertiesWindow( + VOID + ) +{ + BOOL result; + MSG message; + PH_AUTO_POOL autoPool; + + PhInitializeAutoPool(&autoPool); + + PvPropertiesWindowHandle = PhCreateDialog( + PhInstanceHandle, + MAKEINTRESOURCE(IDD_TABWINDOW), + NULL, + PvTabWindowDialogProc, + NULL + ); + + if (PhGetIntegerSetting(L"MainWindowState") == SW_MAXIMIZE) + PvPropertiesWindowShowCommand = SW_MAXIMIZE; + + ShowWindow(PvPropertiesWindowHandle, PvPropertiesWindowShowCommand); + SetForegroundWindow(PvPropertiesWindowHandle); + + while (result = GetMessage(&message, NULL, 0, 0)) + { + if (result == -1) + break; + + if (!IsDialogMessage(PvPropertiesWindowHandle, &message)) + { + TranslateMessage(&message); + DispatchMessage(&message); + } + + PhDrainAutoPool(&autoPool); + } + + PhDeleteAutoPool(&autoPool); +} + +VOID PvAddTreeViewSections( + VOID + ) +{ + PPV_WINDOW_SECTION section; + PH_MAPPED_IMAGE_IMPORTS imports; + PH_MAPPED_IMAGE_EXPORTS exports; + PIMAGE_LOAD_CONFIG_DIRECTORY32 config32; + PIMAGE_LOAD_CONFIG_DIRECTORY64 config64; + PIMAGE_DATA_DIRECTORY entry; + + PvTabSectionList = PhCreateList(30); + PvTabCurrentSection = NULL; + + // General page + section = PvCreateTabSection( + L"General", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEGENERAL), + PvPeGeneralDlgProc, + NULL + ); + + // Headers page + PvCreateTabSection( + L"Headers", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEHEADERS), + PvPeHeadersDlgProc, + NULL + ); + + // Load Config page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"Load Config", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PELOADCONFIG), + PvPeLoadConfigDlgProc, + NULL + ); + } + + // Sections page + PvCreateTabSection( + L"Sections", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PESECTIONS), + PvPeSectionsDlgProc, + NULL + ); + + // Directories page + PvCreateTabSection( + L"Directories", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEDIRECTORY), + PvPeDirectoryDlgProc, + NULL + ); + + // Imports page + if ((NT_SUCCESS(PhGetMappedImageImports(&imports, &PvMappedImage)) && imports.NumberOfDlls != 0) || + (NT_SUCCESS(PhGetMappedImageDelayImports(&imports, &PvMappedImage)) && imports.NumberOfDlls != 0)) + { + PvCreateTabSection( + L"Imports", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEIMPORTS), + PvPeImportsDlgProc, + NULL + ); + } + + // Exports page + if (NT_SUCCESS(PhGetMappedImageExports(&exports, &PvMappedImage)) && exports.NumberOfEntries != 0) + { + PvCreateTabSection( + L"Exports", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEEXPORTS), + PvPeExportsDlgProc, + NULL + ); + } + + // Resources page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_RESOURCE, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"Resources", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PERESOURCES), + PvPeResourcesDlgProc, + NULL + ); + } + + // CLR page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &entry)) && + entry->VirtualAddress && + (PvImageCor20Header = PhMappedImageRvaToVa(&PvMappedImage, entry->VirtualAddress, NULL))) + { + NTSTATUS status = STATUS_SUCCESS; + + __try + { + PhProbeAddress( + PvImageCor20Header, + sizeof(IMAGE_COR20_HEADER), + PvMappedImage.ViewBase, + PvMappedImage.Size, + 4 + ); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + status = GetExceptionCode(); + } + + if (NT_SUCCESS(status)) + { + PvCreateTabSection( + L"CLR", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PECLR), + PvpPeClrDlgProc, + NULL + ); + + PvCreateTabSection( + L"CLR Imports", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PECLRIMPORTS), + PvpPeClrImportsDlgProc, + NULL + ); + } + } + + // CFG page + if (PvMappedImage.NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF) + { + PvCreateTabSection( + L"CFG", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PECFG), + PvpPeCgfDlgProc, + NULL + ); + } + + // TLS page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_TLS, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"TLS", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_TLS), + PvpPeTlsDlgProc, + NULL + ); + } + + // RICH header page + // .NET executables don't include a RICH header. + if (!(PvImageCor20Header && (PvImageCor20Header->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)) + { + PvCreateTabSection( + L"ProdID", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEPRODID), + PvpPeProdIdDlgProc, + NULL + ); + } + + // Exceptions page + { + BOOLEAN has_exceptions = FALSE; + + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + if (NT_SUCCESS(PhGetMappedImageLoadConfig32(&PvMappedImage, &config32)) && + RTL_CONTAINS_FIELD(config32, config32->Size, SEHandlerCount)) + { + if (config32->SEHandlerCount && config32->SEHandlerTable) + has_exceptions = TRUE; + } + } + else + { + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &entry)) && entry->VirtualAddress) + { + has_exceptions = TRUE; + } + } + + if (has_exceptions) + { + PvCreateTabSection( + L"Exceptions", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEEXCEPTIONS), + PvpPeExceptionDlgProc, + NULL + ); + } + } + + // Relocations page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_BASERELOC, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"Relocations", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PERELOCATIONS), + PvpPeRelocationDlgProc, + NULL + ); + } + + // Certificates page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_SECURITY, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"Certificates", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PESECURITY), + PvpPeSecurityDlgProc, + NULL + ); + } + + // Debug page + if (NT_SUCCESS(PhGetMappedImageDataEntry(&PvMappedImage, IMAGE_DIRECTORY_ENTRY_DEBUG, &entry)) && entry->VirtualAddress) + { + PvCreateTabSection( + L"Debug", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEDEBUG), + PvpPeDebugDlgProc, + NULL + ); + } + + // EH continuation page + { + BOOLEAN has_ehcont = FALSE; + + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + if (NT_SUCCESS(PhGetMappedImageLoadConfig32(&PvMappedImage, &config32)) && + RTL_CONTAINS_FIELD(config32, config32->Size, GuardEHContinuationCount)) + { + if (config32->GuardEHContinuationTable && config32->GuardEHContinuationCount) + has_ehcont = TRUE; + } + } + else + { + if (NT_SUCCESS(PhGetMappedImageLoadConfig64(&PvMappedImage, &config64)) && + RTL_CONTAINS_FIELD(config64, config64->Size, GuardEHContinuationCount)) + { + if (config64->GuardEHContinuationTable && config64->GuardEHContinuationCount) + has_ehcont = TRUE; + } + } + + if (has_ehcont) + { + PvCreateTabSection( + L"EH Continuation", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEEHCONT), + PvpPeEhContDlgProc, + NULL + ); + } + } + + // Debug POGO page + { + BOOLEAN debugPogoValid = FALSE; + PVOID debugEntry; + + if (NT_SUCCESS(PhGetMappedImageDebugEntryByType( + &PvMappedImage, + IMAGE_DEBUG_TYPE_POGO, + NULL, + &debugEntry + ))) + { + debugPogoValid = TRUE; + } + + if (debugPogoValid) + { + PvCreateTabSection( + L"POGO", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEDEBUGPOGO), + PvpPeDebugPogoDlgProc, + NULL + ); + + PvCreateTabSection( + L"CRT", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEDEBUGCRT), + PvpPeDebugCrtDlgProc, + NULL + ); + } + } + + // Properties page + PvCreateTabSection( + L"Properties", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEPROPSTORAGE), + PvpPePropStoreDlgProc, + NULL + ); + + // Extended attributes page + PvCreateTabSection( + L"Attributes", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEATTR), + PvpPeExtendedAttributesDlgProc, + NULL + ); + + // Streams page + PvCreateTabSection( + L"Streams", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PESTREAMS), + PvpPeStreamsDlgProc, + NULL + ); + + // Layout page + PvCreateTabSection( + L"Layout", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PELAYOUT), + PvpPeLayoutDlgProc, + NULL + ); + + // Links page + PvCreateTabSection( + L"Links", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PELINKS), + PvpPeLinksDlgProc, + NULL + ); + + // Processes page + PvCreateTabSection( + L"Processes", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PIDS), + PvpPeProcessesDlgProc, + NULL + ); + + // Hashes page + PvCreateTabSection( + L"Hashes", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEHASHES), + PvpPeHashesDlgProc, + NULL + ); + + // Text preview page + PvCreateTabSection( + L"Preview", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PEPREVIEW), + PvpPePreviewDlgProc, + NULL + ); + + // Symbols page + PvCreateTabSection( + L"Symbols", + PhInstanceHandle, + MAKEINTRESOURCE(IDD_PESYMBOLS), + PvpSymbolsDlgProc, + NULL + ); + + if (PhGetIntegerSetting(L"MainWindowPageRestoreEnabled")) + { + PPH_STRING startPage; + PPV_WINDOW_SECTION startSection; + BOOLEAN foundStartPage = FALSE; + + if (startPage = PhGetStringSetting(L"MainWindowPage")) + { + if (startSection = PvFindTabSectionByName(&startPage->sr)) + { + TreeView_SelectItem(PvTabTreeControl, startSection->TreeItemHandle); + foundStartPage = TRUE; + } + + PhDereferenceObject(startPage); + } + + if (!foundStartPage) + { + TreeView_SelectItem(PvTabTreeControl, section->TreeItemHandle); + } + + SetFocus(PvTabTreeControl); + } + else + { + TreeView_SelectItem(PvTabTreeControl, section->TreeItemHandle); + SetFocus(PvTabTreeControl); + //PvEnterTabSectionView(section); + } + + PvTabWindowOnSize(); +} + +INT_PTR CALLBACK PvTabWindowDialogProc( + _In_ HWND hwndDlg, + _In_ UINT uMsg, + _In_ WPARAM wParam, + _In_ LPARAM lParam + ) +{ + switch (uMsg) + { + case WM_INITDIALOG: + { + PvTabTreeControl = GetDlgItem(hwndDlg, IDC_SECTIONTREE); + PvTabContainerControl = GetDlgItem(hwndDlg, IDD_CONTAINER); + PvTabTreeImageList = PhImageListCreate(2, PV_SCALE_DPI(24), ILC_MASK | ILC_COLOR32, 1, 1); + + PhSetWindowText(hwndDlg, PhaFormatString(L"%s Properties", PhGetString(PvFileName))->Buffer); + + //PhSetWindowStyle(GetDlgItem(hwndDlg, IDC_SEPARATOR), SS_OWNERDRAW, SS_OWNERDRAW); + PhSetControlTheme(PvTabTreeControl, L"explorer"); + TreeView_SetExtendedStyle(PvTabTreeControl, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER); + TreeView_SetImageList(PvTabTreeControl, PvTabTreeImageList, TVSIL_NORMAL); + TreeView_SetBkColor(PvTabTreeControl, GetSysColor(COLOR_3DFACE)); + + PhInitializeLayoutManager(&PvTabWindowLayoutManager, hwndDlg); + PhAddLayoutItem(&PvTabWindowLayoutManager, PvTabTreeControl, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_BOTTOM); + //PhAddLayoutItem(&PvTabWindowLayoutManager, GetDlgItem(hwndDlg, IDC_SEPARATOR), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_BOTTOM); + PhAddLayoutItem(&PvTabWindowLayoutManager, PvTabContainerControl, NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); + PhAddLayoutItem(&PvTabWindowLayoutManager, GetDlgItem(hwndDlg, IDC_OPTIONS), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM); + PhAddLayoutItem(&PvTabWindowLayoutManager, GetDlgItem(hwndDlg, IDC_SECURITY), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM); + PhAddLayoutItem(&PvTabWindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); + + if (PeEnableThemeSupport) + PhInitializeWindowTheme(hwndDlg, TRUE); + + { + HICON smallIcon; + HICON largeIcon; + + if (!PhExtractIcon(PvFileName->Buffer, &PvImageLargeIcon, &PvImageSmallIcon)) + { + PhGetStockApplicationIcon(&PvImageSmallIcon, &PvImageLargeIcon); + } + + PhGetStockApplicationIcon(&smallIcon, &largeIcon); + + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)smallIcon); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)largeIcon); + } + + if (PvpLoadDbgHelp(&PvSymbolProvider)) + { + PPH_STRING fileName; + + if (NT_SUCCESS(PhGetProcessMappedFileName(NtCurrentProcess(), PvMappedImage.ViewBase, &fileName))) + { + if (PvMappedImage.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + PhLoadModuleSymbolProvider( + PvSymbolProvider, + fileName->Buffer, + (ULONG64)PvMappedImage.NtHeaders32->OptionalHeader.ImageBase, + PvMappedImage.NtHeaders32->OptionalHeader.SizeOfImage + ); + } + else + { + PhLoadModuleSymbolProvider( + PvSymbolProvider, + fileName->Buffer, + (ULONG64)PvMappedImage.NtHeaders->OptionalHeader.ImageBase, + PvMappedImage.NtHeaders->OptionalHeader.SizeOfImage + ); + } + + PhDereferenceObject(fileName); + } + + PhLoadModulesForProcessSymbolProvider(PvSymbolProvider, NtCurrentProcessId()); + } + + PvAddTreeViewSections(); + + if (PhGetIntegerPairSetting(L"MainWindowPosition").X) + PhLoadWindowPlacementFromSetting(L"MainWindowPosition", L"MainWindowSize", hwndDlg); + else + PhCenterWindow(hwndDlg, NULL); + } + break; + case WM_DESTROY: + { + ULONG i; + PPV_WINDOW_SECTION section; + + PhSaveWindowPlacementToSetting(L"MainWindowPosition", L"MainWindowSize", hwndDlg); + PvSaveWindowState(hwndDlg); + + if (PhGetIntegerSetting(L"MainWindowPageRestoreEnabled")) + PhSetStringSetting(L"MainWindowPage", PvTabCurrentSection->Name.Buffer); + + PhDeleteLayoutManager(&PvTabWindowLayoutManager); + + for (i = 0; i < PvTabSectionList->Count; i++) + { + section = PvTabSectionList->Items[i]; + PvDestroyTabSection(section); + } + + PhDereferenceObject(PvTabSectionList); + PvTabSectionList = NULL; + + if (PvTabTreeImageList) + PhImageListDestroy(PvTabTreeImageList); + + PostQuitMessage(0); + } + break; + case WM_SIZE: + { + PvTabWindowOnSize(); + } + break; + case WM_COMMAND: + { + switch (GET_WM_COMMAND_ID(wParam, lParam)) + { + case IDCANCEL: + case IDOK: + DestroyWindow(hwndDlg); + break; + case IDC_OPTIONS: + { + PvShowOptionsWindow(hwndDlg); + } + break; + case IDC_SECURITY: + { + PhEditSecurity( + hwndDlg, + PhGetString(PvFileName), + L"FileObject", + PhpOpenFileSecurity, + NULL, + NULL + ); + } + break; + } + } + break; + case WM_DRAWITEM: + { + PDRAWITEMSTRUCT drawInfo = (PDRAWITEMSTRUCT)lParam; + + //if (drawInfo->CtlID == IDC_SEPARATOR) + //{ + // RECT rect; + // + // rect = drawInfo->rcItem; + // rect.right = 2; + // + // if (PhEnableThemeSupport) + // { + // switch (PhCsGraphColorMode) + // { + // case 0: // New colors + // { + // FillRect(drawInfo->hDC, &rect, GetSysColorBrush(COLOR_3DHIGHLIGHT)); + // rect.left += 1; + // FillRect(drawInfo->hDC, &rect, GetSysColorBrush(COLOR_3DSHADOW)); + // } + // break; + // case 1: // Old colors + // { + // SetDCBrushColor(drawInfo->hDC, RGB(0, 0, 0)); + // FillRect(drawInfo->hDC, &rect, GetStockBrush(DC_BRUSH)); + // } + // break; + // } + // } + // else + // { + // FillRect(drawInfo->hDC, &rect, GetSysColorBrush(COLOR_3DHIGHLIGHT)); + // rect.left += 1; + // FillRect(drawInfo->hDC, &rect, GetSysColorBrush(COLOR_3DSHADOW)); + // } + // + // return TRUE; + //} + } + break; + case WM_NOTIFY: + { + LPNMHDR header = (LPNMHDR)lParam; + + switch (header->code) + { + case TVN_SELCHANGED: + { + LPNMTREEVIEW treeview = (LPNMTREEVIEW)lParam; + PPV_WINDOW_SECTION section; + + if (section = PvGetSelectedTabSection(treeview->itemNew.hItem)) + { + PvEnterTabSectionView(section); + } + } + break; + //case NM_SETCURSOR: + // { + // if (header->hwndFrom == OptionsTreeControl) + // { + // HCURSOR cursor = (HCURSOR)LoadImage( + // NULL, + // IDC_ARROW, + // IMAGE_CURSOR, + // 0, + // 0, + // LR_SHARED + // ); + // if (cursor != GetCursor()) + // { + // SetCursor(cursor); + // } + // SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + // return TRUE; + // } + // } + // break; + } + } + break; + } + + return FALSE; +} + +VOID PvTabWindowOnSize( + VOID + ) +{ + PhLayoutManagerLayout(&PvTabWindowLayoutManager); + + if (PvTabSectionList && PvTabSectionList->Count != 0) + { + PvLayoutTabSectionView(); + } +} + +HTREEITEM PvTreeViewInsertItem( + _In_opt_ HTREEITEM HandleInsertAfter, + _In_ PWSTR Text, + _In_ PVOID Context + ) +{ + TV_INSERTSTRUCT insert; + + memset(&insert, 0, sizeof(TV_INSERTSTRUCT)); + insert.hParent = TVI_ROOT; + insert.hInsertAfter = HandleInsertAfter; + insert.item.mask = TVIF_TEXT | TVIF_PARAM; + insert.item.pszText = Text; + insert.item.lParam = (LPARAM)Context; + + return TreeView_InsertItem(PvTabTreeControl, &insert); +} + +PPV_WINDOW_SECTION PvGetSelectedTabSection( + _In_opt_ PVOID TreeItemHandle + ) +{ + TVITEM item; + HTREEITEM itemHandle; + + if (TreeItemHandle) + itemHandle = TreeItemHandle; + else + itemHandle = TreeView_GetSelection(PvTabTreeControl); + + memset(&item, 0, sizeof(TVITEM)); + item.mask = TVIF_PARAM | TVIF_HANDLE; + item.hItem = itemHandle; + + if (!TreeView_GetItem(PvTabTreeControl, &item)) + return NULL; + + return (PPV_WINDOW_SECTION)item.lParam; +} + +PPV_WINDOW_SECTION PvCreateTabSection( + _In_ PWSTR Name, + _In_ PVOID Instance, + _In_ PWSTR Template, + _In_ DLGPROC DialogProc, + _In_opt_ PVOID Parameter + ) +{ + PPV_WINDOW_SECTION section; + + section = PhAllocateZero(sizeof(PV_WINDOW_SECTION)); + PhInitializeStringRefLongHint(§ion->Name, Name); + section->Instance = Instance; + section->Template = Template; + section->DialogProc = DialogProc; + section->Parameter = Parameter; + section->TreeItemHandle = PvTreeViewInsertItem(TVI_LAST, Name, section); + + PhAddItemList(PvTabSectionList, section); + + return section; +} + +PPV_WINDOW_SECTION PhOptionsCreateSectionAdvanced( + _In_ PWSTR Name, + _In_ PVOID Instance, + _In_ PWSTR Template, + _In_ DLGPROC DialogProc, + _In_opt_ PVOID Parameter + ) +{ + PPV_WINDOW_SECTION section; + + section = PhAllocateZero(sizeof(PV_WINDOW_SECTION)); + PhInitializeStringRefLongHint(§ion->Name, Name); + section->Instance = Instance; + section->Template = Template; + section->DialogProc = DialogProc; + section->Parameter = Parameter; + + PhAddItemList(PvTabSectionList, section); + + return section; +} + +VOID PvDestroyTabSection( + _In_ PPV_WINDOW_SECTION Section + ) +{ + PhFree(Section); +} + +PPV_WINDOW_SECTION PvFindTabSectionByName( + _In_ PPH_STRINGREF Name + ) +{ + ULONG i; + PPV_WINDOW_SECTION section; + + for (i = 0; i < PvTabSectionList->Count; i++) + { + section = PvTabSectionList->Items[i]; + + if (PhEqualStringRef(§ion->Name, Name, TRUE)) + return section; + } + + return NULL; +} + +VOID PvLayoutTabSectionView( + VOID + ) +{ + if (PvTabCurrentSection && PvTabCurrentSection->DialogHandle) + { + RECT clientRect; + + GetClientRect(PvTabContainerControl, &clientRect); + + SetWindowPos( + PvTabCurrentSection->DialogHandle, + NULL, + 0, + 0, + clientRect.right - clientRect.left, + clientRect.bottom - clientRect.top, + SWP_NOACTIVATE | SWP_NOZORDER + ); + } +} + +VOID PvEnterTabSectionView( + _In_ PPV_WINDOW_SECTION NewSection + ) +{ + ULONG i; + PPV_WINDOW_SECTION section; + PPV_WINDOW_SECTION oldSection; + HDWP containerDeferHandle; + + if (PvTabCurrentSection == NewSection) + return; + + oldSection = PvTabCurrentSection; + PvTabCurrentSection = NewSection; + + containerDeferHandle = BeginDeferWindowPos(PvTabSectionList->Count); + + PvEnterTabSectionViewInner(NewSection, &containerDeferHandle); + PvLayoutTabSectionView(); + + for (i = 0; i < PvTabSectionList->Count; i++) + { + section = PvTabSectionList->Items[i]; + + if (section != NewSection) + PvEnterTabSectionViewInner(section, &containerDeferHandle); + } + + EndDeferWindowPos(containerDeferHandle); + + if (NewSection->DialogHandle) + RedrawWindow(NewSection->DialogHandle, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW); +} + +VOID PvEnterTabSectionViewInner( + _In_ PPV_WINDOW_SECTION Section, + _Inout_ HDWP *ContainerDeferHandle + ) +{ + if (Section == PvTabCurrentSection && !Section->DialogHandle) + PvCreateTabSectionDialog(Section); + + if (Section->DialogHandle) + { + if (Section == PvTabCurrentSection) + *ContainerDeferHandle = DeferWindowPos(*ContainerDeferHandle, Section->DialogHandle, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW_ONLY | SWP_NOREDRAW); + else + *ContainerDeferHandle = DeferWindowPos(*ContainerDeferHandle, Section->DialogHandle, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW_ONLY | SWP_NOREDRAW); + } +} + +VOID PvCreateTabSectionDialog( + _In_ PPV_WINDOW_SECTION Section + ) +{ + Section->DialogHandle = PhCreateDialogFromTemplate( + PvTabContainerControl, + DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE, + Section->Instance, + Section->Template, + Section->DialogProc, + Section->Parameter + ); + + PhInitializeWindowTheme(Section->DialogHandle, PeEnableThemeSupport); +} diff --git a/ProcessHacker/tools/peview/perelocprp.c b/ProcessHacker/tools/peview/perelocprp.c index 558bb25d..13fe1769 100644 --- a/ProcessHacker/tools/peview/perelocprp.c +++ b/ProcessHacker/tools/peview/perelocprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2021 dmex + * Copyright (C) 2021-2022 dmex * * This file is part of Process Hacker. * @@ -252,6 +252,17 @@ INT_PTR CALLBACK PvpPeRelocationDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/pesectionprp.c b/ProcessHacker/tools/peview/pesectionprp.c index 8a811576..4c73dad1 100644 --- a/ProcessHacker/tools/peview/pesectionprp.c +++ b/ProcessHacker/tools/peview/pesectionprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -86,7 +86,6 @@ typedef struct _PV_SECTION_CONTEXT HWND SearchHandle; HWND TreeNewHandle; HWND ParentWindowHandle; - HANDLE UpdateTimerHandle; PPH_STRING SearchboxText; PPH_STRING TreeText; @@ -215,19 +214,6 @@ VOID PvAddPendingSectionNodes( TreeNew_SetRedraw(Context->TreeNewHandle, TRUE); } -VOID CALLBACK PvSectionTreeUpdateCallback( - _In_ PPV_SECTION_CONTEXT Context, - _In_ BOOLEAN TimerOrWaitFired - ) -{ - if (!Context->UpdateTimerHandle) - return; - - PvAddPendingSectionNodes(Context); - - RtlUpdateTimer(PhGetGlobalTimerQueue(), Context->UpdateTimerHandle, 1000, INFINITE); -} - PPH_STRING PvGetSectionCharacteristics( _In_ ULONG Characteristics ) @@ -302,7 +288,7 @@ NTSTATUS PvpPeSectionsEnumerateThread( WCHAR value[PH_INT64_STR_LEN_1]; sectionNode = PhAllocateZero(sizeof(PV_SECTION_NODE)); - sectionNode->UniqueId = i + 1; + sectionNode->UniqueId = UInt32Add32To64(i, 1); sectionNode->UniqueIdString = PhFormatUInt64(sectionNode->UniqueId, FALSE); sectionNode->SectionHeader = &PvMappedImage.Sections[i]; @@ -503,27 +489,11 @@ INT_PTR CALLBACK PvPeSectionsDlgProc( PhCreateThread2(PvpPeSectionsEnumerateThread, context); - RtlCreateTimer( - PhGetGlobalTimerQueue(), - &context->UpdateTimerHandle, - PvSectionTreeUpdateCallback, - context, - 0, - 1000, - 0 - ); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); } break; case WM_DESTROY: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PhSaveSettingsSectionList(context); PvDeleteSectionTree(context); } @@ -661,12 +631,6 @@ INT_PTR CALLBACK PvPeSectionsDlgProc( break; case WM_PV_SEARCH_FINISHED: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PvAddPendingSectionNodes(context); TreeNew_SetEmptyText(context->TreeNewHandle, &EmptySectionsText, 0); @@ -720,6 +684,17 @@ INT_PTR CALLBACK PvPeSectionsDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/peview.rc b/ProcessHacker/tools/peview/peview.rc index 5bad8059..d2025cf4 100644 --- a/ProcessHacker/tools/peview/peview.rc +++ b/ProcessHacker/tools/peview/peview.rc @@ -303,6 +303,22 @@ BEGIN TOPMARGIN, 3 BOTTOMMARGIN, 277 END + + IDD_ELFIMPORTS, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 297 + TOPMARGIN, 3 + BOTTOMMARGIN, 277 + END + + IDD_ELFEXPORTS, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 297 + TOPMARGIN, 3 + BOTTOMMARGIN, 277 + END END #endif // APSTUDIO_INVOKED @@ -677,6 +693,22 @@ BEGIN CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,3,3,294,274 END +IDD_ELFIMPORTS DIALOGEX 0, 0, 300, 280 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Imports" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,3,3,294,274 +END + +IDD_ELFEXPORTS DIALOGEX 0, 0, 300, 280 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Exports" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,3,3,294,274 +END + #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/ProcessHacker/tools/peview/peview.vcxproj b/ProcessHacker/tools/peview/peview.vcxproj index a4065aa0..1ce33167 100644 --- a/ProcessHacker/tools/peview/peview.vcxproj +++ b/ProcessHacker/tools/peview/peview.vcxproj @@ -136,6 +136,7 @@ stdcpplatest stdc17 /utf-8 %(AdditionalOptions) + false aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;%(AdditionalDependencies) @@ -171,6 +172,7 @@ stdcpplatest stdc17 /utf-8 %(AdditionalOptions) + false aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;%(AdditionalDependencies) @@ -205,6 +207,7 @@ stdcpplatest stdc17 /utf-8 %(AdditionalOptions) + false aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;%(AdditionalDependencies) @@ -246,7 +249,7 @@ /utf-8 %(AdditionalOptions) - aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;samlib.lib;..\thirdparty\bin\Release32\thirdparty.lib;%(AdditionalDependencies) + aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;..\thirdparty\bin\Release32\thirdparty.lib;Samlib.lib;%(AdditionalDependencies) ..\..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories) @@ -290,7 +293,7 @@ /utf-8 %(AdditionalOptions) - aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;samlib.lib;..\thirdparty\bin\Release64\thirdparty.lib;%(AdditionalDependencies) + aclui.lib;bcrypt.lib;cryptui.lib;crypt32.lib;propsys.lib;phlib.lib;ntdll.lib;uxtheme.lib;userenv.lib;windowscodecs.lib;winhttp.lib;winsta.lib;noarg.obj;noenv.obj;..\thirdparty\bin\Release64\thirdparty.lib;Samlib.lib;%(AdditionalDependencies) ..\..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories) diff --git a/ProcessHacker/tools/peview/peview.vcxproj.filters b/ProcessHacker/tools/peview/peview.vcxproj.filters index 71fc94e1..e9cd803f 100644 --- a/ProcessHacker/tools/peview/peview.vcxproj.filters +++ b/ProcessHacker/tools/peview/peview.vcxproj.filters @@ -22,12 +22,6 @@ {3213da7e-9e01-48a4-8895-c4dd1499b2fa} - - {84ecc5ac-b90d-41b6-a9f2-5cf08691450e} - - - {349c41fa-6b58-4e7f-a61e-0b384b92ca8f} - {ce2627d7-7f04-4e4b-ab4b-64e8e5cd0e25} diff --git a/ProcessHacker/tools/peview/previewprp.c b/ProcessHacker/tools/peview/previewprp.c index 4c4fcd51..ff6ef7b3 100644 --- a/ProcessHacker/tools/peview/previewprp.c +++ b/ProcessHacker/tools/peview/previewprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -158,6 +158,17 @@ INT_PTR CALLBACK PvpPePreviewDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/processes.c b/ProcessHacker/tools/peview/processes.c index 59171a37..471c6bd9 100644 --- a/ProcessHacker/tools/peview/processes.c +++ b/ProcessHacker/tools/peview/processes.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -184,6 +184,17 @@ INT_PTR CALLBACK PvpPeProcessesDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/propstore.c b/ProcessHacker/tools/peview/propstore.c index eb918cca..1c99b599 100644 --- a/ProcessHacker/tools/peview/propstore.c +++ b/ProcessHacker/tools/peview/propstore.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2018-2021 dmex + * Copyright (C) 2018-2022 dmex * * This file is part of Process Hacker. * @@ -244,6 +244,17 @@ INT_PTR CALLBACK PvpPePropStoreDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/resource.h b/ProcessHacker/tools/peview/resource.h index 6bf3c747..483f2e71 100644 --- a/ProcessHacker/tools/peview/resource.h +++ b/ProcessHacker/tools/peview/resource.h @@ -42,6 +42,8 @@ #define IDD_CHOOSECOLUMNS 166 #define IDD_PEHEADERS 167 #define IDD_PECLRIMPORTS 168 +#define IDD_ELFIMPORTS 169 +#define IDD_ELFEXPORTS 170 #define IDD_CONTAINER 205 #define IDC_TARGETMACHINE 1003 #define IDC_LIST 1008 @@ -90,7 +92,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 164 +#define _APS_NEXT_RESOURCE_VALUE 165 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1036 #define _APS_NEXT_SYMED_VALUE 115 diff --git a/ProcessHacker/tools/peview/resprp.c b/ProcessHacker/tools/peview/resprp.c index 2b6f7e14..973d5569 100644 --- a/ProcessHacker/tools/peview/resprp.c +++ b/ProcessHacker/tools/peview/resprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2017-2021 dmex + * Copyright (C) 2017-2022 dmex * * This file is part of Process Hacker. * @@ -69,7 +69,6 @@ typedef struct _PV_RESOURCES_CONTEXT HWND SearchHandle; HWND TreeNewHandle; HWND ParentWindowHandle; - HANDLE UpdateTimerHandle; PPH_STRING SearchboxText; PPH_STRING TreeText; @@ -162,19 +161,6 @@ VOID PvAddPendingResourcesNodes( TreeNew_SetRedraw(Context->TreeNewHandle, TRUE); } -VOID CALLBACK PvResourcesTreeUpdateCallback( - _In_ PPV_RESOURCES_CONTEXT Context, - _In_ BOOLEAN TimerOrWaitFired - ) -{ - if (!Context->UpdateTimerHandle) - return; - - PvAddPendingResourcesNodes(Context); - - RtlUpdateTimer(PhGetGlobalTimerQueue(), Context->UpdateTimerHandle, 1000, INFINITE); -} - PPH_STRING PvpGetResourceTypeString( _In_ ULONG_PTR Type ) @@ -521,27 +507,11 @@ INT_PTR CALLBACK PvPeResourcesDlgProc( PhCreateThread2(PvpPeResourcesEnumerateThread, context); - RtlCreateTimer( - PhGetGlobalTimerQueue(), - &context->UpdateTimerHandle, - PvResourcesTreeUpdateCallback, - context, - 0, - 1000, - 0 - ); - PhInitializeWindowTheme(hwndDlg, PeEnableThemeSupport); } break; case WM_DESTROY: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PhSaveSettingsResourcesList(context); PvDeleteResourcesTree(context); } @@ -603,12 +573,6 @@ INT_PTR CALLBACK PvPeResourcesDlgProc( break; case WM_PV_SEARCH_FINISHED: { - if (context->UpdateTimerHandle) - { - RtlDeleteTimer(PhGetGlobalTimerQueue(), context->UpdateTimerHandle, NULL); - context->UpdateTimerHandle = NULL; - } - PvAddPendingResourcesNodes(context); TreeNew_SetEmptyText(context->TreeNewHandle, &EmptyResourcesText, 0); @@ -670,6 +634,17 @@ INT_PTR CALLBACK PvPeResourcesDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/richprp.c b/ProcessHacker/tools/peview/richprp.c index 01453012..f0282c6d 100644 --- a/ProcessHacker/tools/peview/richprp.c +++ b/ProcessHacker/tools/peview/richprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -26,7 +26,6 @@ typedef struct _PVP_PE_PRODUCTION_ID_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PVP_PE_PRODUCTION_ID_CONTEXT, *PPVP_PE_PRODUCTION_ID_CONTEXT; @@ -429,6 +428,8 @@ INT_PTR CALLBACK PvpPeProdIdDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; + context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); @@ -450,8 +451,8 @@ INT_PTR CALLBACK PvpPeProdIdDlgProc( PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PRODHASH2), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PvpPeEnumProdEntries(hwndDlg, context->ListViewHandle); @@ -461,11 +462,7 @@ INT_PTR CALLBACK PvpPeProdIdDlgProc( case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"ImageProdIdListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -495,6 +492,17 @@ INT_PTR CALLBACK PvpPeProdIdDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/searchbox.c b/ProcessHacker/tools/peview/searchbox.c index 2ff0cecd..bd9b4083 100644 --- a/ProcessHacker/tools/peview/searchbox.c +++ b/ProcessHacker/tools/peview/searchbox.c @@ -33,9 +33,13 @@ typedef struct _EDIT_CONTEXT ULONG Flags; struct { + ULONG ThemeSupport : 1; ULONG Hot : 1; + ULONG ButtonHot : 1; ULONG Pushed : 1; - ULONG Spare : 30; + ULONG HotTrack : 1; + ULONG ColorMode : 8; + ULONG Spare : 19; }; }; @@ -43,11 +47,10 @@ typedef struct _EDIT_CONTEXT INT CXBorder; INT ImageWidth; INT ImageHeight; - HWND WindowHandle; - HFONT WindowFont; - HICON BitmapActive; - HICON BitmapInactive; WNDPROC DefaultWindowProc; + HFONT WindowFont; + HIMAGELIST ImageListHandle; + PPH_STRING CueBannerText; } EDIT_CONTEXT, *PEDIT_CONTEXT; HICON PhpSearchBitmapToIcon( @@ -64,7 +67,8 @@ VOID PhpSearchFreeTheme( } VOID PhpSearchInitializeFont( - _Inout_ PEDIT_CONTEXT Context + _Inout_ PEDIT_CONTEXT Context, + _In_ HWND WindowHandle ) { LOGFONT logFont; @@ -92,20 +96,22 @@ VOID PhpSearchInitializeFont( logFont.lfFaceName ); - SetWindowFont(Context->WindowHandle, Context->WindowFont, TRUE); + SetWindowFont(WindowHandle, Context->WindowFont, TRUE); } VOID PhpSearchInitializeTheme( - _Inout_ PEDIT_CONTEXT Context + _Inout_ PEDIT_CONTEXT Context, + _In_ HWND WindowHandle ) { - Context->CXWidth = PhMultiplyDivideSigned(20, PhGlobalDpi, 96);// PH_SCALE_DPI(20); + Context->CXWidth = PhMultiplyDivideSigned(20, PhGlobalDpi, 96);//PH_SCALE_DPI(20); + Context->ColorMode = PhGetIntegerSetting(L"GraphColorMode"); if (IsThemeActive()) { HTHEME themeDataHandle; - if (themeDataHandle = OpenThemeData(Context->WindowHandle, VSCLASS_EDIT)) + if (themeDataHandle = OpenThemeData(WindowHandle, VSCLASS_EDIT)) { //IsThemePartDefined_I(themeDataHandle, EP_EDITBORDER_NOSCROLL, EPSHV_NORMAL); @@ -159,14 +165,14 @@ HBITMAP PhLoadPngImageFromResource( WICPixelFormatGUID pixelFormat; WICRect rect = { 0, 0, Width, Height }; - // Create the ImagingFactory - if (FAILED(PhGetClassObject(L"windowscodecs.dll", &CLSID_WICImagingFactory1, &IID_IWICImagingFactory, &wicFactory))) - goto CleanupExit; - // Load the resource if (!PhLoadResource(DllBase, Name, L"PNG", &resourceLength, &resourceBuffer)) goto CleanupExit; + // Create the ImagingFactory + if (FAILED(PhGetClassObject(L"windowscodecs.dll", &CLSID_WICImagingFactory1, &IID_IWICImagingFactory, &wicFactory))) + goto CleanupExit; + // Create the Stream if (FAILED(IWICImagingFactory_CreateStream(wicFactory, &wicStream))) goto CleanupExit; @@ -275,15 +281,9 @@ HBITMAP PhLoadPngImageFromResource( IWICImagingFactory_Release(wicFactory); if (success) - { return bitmapHandle; - } - - if (bitmapHandle) - { - DeleteBitmap(bitmapHandle); - } + if (bitmapHandle) DeleteBitmap(bitmapHandle); return NULL; } @@ -295,27 +295,33 @@ VOID PhpSearchInitializeImages( Context->ImageWidth = PhSmallIconSize.X + 4; //GetSystemMetrics(SM_CXSMICON) + 4; Context->ImageHeight = PhSmallIconSize.Y + 4; //GetSystemMetrics(SM_CYSMICON) + 4; + Context->ImageListHandle = PhImageListCreate( + Context->ImageWidth, + Context->ImageHeight, + ILC_MASK | ILC_COLOR32, + 2, + 0 + ); + PhImageListSetImageCount(Context->ImageListHandle, 2); if (bitmap = PhLoadPngImageFromResource(PhInstanceHandle, Context->ImageWidth, Context->ImageHeight, MAKEINTRESOURCE(IDB_SEARCH_ACTIVE), TRUE)) { - Context->BitmapActive = PhpSearchBitmapToIcon(bitmap, Context->ImageWidth, Context->ImageHeight); + PhImageListReplace(Context->ImageListHandle, 0, bitmap, NULL); DeleteBitmap(bitmap); } - else if (bitmap = LoadImage(PhInstanceHandle, MAKEINTRESOURCE(IDB_SEARCH_ACTIVE_BMP), IMAGE_BITMAP, 0, 0, 0)) + else { - Context->BitmapActive = PhpSearchBitmapToIcon(bitmap, Context->ImageWidth, Context->ImageHeight); - DeleteBitmap(bitmap); + PhSetImageListBitmap(Context->ImageListHandle, 0, PhInstanceHandle, MAKEINTRESOURCE(IDB_SEARCH_ACTIVE_BMP)); } if (bitmap = PhLoadPngImageFromResource(PhInstanceHandle, Context->ImageWidth, Context->ImageHeight, MAKEINTRESOURCE(IDB_SEARCH_INACTIVE), TRUE)) { - Context->BitmapInactive = PhpSearchBitmapToIcon(bitmap, Context->ImageWidth, Context->ImageHeight); + PhImageListReplace(Context->ImageListHandle, 1, bitmap, NULL); DeleteBitmap(bitmap); } - else if (bitmap = LoadImage(PhInstanceHandle, MAKEINTRESOURCE(IDB_SEARCH_INACTIVE_BMP), IMAGE_BITMAP, 0, 0, 0)) + else { - Context->BitmapInactive = PhpSearchBitmapToIcon(bitmap, Context->ImageWidth, Context->ImageHeight); - DeleteBitmap(bitmap); + PhSetImageListBitmap(Context->ImageListHandle, 1, PhInstanceHandle, MAKEINTRESOURCE(IDB_SEARCH_INACTIVE_BMP)); } } @@ -332,80 +338,179 @@ VOID PhpSearchGetButtonRect( VOID PhpSearchDrawButton( _Inout_ PEDIT_CONTEXT Context, + _In_ HWND WindowHandle, + _In_ HDC Hdc, + _In_ RECT WindowRect, _In_ RECT ButtonRect ) { - HDC hdc; - HDC bufferDc; - HBITMAP bufferBitmap; - HBITMAP oldBufferBitmap; - RECT bufferRect = + if (Context->ThemeSupport) // HACK { - 0, 0, - ButtonRect.right - ButtonRect.left, - ButtonRect.bottom - ButtonRect.top - }; - - if (!(hdc = GetWindowDC(Context->WindowHandle))) - return; - - bufferDc = CreateCompatibleDC(hdc); - bufferBitmap = CreateCompatibleBitmap(hdc, bufferRect.right, bufferRect.bottom); - oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + if (GetFocus() == WindowHandle) + { + //switch (Context->ColorMode) + //{ + //case 0: // New colors + // SetDCBrushColor(Hdc, RGB(0, 0, 0)); + // break; + //case 1: // Old colors + SetDCBrushColor(Hdc, RGB(65, 65, 65)); + // break; + //} + + SelectBrush(Hdc, GetStockBrush(DC_BRUSH)); + PatBlt(Hdc, WindowRect.left, WindowRect.top, 1, WindowRect.bottom - WindowRect.top, PATCOPY); + PatBlt(Hdc, WindowRect.right - 1, WindowRect.top, 1, WindowRect.bottom - WindowRect.top, PATCOPY); + PatBlt(Hdc, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, 1, PATCOPY); + PatBlt(Hdc, WindowRect.left, WindowRect.bottom - 1, WindowRect.right - WindowRect.left, 1, PATCOPY); + + //switch (Context->ColorMode) + //{ + //case 0: // New colors + // SetDCBrushColor(Hdc, RGB(0xff, 0xff, 0xff)); + // break; + //case 1: // Old colors + SetDCBrushColor(Hdc, RGB(60, 60, 60)); + // break; + //} + + SelectBrush(Hdc, GetStockBrush(DC_BRUSH)); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.top + 1, 1, WindowRect.bottom - WindowRect.top - 2, PATCOPY); + PatBlt(Hdc, WindowRect.right - 2, WindowRect.top + 1, 1, WindowRect.bottom - WindowRect.top - 2, PATCOPY); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.top + 1, WindowRect.right - WindowRect.left - 2, 1, PATCOPY); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.bottom - 2, WindowRect.right - WindowRect.left - 2, 1, PATCOPY); + } + else + { + //switch (Context->ColorMode) + //{ + //case 0: // New colors + // SetDCBrushColor(Hdc, RGB(0, 0, 0)); + // break; + //case 1: // Old colors + SetDCBrushColor(Hdc, RGB(65, 65, 65)); + // break; + //} + + SelectBrush(Hdc, GetStockBrush(DC_BRUSH)); + PatBlt(Hdc, WindowRect.left, WindowRect.top, 1, WindowRect.bottom - WindowRect.top, PATCOPY); + PatBlt(Hdc, WindowRect.right - 1, WindowRect.top, 1, WindowRect.bottom - WindowRect.top, PATCOPY); + PatBlt(Hdc, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, 1, PATCOPY); + PatBlt(Hdc, WindowRect.left, WindowRect.bottom - 1, WindowRect.right - WindowRect.left, 1, PATCOPY); + + //switch (Context->ColorMode) + //{ + //case 0: // New colors + // SetDCBrushColor(Hdc, RGB(0xff, 0xff, 0xff)); + // break; + //case 1: // Old colors + SetDCBrushColor(Hdc, RGB(60, 60, 60)); + // break; + //} + + SelectBrush(Hdc, GetStockBrush(DC_BRUSH)); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.top + 1, 1, WindowRect.bottom - WindowRect.top - 2, PATCOPY); + PatBlt(Hdc, WindowRect.right - 2, WindowRect.top + 1, 1, WindowRect.bottom - WindowRect.top - 2, PATCOPY); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.top + 1, WindowRect.right - WindowRect.left - 2, 1, PATCOPY); + PatBlt(Hdc, WindowRect.left + 1, WindowRect.bottom - 2, WindowRect.right - WindowRect.left - 2, 1, PATCOPY); + } + } if (Context->Pushed) { - SetDCBrushColor(bufferDc, RGB(153, 209, 255)); - FillRect(bufferDc, &bufferRect, GetStockBrush(DC_BRUSH)); - //FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(0xff, 0, 0))); + if (Context->ThemeSupport) + { + switch (Context->ColorMode) + { + case 0: // New colors + SetDCBrushColor(Hdc, RGB(153, 209, 255)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + break; + case 1: // Old colors + //SetTextColor(Hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetDCBrushColor(Hdc, RGB(99, 99, 99)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + break; + } + } + else + { + SetDCBrushColor(Hdc, RGB(153, 209, 255)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + //FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(0xff, 0, 0))); + } } - else if (Context->Hot) + else if (Context->ButtonHot) { - SetDCBrushColor(bufferDc, RGB(205, 232, 255)); - FillRect(bufferDc, &bufferRect, GetStockBrush(DC_BRUSH)); - //FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(38, 160, 218))); + if (Context->ThemeSupport) + { + switch (Context->ColorMode) + { + case 0: // New colors + SetDCBrushColor(Hdc, RGB(205, 232, 255)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + break; + case 1: // Old colors + //SetTextColor(Hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetDCBrushColor(Hdc, RGB(78, 78, 78)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + break; + } + } + else + { + SetDCBrushColor(Hdc, RGB(205, 232, 255)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + //FrameRect(bufferDc, &bufferRect, CreateSolidBrush(RGB(38, 160, 218))); + } } else { - //SetDCBrushColor(bufferDc, GetSysColor(COLOR_WINDOW)); - FillRect(bufferDc, &bufferRect, GetSysColorBrush(COLOR_WINDOW)); + if (Context->ThemeSupport) + { + switch (Context->ColorMode) + { + case 0: // New colors + FillRect(Hdc, &ButtonRect, GetSysColorBrush(COLOR_WINDOW)); + break; + case 1: // Old colors + //SetTextColor(Hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetDCBrushColor(Hdc, RGB(60, 60, 60)); + FillRect(Hdc, &ButtonRect, GetStockBrush(DC_BRUSH)); + break; + } + + } + else + { + FillRect(Hdc, &ButtonRect, GetSysColorBrush(COLOR_WINDOW)); + } } - if (Edit_GetTextLength(Context->WindowHandle) > 0) + if (Edit_GetTextLength(WindowHandle) > 0) { - DrawIconEx( - bufferDc, - bufferRect.left + 1, // offset - bufferRect.top, - Context->BitmapActive, - Context->ImageWidth, - Context->ImageHeight, + PhImageListDrawIcon( + Context->ImageListHandle, 0, - NULL, - DI_NORMAL + Hdc, + ButtonRect.left + 1, // offset + ButtonRect.top, + ILD_TRANSPARENT, + FALSE ); } else { - DrawIconEx( - bufferDc, - bufferRect.left + 2, // offset - bufferRect.top + 1, // offset - Context->BitmapInactive, - Context->ImageWidth, - Context->ImageHeight, - 0, - NULL, - DI_NORMAL + PhImageListDrawIcon( + Context->ImageListHandle, + 1, + Hdc, + ButtonRect.left + 2, // offset + ButtonRect.top + 1, // offset + ILD_TRANSPARENT, + FALSE ); } - - BitBlt(hdc, ButtonRect.left, ButtonRect.top, ButtonRect.right, ButtonRect.bottom, bufferDc, 0, 0, SRCCOPY); - SelectBitmap(bufferDc, oldBufferBitmap); - DeleteBitmap(bufferBitmap); - DeleteDC(bufferDc); - - ReleaseDC(Context->WindowHandle, hdc); } LRESULT CALLBACK PhpSearchWndSubclassProc( @@ -425,12 +530,27 @@ LRESULT CALLBACK PhpSearchWndSubclassProc( switch (uMsg) { - case WM_NCDESTROY: + case WM_DESTROY: { PhpSearchFreeTheme(context); if (context->WindowFont) + { DeleteFont(context->WindowFont); + context->WindowFont = NULL; + } + + if (context->ImageListHandle) + { + PhImageListDestroy(context->ImageListHandle); + context->ImageListHandle = NULL; + } + + if (context->CueBannerText) + { + PhDereferenceObject(context->CueBannerText); + context->CueBannerText = NULL; + } SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)oldWndProc); PhRemoveWindowContext(hWnd, SHRT_MAX); @@ -453,21 +573,102 @@ LRESULT CALLBACK PhpSearchWndSubclassProc( case WM_NCPAINT: { RECT windowRect; + RECT buttonRect; + HDC hdc; + ULONG flags; + HRGN updateRegion; - // Let Windows handle the non-client defaults. - CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); + updateRegion = (HRGN)wParam; - // Get the screen coordinates of the window. - GetWindowRect(hWnd, &windowRect); + if (updateRegion == (HRGN)1) // HRGN_FULL + updateRegion = NULL; - // Adjust the coordinates (start from 0,0). - OffsetRect(&windowRect, -windowRect.left, -windowRect.top); + // Note the use of undocumented flags below. GetDCEx doesn't work without these. + flags = DCX_WINDOW | DCX_LOCKWINDOWUPDATE | 0x10000; - // Get the position of the inserted button. - PhpSearchGetButtonRect(context, &windowRect); + if (updateRegion) + flags |= DCX_INTERSECTRGN | 0x40000; - // Draw the button. - PhpSearchDrawButton(context, windowRect); + if (hdc = GetDCEx(hWnd, updateRegion, flags)) + { + HDC bufferDc; + RECT bufferRect; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; + + // Get the screen coordinates of the window. + GetWindowRect(hWnd, &windowRect); + // Adjust the coordinates (start from 0,0). + PhOffsetRect(&windowRect, -windowRect.left, -windowRect.top); + buttonRect = windowRect; + // Get the position of the inserted button. + PhpSearchGetButtonRect(context, &buttonRect); + // Exclude client area. + ExcludeClipRect( + hdc, + windowRect.left + 2, + windowRect.top + 2, + windowRect.right - context->CXWidth - 2, + windowRect.bottom - 2 + ); + + bufferRect.left = 0; + bufferRect.top = 0; + bufferRect.right = windowRect.right - windowRect.left; + bufferRect.bottom = windowRect.bottom - windowRect.top; + + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, bufferRect.right, bufferRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + + if (GetFocus() == hWnd) + { + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_HOTLIGHT)); + PhInflateRect(&windowRect, -1, -1); + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_WINDOW)); + } + else if (context->Hot || context->ButtonHot) + { + if (context->ThemeSupport) + { + SetDCBrushColor(bufferDc, RGB(0x8f, 0x8f, 0x8f)); + FrameRect(bufferDc, &windowRect, GetStockBrush(DC_BRUSH)); + } + else + { + SetDCBrushColor(bufferDc, RGB(43, 43, 43)); + FrameRect(bufferDc, &windowRect, GetStockBrush(DC_BRUSH)); + } + + PhInflateRect(&windowRect, -1, -1); + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_WINDOW)); + } + else + { + if (context->ThemeSupport) + { + //SetDCBrushColor(bufferDc, RGB(43, 43, 43)); + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_WINDOWFRAME)); + } + else + { + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_WINDOWFRAME)); + } + + PhInflateRect(&windowRect, -1, -1); + FrameRect(bufferDc, &windowRect, GetSysColorBrush(COLOR_WINDOW)); + } + + // Draw the button. + PhpSearchDrawButton(context, hWnd, bufferDc, windowRect, buttonRect); + + BitBlt(hdc, bufferRect.left, bufferRect.top, bufferRect.right, bufferRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + + ReleaseDC(hWnd, hdc); + } } return 0; case WM_NCHITTEST: @@ -566,8 +767,8 @@ LRESULT CALLBACK PhpSearchWndSubclassProc( case WM_THEMECHANGED: { PhpSearchFreeTheme(context); - PhpSearchInitializeTheme(context); - PhpSearchInitializeFont(context); + PhpSearchInitializeTheme(context, hWnd); + PhpSearchInitializeFont(context, hWnd); // Reset the client area margins. SendMessage(hWnd, EM_SETMARGINS, EC_LEFTMARGIN, MAKELPARAM(0, 0)); @@ -579,6 +780,7 @@ LRESULT CALLBACK PhpSearchWndSubclassProc( RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } break; + case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: { POINT windowPoint; @@ -590,61 +792,184 @@ LRESULT CALLBACK PhpSearchWndSubclassProc( // Get the screen coordinates of the window. GetWindowRect(hWnd, &windowRect); + context->Hot = PtInRect(&windowRect, windowPoint); // Get the position of the inserted button. PhpSearchGetButtonRect(context, &windowRect); + context->ButtonHot = PtInRect(&windowRect, windowPoint); + + if ((wParam & MK_LBUTTON) && GetCapture() == hWnd) + { + // Check that the mouse is within the inserted button. + context->Pushed = PtInRect(&windowRect, windowPoint); + } // Check that the mouse is within the inserted button. - if (PtInRect(&windowRect, windowPoint) && !context->Hot) + if (!context->HotTrack) { TRACKMOUSEEVENT trackMouseEvent; - trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT); trackMouseEvent.dwFlags = TME_LEAVE | TME_NONCLIENT; trackMouseEvent.hwndTrack = hWnd; trackMouseEvent.dwHoverTime = 0; - context->Hot = TRUE; - - RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + context->HotTrack = TRUE; TrackMouseEvent(&trackMouseEvent); } + + RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } break; + case WM_MOUSELEAVE: case WM_NCMOUSELEAVE: { - if (context->Hot) - { - context->Hot = FALSE; - RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); - } + POINT windowPoint; + RECT windowRect; + + context->HotTrack = FALSE; + + // Get the screen coordinates of the mouse. + if (!GetCursorPos(&windowPoint)) + break; + + // Get the screen coordinates of the window. + GetWindowRect(hWnd, &windowRect); + context->Hot = PtInRect(&windowRect, windowPoint); + + // Get the position of the inserted button. + PhpSearchGetButtonRect(context, &windowRect); + context->ButtonHot = PtInRect(&windowRect, windowPoint); + + RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); } break; - case WM_MOUSEMOVE: + case WM_PAINT: { - if ((wParam & MK_LBUTTON) && GetCapture() == hWnd) + if ( + PhIsNullOrEmptyString(context->CueBannerText) || + GetFocus() == hWnd || + CallWindowProc(oldWndProc, hWnd, WM_GETTEXTLENGTH, 0, 0) > 0 // Edit_GetTextLength + ) { - POINT windowPoint; - RECT windowRect; - - // Get the screen coordinates of the mouse. - if (!GetCursorPos(&windowPoint)) - break; + return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); + } - // Get the screen coordinates of the window. - GetWindowRect(hWnd, &windowRect); + HDC hdc = (HDC)wParam ? (HDC)wParam : GetDC(hWnd); - // Get the position of the inserted button. - PhpSearchGetButtonRect(context, &windowRect); - - // Check that the mouse is within the inserted button. - context->Pushed = PtInRect(&windowRect, windowPoint); + if (hdc) + { + HDC bufferDc; + RECT clientRect; + HFONT oldFont; + HBITMAP bufferBitmap; + HBITMAP oldBufferBitmap; + + GetClientRect(hWnd, &clientRect); + + bufferDc = CreateCompatibleDC(hdc); + bufferBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom); + oldBufferBitmap = SelectBitmap(bufferDc, bufferBitmap); + + SetBkMode(bufferDc, TRANSPARENT); + + if (context->ThemeSupport) + { + SetTextColor(bufferDc, RGB(170, 170, 170)); + SetDCBrushColor(bufferDc, RGB(60, 60, 60)); + FillRect(bufferDc, &clientRect, GetStockBrush(DC_BRUSH)); + } + else + { + SetTextColor(bufferDc, GetSysColor(COLOR_GRAYTEXT)); + FillRect(bufferDc, &clientRect, GetSysColorBrush(COLOR_WINDOW)); + } + + oldFont = SelectFont(bufferDc, GetWindowFont(hWnd)); + clientRect.left += 2; + DrawText( + bufferDc, + context->CueBannerText->Buffer, + (UINT)context->CueBannerText->Length / sizeof(WCHAR), + &clientRect, + DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOCLIP + ); + clientRect.left -= 2; + SelectFont(bufferDc, oldFont); + + BitBlt(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, bufferDc, 0, 0, SRCCOPY); + SelectBitmap(bufferDc, oldBufferBitmap); + DeleteBitmap(bufferBitmap); + DeleteDC(bufferDc); + + if (!(HDC)wParam) + { + ReleaseDC(hWnd, hdc); + } + } - RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } + break; + case WM_KEYDOWN: + { + // Delete previous word for ctrl+backspace (thanks to Katayama Hirofumi MZ) (modified) (dmex) + if (wParam == VK_BACK && GetAsyncKeyState(VK_CONTROL) < 0) + { + UINT textStart = 0; + UINT textEnd = 0; + UINT textLength; + + textLength = (UINT)CallWindowProc(oldWndProc, hWnd, WM_GETTEXTLENGTH, 0, 0); + CallWindowProc(oldWndProc, hWnd, EM_GETSEL, (WPARAM)&textStart, (LPARAM)&textEnd); + + if (textLength > 0 && textStart == textEnd) + { + PWSTR textBuffer; + + textBuffer = PhAllocateZero((textLength + 1) * sizeof(WCHAR)); + GetWindowText(hWnd, textBuffer, textLength); + + for (; 0 < textStart; --textStart) + { + if (textBuffer[textStart - 1] == L' ' && iswalnum(textBuffer[textStart])) + { + CallWindowProc(oldWndProc, hWnd, EM_SETSEL, textStart, textEnd); + CallWindowProc(oldWndProc, hWnd, EM_REPLACESEL, TRUE, (LPARAM)L""); + PhFree(textBuffer); + return 1; + } + } + + if (textStart == 0) + { + //CallWindowProc(oldWndProc, hWnd, WM_SETTEXT, 0, (LPARAM)L""); + PhSetWindowText(hWnd, L""); + PhFree(textBuffer); + return 1; + } + + PhFree(textBuffer); + } } } break; + case WM_CHAR: + { + // Delete previous word for ctrl+backspace (dmex) + if (wParam == VK_F16 && GetAsyncKeyState(VK_CONTROL) < 0) + return 1; + } + break; + case EM_SETCUEBANNER: + { + PWSTR text = (PWSTR)lParam; + + PhMoveReference(&context->CueBannerText, PhCreateString(text)); + + RedrawWindow(hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE); + } + return TRUE; } return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); @@ -661,7 +986,7 @@ HICON PhpSearchBitmapToIcon( HBITMAP screenBitmap; ICONINFO iconInfo = { 0 }; - screenDc = GetDC(NULL); + screenDc = CreateCompatibleDC(NULL); screenBitmap = CreateCompatibleBitmap(screenDc, Width, Height); iconInfo.fIcon = TRUE; @@ -671,7 +996,7 @@ HICON PhpSearchBitmapToIcon( icon = CreateIconIndirect(&iconInfo); DeleteBitmap(screenBitmap); - ReleaseDC(NULL, screenDc); + DeleteDC(screenDc); return icon; } @@ -684,14 +1009,15 @@ VOID PvCreateSearchControl( PEDIT_CONTEXT context; context = PhAllocateZero(sizeof(EDIT_CONTEXT)); - context->WindowHandle = WindowHandle; + context->ThemeSupport = !!PhGetIntegerSetting(L"EnableThemeSupport"); // HACK + context->ColorMode = PhGetIntegerSetting(L"GraphColorMode"); //PhpSearchInitializeTheme(context); PhpSearchInitializeImages(context); // Set initial text if (BannerText) - Edit_SetCueBannerText(context->WindowHandle, BannerText); + context->CueBannerText = PhCreateString(BannerText); // Subclass the Edit control window procedure. context->DefaultWindowProc = (WNDPROC)GetWindowLongPtr(WindowHandle, GWLP_WNDPROC); @@ -699,5 +1025,5 @@ VOID PvCreateSearchControl( SetWindowLongPtr(WindowHandle, GWLP_WNDPROC, (LONG_PTR)PhpSearchWndSubclassProc); // Initialize the theme parameters. - SendMessage(context->WindowHandle, WM_THEMECHANGED, 0, 0); + SendMessage(WindowHandle, WM_THEMECHANGED, 0, 0); } diff --git a/ProcessHacker/tools/peview/secprp.c b/ProcessHacker/tools/peview/secprp.c index 86d1fa86..f84aaf05 100644 --- a/ProcessHacker/tools/peview/secprp.c +++ b/ProcessHacker/tools/peview/secprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2020-2021 dmex + * Copyright (C) 2020-2022 dmex * * This file is part of Process Hacker. * @@ -1767,6 +1767,17 @@ INT_PTR CALLBACK PvpPeSecurityDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/settings.c b/ProcessHacker/tools/peview/settings.c index 3170416d..2b90ad25 100644 --- a/ProcessHacker/tools/peview/settings.c +++ b/ProcessHacker/tools/peview/settings.c @@ -57,12 +57,12 @@ VOID PhAddDefaultSettings( PhpAddStringSetting(L"ImageImportsTreeListSort", L"0,1"); // 0, AscendingSortOrder PhpAddStringSetting(L"ImageSectionsTreeListColumns", L""); PhpAddStringSetting(L"ImageSectionsTreeListSort", L"0,1"); // 0, AscendingSortOrder - PhpAddIntegerSetting(L"ImageSectionsTreeListFlags", L"1e0"); + PhpAddIntegerSetting(L"ImageSectionsTreeListFlags", L"0"); PhpAddStringSetting(L"ImageResourcesTreeListColumns", L""); PhpAddStringSetting(L"ImageResourcesTreeListSort", L"0,1"); // 0, AscendingSortOrder PhpAddStringSetting(L"ImageLoadCfgListViewColumns", L""); - PhpAddStringSetting(L"ImageExceptions32ListViewColumns", L""); - PhpAddStringSetting(L"ImageExceptions64ListViewColumns", L""); + PhpAddStringSetting(L"ImageExceptionsIa32ListViewColumns", L""); + PhpAddStringSetting(L"ImageExceptionsAmd64ListViewColumns", L""); PhpAddStringSetting(L"ImageHeadersListViewColumns", L""); PhpAddStringSetting(L"ImageHeadersListViewGroupStates", L""); PhpAddStringSetting(L"ImageLayoutTreeColumns", L""); diff --git a/ProcessHacker/tools/peview/streams.c b/ProcessHacker/tools/peview/streams.c index d47cdbdf..f98883fe 100644 --- a/ProcessHacker/tools/peview/streams.c +++ b/ProcessHacker/tools/peview/streams.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2018-2021 dmex + * Copyright (C) 2018-2022 dmex * * This file is part of Process Hacker. * @@ -26,7 +26,6 @@ typedef struct _PVP_PE_STREAMS_CONTEXT { HWND WindowHandle; HWND ListViewHandle; - HIMAGELIST ListViewImageList; PH_LAYOUT_MANAGER LayoutManager; PPV_PROPPAGECONTEXT PropSheetContext; } PVP_PE_STREAMS_CONTEXT, *PPVP_PE_STREAMS_CONTEXT; @@ -198,6 +197,8 @@ INT_PTR CALLBACK PvpPeStreamsDlgProc( { case WM_INITDIALOG: { + HIMAGELIST listViewImageList; + context->WindowHandle = hwndDlg; context->ListViewHandle = GetDlgItem(hwndDlg, IDC_LIST); @@ -214,8 +215,8 @@ INT_PTR CALLBACK PvpPeStreamsDlgProc( PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->ListViewHandle, NULL, PH_ANCHOR_ALL); - if (context->ListViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) - ListView_SetImageList(context->ListViewHandle, context->ListViewImageList, LVSIL_SMALL); + if (listViewImageList = PhImageListCreate(2, 20, ILC_MASK | ILC_COLOR, 1, 1)) + ListView_SetImageList(context->ListViewHandle, listViewImageList, LVSIL_SMALL); PvpPeEnumerateFileStreams(context->ListViewHandle); @@ -225,12 +226,7 @@ INT_PTR CALLBACK PvpPeStreamsDlgProc( case WM_DESTROY: { PhSaveListViewColumnsToSetting(L"ImageStreamsListViewColumns", context->ListViewHandle); - - if (context->ListViewImageList) - PhImageListDestroy(context->ListViewImageList); - PhDeleteLayoutManager(&context->LayoutManager); - PhFree(context); } break; @@ -303,6 +299,17 @@ INT_PTR CALLBACK PvpPeStreamsDlgProc( } } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/ProcessHacker/tools/peview/tlsprp.c b/ProcessHacker/tools/peview/tlsprp.c index 8385d176..320b8678 100644 --- a/ProcessHacker/tools/peview/tlsprp.c +++ b/ProcessHacker/tools/peview/tlsprp.c @@ -2,7 +2,7 @@ * Process Hacker - * PE viewer * - * Copyright (C) 2019-2021 dmex + * Copyright (C) 2019-2022 dmex * * This file is part of Process Hacker. * @@ -173,6 +173,17 @@ INT_PTR CALLBACK PvpPeTlsDlgProc( PvHandleListViewCommandCopy(hwndDlg, lParam, wParam, context->ListViewHandle); } break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + { + SetBkMode((HDC)wParam, TRANSPARENT); + SetTextColor((HDC)wParam, RGB(0, 0, 0)); + SetDCBrushColor((HDC)wParam, RGB(255, 255, 255)); + return (INT_PTR)GetStockBrush(DC_BRUSH); + } + break; } return FALSE; diff --git a/TaskExplorer/API/Windows/ProcessHacker.h b/TaskExplorer/API/Windows/ProcessHacker.h index 99135ccc..fcd4bd43 100644 --- a/TaskExplorer/API/Windows/ProcessHacker.h +++ b/TaskExplorer/API/Windows/ProcessHacker.h @@ -76,7 +76,7 @@ PPH_STRING CastQString(const QString& qString); // Missing phlib definitions extern "C" { - VERIFY_RESULT NTAPI PhVerifyFileCached(_In_ PPH_STRING FileName, _In_opt_ PPH_STRING PackageFullName, _Out_opt_ PPH_STRING *SignerName, _In_ BOOLEAN CachedOnly); + VERIFY_RESULT NTAPI PhVerifyFileCached(_In_ PPH_STRING FileName, _In_opt_ PPH_STRING PackageFullName, _Out_opt_ PPH_STRING* SignerName, _In_ BOOLEAN NativeFileName, _In_ BOOLEAN CachedOnly); VERIFY_RESULT NTAPI PhVerifyFileWithAdditionalCatalog(_In_ PPH_VERIFY_FILE_INFO Information, _In_opt_ PPH_STRING PackageFullName, _Out_opt_ PPH_STRING *SignerName); } diff --git a/TaskExplorer/API/Windows/ProcessHacker/DotNetCounters.cpp b/TaskExplorer/API/Windows/ProcessHacker/DotNetCounters.cpp index 1d26e866..af1270ee 100644 --- a/TaskExplorer/API/Windows/ProcessHacker/DotNetCounters.cpp +++ b/TaskExplorer/API/Windows/ProcessHacker/DotNetCounters.cpp @@ -510,7 +510,7 @@ BOOLEAN OpenDotNetPublicControlBlock_V4( ) { BOOLEAN result = FALSE; - PVOID boundaryDescriptorHandle = NULL; + POBJECT_BOUNDARY_DESCRIPTOR boundaryDescriptorHandle = NULL; HANDLE privateNamespaceHandle = NULL; HANDLE blockTableHandle = NULL; HANDLE tokenHandle = NULL; diff --git a/TaskExplorer/API/Windows/WinModule.cpp b/TaskExplorer/API/Windows/WinModule.cpp index 0e7ee8e3..534f4cc1 100644 --- a/TaskExplorer/API/Windows/WinModule.cpp +++ b/TaskExplorer/API/Windows/WinModule.cpp @@ -38,7 +38,7 @@ bool CWinModule::InitStaticData(struct _PH_MODULE_INFO* module, quint64 ProcessH QWriteLocker Locker(&m_Mutex); m_IsLoaded = true; - m_FileName = CastPhString(module->FileName, false); + m_FileName = CastPhString(module->FileNameWin32, false); m_ModuleName = CastPhString(module->Name, false); m_BaseAddress = (quint64)module->BaseAddress; @@ -89,7 +89,7 @@ bool CWinModule::InitStaticData(struct _PH_MODULE_INFO* module, quint64 ProcessH // 1. It (should be) faster than opening the file and mapping it in, and // 2. It contains the correct original image base relocated by ASLR, if present. - m_Flags &= ~LDRP_IMAGE_NOT_AT_BASE; + //m_Flags &= ~LDRP_IMAGE_NOT_AT_BASE; if (NT_SUCCESS(PhLoadRemoteMappedImageEx((HANDLE)ProcessHandle, &m_BaseAddress, readVirtualMemoryCallback, &remoteMappedImage))) { @@ -116,8 +116,8 @@ bool CWinModule::InitStaticData(struct _PH_MODULE_INFO* module, quint64 ProcessH m_ImageDllCharacteristics = optionalHeader->DllCharacteristics; } - if (imageBase != (ULONG_PTR)m_BaseAddress) - m_Flags |= LDRP_IMAGE_NOT_AT_BASE; + //if (imageBase != (ULONG_PTR)m_BaseAddress) + // m_Flags |= LDRP_IMAGE_NOT_AT_BASE; if (entryPoint != 0) m_EntryPoint = (quint64)PTR_ADD_OFFSET(m_BaseAddress, entryPoint); @@ -348,7 +348,7 @@ QVariantMap CWinModule::InitAsyncData(QVariantMap Params) VERIFY_RESULT VerifyResult = VERIFY_RESULT(0); //VrUnknown PPH_STRING VerifySignerName = NULL; if(theConf->GetBool("Options/VerifySignatures", true)) - VerifyResult = PhVerifyFileCached(FileName, PackageFullName, &VerifySignerName, FALSE); + VerifyResult = PhVerifyFileCached(FileName, PackageFullName, &VerifySignerName, FALSE, FALSE); BOOLEAN IsPacked; ulong ImportFunctions; diff --git a/TaskExplorer/API/Windows/WinProcess.cpp b/TaskExplorer/API/Windows/WinProcess.cpp index 5f2f68d6..806d104f 100644 --- a/TaskExplorer/API/Windows/WinProcess.cpp +++ b/TaskExplorer/API/Windows/WinProcess.cpp @@ -1317,6 +1317,7 @@ static BOOLEAN NTAPI EnumModulesCallback(_In_ PPH_MODULE_INFO Module, _In_opt_ P copy = (PPH_MODULE_INFO)PhAllocateCopy(Module, sizeof(PH_MODULE_INFO)); PhReferenceObject(copy->Name); + PhReferenceObject(copy->FileNameWin32); PhReferenceObject(copy->FileName); PhAddItemList((PPH_LIST)Context, copy); @@ -1446,6 +1447,7 @@ bool CWinProcess::UpdateModules() PPH_MODULE_INFO module = (PPH_MODULE_INFO)modules->Items[i]; PhDereferenceObject(module->Name); + PhDereferenceObject(module->FileNameWin32); PhDereferenceObject(module->FileName); PhFree(module); } diff --git a/TaskExplorer/API/Windows/WindowsAPI.cpp b/TaskExplorer/API/Windows/WindowsAPI.cpp index 457ed95a..fa93344a 100644 --- a/TaskExplorer/API/Windows/WindowsAPI.cpp +++ b/TaskExplorer/API/Windows/WindowsAPI.cpp @@ -147,6 +147,8 @@ CWindowsAPI::CWindowsAPI(QObject *parent) : CSystemAPI(parent) m_uDriverStatus = 0; m_uDriverFeatures = 0; + //m_RpcUpdatePending = false; + m = new SWindowsAPI(); } @@ -1945,6 +1947,10 @@ bool CWindowsAPI::UpdateRpcList(void* server, void* protocol, QMap Added; QSet Changed; QSet Removed; @@ -1953,7 +1959,7 @@ bool CWindowsAPI::UpdateRpcList() UpdateRpcList(NULL, L"ncalrpc", OldRpcTableList, Added, Changed); - RPC_WSTR protocols[] = { + /*RPC_WSTR protocols[] = { (RPC_WSTR)L"ncacn_ip_tcp", (RPC_WSTR)L"ncadg_ip_udp", (RPC_WSTR)L"ncacn_np", @@ -1962,7 +1968,7 @@ bool CWindowsAPI::UpdateRpcList() }; for (int i = 0; i < 5; i++) { UpdateRpcList(L"127.0.0.1", protocols[i], OldRpcTableList, Added, Changed); - } + }*/ QWriteLocker Locker(&m_RpcTableMutex); foreach(QString TagName, OldRpcTableList.keys()) @@ -1980,6 +1986,8 @@ bool CWindowsAPI::UpdateRpcList() emit RpcListUpdated(Added, Changed, Removed); + //m_RpcUpdatePending = false; + return true; } diff --git a/TaskExplorer/API/Windows/WindowsAPI.h b/TaskExplorer/API/Windows/WindowsAPI.h index 4d6beecb..f7257d04 100644 --- a/TaskExplorer/API/Windows/WindowsAPI.h +++ b/TaskExplorer/API/Windows/WindowsAPI.h @@ -222,6 +222,7 @@ public slots: QHash > m_WindowMap; // > QHash > m_WindowRevMap; + //bool m_RpcUpdatePending; mutable QReadWriteLock m_RpcTableMutex; QMapm_RpcTableList; diff --git a/TaskExplorer/GUI/TaskExplorer.h b/TaskExplorer/GUI/TaskExplorer.h index 3417a33d..d6eb0503 100644 --- a/TaskExplorer/GUI/TaskExplorer.h +++ b/TaskExplorer/GUI/TaskExplorer.h @@ -10,7 +10,7 @@ #define VERSION_MJR 1 #define VERSION_MIN 4 -#define VERSION_REV 0 +#define VERSION_REV 1 #define VERSION_UPD 0 class CGraphBar; diff --git a/TaskExplorer/GUI/TaskInfo/ProcessView.cpp b/TaskExplorer/GUI/TaskInfo/ProcessView.cpp index 13f5f18c..bdc776a8 100644 --- a/TaskExplorer/GUI/TaskInfo/ProcessView.cpp +++ b/TaskExplorer/GUI/TaskInfo/ProcessView.cpp @@ -523,17 +523,36 @@ void CProcessView::OnCurrentChanged(const QModelIndex ¤t, const QModelInde void CProcessView::OnCertificate(const QString& Link) { #ifdef WIN32 - wstring fileName = Link.toStdWString(); - PH_VERIFY_FILE_INFO info; - memset(&info, 0, sizeof(PH_VERIFY_FILE_INFO)); - info.FileName = (wchar_t*)fileName.c_str(); - info.Flags = PH_VERIFY_VIEW_PROPERTIES; - info.hWnd = NULL; + NTSTATUS status; + HANDLE fileHandle; + + wstring fileName = Link.toStdWString(); PPH_STRING packageFullName = m_Processes.isEmpty() ? NULL : CastQString(m_Processes.first().staticCast()->GetPackageName()); - PhVerifyFileWithAdditionalCatalog(&info, packageFullName, NULL); + status = PhCreateFileWin32( + &fileHandle, + (wchar_t*)fileName.c_str(), + FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT + ); + + if (NT_SUCCESS(status)) + { + PH_VERIFY_FILE_INFO info; + + memset(&info, 0, sizeof(PH_VERIFY_FILE_INFO)); + info.FileHandle = fileHandle; + info.Flags = PH_VERIFY_VIEW_PROPERTIES; + info.hWnd = NULL; + PhVerifyFileWithAdditionalCatalog(&info, packageFullName, NULL); + + NtClose(fileHandle); + } PhDereferenceObject(packageFullName); #endif diff --git a/TaskExplorer/GUI/TaskInfo/SbieView.cpp b/TaskExplorer/GUI/TaskInfo/SbieView.cpp index 2e21e86e..fc5fc138 100644 --- a/TaskExplorer/GUI/TaskInfo/SbieView.cpp +++ b/TaskExplorer/GUI/TaskInfo/SbieView.cpp @@ -246,8 +246,10 @@ void CSbieView::ShowProcesses(const QList& Processes) FinishPaths(OldPaths, m_pKey, m_iKey, tr("Keys")); PrepPaths(OldPaths, m_pIpc); + UpdatePaths('in', OldPaths, m_pIpc); UpdatePaths('io', OldPaths, m_pIpc); UpdatePaths('ic', OldPaths, m_pIpc); + UpdatePaths('ir', OldPaths, m_pIpc); FinishPaths(OldPaths, m_pIpc, m_iIpc, tr("Ipc")); //OpenIpcPath=$:program.exe //Permits a program running inside the sandbox to have full access into the address space of a diff --git a/TaskExplorer/main.cpp b/TaskExplorer/main.cpp index b8fe44c6..34f3ae71 100644 --- a/TaskExplorer/main.cpp +++ b/TaskExplorer/main.cpp @@ -9,12 +9,16 @@ #include "API/Windows/WinAdmin.h" #include #include "../QtSingleApp/src/qtsingleapplication.h" +#include "../MiscHelpers/Common/qRC4.h" bool SkipUacRun(bool test_only = false); #endif CSettings* theConf = NULL; +void PackDriver(); +void UnPackDrivers(); + int main(int argc, char *argv[]) { #ifndef _DEBUG @@ -91,18 +95,29 @@ int main(int argc, char *argv[]) new QCoreApplication(argc, argv); else { #ifdef Q_OS_WIN - SetProcessDPIAware(); + //SetProcessDPIAware(); #endif // Q_OS_WIN - - //QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); //QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); //new QApplication(argc, argv); - QtSingleApplication* pApp = new QtSingleApplication(argc, argv); + pApp = new QtSingleApplication(argc, argv); } theConf = new CSettings("TaskExplorer"); +#ifdef WIN32 + //InitConsole(false); + if (pApp->arguments().contains("-rc4")) + { + PackDriver(); + return 0; + } + + if(IsElevated()) + UnPackDrivers(); +#endif + if (pApp && !theConf->GetBool("Options/AllowMultipleInstances", false) && !bMulti && pApp->sendMessage("ShowWnd")) return 0; @@ -203,3 +218,114 @@ int main(int argc, char *argv[]) return ret; } + + +bool TransformFile(const QString& InName, const QString& OutName, const QString& Key = "default_key") +{ + QFile InFile(InName); + QFile OutFile(OutName); + if (InFile.open(QIODevice::ReadOnly)) + { + if (OutFile.open(QIODevice::WriteOnly)) + { + rc4_sbox_s sbox; + rc4_init(&sbox, Key.toLatin1()); + OutFile.write(rc4_transform(&sbox, InFile.readAll())); + OutFile.flush(); + return true; + } + } + return false; +} + +bool TestFile(const QString& OutName) +{ + QThread::sleep(3); + return QFile::exists(OutName); +} + +void PackDriver() +{ + int pos = QCoreApplication::arguments().indexOf("-rc4"); + QString InName = QCoreApplication::arguments().at(pos + 1); + QString OutName = InName; + if (OutName.right(4) == ".rc4") + OutName.truncate(OutName.length() - 4); + else + OutName.append(".rc4"); + + if (TransformFile(InName, OutName)) + printf("success\r\n"); + else + printf("failed\r\n"); +} + +bool NotifyCert() +{ + QString Caption = QObject::tr( + "

Important Notie

" + ); + QString Text = QObject::tr( + "

TaskExplorer requires a driver to operate (xprocesshacker.sys), Windows however denies loading a driver file that has not been digitally signed.

" + "

Luckily brave hackers have Leaked a few of these Certificates over the years, one of them was found by the author of this software and put to good use.

" + "

Unfortunately, such certificates have been abused by malware authors resulting in many Anti Malware Fools being Lazy and flagging Everything signed with them Wrongfully as Malware. " + "This Prejudice is Damaging the Open Source Ecosystem.

" + "

Therefore, the required driver is provided in an obfuscated form and before use must be unpacked. " + "When doing so said Anti Viruses will complain and attempt to destroy the freshly created file. " + "Please be aware that this is a false positive caused by the necessary use of a compromised certificate. " + "If this happens you will be notified and offered the option to repeat the unpacking operation, for the operation to succeed you will need to configure an appropriate exemption.

" + + "

If you want to proceed with the unpacking of the driver press YES.

" + ); + QMessageBox *msgBox = new QMessageBox(NULL); + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setWindowTitle("TaskExplorer"); + msgBox->setText(Caption); + msgBox->setInformativeText(Text); + msgBox->setStandardButtons(QMessageBox::Yes); + msgBox->addButton(QMessageBox::No); + msgBox->setDefaultButton(QMessageBox::Yes); + + QIcon ico(QLatin1String(":/TaskExplorer.png")); + msgBox->setIconPixmap(ico.pixmap(64, 64)); + + return msgBox->exec() == QMessageBox::Yes; +} + +void UnPackDrivers() +{ + bool notifyNotOk = false; + QDir appDir(QApplication::applicationDirPath()); + foreach(const QString& FileName, appDir.entryList(QStringList("*.sys.rc4"), QDir::Files)) + { + QString InName = QApplication::applicationDirPath() + "/" + FileName; + QString OutName = InName.mid(0, InName.length() - 4); + + QFileInfo InInfo(InName); + QFileInfo OutInfo(OutName); + if (InInfo.size() != OutInfo.size() || InInfo.lastModified() > OutInfo.lastModified()) + { + if (theConf->GetBool("Options/NotifyUnPack", true)) { + if (!NotifyCert()) { + notifyNotOk = true; + break; + } + theConf->SetValue("Options/NotifyUnPack", false); + } + + retry: + if (!TransformFile(InName, OutName)) + QMessageBox::warning(NULL, "TaskExplorer", QObject::tr("Failed to decrypt %1 ensure app directory is writable.").arg(FileName)); + else if (!TestFile(OutName)) + { + if (QMessageBox("TaskExplorer", + QObject::tr("The decrypted file %1 seam to have been removed. Retry file extraction?").arg(FileName), + QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::Cancel, QMessageBox::NoButton).exec() == QMessageBox::Yes) + goto retry; + notifyNotOk = true; + } + } + } + if (notifyNotOk) + QMessageBox::warning(NULL, "TaskExplorer", QObject::tr("Without the Driver TaskExplorer wont be able to run properly.")); +} \ No newline at end of file