From 5c35f5862fabb692803843ef368a2aa557344330 Mon Sep 17 00:00:00 2001 From: Amrsatrio Date: Wed, 13 Mar 2024 06:57:27 +0700 Subject: [PATCH] Taskbar10: Fixed a bug where SCOOBE would repeatedly crash Explorer when Language Switcher is set to anything other than Windows 11 (the default) ^2 --- ExplorerPatcher/ExplorerPatcher.vcxproj | 5 + ExplorerPatcher/InputSwitch.cpp | 198 ++++++++++++++++++++++++ ExplorerPatcher/InputSwitch.h | 122 +++++++++++++++ ExplorerPatcher/dllmain.c | 192 ++--------------------- 4 files changed, 339 insertions(+), 178 deletions(-) create mode 100644 ExplorerPatcher/InputSwitch.cpp create mode 100644 ExplorerPatcher/InputSwitch.h diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj index 0f3e999..ba2daba 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj @@ -266,6 +266,10 @@ true true + + true + true + true @@ -334,6 +338,7 @@ + diff --git a/ExplorerPatcher/InputSwitch.cpp b/ExplorerPatcher/InputSwitch.cpp new file mode 100644 index 0000000..0bce70a --- /dev/null +++ b/ExplorerPatcher/InputSwitch.cpp @@ -0,0 +1,198 @@ +#include "InputSwitch.h" + +#include +#include +#include + +#define TB_POS_NOWHERE 0 +#define TB_POS_BOTTOM 1 +#define TB_POS_TOP 2 +#define TB_POS_LEFT 3 +#define TB_POS_RIGHT 4 +extern "C" UINT GetTaskbarLocationAndSize(POINT ptCursor, RECT* rc); + +extern "C" __MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 dwIMEStyle; +extern "C" HRESULT CInputSwitchControl_ModifyAnchor(UINT dwNumberOfProfiles, RECT* lpRect); + +HRESULT CInputSwitchControl_ModifyAnchor(UINT dwNumberOfProfiles, RECT* lpRect) +{ + if (!dwIMEStyle) // impossible case (this is not called for the Windows 11 language switcher), but just in case + { + return S_FALSE; + } + + HWND hWndTaskbar = FindWindowW(L"Shell_TrayWnd", NULL); + + UINT dpiX = 96, dpiY = 96; + HRESULT hr = GetDpiForMonitor( + MonitorFromWindow(hWndTaskbar, MONITOR_DEFAULTTOPRIMARY), + MDT_DEFAULT, + &dpiX, + &dpiY + ); + double dpix = dpiX / 96.0; + double dpiy = dpiY / 96.0; + + //printf("RECT %d %d %d %d - %d %d\n", lpRect->left, lpRect->right, lpRect->top, lpRect->bottom, dwNumberOfProfiles, a3); + + RECT rc; + GetWindowRect(hWndTaskbar, &rc); + POINT pt; + pt.x = rc.left; + pt.y = rc.top; + UINT tbPos = GetTaskbarLocationAndSize(pt, &rc); + if (tbPos == TB_POS_BOTTOM) + { + } + else if (tbPos == TB_POS_TOP) + { + if (dwIMEStyle == 1) // Windows 10 (with Language preferences link) + { + lpRect->top = rc.top + (rc.bottom - rc.top) + (UINT)(((double)dwNumberOfProfiles * (60.0 * dpiy)) + (5.0 * dpiy * 4.0) + (dpiy) + (48.0 * dpiy)); + } + else if (dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) // LOGONUI, UAC, Windows 10, OOBE + { + lpRect->top = rc.top + (rc.bottom - rc.top) + (UINT)(((double)dwNumberOfProfiles * (60.0 * dpiy)) + (5.0 * dpiy * 2.0)); + } + } + else if (tbPos == TB_POS_LEFT) + { + if (dwIMEStyle == 1 || dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) + { + lpRect->right = rc.left + (rc.right - rc.left) + (UINT)((double)(300.0 * dpix)); + lpRect->top += (lpRect->bottom - lpRect->top); + } + } + if (tbPos == TB_POS_RIGHT) + { + if (dwIMEStyle == 1 || dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) + { + lpRect->right = lpRect->right - (rc.right - rc.left); + lpRect->top += (lpRect->bottom - lpRect->top); + } + } + + if (dwIMEStyle == 4) + { + lpRect->right -= (UINT)((double)(300.0 * dpix)) - (lpRect->right - lpRect->left); + } + + return S_OK; +} + +class CInputSwitchControlProxy : public Microsoft::WRL::RuntimeClass, IInputSwitchControl> +{ +public: + CInputSwitchControlProxy() + : m_type((__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001)-1) + { + } + + HRESULT RuntimeClassInitialize(IInputSwitchControl* original) + { + m_original = original; + return S_OK; + } + + STDMETHODIMP Init(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 type) override + { + m_type = type; + return m_original->Init(type == ISCT_IDL_DESKTOP && dwIMEStyle != ISCT_IDL_DESKTOP ? dwIMEStyle : type); + } + + STDMETHODIMP ShowInputSwitch(const RECT* rect) override + { + RECT myRect = *rect; + if (m_type == ISCT_IDL_DESKTOP) + { + UINT dwNumberOfProfiles = 0; + BOOL bImePresent = FALSE; + m_original->GetProfileCount(&dwNumberOfProfiles, &bImePresent); + CInputSwitchControl_ModifyAnchor(dwNumberOfProfiles, &myRect); + } + return m_original->ShowInputSwitch(&myRect); + } + + STDMETHODIMP SetCallback(IInputSwitchCallback* callback) override { return m_original->SetCallback(callback); } + STDMETHODIMP GetProfileCount(UINT* count, BOOL* bOutImePresent) override { return m_original->GetProfileCount(count, bOutImePresent); } + STDMETHODIMP GetCurrentProfile(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0002* data) override { return m_original->GetCurrentProfile(data); } + STDMETHODIMP RegisterHotkeys() override { return m_original->RegisterHotkeys(); } + STDMETHODIMP ClickImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004 type, POINT point, const RECT* rect) override { return m_original->ClickImeModeItem(type, point, rect); } + STDMETHODIMP ForceHide() override { return m_original->ForceHide(); } + STDMETHODIMP ShowTouchKeyboardInputSwitch(const RECT* rect, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0006 align, int a3, DWORD a4, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0005 a5) override { return m_original->ShowTouchKeyboardInputSwitch(rect, align, a3, a4, a5); } + STDMETHODIMP GetContextFlags(DWORD* flags) override { return m_original->GetContextFlags(flags); } + STDMETHODIMP SetContextOverrideMode(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0008 mode) override { return m_original->SetContextOverrideMode(mode); } + STDMETHODIMP GetCurrentImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0003* data) override { return m_original->GetCurrentImeModeItem(data); } + STDMETHODIMP ActivateInputProfile(const WCHAR* profile) override { return m_original->ActivateInputProfile(profile); } + STDMETHODIMP SetUserSid(const WCHAR* sid) override { return m_original->SetUserSid(sid); } + +private: + Microsoft::WRL::ComPtr m_original; + __MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 m_type; +}; + +HRESULT CInputSwitchControlProxy_CreateInstance(IInputSwitchControl* original, REFIID riid, void** ppvObject) +{ + Microsoft::WRL::ComPtr proxy; + RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&proxy, original)); + RETURN_HR(proxy.CopyTo(riid, ppvObject)); +} + +class CInputSwitchControlProxySV2 : public Microsoft::WRL::RuntimeClass, IInputSwitchControlSV2> +{ +public: + CInputSwitchControlProxySV2() + : m_type((__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001)-1) + { + } + + HRESULT RuntimeClassInitialize(IInputSwitchControlSV2* original) + { + m_original = original; + return S_OK; + } + + STDMETHODIMP Init(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 type) override + { + m_type = type; + return m_original->Init(type == ISCT_IDL_DESKTOP && dwIMEStyle != ISCT_IDL_DESKTOP ? dwIMEStyle : type); + } + + STDMETHODIMP ShowInputSwitch(const RECT* rect) override + { + RECT myRect = *rect; + if (m_type == ISCT_IDL_DESKTOP) + { + UINT dwNumberOfProfiles = 0; + BOOL bImePresent = FALSE; + m_original->GetProfileCount(&dwNumberOfProfiles, &bImePresent); + CInputSwitchControl_ModifyAnchor(dwNumberOfProfiles, &myRect); + } + return m_original->ShowInputSwitch(&myRect); + } + + STDMETHODIMP SetCallback(IInputSwitchCallback* callback) override { return m_original->SetCallback(callback); } + STDMETHODIMP GetProfileCount(UINT* count, BOOL* bOutImePresent) override { return m_original->GetProfileCount(count, bOutImePresent); } + STDMETHODIMP GetCurrentProfile(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0002* data) override { return m_original->GetCurrentProfile(data); } + STDMETHODIMP RegisterHotkeys() override { return m_original->RegisterHotkeys(); } + STDMETHODIMP ClickImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004 type, POINT point, const RECT* rect) override { return m_original->ClickImeModeItem(type, point, rect); } + STDMETHODIMP ClickImeModeItemWithAnchor(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004 type, IUnknown* anchor) override { return m_original->ClickImeModeItemWithAnchor(type, anchor); } + STDMETHODIMP ForceHide() override { return m_original->ForceHide(); } + STDMETHODIMP ShowTouchKeyboardInputSwitch(const RECT* rect, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0006 align, int a3, DWORD a4, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0005 a5) override { return m_original->ShowTouchKeyboardInputSwitch(rect, align, a3, a4, a5); } + STDMETHODIMP GetContextFlags(DWORD* flags) override { return m_original->GetContextFlags(flags); } + STDMETHODIMP SetContextOverrideMode(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0008 mode) override { return m_original->SetContextOverrideMode(mode); } + STDMETHODIMP GetCurrentImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0003* data) override { return m_original->GetCurrentImeModeItem(data); } + STDMETHODIMP ActivateInputProfile(const WCHAR* profile) override { return m_original->ActivateInputProfile(profile); } + STDMETHODIMP SetUserSid(const WCHAR* sid) override { return m_original->SetUserSid(sid); } + +private: + Microsoft::WRL::ComPtr m_original; + __MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 m_type; +}; + +HRESULT CInputSwitchControlProxySV2_CreateInstance(IInputSwitchControlSV2* original, REFIID riid, void** ppvObject) +{ + Microsoft::WRL::ComPtr proxy; + RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&proxy, original)); + RETURN_HR(proxy.CopyTo(riid, ppvObject)); +} diff --git a/ExplorerPatcher/InputSwitch.h b/ExplorerPatcher/InputSwitch.h new file mode 100644 index 0000000..daa1ef0 --- /dev/null +++ b/ExplorerPatcher/InputSwitch.h @@ -0,0 +1,122 @@ +#pragma once + +#include + +DEFINE_GUID(CLSID_InputSwitchControl, 0xb9bc2a50, 0x43c3, 0x41aa, 0xa0, 0x86, 0x5d, 0xb1, 0x4e, 0x18, 0x4b, 0xae); +DEFINE_GUID(IID_IInputSwitchControl, 0xb9bc2a50, 0x43c3, 0x41aa, 0xa0, 0x82, 0x5d, 0xb1, 0x4e, 0x18, 0x4b, 0xae); + +enum __MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 +{ + ISCT_IDL_DESKTOP, + ISCT_IDL_TOUCHKEYBOARD, + ISCT_IDL_LOGONUI, + ISCT_IDL_UAC, + ISCT_IDL_SETTINGSPANE, + ISCT_IDL_OOBE, + ISCT_IDL_USEROOBE +}; + +struct __MIDL___MIDL_itf_inputswitchserver_0000_0000_0002 +{ + int dummy; // We don't need its contents +}; + +struct __MIDL___MIDL_itf_inputswitchserver_0000_0000_0003 +{ + WCHAR* pszTooltip; + HICON hIcon; + BOOL fDisabled; + BOOL fHidden; + WCHAR* pszIconGlyph; +}; + +enum __MIDL___MIDL_itf_inputswitchserver_0000_0000_0004 +{ + INPUT_SWITCH_IDL_IME_CLICK_TYPE_LEFT, + INPUT_SWITCH_IDL_IME_CLICK_TYPE_RIGHT, + INPUT_SWITCH_IDL_IME_CLICK_TYPE_LEFT_DISABLED +}; + +enum __MIDL___MIDL_itf_inputswitchserver_0000_0000_0005 +{ + INPUT_SWITCH_IDL_MODALITY_STANDARDKEYBOARD = 0x1, + INPUT_SWITCH_IDL_MODALITY_SPLITKEYBOARD = 0x2, + INPUT_SWITCH_IDL_MODALITY_CLASSICKEYBOARD = 0x4, + INPUT_SWITCH_IDL_MODALITY_HANDWRITING = 0x8, + INPUT_SWITCH_IDL_MODALITY_HIDE = 0x10, + INPUT_SWITCH_IDL_MODALITY_ONEHANDEDKEYBOARD = 0x20, +}; + +enum __MIDL___MIDL_itf_inputswitchserver_0000_0000_0006 +{ + INPUT_SWITCH_IDL_ALIGN_DEFAULT, + INPUT_SWITCH_IDL_ALIGN_RIGHT_EDGE, + INPUT_SWITCH_IDL_ALIGN_LEFT_EDGE, +}; + +enum __MIDL___MIDL_itf_inputswitchserver_0000_0000_0008 +{ + INPUT_SWITCH_IDL_CFOM_NO_OVERRIDE, + INPUT_SWITCH_IDL_CFOM_DESKTOP, + INPUT_SWITCH_IDL_CFOM_IMMERSIVE, +}; + +interface IInputSwitchCallback; + +#ifdef __cplusplus +MIDL_INTERFACE("b9bc2a50-43c3-41aa-a082-5db14e184bae") +IInputSwitchControl : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE Init(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001) = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback(IInputSwitchCallback*) = 0; + virtual HRESULT STDMETHODCALLTYPE ShowInputSwitch(const RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetProfileCount(UINT*, BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentProfile(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0002*) = 0; + virtual HRESULT STDMETHODCALLTYPE RegisterHotkeys() = 0; + virtual HRESULT STDMETHODCALLTYPE ClickImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004, POINT, const RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE ForceHide() = 0; + virtual HRESULT STDMETHODCALLTYPE ShowTouchKeyboardInputSwitch(const RECT*, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0006, int, DWORD, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0005) = 0; + virtual HRESULT STDMETHODCALLTYPE GetContextFlags(DWORD*) = 0; + virtual HRESULT STDMETHODCALLTYPE SetContextOverrideMode(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0008) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0003*) = 0; + virtual HRESULT STDMETHODCALLTYPE ActivateInputProfile(const WCHAR*) = 0; + virtual HRESULT STDMETHODCALLTYPE SetUserSid(const WCHAR*) = 0; +}; +#else +typedef interface IInputSwitchControl IInputSwitchControl; +#endif + +#ifdef __cplusplus +MIDL_INTERFACE("b9bc2a50-43c3-41aa-a082-5db14e184bae") +IInputSwitchControlSV2 : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE Init(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001) = 0; + virtual HRESULT STDMETHODCALLTYPE SetCallback(IInputSwitchCallback*) = 0; + virtual HRESULT STDMETHODCALLTYPE ShowInputSwitch(const RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetProfileCount(UINT*, BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentProfile(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0002*) = 0; + virtual HRESULT STDMETHODCALLTYPE RegisterHotkeys() = 0; + virtual HRESULT STDMETHODCALLTYPE ClickImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004, POINT, const RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE ClickImeModeItemWithAnchor(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0004, IUnknown*) = 0; + virtual HRESULT STDMETHODCALLTYPE ForceHide() = 0; + virtual HRESULT STDMETHODCALLTYPE ShowTouchKeyboardInputSwitch(const RECT*, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0006, int, DWORD, __MIDL___MIDL_itf_inputswitchserver_0000_0000_0005) = 0; + virtual HRESULT STDMETHODCALLTYPE GetContextFlags(DWORD*) = 0; + virtual HRESULT STDMETHODCALLTYPE SetContextOverrideMode(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0008) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentImeModeItem(__MIDL___MIDL_itf_inputswitchserver_0000_0000_0003*) = 0; + virtual HRESULT STDMETHODCALLTYPE ActivateInputProfile(const WCHAR*) = 0; + virtual HRESULT STDMETHODCALLTYPE SetUserSid(const WCHAR*) = 0; +}; +#else +typedef interface IInputSwitchControlSV2 IInputSwitchControlSV2; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +HRESULT CInputSwitchControlProxy_CreateInstance(IInputSwitchControl* original, REFIID riid, void** ppvObject); +HRESULT CInputSwitchControlProxySV2_CreateInstance(IInputSwitchControlSV2* original, REFIID riid, void** ppvObject); + +#ifdef __cplusplus +} +#endif diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index 1934100..f620431 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -205,6 +205,7 @@ BOOL g_bIsDesktopRaised = FALSE; #include "symbols.h" #include "dxgi_imp.h" #include "ArchiveMenu.h" +#include "InputSwitch.h" #include "StartupSound.h" #include "StartMenu.h" #include "TaskbarCenter.h" @@ -8807,197 +8808,32 @@ HRESULT ExplorerFrame_CoCreateInstanceHook(REFCLSID rclsid, LPUNKNOWN pUnkOuter, #pragma region "Change language UI style + Enable old taskbar" #ifdef _WIN64 -DEFINE_GUID(CLSID_InputSwitchControl, - 0xB9BC2A50, - 0x43C3, 0x41AA, 0xa0, 0x86, - 0x5D, 0xB1, 0x4e, 0x18, 0x4b, 0xae -); - -DEFINE_GUID(IID_IInputSwitchControl, - 0xB9BC2A50, - 0x43C3, 0x41AA, 0xa0, 0x82, - 0x5D, 0xB1, 0x4e, 0x18, 0x4b, 0xae -); - -#define LANGUAGEUI_STYLE_DESKTOP 0 // Windows 11 style -#define LANGUAGEUI_STYLE_TOUCHKEYBOARD 1 // Windows 10 style -#define LANGUAGEUI_STYLE_LOGONUI 2 -#define LANGUAGEUI_STYLE_UAC 3 -#define LANGUAGEUI_STYLE_SETTINGSPANE 4 -#define LANGUAGEUI_STYLE_OOBE 5 -#define LANGUAGEUI_STYLE_OTHER 100 - -// char mov_edx_val[6] = { 0xBA, 0x00, 0x00, 0x00, 0x00, 0xC3 }; -// char* ep_pf = NULL; - -typedef interface IInputSwitchControl IInputSwitchControl; - -typedef struct IInputSwitchControlVtbl -{ - BEGIN_INTERFACE - - HRESULT(STDMETHODCALLTYPE* QueryInterface)( - IInputSwitchControl* This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void** ppvObject); - - ULONG(STDMETHODCALLTYPE* AddRef)( - IInputSwitchControl* This); - - ULONG(STDMETHODCALLTYPE* Release)( - IInputSwitchControl* This); - - HRESULT(STDMETHODCALLTYPE* Init)( - IInputSwitchControl* This, - /* [in] */ unsigned int clientType); - - HRESULT(STDMETHODCALLTYPE* SetCallback)( - IInputSwitchControl* This, - /* [in] */ void* pInputSwitchCallback); - - HRESULT(STDMETHODCALLTYPE* ShowInputSwitch)( - IInputSwitchControl* This, - /* [in] */ RECT* lpRect); - - HRESULT(STDMETHODCALLTYPE* GetProfileCount)( - IInputSwitchControl* This, - /* [in] */ unsigned int* pOutNumberOfProfiles, - /* [in] */ int* a3); - - // ... - - END_INTERFACE -} IInputSwitchControlVtbl; - -interface IInputSwitchControl -{ - CONST_VTBL struct IInputSwitchControlVtbl* lpVtbl; -}; - -IInputSwitchControl* g_pDesktopInputSwitchControl; - -HRESULT(*CInputSwitchControl_InitFunc)(IInputSwitchControl*, unsigned int); -HRESULT CInputSwitchControl_InitHook(IInputSwitchControl* _this, unsigned int dwOriginalIMEStyle) -{ - // Note: Other than in explorer.exe!CTrayInputIndicator::_RegisterInputSwitch, we're also called by - // explorer.exe!HostAppEnvironment::_SetupInputSwitchServer which passes ISCT_IDL_USEROOBE (6) as the style. - if (dwOriginalIMEStyle == 0) // ISCT_IDL_DESKTOP - { - g_pDesktopInputSwitchControl = _this; - } - return CInputSwitchControl_InitFunc(_this, dwOriginalIMEStyle == 0 && dwIMEStyle ? dwIMEStyle : dwOriginalIMEStyle); -} - -HRESULT (*CInputSwitchControl_ShowInputSwitchFunc)(IInputSwitchControl*, RECT*); -HRESULT CInputSwitchControl_ShowInputSwitchHook(IInputSwitchControl* _this, RECT* lpRect) -{ - if (_this != g_pDesktopInputSwitchControl || !dwIMEStyle) // impossible case (this is not called for the Windows 11 language switcher), but just in case - { - return CInputSwitchControl_ShowInputSwitchFunc(_this, lpRect); - } - - unsigned int dwNumberOfProfiles = 0; - int a3 = 0; - _this->lpVtbl->GetProfileCount(_this, &dwNumberOfProfiles, &a3); - - HWND hWndTaskbar = FindWindowW(L"Shell_TrayWnd", NULL); - - UINT dpiX = 96, dpiY = 96; - HRESULT hr = GetDpiForMonitor( - MonitorFromWindow(hWndTaskbar, MONITOR_DEFAULTTOPRIMARY), - MDT_DEFAULT, - &dpiX, - &dpiY - ); - double dpix = dpiX / 96.0; - double dpiy = dpiY / 96.0; - - //printf("RECT %d %d %d %d - %d %d\n", lpRect->left, lpRect->right, lpRect->top, lpRect->bottom, dwNumberOfProfiles, a3); - - RECT rc; - GetWindowRect(hWndTaskbar, &rc); - POINT pt; - pt.x = rc.left; - pt.y = rc.top; - UINT tbPos = GetTaskbarLocationAndSize(pt, &rc); - if (tbPos == TB_POS_BOTTOM) - { - } - else if (tbPos == TB_POS_TOP) - { - if (dwIMEStyle == 1) // Windows 10 (with Language preferences link) - { - lpRect->top = rc.top + (rc.bottom - rc.top) + (UINT)(((double)dwNumberOfProfiles * (60.0 * dpiy)) + (5.0 * dpiy * 4.0) + (dpiy) + (48.0 * dpiy)); - } - else if (dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) // LOGONUI, UAC, Windows 10, OOBE - { - lpRect->top = rc.top + (rc.bottom - rc.top) + (UINT)(((double)dwNumberOfProfiles * (60.0 * dpiy)) + (5.0 * dpiy * 2.0)); - } - } - else if (tbPos == TB_POS_LEFT) - { - if (dwIMEStyle == 1 || dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) - { - lpRect->right = rc.left + (rc.right - rc.left) + (UINT)((double)(300.0 * dpix)); - lpRect->top += (lpRect->bottom - lpRect->top); - } - } - if (tbPos == TB_POS_RIGHT) - { - if (dwIMEStyle == 1 || dwIMEStyle == 2 || dwIMEStyle == 3 || dwIMEStyle == 4 || dwIMEStyle == 5) - { - lpRect->right = lpRect->right - (rc.right - rc.left); - lpRect->top += (lpRect->bottom - lpRect->top); - } - } - - if (dwIMEStyle == 4) - { - lpRect->right -= (UINT)((double)(300.0 * dpix)) - (lpRect->right - lpRect->left); - } - - return CInputSwitchControl_ShowInputSwitchFunc(_this, lpRect); -} - DEFINE_GUID(CLSID_TrayUIComponent, 0x88FC85D3, 0x7090, 0x4F53, 0x8F, 0x7A, 0xEB, 0x02, 0x68, 0x16, 0x27, 0x88 ); -HRESULT explorer_CoCreateInstanceHook( - REFCLSID rclsid, - LPUNKNOWN pUnkOuter, - DWORD dwClsContext, - REFIID riid, - IUnknown** ppv -) +HRESULT EPTrayUIComponent_CreateInstance(REFIID riid, void** ppvObject); + +__declspec(dllexport) HRESULT explorer_CoCreateInstanceHook(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, void** ppv) { if (IsEqualCLSID(rclsid, &CLSID_InputSwitchControl) && IsEqualIID(riid, &IID_IInputSwitchControl)) { HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv); if (SUCCEEDED(hr) && bOldTaskbar && dwIMEStyle) { - // The commented method below is no longer required as I have now came to patching - // the interface's vtable. - // Also, make sure to read the explanation below as well, it's useful for understanding - // how this worked. - IInputSwitchControl* pInputSwitchControl = *ppv; - DWORD flOldProtect = 0; - if (VirtualProtect(pInputSwitchControl->lpVtbl, sizeof(IInputSwitchControlVtbl), PAGE_EXECUTE_READWRITE, &flOldProtect)) + // The commented method below is no longer required as I have now came to creating a wrapper class. + // Also, make sure to read the explanation below as well, it's useful for understanding how this worked. + // Note: Other than in explorer.exe!CTrayInputIndicator::_RegisterInputSwitch, we're also called by + // explorer.exe!HostAppEnvironment::_SetupInputSwitchServer which passes ISCT_IDL_USEROOBE (6) as the style. + if (IsWindows11Version22H2OrHigher()) { - if (pInputSwitchControl->lpVtbl->ShowInputSwitch != CInputSwitchControl_ShowInputSwitchHook) - { - CInputSwitchControl_ShowInputSwitchFunc = pInputSwitchControl->lpVtbl->ShowInputSwitch; - pInputSwitchControl->lpVtbl->ShowInputSwitch = CInputSwitchControl_ShowInputSwitchHook; - } - if (pInputSwitchControl->lpVtbl->Init != CInputSwitchControl_InitHook) - { - CInputSwitchControl_InitFunc = pInputSwitchControl->lpVtbl->Init; - pInputSwitchControl->lpVtbl->Init = CInputSwitchControl_InitHook; - } - VirtualProtect(pInputSwitchControl->lpVtbl, sizeof(IInputSwitchControlVtbl), flOldProtect, &flOldProtect); + hr = CInputSwitchControlProxySV2_CreateInstance(*ppv, riid, ppv); + } + else + { + hr = CInputSwitchControlProxy_CreateInstance(*ppv, riid, ppv); } // Pff... how this works: //