6 changed files with 366 additions and 246 deletions
@ -1,45 +0,0 @@
@@ -1,45 +0,0 @@
|
||||
#include "utility.h" |
||||
|
||||
#pragma region "Enable old taskbar" |
||||
/***
|
||||
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 can to make the last |
||||
argument of that function be set to false, so that we'll get the Windows 10 taskbar instead of the Windows 11 one that |
||||
gets constructed through `CTray::InitializeTrayUIComponent()`. |
||||
|
||||
Alternatively, we can modify the behavior of `CTray::InitializeTrayUIComponent`. It contains the code to call |
||||
`TrayUI_CreateInstance()` that resides in `Taskbar.dll` (checked through HKLM\SOFTWARE\Classes\CLSID\<the CLSID>) which |
||||
is a copy of the Windows 10 taskbar code but modified over the time to support the Windows 11 taskbar. We see that it |
||||
calls `CoCreateInstance` to get an `ITrayUIComponent` interface to an instance of `TrayUIComponent`. We hook that |
||||
function to make it return our own custom `ITrayUIComponent` instance. Our `ITrayUIComponent::InitializeWithTray()` |
||||
function calls `TrayUI_CreateInstance()` of `explorer.exe` that is also called when the last argument of |
||||
`IsExtensionAvailable()` after the call is false. |
||||
|
||||
This way, we can get the Windows 10 taskbar which resides in explorer.exe without hooking LoadLibraryExW() in order to |
||||
perform our initial method which has been known to be inconsistent on some systems. (Thanks feature flags!) |
||||
***/ |
||||
|
||||
static ULONG STDMETHODCALLTYPE nimplAddRefRelease(IUnknown* This) |
||||
{ |
||||
return 1; |
||||
} |
||||
|
||||
static HRESULT STDMETHODCALLTYPE ITrayUIComponent_QueryInterface(ITrayUIComponent* This, REFIID riid, void** ppvObject) |
||||
{ |
||||
// Should never be called
|
||||
return E_NOTIMPL; |
||||
} |
||||
|
||||
static HRESULT STDMETHODCALLTYPE ITrayUIComponent_InitializeWithTray(ITrayUIComponent* This, ITrayUIHost* host, ITrayUI** result) |
||||
{ |
||||
return explorer_TrayUI_CreateInstanceFunc(host, &IID_ITrayUI, (void**)result); |
||||
} |
||||
|
||||
static const ITrayUIComponentVtbl instanceof_ITrayUIComponentVtbl = { |
||||
.QueryInterface = ITrayUIComponent_QueryInterface, |
||||
.AddRef = nimplAddRefRelease, |
||||
.Release = nimplAddRefRelease, |
||||
.InitializeWithTray = ITrayUIComponent_InitializeWithTray |
||||
}; |
||||
const ITrayUIComponent instanceof_ITrayUIComponent = { &instanceof_ITrayUIComponentVtbl }; |
||||
#pragma endregion |
||||
@ -0,0 +1,267 @@
@@ -0,0 +1,267 @@
|
||||
#include "utility.h" |
||||
|
||||
#include <dcomptypes.h> |
||||
|
||||
#include <wrl/implements.h> |
||||
#include <wrl/wrappers/corewrappers.h> |
||||
#include <wil/result_macros.h> |
||||
|
||||
extern "C" DWORD (*CImmersiveColor_GetColorFunc)(int colorType); |
||||
|
||||
#pragma region "Enable old taskbar" |
||||
/***
|
||||
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 can to make the last |
||||
argument of that function be set to false, so that we'll get the Windows 10 taskbar instead of the Windows 11 one that |
||||
gets constructed through `CTray::InitializeTrayUIComponent()`. |
||||
|
||||
Alternatively, we can modify the behavior of `CTray::InitializeTrayUIComponent`. It contains the code to call |
||||
`TrayUI_CreateInstance()` that resides in `Taskbar.dll` (checked through HKLM\SOFTWARE\Classes\CLSID\<the CLSID>) which |
||||
is a copy of the Windows 10 taskbar code but modified over the time to support the Windows 11 taskbar. We see that it |
||||
calls `CoCreateInstance` to get an `ITrayUIComponent` interface to an instance of `TrayUIComponent`. We hook that |
||||
function to make it return our own custom `ITrayUIComponent` instance. Our `ITrayUIComponent::InitializeWithTray()` |
||||
function calls `TrayUI_CreateInstance()` of `explorer.exe` that is also called when the last argument of |
||||
`IsExtensionAvailable()` after the call is false. |
||||
|
||||
This way, we can get the Windows 10 taskbar which resides in explorer.exe without hooking LoadLibraryExW() in order to |
||||
perform our initial method which has been known to be inconsistent on some systems. (Thanks feature flags!) |
||||
***/ |
||||
|
||||
MIDL_INTERFACE("27775f88-01d3-46ec-a1c1-64b4c09b211b") |
||||
ITrayUIComponent : IUnknown |
||||
{ |
||||
virtual HRESULT STDMETHODCALLTYPE InitializeWithTray(ITrayUIHost* host, ITrayUI** result) = 0; |
||||
}; |
||||
|
||||
class EPTrayUIComponent : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ITrayUIComponent> |
||||
{ |
||||
public: |
||||
STDMETHODIMP InitializeWithTray(ITrayUIHost* host, ITrayUI** result) override |
||||
{ |
||||
RETURN_IF_FAILED(explorer_TrayUI_CreateInstanceFunc(host, IID_ITrayUI, (void**)result)); |
||||
return S_OK; |
||||
} |
||||
}; |
||||
|
||||
extern "C" HRESULT EPTrayUIComponent_CreateInstance(REFIID riid, void** ppvObject) |
||||
{ |
||||
Microsoft::WRL::ComPtr<EPTrayUIComponent> instance; |
||||
RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize<EPTrayUIComponent>(&instance)); |
||||
RETURN_HR(instance.CopyTo(riid, ppvObject)); |
||||
} |
||||
#pragma endregion |
||||
|
||||
#pragma region "Restore acrylic background" |
||||
typedef enum WINDOWCOMPOSITIONATTRIB |
||||
{ |
||||
WCA_UNDEFINED = 0, |
||||
WCA_NCRENDERING_ENABLED = 1, |
||||
WCA_NCRENDERING_POLICY = 2, |
||||
WCA_TRANSITIONS_FORCEDISABLED = 3, |
||||
WCA_ALLOW_NCPAINT = 4, |
||||
WCA_CAPTION_BUTTON_BOUNDS = 5, |
||||
WCA_NONCLIENT_RTL_LAYOUT = 6, |
||||
WCA_FORCE_ICONIC_REPRESENTATION = 7, |
||||
WCA_EXTENDED_FRAME_BOUNDS = 8, |
||||
WCA_HAS_ICONIC_BITMAP = 9, |
||||
WCA_THEME_ATTRIBUTES = 10, |
||||
WCA_NCRENDERING_EXILED = 11, |
||||
WCA_NCADORNMENTINFO = 12, |
||||
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13, |
||||
WCA_VIDEO_OVERLAY_ACTIVE = 14, |
||||
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15, |
||||
WCA_DISALLOW_PEEK = 16, |
||||
WCA_CLOAK = 17, |
||||
WCA_CLOAKED = 18, |
||||
WCA_ACCENT_POLICY = 19, |
||||
WCA_FREEZE_REPRESENTATION = 20, |
||||
WCA_EVER_UNCLOAKED = 21, |
||||
WCA_VISUAL_OWNER = 22, |
||||
WCA_HOLOGRAPHIC = 23, |
||||
WCA_EXCLUDED_FROM_DDA = 24, |
||||
WCA_PASSIVEUPDATEMODE = 25, |
||||
WCA_USEDARKMODECOLORS = 26, |
||||
WCA_CORNER_STYLE = 27, |
||||
WCA_PART_COLOR = 28, |
||||
WCA_DISABLE_MOVESIZE_FEEDBACK = 29, |
||||
WCA_SYSTEMBACKDROP_TYPE = 30, |
||||
WCA_SET_TAGGED_WINDOW_RECT = 31, |
||||
WCA_CLEAR_TAGGED_WINDOW_RECT = 32, |
||||
WCA_LAST = 33, |
||||
} WINDOWCOMPOSITIONATTRIB; |
||||
|
||||
typedef struct tagWINDOWCOMPOSITIONATTRIBDATA |
||||
{ |
||||
WINDOWCOMPOSITIONATTRIB Attrib; |
||||
void* pvData; |
||||
unsigned int cbData; |
||||
} WINDOWCOMPOSITIONATTRIBDATA; |
||||
|
||||
typedef enum ACCENT_STATE |
||||
{ |
||||
ACCENT_DISABLED = 0, |
||||
ACCENT_ENABLE_GRADIENT = 1, |
||||
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, |
||||
ACCENT_ENABLE_BLURBEHIND = 3, |
||||
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, |
||||
ACCENT_ENABLE_HOSTBACKDROP = 5, |
||||
ACCENT_INVALID_STATE = 6, |
||||
} ACCENT_STATE; |
||||
|
||||
typedef struct ACCENT_POLICY |
||||
{ |
||||
ACCENT_STATE AccentState; |
||||
unsigned int AccentFlags; |
||||
unsigned long GradientColor; |
||||
long AnimationId; |
||||
} ACCENT_POLICY; |
||||
|
||||
namespace ABI::WindowsUdk::UI::Themes |
||||
{ |
||||
enum class VisualTheme |
||||
{ |
||||
Dark = 0, |
||||
Light = 1, |
||||
HighContrastBlack = 2, |
||||
HighContrastWhite = 3, |
||||
}; |
||||
|
||||
MIDL_INTERFACE("8f0a6c35-72ca-5f4a-a5fb-1a731ec8b514") |
||||
ISystemVisualThemeStatics : IInspectable |
||||
{ |
||||
virtual HRESULT STDMETHODCALLTYPE get_Current(VisualTheme* value) = 0; |
||||
virtual HRESULT STDMETHODCALLTYPE add_Changed(void* handler, EventRegistrationToken* token) = 0; |
||||
virtual HRESULT STDMETHODCALLTYPE remove_Changed(EventRegistrationToken token) = 0; |
||||
}; |
||||
} |
||||
|
||||
struct TaskbarTheme |
||||
{ |
||||
bool bColorPrevalence; |
||||
bool bEnableTransparency; |
||||
ABI::WindowsUdk::UI::Themes::VisualTheme visualTheme; |
||||
|
||||
bool IsHighContrast() const |
||||
{ |
||||
using namespace ABI::WindowsUdk::UI::Themes; |
||||
return visualTheme == VisualTheme::HighContrastBlack || visualTheme == VisualTheme::HighContrastWhite; |
||||
} |
||||
|
||||
bool IsDark() const |
||||
{ |
||||
using namespace ABI::WindowsUdk::UI::Themes; |
||||
return visualTheme == VisualTheme::Dark || visualTheme == VisualTheme::HighContrastBlack; |
||||
} |
||||
}; |
||||
|
||||
struct struct_b |
||||
{ |
||||
int a; |
||||
int b; |
||||
int c; |
||||
int d; |
||||
}; |
||||
|
||||
typedef HRESULT (*NtDCompositionGetFrameStatistics_t)(DCOMPOSITION_FRAME_STATISTICS*, struct_b*); |
||||
|
||||
inline HRESULT NtDCompositionGetFrameStatistics(DCOMPOSITION_FRAME_STATISTICS* a, struct_b* b) |
||||
{ |
||||
static NtDCompositionGetFrameStatistics_t f = nullptr; |
||||
if (!f) |
||||
{ |
||||
HMODULE h = GetModuleHandleW(L"dcomp.dll"); |
||||
if (h) |
||||
f = (NtDCompositionGetFrameStatistics_t)GetProcAddress(h, MAKEINTRESOURCEA(1046)); |
||||
} |
||||
return f ? f(a, b) : E_NOTIMPL; |
||||
} |
||||
|
||||
bool ShouldApplyBlur() |
||||
{ |
||||
DCOMPOSITION_FRAME_STATISTICS v7; |
||||
struct_b v6; |
||||
return SUCCEEDED(NtDCompositionGetFrameStatistics(&v7, &v6)) && v6.d && !v6.c; |
||||
} |
||||
|
||||
TaskbarTheme GetTaskbarTheme() |
||||
{ |
||||
TaskbarTheme rv; |
||||
// rv.visualTheme = winrt::WindowsUdk::UI::Themes::SystemVisualTheme::Current();
|
||||
|
||||
rv.visualTheme = ABI::WindowsUdk::UI::Themes::VisualTheme::Light; |
||||
Microsoft::WRL::ComPtr<ABI::WindowsUdk::UI::Themes::ISystemVisualThemeStatics> systemVisualTheme; |
||||
HRESULT hr = RoGetActivationFactory( |
||||
Microsoft::WRL::Wrappers::HStringReference(L"WindowsUdk.UI.Themes.SystemVisualTheme").Get(), |
||||
IID_PPV_ARGS(&systemVisualTheme) |
||||
); |
||||
if (SUCCEEDED_LOG(hr)) |
||||
{ |
||||
ABI::WindowsUdk::UI::Themes::VisualTheme theme; |
||||
if (SUCCEEDED_LOG(systemVisualTheme->get_Current(&theme))) |
||||
{ |
||||
rv.visualTheme = theme; |
||||
} |
||||
} |
||||
|
||||
DWORD bColorPrevalence = 0; |
||||
rv.bColorPrevalence = |
||||
SUCCEEDED(SHRegGetDWORD( |
||||
HKEY_CURRENT_USER, |
||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", |
||||
L"ColorPrevalence", |
||||
&bColorPrevalence |
||||
)) && bColorPrevalence; |
||||
|
||||
bool bApplyBlur = ShouldApplyBlur(); |
||||
DWORD bEnableTransparency; |
||||
rv.bEnableTransparency = !rv.IsHighContrast() && bApplyBlur |
||||
&& SUCCEEDED(SHRegGetDWORD( |
||||
HKEY_CURRENT_USER, |
||||
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", |
||||
L"EnableTransparency", |
||||
&bEnableTransparency |
||||
)) && bEnableTransparency; |
||||
|
||||
return rv; |
||||
} |
||||
|
||||
DWORD GetTaskbarColor() |
||||
{ |
||||
TaskbarTheme tt = GetTaskbarTheme(); |
||||
|
||||
if (tt.IsHighContrast()) |
||||
return GetSysColor(COLOR_WINDOW); |
||||
|
||||
if (tt.bColorPrevalence && CImmersiveColor_GetColorFunc) |
||||
{ |
||||
DWORD result = CImmersiveColor_GetColorFunc(tt.IsDark() ? 6 /*IMCLR_SystemAccentDark2*/ : 2 /*IMCLR_SystemAccentLight2*/); |
||||
if (tt.bEnableTransparency) |
||||
return (result & 0xFFFFFF) | 0xCC000000; |
||||
return result; |
||||
} |
||||
|
||||
if (tt.IsDark()) |
||||
return tt.bEnableTransparency ? 0x80202020 : 0xFF202020; |
||||
|
||||
return tt.bEnableTransparency ? 0xF3F3F3 : 0xFFF3F3F3; |
||||
} |
||||
|
||||
extern "C" void UpdateWindowAccentProperties_PatchAttribData(WINDOWCOMPOSITIONATTRIBDATA* pAttrData) |
||||
{ |
||||
ACCENT_POLICY* pAccentPolicy = (ACCENT_POLICY*)pAttrData->pvData; |
||||
if (false) // STTest makes it like this:
|
||||
{ |
||||
pAccentPolicy->AccentState = ACCENT_ENABLE_TRANSPARENTGRADIENT; |
||||
pAccentPolicy->GradientColor = 0; |
||||
pAccentPolicy->AnimationId = 0; |
||||
} |
||||
else |
||||
{ |
||||
pAccentPolicy->AccentState = GetTaskbarTheme().bEnableTransparency ? ACCENT_ENABLE_ACRYLICBLURBEHIND : ACCENT_ENABLE_GRADIENT; |
||||
pAccentPolicy->GradientColor = GetTaskbarColor(); |
||||
pAccentPolicy->AnimationId = 0; |
||||
} |
||||
|
||||
pAccentPolicy->AccentFlags = 0x1 | 0x2 | 0x10; |
||||
} |
||||
#pragma endregion |
||||
Loading…
Reference in new issue