|
29 | 29 | #define _LIBVALINET_DEBUG_HOOKING_IATPATCH
|
30 | 30 | #endif
|
31 | 31 | #include <valinet/hooking/iatpatch.h>
|
| 32 | +#include <valinet/utility/memmem.h> |
32 | 33 |
|
33 | 34 | #define EP_CLSID "{D17F1E1A-5919-4427-8F89-A1A8503CA3EB}"
|
34 | 35 |
|
@@ -66,6 +67,7 @@ DWORD bClassicThemeMitigations = FALSE;
|
66 | 67 | DWORD bHookStartMenu = TRUE;
|
67 | 68 | DWORD bNoMenuAccelerator = FALSE;
|
68 | 69 | DWORD bTaskbarMonitorOverride = 0;
|
| 70 | +DWORD dwIMEStyle = 0; |
69 | 71 | HMODULE hModule = NULL;
|
70 | 72 | HANDLE hSettingsMonitorThread = NULL;
|
71 | 73 | HANDLE hDelayedInjectionThread = NULL;
|
@@ -2941,6 +2943,15 @@ void WINAPI LoadSettings(BOOL bIsExplorer)
|
2941 | 2943 | &bTaskbarMonitorOverride,
|
2942 | 2944 | &dwSize
|
2943 | 2945 | );
|
| 2946 | + dwSize = sizeof(DWORD); |
| 2947 | + RegQueryValueExW( |
| 2948 | + hKey, |
| 2949 | + TEXT("IMEStyle"), |
| 2950 | + 0, |
| 2951 | + NULL, |
| 2952 | + &dwIMEStyle, |
| 2953 | + &dwSize |
| 2954 | + ); |
2944 | 2955 | RegCloseKey(hKey);
|
2945 | 2956 | }
|
2946 | 2957 |
|
@@ -3613,6 +3624,7 @@ HRESULT explorer_DrawThemeTextEx(
|
3613 | 3624 | #pragma endregion
|
3614 | 3625 |
|
3615 | 3626 |
|
| 3627 | +#pragma region "Change clock links" |
3616 | 3628 | HINSTANCE explorer_ShellExecuteW(
|
3617 | 3629 | HWND hwnd,
|
3618 | 3630 | LPCWSTR lpOperation,
|
@@ -3640,6 +3652,102 @@ HINSTANCE explorer_ShellExecuteW(
|
3640 | 3652 | }
|
3641 | 3653 | return ShellExecuteW(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd);
|
3642 | 3654 | }
|
| 3655 | +#pragma endregion |
| 3656 | + |
| 3657 | + |
| 3658 | +#pragma region "Change language UI style" |
| 3659 | +DEFINE_GUID(CLSID_InputSwitchControl, |
| 3660 | + 0xB9BC2A50, |
| 3661 | + 0x43C3, 0x41AA, 0xa0, 0x86, |
| 3662 | + 0x5D, 0xB1, 0x4e, 0x18, 0x4b, 0xae |
| 3663 | +); |
| 3664 | + |
| 3665 | +DEFINE_GUID(IID_InputSwitchControl, |
| 3666 | + 0xB9BC2A50, |
| 3667 | + 0x43C3, 0x41AA, 0xa0, 0x82, |
| 3668 | + 0x5D, 0xB1, 0x4e, 0x18, 0x4b, 0xae |
| 3669 | +); |
| 3670 | + |
| 3671 | +#define LANGUAGEUI_STYLE_DESKTOP 0 |
| 3672 | +#define LANGUAGEUI_STYLE_TOUCHKEYBOARD 1 |
| 3673 | +#define LANGUAGEUI_STYLE_LOGONUI 2 |
| 3674 | +#define LANGUAGEUI_STYLE_UAC 3 |
| 3675 | +#define LANGUAGEUI_STYLE_SETTINGSPANE 4 |
| 3676 | +#define LANGUAGEUI_STYLE_OOBE 5 |
| 3677 | +#define LANGUAGEUI_STYLE_OTHER 100 |
| 3678 | + |
| 3679 | +char mov_edx_val[6] = { 0xBA, 0x00, 0x00, 0x00, 0x00, 0xC3 }; |
| 3680 | +char* ep_pf = NULL; |
| 3681 | + |
| 3682 | +HRESULT explorer_CoCreateInstanceHook( |
| 3683 | + REFCLSID rclsid, |
| 3684 | + LPUNKNOWN pUnkOuter, |
| 3685 | + DWORD dwClsContext, |
| 3686 | + REFIID riid, |
| 3687 | + LPVOID* ppv |
| 3688 | +) |
| 3689 | +{ |
| 3690 | + if (IsEqualCLSID(rclsid, &CLSID_InputSwitchControl) && IsEqualIID(riid, &IID_InputSwitchControl)) |
| 3691 | + { |
| 3692 | + HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); |
| 3693 | + if (SUCCEEDED(hr)) |
| 3694 | + { |
| 3695 | + // Pff... how this works: |
| 3696 | + // |
| 3697 | + // * This `CoCreateInstance` call will get a pointer to an IInputSwitchControl interface |
| 3698 | + // (the call to here is made from `explorer!CTrayInputIndicator::_RegisterInputSwitch`); |
| 3699 | + // the next call on this pointer will be on the `IInputSwitchControl::Init` function. |
| 3700 | + // |
| 3701 | + // * `IInputSwitchControl::Init`'s second parameter is a number (x) which tells which |
| 3702 | + // language switcher UI to prepare (check `IsUtil::MapClientTypeToString` in |
| 3703 | + // `InputSwitch.dll`). "explorer" requests the "DESKTOP" UI (x = 0), which is the new |
| 3704 | + // Windows 11 UI; if we replace that number with something else, some other UI will |
| 3705 | + // be created |
| 3706 | + // |
| 3707 | + // * We cannot patch the vtable of the COM object because the executable is protected |
| 3708 | + // by control flow guard and we would make a jump to an invalid site (maybe there is |
| 3709 | + // some clever workaround fpr this as well, somehow telling the compiler to place a certain |
| 3710 | + // canary before our trampoline, so it matches with what the runtime support for CFG expects, |
| 3711 | + // but we'd have to keep that canary in sync with the one in explorer.exe, so not very |
| 3712 | + // future proof). |
| 3713 | + // |
| 3714 | + // * Taking advantage of the fact that the call to `IInputSwitchControl::Init` is the thing |
| 3715 | + // that happens right after we return from here, and looking on the disassembly, we see nothing |
| 3716 | + // else changes `rdx` (which is the second argument to a function call), basically x, besides the |
| 3717 | + // very `xor edx, edx` instruction before the call. Thus, we patch that out, and we also do |
| 3718 | + // `mov edx, whatever` here; afterwards, we do NOTHING else, but just return and hope that |
| 3719 | + // edx will stick |
| 3720 | + // |
| 3721 | + // * Needless to say this is **HIGHLY** amd64 |
| 3722 | + char pattern[2] = { 0x33, 0xD2 }; |
| 3723 | + DWORD dwOldProtect; |
| 3724 | + char* p_mov_edx_val = mov_edx_val; |
| 3725 | + if (!ep_pf) |
| 3726 | + { |
| 3727 | + ep_pf = memmem(_ReturnAddress(), 200, pattern, 2); |
| 3728 | + if (ep_pf) |
| 3729 | + { |
| 3730 | + // Cancel out `xor edx, edx` |
| 3731 | + VirtualProtect(ep_pf, 2, PAGE_EXECUTE_READWRITE, &dwOldProtect); |
| 3732 | + memset(ep_pf, 0x90, 2); |
| 3733 | + VirtualProtect(ep_pf, 2, dwOldProtect, &dwOldProtect); |
| 3734 | + } |
| 3735 | + VirtualProtect(p_mov_edx_val, 6, PAGE_EXECUTE_READWRITE, &dwOldProtect); |
| 3736 | + } |
| 3737 | + if (ep_pf) |
| 3738 | + { |
| 3739 | + // Craft a "function" which does `mov edx, whatever; ret` and call it |
| 3740 | + DWORD* pVal = mov_edx_val + 1; |
| 3741 | + *pVal = dwIMEStyle; |
| 3742 | + void(*pf_mov_edx_val)() = p_mov_edx_val; |
| 3743 | + pf_mov_edx_val(); |
| 3744 | + } |
| 3745 | + } |
| 3746 | + return hr; |
| 3747 | + } |
| 3748 | + return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); |
| 3749 | +} |
| 3750 | +#pragma endregion |
3643 | 3751 |
|
3644 | 3752 |
|
3645 | 3753 | DWORD InjectBasicFunctions(BOOL bIsExplorer, BOOL bInstall)
|
@@ -4161,6 +4269,10 @@ __declspec(dllexport) DWORD WINAPI main(
|
4161 | 4269 | VnPatchIAT(hExplorer, "user32.dll", "SetWindowCompositionAttribute", explorer_SetWindowCompositionAttribute);
|
4162 | 4270 | }
|
4163 | 4271 | //VnPatchDelayIAT(hExplorer, "ext-ms-win-rtcore-ntuser-window-ext-l1-1-0.dll", "CreateWindowExW", explorer_CreateWindowExW);
|
| 4272 | + if (dwIMEStyle) |
| 4273 | + { |
| 4274 | + VnPatchIAT(hExplorer, "api-ms-win-core-com-l1-1-0.dll", "CoCreateInstance", explorer_CoCreateInstanceHook); |
| 4275 | + } |
4164 | 4276 |
|
4165 | 4277 |
|
4166 | 4278 | #ifdef USE_PRIVATE_INTERFACES
|
|
0 commit comments