2023-02-26 22:08:55 +00:00
// ==WindhawkMod==
// @id classic-theme-explorer
// @name Classic Theme Explorer
// @description Classic Theme mitigations for Explorer as a Windhawk mod
// @version 0.1
// @author Cynosphere
// @github https://github.com/Cynosphere
// @homepage https://c7.pm/
// @include explorer.exe
2023-03-31 02:40:29 +00:00
// @compilerOptions -lcomctl32 -luxtheme -lgdi32
2023-02-26 22:08:55 +00:00
// ==/WindhawkMod==
// ==WindhawkModReadme==
/*
# Classic Theme Explorer
Classic Theme mitigations for Explorer as a Windhawk mod .
2023-03-31 02:40:29 +00:00
Based on [ ExplorerPatcher ] ( https : //github.com/valinet/ExplorerPatcher), [SimpleClassicTheme.FileExplorerHook](https://github.com/AEAEAEAE4343/SimpleClassicTheme.FileExplorerHook) and the AutoHotkey scripts that came before it.
2023-02-26 22:08:55 +00:00
*/
// ==/WindhawkModReadme==
// ==WindhawkModSettings==
/*
- clientEdge : true
$ name : " Client Edge "
$ description : " Adds Client Edge styling "
- rebarBorder : true
$ name : " Bar Borders "
$ description : " Adds borders to RebarWindow32 controls "
- rebarFixedHeight : false
$ name : " Fixed Bar Height "
$ description : " Resizes all toolbars to the tallest bar's height "
- hideNavigation : true
$ name : " Hide Navigation "
$ description : " Hide default navigation for use with Classic Explorer Bar and Classic Address Bar/Quero "
- addressSync : true
$ name : " Classic Address Bar Sync "
$ description : " Syncs address bar location on folder change "
- addressSyncFullPath : true
$ name : " Address Sync: Use full path "
$ description : " Uses full path instead of folder name "
- addressHeight : true
$ name : " Classic Address Bar Height "
$ description : " Resizes address bar to 22px "
- hideRefresh : true
$ name : " Hide Refresh Button "
$ description : " Hides the refresh button from Classic Address Bar "
2023-03-31 02:40:29 +00:00
- epMitigate : true
$ name : " ExplorerPatcher's Mitigations "
$ description : " ExplorerPatcher's Mitigations "
2023-02-26 22:08:55 +00:00
*/
// ==/WindhawkModSettings==
# include <windows.h>
# include <objbase.h>
# include <initguid.h>
# include <commctrl.h>
# include <dwmapi.h>
2023-03-31 02:40:29 +00:00
# include <uxtheme.h>
# include <wingdi.h>
2023-02-26 22:08:55 +00:00
# include <string>
# include <regex>
# include <locale>
# include <codecvt>
struct {
bool clientEdge ;
bool rebarBorder ;
bool rebarFixedHeight ;
bool hideNavigation ;
bool addressSync ;
bool addressSyncFullPath ;
bool addressHeight ;
bool hideRefresh ;
2023-03-31 02:40:29 +00:00
bool epMitigate ;
2023-02-26 22:08:55 +00:00
} settings ;
void LoadSettings ( ) {
settings . clientEdge = Wh_GetIntSetting ( L " clientEdge " ) ;
settings . rebarBorder = Wh_GetIntSetting ( L " rebarBorder " ) ;
settings . rebarFixedHeight = Wh_GetIntSetting ( L " rebarFixedHeight " ) ;
settings . hideNavigation = Wh_GetIntSetting ( L " hideNavigation " ) ;
settings . addressSync = Wh_GetIntSetting ( L " addressSync " ) ;
settings . addressSyncFullPath = Wh_GetIntSetting ( L " addressSyncFullPath " ) ;
settings . addressHeight = Wh_GetIntSetting ( L " addressHeight " ) ;
settings . hideRefresh = Wh_GetIntSetting ( L " hideRefresh " ) ;
2023-03-31 02:40:29 +00:00
settings . epMitigate = Wh_GetIntSetting ( L " epMitigate " ) ;
2023-02-26 22:08:55 +00:00
}
// Explorer modifications
typedef struct EnumChildProcData
{
HWND result ;
int index ;
int instancesFound ;
const wchar_t * className ;
} ;
BOOL CALLBACK EnumChildProc ( _In_ HWND hwnd , _In_ LPARAM lParam )
{
wchar_t buffer [ 256 ] ;
EnumChildProcData * data = ( EnumChildProcData * ) lParam ;
GetClassNameW ( hwnd , buffer , 256 ) ;
if ( lstrcmpW ( buffer , data - > className ) = = 0 )
{
if ( data - > instancesFound + 1 = = data - > index )
{
data - > result = hwnd ;
return FALSE ;
}
else
{
data - > instancesFound + + ;
}
}
return TRUE ;
} ;
HWND GetChildWindow ( HWND parent , const wchar_t * className , int index )
{
EnumChildProcData data = { 0 } ;
data . className = className ;
data . index = index ;
EnumChildWindows ( parent , EnumChildProc , ( LPARAM ) & data ) ;
return data . result ;
}
2023-03-13 17:38:05 +00:00
// QtTabBar's hooking taints the wParam for some reason, so we strip off the extra bits if needed.
BOOL ShouldApply ( WPARAM wParam , BOOL fallback , BOOL checkSix ) {
Wh_Log ( L " 0x%x, %d " , wParam , fallback ) ;
if ( wParam > 0xffff ) {
Wh_Log ( L " above 0xffff " ) ;
if ( ( wParam & 1 ) = = 1 ) {
Wh_Log ( L " 1 set " ) ;
return true ;
} else if ( checkSix & & ( wParam & 6 ) = = 6 ) {
Wh_Log ( L " 6 set " ) ;
return true ;
} else {
Wh_Log ( L " falling back " ) ;
return fallback ;
}
} else {
Wh_Log ( L " falling back " ) ;
return fallback ;
}
}
VOID ClassicThemeExplorer ( HWND hWnd , UINT uMsg , WPARAM wParam )
2023-02-26 22:08:55 +00:00
{
wchar_t classNameBuffer [ 256 ] ;
wchar_t pathBuffer [ MAX_PATH ] ;
HKEY key ;
RECT rect ;
HWND NavBarParent = GetChildWindow ( ( HWND ) hWnd , L " WorkerW " , 1 ) ;
HWND NavBarAddressBandRoot = GetChildWindow ( NavBarParent , L " Address Band Root " , 1 ) ;
HWND NavBarToolBar = GetChildWindow ( NavBarAddressBandRoot , L " ToolbarWindow32 " , 2 ) ;
HWND ClassicAddressBandRoot = GetChildWindow ( ( HWND ) hWnd , L " Address Band Root " , 2 ) ;
HWND ClassicProgressControl = GetChildWindow ( ClassicAddressBandRoot , L " msctls_progress32 " , 1 ) ;
HWND ClassicComboBox = GetChildWindow ( ClassicAddressBandRoot , L " ComboBoxEx32 " , 1 ) ;
HWND ClassicRebar = GetChildWindow ( ( HWND ) hWnd , L " ReBarWindow32 " , 2 ) ;
2023-03-13 17:38:05 +00:00
BOOL shouldApply = uMsg = = WM_PARENTNOTIFY & & ShouldApply ( wParam , wParam = = 1 | | wParam = = 6 , false ) ;
BOOL shouldApply2 = uMsg = = WM_PARENTNOTIFY & & ShouldApply ( wParam , wParam = = 1 , true ) ;
if ( settings . clientEdge & & shouldApply ) {
Wh_Log ( L " applying client edge " ) ;
2023-02-26 22:08:55 +00:00
HWND TreeView = GetChildWindow ( ( HWND ) hWnd , L " SysTreeView32 " , 1 ) ;
LONG TreeViewExtendedStyle = GetWindowLongPtrW ( TreeView , GWL_EXSTYLE ) ;
TreeViewExtendedStyle | = WS_EX_CLIENTEDGE ;
SetWindowLongPtrW ( TreeView , GWL_EXSTYLE , TreeViewExtendedStyle ) ;
HWND FolderView = GetChildWindow ( ( HWND ) hWnd , L " FolderView " , 1 ) ;
LONG FolderViewExtendedStyle = GetWindowLongPtrW ( FolderView , GWL_EXSTYLE ) ;
FolderViewExtendedStyle | = WS_EX_CLIENTEDGE ;
SetWindowLongPtrW ( FolderView , GWL_EXSTYLE , FolderViewExtendedStyle ) ;
HWND ShellTabWindowClass = GetChildWindow ( ( HWND ) hWnd , L " ShellTabWindowClass " , 1 ) ;
GetWindowRect ( ShellTabWindowClass , & rect ) ;
SetWindowPos ( ShellTabWindowClass , NULL , NULL , NULL , rect . right - rect . left + 1 , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
SetWindowPos ( ShellTabWindowClass , NULL , NULL , NULL , rect . right - rect . left , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
}
2023-03-13 17:38:05 +00:00
if ( settings . rebarBorder & & shouldApply ) {
Wh_Log ( L " applying rebar border " ) ;
2023-02-26 22:08:55 +00:00
LONG ClassicRebarStyle = GetWindowLongPtrW ( ClassicRebar , GWL_STYLE ) ;
ClassicRebarStyle | = RBS_BANDBORDERS ;
ClassicRebarStyle | = WS_BORDER ;
SetWindowLongPtrW ( ClassicRebar , GWL_STYLE , ClassicRebarStyle ) ;
}
2023-03-13 17:38:05 +00:00
if ( settings . rebarFixedHeight & & shouldApply ) {
Wh_Log ( L " applying rebar fixed height " ) ;
2023-02-26 22:08:55 +00:00
LONG ClassicRebarStyle = GetWindowLongPtrW ( ClassicRebar , GWL_STYLE ) ;
ClassicRebarStyle & = ~ RBS_VARHEIGHT ;
SetWindowLongPtrW ( ClassicRebar , GWL_STYLE , ClassicRebarStyle ) ;
}
// Apply bar changes
2023-03-13 17:38:05 +00:00
if ( ( settings . rebarBorder | | settings . rebarFixedHeight ) & & shouldApply ) {
2023-02-26 22:08:55 +00:00
GetWindowRect ( ClassicRebar , & rect ) ;
SetWindowPos ( ClassicRebar , NULL , NULL , NULL , rect . right - rect . left + 1 , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
SetWindowPos ( ClassicRebar , NULL , NULL , NULL , rect . right - rect . left , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
}
2023-03-13 17:38:05 +00:00
if ( settings . hideNavigation & & shouldApply2 ) {
2023-02-26 22:08:55 +00:00
// Save the location of the Rebar
HWND NavBarRebar = GetChildWindow ( ( HWND ) hWnd , L " ReBarWindow32 " , 1 ) ;
GetWindowRect ( NavBarRebar , & rect ) ;
LONG xRebar = rect . left ;
LONG yRebar = rect . top ;
LONG cxRebar = rect . right - rect . left ;
LONG cyRebar = rect . bottom - rect . top ;
// Destroy the NC area of the rebar
SendMessageW ( NavBarRebar , WM_NCDESTROY , 0 , 0 ) ;
// Hide the WorkerW and the Rebar
ShowWindow ( NavBarParent , SW_HIDE ) ;
ShowWindow ( NavBarRebar , SW_HIDE ) ;
// Save the location of the ShellTabWindowClass
HWND ShellTabWnd = GetChildWindow ( ( HWND ) hWnd , L " ShellTabWindowClass " , 1 ) ;
GetWindowRect ( NavBarRebar , & rect ) ;
LONG xTabWnd = rect . left ;
LONG yTabWnd = rect . top ;
LONG cxTabWnd = rect . right - rect . left ;
LONG cyTabWnd = rect . bottom - rect . top ;
// Move ShellTabWindow to (*; yRebar; *; yTabWnd - yRebar + cyTabWnd)
SetWindowPos ( ShellTabWnd , NULL , xTabWnd , yRebar , cxTabWnd , yTabWnd - yRebar + cyTabWnd , SWP_NOZORDER ) ;
// Move Rebar to (*; *; *; 0)
SetWindowPos ( NavBarRebar , NULL , xRebar , yRebar , cxRebar , 0 , SWP_NOZORDER ) ;
// Resize the window to apply
GetWindowRect ( ( HWND ) hWnd , & rect ) ;
SetWindowPos ( ( HWND ) hWnd , NULL , NULL , NULL , rect . right - rect . left , rect . bottom - rect . top + 1 , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
SetWindowPos ( ( HWND ) hWnd , NULL , NULL , NULL , rect . right - rect . left , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
// Redraw the entire explorer window
RedrawWindow ( ( HWND ) hWnd , NULL , NULL , RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN ) ;
}
if ( settings . addressSync ) {
if ( settings . addressSyncFullPath ) {
HWND toolbarwindow = GetChildWindow ( NavBarAddressBandRoot , L " ToolbarWindow32 " , 1 ) ;
GetWindowTextW ( toolbarwindow , pathBuffer , MAX_PATH ) ;
2023-03-13 17:38:05 +00:00
// FIXME: codecvt deprecated as of c++17
2023-02-26 22:08:55 +00:00
std : : wstring_convert < std : : codecvt_utf8_utf16 < wchar_t > > converter ;
2023-03-13 17:38:05 +00:00
// remove "Address: "
// FIXME: support more locales
2023-02-26 22:08:55 +00:00
std : : wstring _pathStr = pathBuffer ;
std : : string pathStr ( _pathStr . begin ( ) , _pathStr . end ( ) ) ;
pathStr = std : : regex_replace ( pathStr , std : : regex ( " Address: " ) , " " ) ;
_pathStr = converter . from_bytes ( pathStr ) ;
wcscpy ( pathBuffer , _pathStr . c_str ( ) ) ;
} else {
HWND shelltabwindow = GetChildWindow ( ( HWND ) hWnd , L " ShellTabWindowClass " , 1 ) ;
GetWindowTextW ( shelltabwindow , pathBuffer , MAX_PATH ) ;
}
HWND AddressBarEdit = GetChildWindow ( ClassicAddressBandRoot , L " Edit " , 1 ) ;
for ( int i = 0 ; i < 3 ; i + + )
SendMessageW ( AddressBarEdit , WM_SETTEXT , 0 , ( LPARAM ) pathBuffer ) ;
// TODO: figure out how to get and set folder icon
}
2023-03-13 17:38:05 +00:00
if ( settings . hideRefresh & & shouldApply ) {
2023-02-26 22:08:55 +00:00
HWND GoButtonToolbar = GetChildWindow ( ClassicAddressBandRoot , L " ToolbarWindow32 " , 1 ) ;
SendMessageW ( GoButtonToolbar , WM_CLOSE , 0 , 0 ) ;
}
if ( settings . addressHeight ) {
// Allocate memory inside Explorer
DWORD count = SendMessage ( GetParent ( ClassicAddressBandRoot ) , RB_GETBANDCOUNT , 0 , 0 ) ;
SIZE_T bytesRead = 0 ;
DWORD ExplorerPID = 0 ;
GetWindowThreadProcessId ( ClassicAddressBandRoot , & ExplorerPID ) ;
HANDLE ExplorerProcess = OpenProcess ( PROCESS_ALL_ACCESS , FALSE , ExplorerPID ) ;
void * ExplorerMemoryRebar = VirtualAllocEx ( ExplorerProcess , NULL , sizeof ( REBARBANDINFO ) , MEM_COMMIT , PAGE_READWRITE ) ;
void * ExplorerMemoryComboBoxItem = VirtualAllocEx ( ExplorerProcess , NULL , sizeof ( COMBOBOXEXITEM ) , MEM_COMMIT , PAGE_READWRITE ) ;
void * ExplorerMemoryToolbarButton = VirtualAllocEx ( ExplorerProcess , NULL , sizeof ( TBBUTTON ) , MEM_COMMIT , PAGE_READWRITE ) ;
// Make the band that's 39 pixels high, 22 pixels high
// MOD: Except this bar isn't always 39 pixels, so lets check between 39-23px instead
REBARBANDINFO bandInfo = { 0 } ;
for ( int i = 0 ; i < count ; i + + )
{
bandInfo = { 0 } ;
bandInfo . cbSize = sizeof ( REBARBANDINFO ) ;
bandInfo . fMask = RBBIM_CHILDSIZE ;
WriteProcessMemory ( ExplorerProcess , ExplorerMemoryRebar , & bandInfo , sizeof ( REBARBANDINFO ) , & bytesRead ) ;
SendMessageW ( GetParent ( ClassicAddressBandRoot ) , RB_GETBANDINFO , i , ( LPARAM ) ExplorerMemoryRebar ) ;
ReadProcessMemory ( ExplorerProcess , ExplorerMemoryRebar , & bandInfo , sizeof ( REBARBANDINFO ) , & bytesRead ) ;
if ( bandInfo . cyMinChild < = 39 & & bandInfo . cyMinChild > 22 ) {
bandInfo . cyMinChild = 22 ;
WriteProcessMemory ( ExplorerProcess , ExplorerMemoryRebar , & bandInfo , sizeof ( REBARBANDINFO ) , & bytesRead ) ;
SendMessageW ( GetParent ( ClassicAddressBandRoot ) , RB_SETBANDINFO , i , ( LPARAM ) ExplorerMemoryRebar ) ;
}
}
// Free Explorer Memory
VirtualFreeEx ( ExplorerProcess , ExplorerMemoryRebar , sizeof ( REBARBANDINFO ) , MEM_DECOMMIT ) ;
VirtualFreeEx ( ExplorerProcess , ExplorerMemoryToolbarButton , sizeof ( REBARBANDINFO ) , MEM_DECOMMIT ) ;
CloseHandle ( ExplorerProcess ) ;
// Set ComboBox height
SendMessageW ( ClassicComboBox , CB_SETITEMHEIGHT , - 1 , 22 - 6 ) ;
SetParent ( ClassicComboBox , ClassicAddressBandRoot ) ;
// Remove ProgressBsr
SendMessageW ( ClassicProgressControl , WM_CLOSE , 0 , 0 ) ;
// Fix ComboBox
GetWindowRect ( ClassicComboBox , & rect ) ;
SetWindowPos ( ClassicComboBox , NULL , NULL , NULL , rect . right - rect . left + 1 , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
SetWindowPos ( ClassicComboBox , NULL , NULL , NULL , rect . right - rect . left , rect . bottom - rect . top , SWP_NOMOVE | SWP_NOZORDER | SWP_DEFERERASE ) ;
// Redraw the ComboBox
RedrawWindow ( ClassicComboBox , NULL , NULL , RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN ) ;
}
}
// boilerplate from hide-search-bar
# if defined(__GNUC__) && __GNUC__ > 8
# define WINAPI_LAMBDA_RETURN(return_t) -> return_t WINAPI
# elif defined(__GNUC__)
# define WINAPI_LAMBDA_RETURN(return_t) WINAPI -> return_t
# else
# define WINAPI_LAMBDA_RETURN(return_t) -> return_t
# endif
DWORD g_uiThreadId ;
inline LSTATUS SHRegGetValueFromHKCUHKLMWithOpt ( PCWSTR pwszKey , PCWSTR pwszValue , REGSAM samDesired , void * pvData , DWORD * pcbData )
{
LSTATUS lRes = ERROR_FILE_NOT_FOUND ;
HKEY hKey = NULL ;
RegOpenKeyExW ( HKEY_CURRENT_USER , pwszKey , 0 , samDesired , & hKey ) ;
if ( hKey = = NULL | | hKey = = INVALID_HANDLE_VALUE ) hKey = NULL ;
if ( hKey )
{
lRes = RegQueryValueExW ( hKey , pwszValue , 0 , NULL , ( LPBYTE ) pvData , ( LPDWORD ) pcbData ) ;
RegCloseKey ( hKey ) ;
if ( lRes = = ERROR_SUCCESS | | lRes = = ERROR_MORE_DATA ) return lRes ;
}
RegOpenKeyExW ( HKEY_LOCAL_MACHINE , pwszKey , 0 , samDesired , & hKey ) ;
if ( hKey = = NULL | | hKey = = INVALID_HANDLE_VALUE ) hKey = NULL ;
if ( hKey )
{
lRes = RegQueryValueExW ( hKey , pwszValue , 0 , NULL , ( LPBYTE ) pvData , ( LPDWORD ) pcbData ) ;
RegCloseKey ( hKey ) ;
if ( lRes = = ERROR_SUCCESS | | lRes = = ERROR_MORE_DATA ) return lRes ;
}
return lRes ;
}
UINT g_subclassRegisteredMsg = RegisterWindowMessage ( L " Windhawk_SetWindowSubclassFromAnyThread_classic-theme-explorer " ) ;
LRESULT CALLBACK ClassicThemeExplorerSubClass ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam , UINT_PTR uIdSubclass , DWORD_PTR dwRefData ) {
if ( uMsg = = WM_DESTROY ) {
2023-03-13 17:38:05 +00:00
Wh_Log ( L " [Destroy] uMsg: 0x%04x, wParam: 0x%x " , uMsg , wParam ) ;
2023-02-26 22:08:55 +00:00
RemoveWindowSubclass ( hWnd , ClassicThemeExplorerSubClass , 0 ) ;
} else if ( uMsg = = g_subclassRegisteredMsg & & ! wParam ) {
2023-03-13 17:38:05 +00:00
Wh_Log ( L " [Unsub] uMsg: 0x%04x, wParam: 0x%x " , uMsg , wParam ) ;
2023-02-26 22:08:55 +00:00
RemoveWindowSubclass ( hWnd , ClassicThemeExplorerSubClass , 0 ) ;
} else if ( uMsg = = WM_PARENTNOTIFY | | uMsg = = WM_SIZE | | uMsg = = WM_GETICON ) {
2023-03-13 17:38:05 +00:00
Wh_Log ( L " [Target] uMsg: 0x%04x, wParam: 0x%x " , uMsg , wParam ) ;
ClassicThemeExplorer ( hWnd , uMsg , wParam ) ;
2023-03-12 21:37:02 +00:00
//} else {
//Wh_Log(L"[Unknown] uMsg: 0x%04x, wParam: 0x%x", uMsg, wParam);
2023-02-26 22:08:55 +00:00
}
return DefSubclassProc ( hWnd , uMsg , wParam , lParam ) ;
}
struct SET_WINDOW_SUBCLASS_FROM_ANY_THREAD_PARAM {
SUBCLASSPROC pfnSubclass ;
UINT_PTR uIdSubclass ;
DWORD_PTR dwRefData ;
BOOL result ;
} ;
LRESULT CALLBACK CallWndProcForWindowSubclass ( int nCode , WPARAM wParam , LPARAM lParam ) {
if ( nCode = = HC_ACTION ) {
const CWPSTRUCT * cwp = ( const CWPSTRUCT * ) lParam ;
if ( cwp - > message = = g_subclassRegisteredMsg & & cwp - > wParam ) {
SET_WINDOW_SUBCLASS_FROM_ANY_THREAD_PARAM * param = ( SET_WINDOW_SUBCLASS_FROM_ANY_THREAD_PARAM * ) cwp - > lParam ;
param - > result = SetWindowSubclass ( cwp - > hwnd , param - > pfnSubclass , param - > uIdSubclass , param - > dwRefData ) ;
}
}
return CallNextHookEx ( nullptr , nCode , wParam , lParam ) ;
}
BOOL SetWindowSubclassFromAnyThread ( HWND hWnd , SUBCLASSPROC pfnSubclass , UINT_PTR uIdSubclass , DWORD_PTR dwRefData ) {
DWORD dwThreadId = GetWindowThreadProcessId ( hWnd , nullptr ) ;
if ( dwThreadId = = 0 ) return FALSE ;
if ( dwThreadId = = GetCurrentThreadId ( ) ) return SetWindowSubclass ( hWnd , pfnSubclass , uIdSubclass , dwRefData ) ;
HHOOK hook = SetWindowsHookEx ( WH_CALLWNDPROC , CallWndProcForWindowSubclass , nullptr , dwThreadId ) ;
if ( ! hook ) return FALSE ;
SET_WINDOW_SUBCLASS_FROM_ANY_THREAD_PARAM param ;
param . pfnSubclass = pfnSubclass ;
param . uIdSubclass = uIdSubclass ;
param . dwRefData = dwRefData ;
param . result = FALSE ;
SendMessage ( hWnd , g_subclassRegisteredMsg , TRUE , ( WPARAM ) & param ) ;
UnhookWindowsHookEx ( hook ) ;
return param . result ;
}
BOOL CALLBACK EnumBrowserWindowsUnsubclassFunc ( HWND hWnd , LPARAM lParam ) {
SendMessage ( hWnd , g_subclassRegisteredMsg , FALSE , 0 ) ;
return TRUE ;
}
HWND ( WINAPI * pOriginalSHCreateWorkerWindow ) ( WNDPROC wndProc , HWND hWndParent , DWORD dwExStyle , DWORD dwStyle , HMENU hMenu , LONG_PTR wnd_extra ) ;
HWND WINAPI SHCreateWorkerWindowHook ( WNDPROC wndProc , HWND hWndParent , DWORD dwExStyle , DWORD dwStyle , HMENU hMenu , LONG_PTR wnd_extra )
{
HWND result ;
LSTATUS lRes = ERROR_FILE_NOT_FOUND ;
DWORD dwSize = 0 ;
2023-03-13 17:38:05 +00:00
Wh_Log ( L " g_uiThreadId: %d, GetCurrentThreadId: %d " , g_uiThreadId , GetCurrentThreadId ( ) ) ;
2023-02-26 22:08:55 +00:00
// is this even needed? it changes thread after some time anyways
//if (g_uiThreadId && g_uiThreadId != GetCurrentThreadId()) return pOriginalSHCreateWorkerWindow(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
/*if (!g_uiThreadId)*/ g_uiThreadId = GetCurrentThreadId ( ) ;
if ( SHRegGetValueFromHKCUHKLMWithOpt (
TEXT ( " SOFTWARE \\ Classes \\ CLSID \\ {056440FD-8568-48e7-A632-72157243B55B} \\ InProcServer32 " ) ,
TEXT ( " " ) ,
KEY_READ | KEY_WOW64_64KEY ,
NULL ,
( LPDWORD ) ( & dwSize )
) = = ERROR_SUCCESS & & ( dwSize < 4 ) & & dwExStyle = = 0x10000 & & dwStyle = = 1174405120 ) result = 0 ;
else result = pOriginalSHCreateWorkerWindow ( wndProc , hWndParent , dwExStyle , dwStyle , hMenu , wnd_extra ) ;
2023-03-13 17:38:05 +00:00
Wh_Log ( L " dwExStyle: 0x%x, dwStyle: 0x%x, result: 0x%x " , dwExStyle , dwStyle , result ) ;
2023-02-26 22:08:55 +00:00
if ( dwExStyle = = 0x10000 & & dwStyle = = 0x46000000 & & result ) SetWindowSubclassFromAnyThread ( hWndParent , ClassicThemeExplorerSubClass , 0 , 0 ) ;
return result ;
}
2023-03-31 02:40:29 +00:00
// taskbar fixes from ExplorerPatcher
using CreateWindowExW_t = decltype ( & CreateWindowExW ) ;
CreateWindowExW_t CreateWindowExW_Orig ;
HWND WINAPI CreateWindowExW_Hook ( DWORD dwExStyle , LPCWSTR lpClassName , LPCWSTR lpWindowName , DWORD dwStyle , int X , int Y , int nWidth , int nHeight , HWND hWndParent , HMENU hMenu , HINSTANCE hInstance , LPVOID lpParam ) {
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " TrayNotifyWnd " ) )
{
dwExStyle | = WS_EX_STATICEDGE ;
}
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " NotifyIconOverflowWindow " ) )
{
dwExStyle | = WS_EX_STATICEDGE ;
}
if ( settings . clientEdge & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ( ! wcscmp ( lpClassName , L " SysListView32 " ) | | ! wcscmp ( lpClassName , L " SysTreeView32 " ) ) ) // !wcscmp(lpClassName, L"FolderView")
{
wchar_t wszClassName [ 200 ] ;
ZeroMemory ( wszClassName , 200 ) ;
GetClassNameW ( GetAncestor ( hWndParent , GA_ROOT ) , wszClassName , 200 ) ;
if ( ! wcscmp ( wszClassName , L " CabinetWClass " ) )
{
dwExStyle | = WS_EX_CLIENTEDGE ;
}
}
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " ReBarWindow32 " ) )
{
wchar_t wszClassName [ 200 ] ;
ZeroMemory ( wszClassName , 200 ) ;
GetClassNameW ( hWndParent , wszClassName , 200 ) ;
if ( ! wcscmp ( wszClassName , L " Shell_TrayWnd " ) )
{
dwStyle | = RBS_BANDBORDERS ;
}
}
HWND hWnd = CreateWindowExW_Orig ( dwExStyle , lpClassName , lpWindowName , dwStyle , X , Y , nWidth , nHeight , hWndParent , hMenu , hInstance , lpParam ) ;
return hWnd ;
}
using SetWindowLongPtrW_t = decltype ( & SetWindowLongPtrW ) ;
SetWindowLongPtrW_t SetWindowLongPtrW_Orig ;
LONG_PTR SetWindowLongPtrW_Hook ( HWND hWnd , int nIndex , LONG_PTR dwNewLong ) {
WCHAR lpClassName [ 200 ] ;
ZeroMemory ( lpClassName , 200 ) ;
GetClassNameW ( hWnd , lpClassName , 200 ) ;
HWND hWndParent = GetParent ( hWnd ) ;
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " TrayNotifyWnd " ) )
{
if ( nIndex = = GWL_EXSTYLE )
{
dwNewLong | = WS_EX_STATICEDGE ;
}
}
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " NotifyIconOverflowWindow " ) )
{
if ( nIndex = = GWL_EXSTYLE )
{
dwNewLong | = WS_EX_STATICEDGE ;
}
}
if ( settings . clientEdge & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ( ! wcscmp ( lpClassName , L " SysListView32 " ) | | ! wcscmp ( lpClassName , L " SysTreeView32 " ) ) ) // !wcscmp(lpClassName, L"FolderView")
{
wchar_t wszClassName [ 200 ] ;
ZeroMemory ( wszClassName , 200 ) ;
GetClassNameW ( GetAncestor ( hWndParent , GA_ROOT ) , wszClassName , 200 ) ;
if ( ! wcscmp ( wszClassName , L " CabinetWClass " ) )
{
if ( nIndex = = GWL_EXSTYLE )
{
dwNewLong | = WS_EX_CLIENTEDGE ;
}
}
}
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( lpClassName ) + 1 ) ) & & ! wcscmp ( lpClassName , L " ReBarWindow32 " ) )
{
wchar_t wszClassName [ 200 ] ;
ZeroMemory ( wszClassName , 200 ) ;
GetClassNameW ( hWndParent , wszClassName , 200 ) ;
if ( ! wcscmp ( wszClassName , L " Shell_TrayWnd " ) )
{
if ( nIndex = = GWL_STYLE )
{
dwNewLong | = RBS_BANDBORDERS ;
}
}
}
return SetWindowLongPtrW_Orig ( hWnd , nIndex , dwNewLong ) ;
}
HTHEME ( * pOriginalOpenThemeDataForDpi ) ( HWND hWnd , LPCWSTR pszClassList , UINT dpi ) ;
HTHEME OpenThemeDataForDpiHook ( HWND hWnd , LPCWSTR pszClassList , UINT dpi )
{
if ( settings . epMitigate & & ( * ( ( WORD * ) & ( pszClassList ) + 1 ) ) & & ! wcscmp ( pszClassList , L " Taskband2 " ) ) {
Wh_Log ( L " Redirecting Taskband2 hTheme " ) ;
return ( HTHEME ) 0xDEADBEEF ;
} else if ( settings . epMitigate & & ( * ( ( WORD * ) & ( pszClassList ) + 1 ) ) & & ! wcscmp ( pszClassList , L " TrayNotifyFlyout " ) ) {
Wh_Log ( L " Redirecting TrayNotifyFlyout hTheme " ) ;
return ( HTHEME ) 0xDEADBEFF ;
}
return pOriginalOpenThemeDataForDpi ( hWnd , pszClassList , dpi ) ;
}
HRESULT ( * pOriginalGetThemeMetric ) ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , int iPropId , int * piVal ) ;
HRESULT GetThemeMetricHook ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , int iPropId , int * piVal ) {
Wh_Log ( L " hTheme: %08X " , hTheme ) ;
if ( ! settings . epMitigate | | ( hTheme ! = ( HTHEME ) 0xDEADBEFF ) ) {
return pOriginalGetThemeMetric ( hTheme , hdc , iPartId , iStateId , iPropId , piVal ) ;
}
const int TMT_WIDTH = 2416 ;
const int TMT_HEIGHT = 2417 ;
if ( hTheme = = ( HTHEME ) 0xDEADBEFF & & iPropId = = TMT_WIDTH & & iPartId = = 3 & & iStateId = = 0 )
{
* piVal = GetSystemMetrics ( SM_CXICON ) ;
}
else if ( hTheme = = ( HTHEME ) 0xDEADBEFF & & iPropId = = TMT_HEIGHT & & iPartId = = 3 & & iStateId = = 0 )
{
* piVal = GetSystemMetrics ( SM_CYICON ) ;
}
return S_OK ;
}
HRESULT ( * pOriginalGetThemeMargins ) ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , int iPropId , LPCRECT prc , MARGINS * pMargins ) ;
HRESULT GetThemeMarginsHook ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , int iPropId , LPCRECT prc , MARGINS * pMargins ) {
Wh_Log ( L " hTheme: %08X " , hTheme ) ;
if ( ! settings . epMitigate | | ( hTheme ! = ( HTHEME ) 0xDEADBEEF & & hTheme ! = ( HTHEME ) 0xDEADBEFF ) ) {
return pOriginalGetThemeMargins ( hTheme , hdc , iPartId , iStateId , iPropId , prc , pMargins ) ;
}
const int TMT_SIZINGMARGINS = 3601 ;
const int TMT_CONTENTMARGINS = 3602 ;
HRESULT hr = S_OK ;
if ( hTheme )
{
hr = pOriginalGetThemeMargins (
hTheme ,
hdc ,
iPartId ,
iStateId ,
iPropId ,
prc ,
pMargins
) ;
}
if ( hTheme = = ( HTHEME ) 0xDEADBEEF & & iPropId = = TMT_CONTENTMARGINS & & iPartId = = 5 & & iStateId = = 1 ) {
// task list button measurements
pMargins - > cxLeftWidth = 4 ;
pMargins - > cyTopHeight = 3 ;
pMargins - > cxRightWidth = 4 ;
pMargins - > cyBottomHeight = 3 ;
} else if ( hTheme = = ( HTHEME ) 0xDEADBEEF & & iPropId = = TMT_CONTENTMARGINS & & iPartId = = 1 & & iStateId = = 0 ) {
// task list measurements
pMargins - > cxLeftWidth = 0 ;
pMargins - > cyTopHeight = 0 ;
pMargins - > cxRightWidth = 4 ;
pMargins - > cyBottomHeight = 0 ;
} else if ( hTheme = = ( HTHEME ) 0xDEADBEEF & & iPropId = = TMT_SIZINGMARGINS & & iPartId = = 5 & & iStateId = = 1 ) {
pMargins - > cxLeftWidth = 10 ;
pMargins - > cyTopHeight = 10 ;
pMargins - > cxRightWidth = 10 ;
pMargins - > cyBottomHeight = 10 ;
} else if ( hTheme = = ( HTHEME ) 0xDEADBEFF & & iPropId = = TMT_CONTENTMARGINS & & iPartId = = 3 & & iStateId = = 0 ) {
pMargins - > cxLeftWidth = 4 ; // GetSystemMetrics(SM_CXICONSPACING);
pMargins - > cyTopHeight = 4 ; // GetSystemMetrics(SM_CYICONSPACING);
pMargins - > cxRightWidth = 4 ; //GetSystemMetrics(SM_CXICONSPACING);
pMargins - > cyBottomHeight = 4 ; // GetSystemMetrics(SM_CYICONSPACING);
}
HWND hShell_TrayWnd = FindWindowEx ( NULL , NULL , L " Shell_TrayWnd " , NULL ) ;
if ( hShell_TrayWnd ) {
LONG dwStyle = 0 ;
dwStyle = GetWindowLongW ( hShell_TrayWnd , GWL_STYLE ) ;
dwStyle | = WS_DLGFRAME ;
SetWindowLongW ( hShell_TrayWnd , GWL_STYLE , dwStyle ) ;
dwStyle & = ~ WS_DLGFRAME ;
SetWindowLongW ( hShell_TrayWnd , GWL_STYLE , dwStyle ) ;
}
HWND hWnd = NULL ;
do {
hWnd = FindWindowEx (
NULL ,
hWnd ,
L " Shell_SecondaryTrayWnd " ,
NULL
) ;
if ( hWnd ) {
LONG dwStyle = 0 ;
dwStyle = GetWindowLongW ( hWnd , GWL_STYLE ) ;
dwStyle | = WS_DLGFRAME ;
SetWindowLongW ( hWnd , GWL_STYLE , dwStyle ) ;
dwStyle & = ~ WS_DLGFRAME ;
SetWindowLongW ( hWnd , GWL_STYLE , dwStyle ) ;
}
} while ( hWnd ) ;
return S_OK ;
}
HRESULT ( * pOriginalDrawThemeTextEx ) ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , LPCWSTR pszText , int cchText , DWORD dwTextFlags , LPRECT pRect , const DTTOPTS * pOptions ) ;
HRESULT DrawThemeTextExHook ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , LPCWSTR pszText , int cchText , DWORD dwTextFlags , LPRECT pRect , const DTTOPTS * pOptions ) {
if ( ! settings . epMitigate ) {
return pOriginalDrawThemeTextEx ( hTheme , hdc , iPartId , iStateId , pszText , cchText , dwTextFlags , pRect , pOptions ) ;
}
COLORREF bc = GetBkColor ( hdc ) ;
COLORREF fc = GetTextColor ( hdc ) ;
int mode = SetBkMode ( hdc , TRANSPARENT ) ;
wchar_t text [ 200 ] ;
GetWindowTextW ( GetForegroundWindow ( ) , text , 200 ) ;
BOOL bIsActiveUnhovered = ( iPartId = = 5 & & iStateId = = 5 ) ;
BOOL bIsInactiveUnhovered = ( iPartId = = 5 & & iStateId = = 1 ) ;
BOOL bIsInactiveHovered = ( iPartId = = 5 & & iStateId = = 2 ) ;
BOOL bIsActiveHovered = bIsInactiveHovered & & ! wcscmp ( text , pszText ) ;
SetTextColor ( hdc , GetSysColor ( COLOR_BTNTEXT ) ) ;
NONCLIENTMETRICSW ncm ;
ncm . cbSize = sizeof ( NONCLIENTMETRICSW ) ;
SystemParametersInfoW ( SPI_GETNONCLIENTMETRICS , sizeof ( NONCLIENTMETRICSW ) , & ncm , 0 ) ;
HFONT hFont = NULL ;
if ( bIsActiveUnhovered )
{
hFont = CreateFontIndirectW ( & ( ncm . lfCaptionFont ) ) ;
}
else if ( bIsInactiveUnhovered )
{
hFont = CreateFontIndirectW ( & ( ncm . lfMenuFont ) ) ;
}
else if ( bIsActiveHovered )
{
hFont = CreateFontIndirectW ( & ( ncm . lfCaptionFont ) ) ;
}
else if ( bIsInactiveHovered )
{
hFont = CreateFontIndirectW ( & ( ncm . lfMenuFont ) ) ;
}
else
{
hFont = CreateFontIndirectW ( & ( ncm . lfMenuFont ) ) ;
}
if ( iPartId = = 5 & & iStateId = = 0 ) // clock
{
pRect - > top + = 2 ;
}
HGDIOBJ hOldFont = SelectObject ( hdc , hFont ) ;
DrawTextW (
hdc ,
pszText ,
cchText ,
pRect ,
dwTextFlags
) ;
SelectObject ( hdc , hOldFont ) ;
DeleteObject ( hFont ) ;
SetBkColor ( hdc , bc ) ;
SetTextColor ( hdc , fc ) ;
SetBkMode ( hdc , mode ) ;
return S_OK ;
}
HRESULT ( * pOriginalDrawThemeBackground ) ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , LPRECT pRect , LPCRECT pClipRect ) ;
HRESULT DrawThemeBackgroundHook ( HTHEME hTheme , HDC hdc , int iPartId , int iStateId , LPRECT pRect , LPCRECT pClipRect ) {
if ( settings . epMitigate ) {
if ( iPartId = = 4 & & iStateId = = 1 ) {
COLORREF bc = GetBkColor ( hdc ) ;
COLORREF fc = GetTextColor ( hdc ) ;
int mode = SetBkMode ( hdc , TRANSPARENT ) ;
SetTextColor ( hdc , GetSysColor ( COLOR_BTNTEXT ) ) ;
NONCLIENTMETRICSW ncm ;
ncm . cbSize = sizeof ( NONCLIENTMETRICSW ) ;
SystemParametersInfoW ( SPI_GETNONCLIENTMETRICS , sizeof ( NONCLIENTMETRICSW ) , & ncm , 0 ) ;
HFONT hFont = CreateFontIndirectW ( & ( ncm . lfCaptionFont ) ) ;
/*UINT dpiX, dpiY;
HRESULT hr = GetDpiForMonitor (
MonitorFromWindow ( WindowFromDC ( hdc ) , MONITOR_DEFAULTTOPRIMARY ) ,
MDT_DEFAULT ,
& dpiX ,
& dpiY
) ;
double dx = dpiX / 96.0 , dy = dpiY / 96.0 ; */
HGDIOBJ hOldFont = SelectObject ( hdc , hFont ) ;
DWORD dwTextFlags = DT_SINGLELINE | DT_CENTER | DT_VCENTER ;
RECT rc = * pRect ;
rc . bottom - = 7 ;
DrawTextW (
hdc ,
L " \u2026 " ,
- 1 ,
& rc ,
dwTextFlags
) ;
SelectObject ( hdc , hOldFont ) ;
DeleteObject ( hFont ) ;
SetBkColor ( hdc , bc ) ;
SetTextColor ( hdc , fc ) ;
SetBkMode ( hdc , mode ) ;
}
return S_OK ;
}
return pOriginalDrawThemeBackground ( hTheme , hdc , iPartId , iStateId , pRect , pClipRect ) ;
}
struct WINCOMPATTRDATA
{
DWORD attribute ;
PVOID pData ;
ULONG dataSize ;
} ;
BOOL ( WINAPI * pOriginalSetWindowCompositionAttribute ) ( HWND hWnd , WINCOMPATTRDATA * pData ) ;
BOOL WINAPI SetWindowCompositionAttributeHook ( HWND hWnd , WINCOMPATTRDATA * pData ) {
if ( settings . epMitigate ) {
return TRUE ;
}
return pOriginalSetWindowCompositionAttribute ( hWnd , pData ) ;
}
2023-02-26 22:08:55 +00:00
// Windhawk boilerplate
BOOL Wh_ModInit ( ) {
LoadSettings ( ) ;
HMODULE hShcore = GetModuleHandle ( L " shcore.dll " ) ;
2023-03-31 02:40:29 +00:00
void * origCWW = ( void * ) GetProcAddress ( hShcore , ( LPCSTR ) 188 ) ;
Wh_SetFunctionHook ( origCWW , ( void * ) SHCreateWorkerWindowHook , ( void * * ) & pOriginalSHCreateWorkerWindow ) ;
HMODULE hUxtheme = GetModuleHandle ( L " uxtheme.dll " ) ;
void * origOTDFD = ( void * ) GetProcAddress ( hUxtheme , " OpenThemeDataForDpi " ) ;
Wh_SetFunctionHook ( origOTDFD , ( void * ) OpenThemeDataForDpiHook , ( void * * ) & pOriginalOpenThemeDataForDpi ) ;
void * origGTMe = ( void * ) GetProcAddress ( hUxtheme , " GetThemeMetric " ) ;
Wh_SetFunctionHook ( origGTMe , ( void * ) GetThemeMetricHook , ( void * * ) & pOriginalGetThemeMetric ) ;
void * origGTMa = ( void * ) GetProcAddress ( hUxtheme , " GetThemeMargins " ) ;
Wh_SetFunctionHook ( origGTMa , ( void * ) GetThemeMarginsHook , ( void * * ) & pOriginalGetThemeMargins ) ;
void * origDTTE = ( void * ) GetProcAddress ( hUxtheme , " DrawThemeTextEx " ) ;
Wh_SetFunctionHook ( origDTTE , ( void * ) DrawThemeTextExHook , ( void * * ) & pOriginalDrawThemeTextEx ) ;
void * origDTB = ( void * ) GetProcAddress ( hUxtheme , " DrawThemeBackground " ) ;
Wh_SetFunctionHook ( origDTB , ( void * ) DrawThemeBackgroundHook , ( void * * ) & pOriginalDrawThemeBackground ) ;
//HMODULE hUser32 = GetModuleHandle(L"user32.dll");
//void* origSWCA = (void*)GetProcAddress(hUser32, "SetWindowCompositionAttribute");
//Wh_SetFunctionHook(origSWCA, (void*)SetWindowCompositionAttributeHook, (void**)&pOriginalSetWindowCompositionAttribute);
Wh_SetFunctionHook ( ( void * ) CreateWindowExW ,
( void * ) CreateWindowExW_Hook ,
( void * * ) & CreateWindowExW_Orig ) ;
Wh_SetFunctionHook ( ( void * ) SetWindowLongPtrW ,
( void * ) SetWindowLongPtrW_Hook ,
( void * * ) & SetWindowLongPtrW_Orig ) ;
2023-02-26 22:08:55 +00:00
return TRUE ;
}
void Wh_ModUninit ( ) {
if ( g_uiThreadId ! = 0 ) EnumThreadWindows ( g_uiThreadId , EnumBrowserWindowsUnsubclassFunc , 0 ) ;
}
void Wh_ModSettingsChanged ( ) {
LoadSettings ( ) ;
}