From 3464f77c749421f66809f4f6ed7e52437ec1c018 Mon Sep 17 00:00:00 2001 From: Valentin Radu Date: Mon, 27 Dec 2021 02:18:26 +0200 Subject: [PATCH] Fixed #598 (context menu of new Microsoft IME not working) --- CHANGELOG.md | 1 + ExplorerPatcher/dllmain.c | 71 ++++++++++++++++++++++++++++++++++++--- ExplorerPatcher/utility.h | 48 +++++++++++++++++++++++++- version.h | 6 ++-- 4 files changed, 118 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80be9c1..f17ec96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ Tested on OS build 22000.376. * Fixed a bug that displayed wrong window previews when the combine taskbar buttons option was set to never combine (#564) (.17) * Possibility to set position on screen (top/bottom) from the Properties UI * Restoring default settings only asks for elevation if required (for the moment, only if you have registered the application as shell extension) (.18) +* Fixed the context menu not working (and a potential associated crash) of the new Microsoft IME (#598, #588) (.19) (huge thanks to @Simplestas) #### Simple Window Switcher diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index 86bbeea..38464ec 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -40,6 +40,7 @@ #define POPUPMENU_BLUETOOTH_TIMEOUT 700 #define POPUPMENU_PNIDUI_TIMEOUT 300 #define POPUPMENU_SNDVOLSSO_TIMEOUT 300 +#define POPUPMENU_INPUTSWITCH_TIMEOUT 700 #define POPUPMENU_EX_ELAPSED 300 BOOL bIsExplorerProcess = FALSE; @@ -2693,6 +2694,60 @@ BOOL bthprops_TrackPopupMenuExHook( } return b; } +long long inputswitch_TrackPopupMenuExElapsed = 0; +BOOL inputswitch_TrackPopupMenuExHook( + HMENU hMenu, + UINT uFlags, + int x, + int y, + HWND hWnd, + LPTPMPARAMS lptpm +) +{ + long long elapsed = milliseconds_now() - inputswitch_TrackPopupMenuExElapsed; + BOOL b = FALSE; + if (elapsed > POPUPMENU_INPUTSWITCH_TIMEOUT || !bFlyoutMenus) + { + if (bCenterMenus) + { + PopupMenuAdjustCoordinatesAndFlags(&x, &y, &uFlags); + } + IsImmersiveMenu = FALSE; + if (!bSkinMenus) + { + EnumPropsA(hWnd, CheckIfImmersiveContextMenu); + if (IsImmersiveMenu) + { + if (ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc) + { + POINT pt; + pt.x = x; + pt.y = y; + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( + hMenu, + hWnd, + &(pt) + ); + } + else + { + RemoveOwnerDrawFromMenu(0, hMenu); + } + } + IsImmersiveMenu = FALSE; + } + b = TrackPopupMenuEx( + hMenu, + uFlags | TPM_RIGHTBUTTON, + x, + y, + hWnd, + lptpm + ); + inputswitch_TrackPopupMenuExElapsed = milliseconds_now(); + } + return b; +} #endif #pragma endregion @@ -2885,7 +2940,6 @@ HRESULT stobject_CoCreateInstanceHook( #pragma endregion - #pragma region "Show WiFi networks on network icon click" #ifdef _WIN64 HRESULT pnidui_CoCreateInstanceHook( @@ -5928,6 +5982,7 @@ BOOL explorer_SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) } #pragma endregion + DWORD InjectBasicFunctions(BOOL bIsExplorer, BOOL bInstall) { //Sleep(150); @@ -6508,6 +6563,7 @@ DWORD Inject(BOOL bIsExplorer) printf("Setup twinui.pcshell functions done\n"); + HANDLE hStobject = LoadLibraryW(L"stobject.dll"); VnPatchIAT(hStobject, "api-ms-win-core-registry-l1-1-0.dll", "RegGetValueW", stobject_RegGetValueW); VnPatchIAT(hStobject, "api-ms-win-core-com-l1-1-0.dll", "CoCreateInstance", stobject_CoCreateInstanceHook); @@ -6548,7 +6604,6 @@ DWORD Inject(BOOL bIsExplorer) - HANDLE hSndvolsso = LoadLibraryW(L"sndvolsso.dll"); VnPatchIAT(hSndvolsso, "user32.dll", "TrackPopupMenuEx", sndvolsso_TrackPopupMenuExHook); VnPatchIAT(hSndvolsso, "api-ms-win-core-registry-l1-1-0.dll", "RegGetValueW", sndvolsso_RegGetValueW); @@ -6562,8 +6617,6 @@ DWORD Inject(BOOL bIsExplorer) - - HANDLE hShell32 = GetModuleHandleW(L"shell32.dll"); if (hShell32) { @@ -6599,9 +6652,18 @@ DWORD Inject(BOOL bIsExplorer) } } } + printf("Setup shell32 functions done\n"); + HANDLE hInputSwitch = LoadLibraryW(L"InputSwitch.dll"); + printf("[IME] Context menu patch status: %d\n", PatchContextMenuOfNewMicrosoftIME(NULL)); + if (hInputSwitch) + { + VnPatchIAT(hInputSwitch, "user32.dll", "TrackPopupMenuEx", inputswitch_TrackPopupMenuExHook); + printf("Setup inputswitch functions done\n"); + } + rv = funchook_install(funchook, 0); @@ -6614,6 +6676,7 @@ DWORD Inject(BOOL bIsExplorer) + /*HANDLE hEvent = CreateEventEx( 0, L"ShellDesktopSwitchEvent", diff --git a/ExplorerPatcher/utility.h b/ExplorerPatcher/utility.h index 13c658f..d9c2ab3 100644 --- a/ExplorerPatcher/utility.h +++ b/ExplorerPatcher/utility.h @@ -475,4 +475,50 @@ inline BOOL IncrementDLLReferenceCount(HINSTANCE hinst) hinst, &hMod); } -#endif \ No newline at end of file + +inline BOOL WINAPI PatchContextMenuOfNewMicrosoftIME(BOOL* bFound) +{ + // huge thanks to @Simplestas: https://github.com/valinet/ExplorerPatcher/issues/598 + if (bFound) *bFound = FALSE; + const DWORD patch_from = 0x50653844, patch_to = 0x54653844; // cmp byte ptr [rbp+50h], r12b + HMODULE hInputSwitch = NULL; + if (!GetModuleHandleExW(0, L"InputSwitch.dll", &hInputSwitch)) + { + return FALSE; + } + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hInputSwitch; + PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)dosHeader + dosHeader->e_lfanew); + PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pNTHeader + 1); + char* mod = 0; + int i; + for (i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++) + { + //if (strcmp((char*)pSectionHeader[i].Name, ".text") == 0) + if ((pSectionHeader[i].Characteristics & IMAGE_SCN_CNT_CODE) && pSectionHeader[i].SizeOfRawData) + { + mod = (char*)dosHeader + pSectionHeader[i].VirtualAddress; + break; + } + } + if (!mod) + { + return FALSE; + } + for (size_t off = 0; off < pSectionHeader[i].Misc.VirtualSize - sizeof(DWORD); ++off) + { + DWORD* ptr = (DWORD*)(mod + off); + if (*ptr == patch_from) + { + if (bFound) *bFound = TRUE; + DWORD prot; + if (VirtualProtect(ptr, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &prot)) + { + *ptr = patch_to; + VirtualProtect(ptr, sizeof(DWORD), prot, &prot); + } + break; + } + } + return TRUE; +} +#endif diff --git a/version.h b/version.h index be8c43e..94538de 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define VER_MAJOR 22000 #define VER_MINOR 376 #define VER_BUILD_HI 40 -#define VER_BUILD_LO 18 +#define VER_BUILD_LO 19 #define VER_FLAGS VS_FF_PRERELEASE @@ -12,5 +12,5 @@ #define VER_STR(arg) #arg // The String form of the version numbers -#define VER_FILE_STRING VALUE "FileVersion", "22000.376.40.18" -#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.376.40.18" +#define VER_FILE_STRING VALUE "FileVersion", "22000.376.40.19" +#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.376.40.19"