mirror of
https://github.com/valinet/ExplorerPatcher.git
synced 2024-11-27 17:00:59 +01:00
Taskbar10: Fixed a bug where SCOOBE would repeatedly crash Explorer when Language Switcher is set to anything other than Windows 11 (the default) ^2
This commit is contained in:
parent
fe7f8005fb
commit
5c35f5862f
@ -266,6 +266,10 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputSwitch.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Localization.cpp" />
|
||||
<ClCompile Include="lvt.c">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
@ -334,6 +338,7 @@
|
||||
<ClInclude Include="hooking.h" />
|
||||
<ClInclude Include="ep_private.h" />
|
||||
<ClInclude Include="ImmersiveFlyouts.h" />
|
||||
<ClInclude Include="InputSwitch.h" />
|
||||
<ClInclude Include="Localization.h" />
|
||||
<ClInclude Include="lvt.h" />
|
||||
<ClInclude Include="osutility.h" />
|
||||
|
198
ExplorerPatcher/InputSwitch.cpp
Normal file
198
ExplorerPatcher/InputSwitch.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
#include "InputSwitch.h"
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
#include <wrl/implements.h>
|
||||
#include <wil/result_macros.h>
|
||||
|
||||
#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<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, 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<IInputSwitchControl> m_original;
|
||||
__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 m_type;
|
||||
};
|
||||
|
||||
HRESULT CInputSwitchControlProxy_CreateInstance(IInputSwitchControl* original, REFIID riid, void** ppvObject)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<CInputSwitchControlProxy> proxy;
|
||||
RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize<CInputSwitchControlProxy>(&proxy, original));
|
||||
RETURN_HR(proxy.CopyTo(riid, ppvObject));
|
||||
}
|
||||
|
||||
class CInputSwitchControlProxySV2 : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, 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<IInputSwitchControlSV2> m_original;
|
||||
__MIDL___MIDL_itf_inputswitchserver_0000_0000_0001 m_type;
|
||||
};
|
||||
|
||||
HRESULT CInputSwitchControlProxySV2_CreateInstance(IInputSwitchControlSV2* original, REFIID riid, void** ppvObject)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<CInputSwitchControlProxySV2> proxy;
|
||||
RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize<CInputSwitchControlProxySV2>(&proxy, original));
|
||||
RETURN_HR(proxy.CopyTo(riid, ppvObject));
|
||||
}
|
122
ExplorerPatcher/InputSwitch.h
Normal file
122
ExplorerPatcher/InputSwitch.h
Normal file
@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
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
|
@ -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:
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user