Skip to content

Commit

Permalink
Taskbar10: Fixed Windows 10 taskbar not showing up on Windows 11 buil…
Browse files Browse the repository at this point in the history
…ds with "Never combine" on the new taskbar
  • Loading branch information
Amrsatrio committed Sep 23, 2023
1 parent 40d63f1 commit bc3bbc7
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 108 deletions.
58 changes: 40 additions & 18 deletions ExplorerPatcher/dllmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -4277,18 +4277,21 @@ INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHo

#pragma region "Enable old taskbar"
#ifdef _WIN64
DEFINE_GUID(GUID_18C02F2E_2754_5A20_8BD5_0B34CE79DA2B,
0x18C02F2E,
0x2754, 0x5A20, 0x8b, 0xd5,
0x0b, 0x34, 0xce, 0x79, 0xda, 0x2b
);
HRESULT explorer_RoGetActivationFactoryHook(HSTRING activatableClassId, GUID* iid, void** factory)
{
PCWSTR StringRawBuffer = WindowsGetStringRawBuffer(activatableClassId, 0);
if (!wcscmp(StringRawBuffer, L"WindowsUdk.ApplicationModel.AppExtensions.XamlExtensions") && IsEqualGUID(iid, &GUID_18C02F2E_2754_5A20_8BD5_0B34CE79DA2B))
if (!wcscmp(StringRawBuffer, L"WindowsUdk.ApplicationModel.AppExtensions.XamlExtensions"))
{
*factory = &XamlExtensionsFactory;
return S_OK;
if (IsEqualGUID(iid, &IID_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics))
{
*factory = &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics;
return S_OK;
}
if (IsEqualGUID(iid, &IID_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2))
{
*factory = &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2;
return S_OK;
}
}
return RoGetActivationFactory(activatableClassId, iid, factory);
}
Expand Down Expand Up @@ -9629,17 +9632,36 @@ struct RTL_FEATURE_CONFIGURATION {
int (*RtlQueryFeatureConfigurationFunc)(UINT32 featureId, int sectionType, INT64* changeStamp, struct RTL_FEATURE_CONFIGURATION* buffer);
int RtlQueryFeatureConfigurationHook(UINT32 featureId, int sectionType, INT64* changeStamp, struct RTL_FEATURE_CONFIGURATION* buffer) {
int rv = RtlQueryFeatureConfigurationFunc(featureId, sectionType, changeStamp, buffer);
switch (featureId)
{
#if !USE_MOMENT_3_FIXES_ON_MOMENT_2
if (IsWindows11Version22H2Build1413OrHigher() && bOldTaskbar && featureId == 26008830) {
// Disable tablet optimized taskbar feature when using the Windows 10 taskbar
//
// For now, this fixes Task View and Win-Tab, Alt-Tab breaking after pressing Win-Tab,
// flyouts alignment, notification center alignment, Windows key shortcuts on
// OS builds 22621.1413+
//
buffer->enabledState = FEATURE_ENABLED_STATE_DISABLED;
}
case 26008830: // STTest
{
if (bOldTaskbar)
{
// Disable tablet optimized taskbar feature when using the Windows 10 taskbar
//
// For now, this fixes Task View and Win-Tab, Alt-Tab breaking after pressing Win-Tab,
// flyouts alignment, notification center alignment, Windows key shortcuts on
// OS builds 22621.1413+
//
buffer->enabledState = FEATURE_ENABLED_STATE_DISABLED;
}
break;
}
#endif
#if 0
case 42952021: // CategorySpecificXamlExtensions
{
if (bOldTaskbar)
{
// Make CTray::Init() use IXamlExtensionsStatics (first version, that we can modify)
buffer->enabledState = FEATURE_ENABLED_STATE_DISABLED;
}
break;
}
#endif
}
return rv;
}
#pragma endregion
Expand Down Expand Up @@ -10962,7 +10984,7 @@ DWORD Inject(BOOL bIsExplorer)
}
if (!symbols_PTRS.twinui_pcshell_PTRS[8] || symbols_PTRS.twinui_pcshell_PTRS[8] == 0xFFFFFFFF)
{
// Ref: CMultitaskingViewManager::_CreateMTVHost
// Ref: CMultitaskingViewManager::_CreateMTVHost()
// 4C 89 74 24 ? ? 8B ? ? 8B ? 8B D7 48 8B CE E8 ? ? ? ? 90
// ^^^^^^^
PBYTE match = FindPattern(
Expand Down
172 changes: 97 additions & 75 deletions ExplorerPatcher/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,102 +6,124 @@ RTL_OSVERSIONINFOW global_rovi;
DWORD32 global_ubr;

#pragma region "Weird stuff"
INT64 STDMETHODCALLTYPE nimpl4_1(INT64 a1, DWORD* a2)
/***
Let me explain the weird stuff. This was not documented here before so updating this was a hell of a task.
Our target is in `CTray::Init()`. It constructs either the Windows 11 or the Windows 10 taskbar based on the result of
`winrt::WindowsUdk::ApplicationModel::AppExtensions::XamlExtensions::IsExtensionAvailable()`. We have to make the last
argument of that function be set to false, so that we'll get the Windows 10 taskbar. In order to make a patch that does
not use patterns, we hook `RoGetActivationFactory` and return a dummy object with our own specially crafted vtable.
So the calls are as follows:
`CTray::Init()` calls `factory_cache_entry<XamlExtensions, IXamlExtensionsStatics>::call()` to get an interface to
`XamlExtensions` (located in windowsudk.shellcommon.dll) through `IXamlExtensionsStatics`. First, the factory cache
system tries to retrieve its activation factory. It calls `RoGetActivationFactory` with the `IID` of
`IXamlExtensionsStatics`. Our hook makes that function return a dummy `IXamlExtensionsStatics` with our own vtable.
Despite the name, it is an activation factory. (Ref: `explorer_RoGetActivationFactoryHook()` in dllmain.c)
Then, the cache system checks if the factory implements `IAgileObject` by calling `QueryInterface(IID_IAgileObject)` of
the factory. This will be used to determine if the factory should be cached or not. We intercept this call and do
nothing to make the process easy, so the factory will never be cached. In reality, `XamlExtensions` does not implement
`IAgileObject`.
Then, the cache system calls the lambda that's passed into `factory_cache_entry<~>::call()` in order to retrieve an
interface that can be used. The lambda that `CTray::Init()` passes into the system, retrieves an instance of
`XamlExtensions` by calling `IXamlExtensionsStatics::Current()` of the factory using COM. Here, we intercept the call
through our custom `IXamlExtensionsStatics` vtable and return a dummy `XamlExtensions` instance with our own vtable
whose `QueryInterface()` with the IID of `IXamlExtensions2` returns a dummy `IXamlExtensions2` with our own vtable.
On builds with the "Never combine" feature on the new taskbar, it uses `IXamlExtensionsStatics2::GetForCategory()`
instead of `IXamlExtensionsStatics::Current()`.
Now that `CTray::Init()` has an instance of `XamlExtensions`, it calls `IXamlExtensions2::IsExtensionAvailable()`.
As the name says, if the extension (or Windows 11 taskbar) is available, `CTray::Init()` will continue to make the
Windows 11 taskbar through `CTray::InitializeTrayUIComponent()`. Otherwise, it will make the Windows 10 taskbar through
`TrayUI_CreateInstance()` that has been since ages.
`CTray::Init()` gets that value through the `IXamlExtensions2` interface of the `XamlExtensions` instance. COM calls are
made, which are `QueryInterface(IID_IXamlExtensions2)` and `IXamlExtensions2::IsExtensionAvailable()` itself. We
intercept the former call through our custom vtable for our dummy `XamlExtensions` instance to return a dummy
`IXamlExtensions2` with our own vtable too. Then, we intercept the latter call through our custom `IXamlExtensions2`
vtable to have the last argument set to false, and now we have the good old taskbar.
***/

static ULONG STDMETHODCALLTYPE nimplAddRefRelease(IUnknown* This)
{
*a2 = 1;
return 0;
}
INT64 STDMETHODCALLTYPE nimpl4_0(INT64 a1, DWORD* a2)
{
*a2 = 0;
return 0;
return 1;
}
__int64 STDMETHODCALLTYPE nimpl2(__int64 a1, uintptr_t* a2)
{
__int64 v2; // rax

v2 = a1 + 8;
if (!a1)
v2 = 0i64;

*a2 = v2;
return 0i64;
}
ULONG STDMETHODCALLTYPE nimpl3()
static HRESULT STDMETHODCALLTYPE nimplReturnHResultNotImpl(IUnknown* This)
{
return 1;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE nimpl()

static HRESULT STDMETHODCALLTYPE WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics_QueryInterface(WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics* This, REFIID riid, void** ppvObject)
{
// Should only be called with IID_IAgileObject
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE nimpl1(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1; // rcx

if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;

*a3 = v4;
static HRESULT STDMETHODCALLTYPE WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics_Current(WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics* This, void** _instance_of_winrt_WindowsUdk_ApplicationModel_AppExtensions_XamlExtensions)
{
*_instance_of_winrt_WindowsUdk_ApplicationModel_AppExtensions_XamlExtensions = &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2;
return S_OK;
}
HRESULT STDMETHODCALLTYPE nimpl1_2(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1 - sizeof(__int64); // rcx

if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;

*a3 = v4;
static HRESULT STDMETHODCALLTYPE WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2_GetForCategory(WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2* This, HSTRING a2, void** _instance_of_winrt_WindowsUdk_ApplicationModel_AppExtensions_XamlExtensions)
{
*_instance_of_winrt_WindowsUdk_ApplicationModel_AppExtensions_XamlExtensions = &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2;
return S_OK;
}
HRESULT STDMETHODCALLTYPE nimpl1_3(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1 - 2 * sizeof(__int64); // rcx

if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;

*a3 = v4;
return S_OK;
static HRESULT STDMETHODCALLTYPE WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2_QueryInterface(WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2* This, REFIID riid, void** ppvObject)
{
if (IsEqualIID(riid, &IID_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2))
{
*ppvObject = &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2;
return S_OK;
}
return E_NOTIMPL;
}
__int64 STDMETHODCALLTYPE nimpl4(__int64 a1, __int64 a2, __int64 a3, BYTE* a4)

static HRESULT STDMETHODCALLTYPE WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2_IsExtensionAvailable(WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2* This, HSTRING a2, HSTRING a3, BYTE* a4)
{
*a4 = 0;
return 0i64;
return S_OK;
}
const IActivationFactoryVtbl _IActivationFactoryVtbl = {
.QueryInterface = nimpl1,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl2
};
const IActivationFactoryVtbl _IActivationFactoryVtbl2 = {
.QueryInterface = nimpl1_2,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl

static const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStaticsVtbl instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStaticsVtbl = {
.QueryInterface = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics_QueryInterface,
.AddRef = nimplAddRefRelease,
.Release = nimplAddRefRelease,
.GetIids = nimplReturnHResultNotImpl,
.GetRuntimeClassName = nimplReturnHResultNotImpl,
.GetTrustLevel = nimplReturnHResultNotImpl,
.Current = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics_Current
};
const IActivationFactoryVtbl _IActivationFactoryVtbl3 = {
.QueryInterface = nimpl1_3,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl4
const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics = { &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStaticsVtbl };

static const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2Vtbl instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2Vtbl = {
.QueryInterface = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics_QueryInterface,
.AddRef = nimplAddRefRelease,
.Release = nimplAddRefRelease,
.GetIids = nimplReturnHResultNotImpl,
.GetRuntimeClassName = nimplReturnHResultNotImpl,
.GetTrustLevel = nimplReturnHResultNotImpl,
.GetForCategory = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2_GetForCategory
};
const IActivationFactoryAA XamlExtensionsFactory = {
.lpVtbl = &_IActivationFactoryVtbl,
.lpVtbl2 = &_IActivationFactoryVtbl2,
.lpVtbl3 = &_IActivationFactoryVtbl3
const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2 instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2 = { &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensionsStatics2Vtbl };

static const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2Vtbl instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2Vtbl = {
.QueryInterface = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2_QueryInterface,
.AddRef = nimplAddRefRelease,
.Release = nimplAddRefRelease,
.GetIids = nimplReturnHResultNotImpl,
.GetRuntimeClassName = nimplReturnHResultNotImpl,
.GetTrustLevel = nimplReturnHResultNotImpl,
.IsExtensionAvailable = WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2_IsExtensionAvailable
};
const WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2 instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2 = { &instanceof_WindowsUdk_ApplicationModel_AppExtensions_IXamlExtensions2Vtbl };
#pragma endregion

void printf_guid(GUID guid)
Expand Down Expand Up @@ -1640,4 +1662,4 @@ BOOL ExtractMonitorByIndex(HMONITOR hMonitor, HDC hDC, LPRECT lpRect, MonitorOve
}
mod->cbIndex++;
return TRUE;
}
}
Loading

0 comments on commit bc3bbc7

Please sign in to comment.