From ca8ce137d86675acab0e316e9f51b01de979b18a Mon Sep 17 00:00:00 2001 From: Valentin Radu Date: Wed, 1 Mar 2023 20:35:31 +0200 Subject: [PATCH] ep_extra: Implemented a loadable module for Windows 7's Alt-Tab As a way to showcase the `ep_extra` loader I wrote in my previous commit, I have developed this module which enables the use of Windows 7's Alt-Tab. Mind you, the implementation might not be complete and 100% ironed out, but rather a functional preview on what it can look like. Grab a copy of `AltTab.dll` from Windows 7 (I have tested against version 6.1.7600.16385) and place it in `C:\Windows`. Then, reload `explorer` with the `ep_extra` loader and this module in `C:\Windows` and when you "alt-tab", you should see the Windows 7 window switcher. This is not a reproduction - it executes the original code from Microsoft's DLL, only slightly patched to work properly in with the updated APIs in the newer Windows versions. --- ep_extra_valinet.win7alttab/README.md | 9 + ep_extra_valinet.win7alttab/Resource.rc | 100 +++++++++++ .../ep_extra_valinet.win7alttab.vcxproj | 161 ++++++++++++++++++ ...p_extra_valinet.win7alttab.vcxproj.filters | 44 +++++ ep_extra_valinet.win7alttab/main.c | 120 +++++++++++++ ep_extra_valinet.win7alttab/resource.h | 14 ++ 6 files changed, 448 insertions(+) create mode 100644 ep_extra_valinet.win7alttab/README.md create mode 100644 ep_extra_valinet.win7alttab/Resource.rc create mode 100644 ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj create mode 100644 ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj.filters create mode 100644 ep_extra_valinet.win7alttab/main.c create mode 100644 ep_extra_valinet.win7alttab/resource.h diff --git a/ep_extra_valinet.win7alttab/README.md b/ep_extra_valinet.win7alttab/README.md new file mode 100644 index 0000000..6b80589 --- /dev/null +++ b/ep_extra_valinet.win7alttab/README.md @@ -0,0 +1,9 @@ +# ExplorerPatcher Windows 7 Alt-Tab Module + +This module patches the Windows 7 genuine Alt-Tab implementation to work on newer Windows versions. + +To install, make sure you have the following files in `C:\Windows`: + +* `ep_extra_valinet.win7alttab.dll` - this DLL +* `ep_extra.dll` - a chainloader capable of being invoked by ExplorerPatcher (implements `ep_extra_EntryPoint` and which loads other `ep_extra_*.dll` modules +* `AltTab.dll` - a copy of the `AltTab.dll` in `C:\Windows\System32` from a Windows 7 installation diff --git a/ep_extra_valinet.win7alttab/Resource.rc b/ep_extra_valinet.win7alttab/Resource.rc new file mode 100644 index 0000000..f0951e3 --- /dev/null +++ b/ep_extra_valinet.win7alttab/Resource.rc @@ -0,0 +1,100 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "VALINET Solutions SRL" + VALUE "FileDescription", "ExplorerPatcher Windows 7 Alt-Tab Module" + VALUE "FileVersion", "1.0.0.0" + VALUE "InternalName", "ep_extra_valinet.win7alttab" + VALUE "LegalCopyright", "Copyright (C) 2006-2022 VALINET Solutions SRL. All rights reserved." + VALUE "OriginalFilename", "ep_extra_valinet.win7alttab" + VALUE "ProductName", "ExplorerPatcher" + VALUE "ProductVersion", "1.0.0.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj b/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj new file mode 100644 index 0000000..596eb3c --- /dev/null +++ b/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {a66c5f27-dbf8-45a4-bdf3-ba54d8d82d0f} + epextravalinetwin7alttab + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)\build\$(Configuration) + + + $(SolutionDir)\build\$(Configuration) + + + $(SolutionDir)\build\$(Configuration) + + + $(SolutionDir)\build\$(Configuration) + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj.filters b/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj.filters new file mode 100644 index 0000000..6578927 --- /dev/null +++ b/ep_extra_valinet.win7alttab/ep_extra_valinet.win7alttab.vcxproj.filters @@ -0,0 +1,44 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/ep_extra_valinet.win7alttab/main.c b/ep_extra_valinet.win7alttab/main.c new file mode 100644 index 0000000..291bf2f --- /dev/null +++ b/ep_extra_valinet.win7alttab/main.c @@ -0,0 +1,120 @@ +#include +#include +#include "../libs/libvalinet/valinet/hooking/iatpatch.h" +#include "../libs/sws/SimpleWindowSwitcher/sws_WindowHelpers.h" +#pragma comment(lib, "Uxtheme.lib") + +HMODULE hModule = NULL; +HMODULE hAltTab = NULL; +IOleCommandTarget* pAltTabSSO = NULL; + +DEFINE_GUID(CLSID_AltTabSSO, + 0xA1607060, 0x5D4C, 0x467A, 0xB7, 0x11, 0x2B, 0x59, 0xA6, 0xF2, 0x59, 0x57); + +HRESULT AltTab_DwmpActivateLivePreview(int s, HWND hWnd, int c, int d) { + return S_OK; +} + +int AltTab_LoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int cchBufferMax) { + if (uID == 0x3E8) { + swprintf_s(lpBuffer, cchBufferMax, L"AltTab"); return 6; + } + else if (uID == 0x3EA) { + if (cchBufferMax < MAX_PATH) return 0; + sws_WindowHelpers_GetDesktopText(lpBuffer); + int len = wcslen(lpBuffer); + for (int i = 0; i < len; ++i) if (lpBuffer[i] == L'&') lpBuffer[i] = L'\u200E'; + return len; + } + return LoadStringW(hInstance, uID, lpBuffer, cchBufferMax); +} + +HTHEME AltTab_OpenThemeData(HWND hwnd, LPCWSTR pszClassList) { + if (!wcscmp(pszClassList, L"AltTab")) return OpenThemeData(hwnd, L"WINDOW"); + return OpenThemeData(hwnd, pszClassList); +} + +HRESULT AltTab_DrawThemeTextEx(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT pRect, const DTTOPTS* pOptions) { + HRESULT hr = S_OK; + HTHEME hTheme2 = OpenThemeData(NULL, L"TEXTSTYLE"); + if (hTheme2) hr = DrawThemeTextEx(hTheme2, hdc, iPartId + 1, iStateId, pszText, cchText, dwTextFlags, pRect, pOptions); + if (hTheme2) CloseThemeData(hTheme2); + return hr; +} + +BOOL AltTab_IsWindowEnabled(HWND hWnd) { + if (!IsWindowEnabled(hWnd)) return FALSE; + BOOL isCloaked; + DwmGetWindowAttribute(hWnd, DWMWA_CLOAKED, &isCloaked, sizeof(BOOL)); + if (isCloaked) return FALSE; + if (sws_IsShellFrameWindow(hWnd) && !_sws_GhostWindowFromHungWindow(hWnd)) return TRUE; + if (_sws_IsShellManagedWindow(hWnd) && !sws_WindowHelpers_ShouldTreatShellManagedWindowAsNotShellManaged(hWnd)) return FALSE; + if (sws_WindowHelpers_IsWindowShellManagedByExplorerPatcher(hWnd)) return FALSE; + return TRUE; +} + +HRESULT AltTab_DwmExtendFrameIntoClientArea(HWND hWnd, const MARGINS* pMarInset) { + HRESULT hr = DwmExtendFrameIntoClientArea(hWnd, pMarInset); + sws_WindowHelpers_SetMicaMaterialForThisWindow(hWnd, TRUE); + return hr; +} + +BOOL AltTab_PostMessageW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + if (hWnd == FindWindowW(L"Shell_TrayWnd", NULL) && uMsg == 0x5B7 && wParam == 0 && lParam == 0) { + return PostMessageW(hWnd, WM_COMMAND, 407, 0); + } + return PostMessageW(hWnd, uMsg, wParam, lParam); +} + +__declspec(dllexport) void clean() { + if (pAltTabSSO) pAltTabSSO->lpVtbl->Release(pAltTabSSO); + if (hAltTab) sws_WindowHelpers_Clear(); +} + +__declspec(dllexport) int setup() { + hAltTab = LoadLibraryW(L"AltTab.dll"); + if (hAltTab) { + sws_WindowHelpers_Initialize(); + VnPatchIAT(hAltTab, "dwmapi.dll", "DwmExtendFrameIntoClientArea", AltTab_DwmExtendFrameIntoClientArea); + VnPatchIAT(hAltTab, "dwmapi.dll", (LPCSTR)113, AltTab_DwmpActivateLivePreview); + VnPatchIAT(hAltTab, "user32.dll", "PostMessageW", AltTab_PostMessageW); + VnPatchIAT(hAltTab, "user32.dll", "LoadStringW", AltTab_LoadStringW); + VnPatchIAT(hAltTab, "user32.dll", "IsWindowEnabled", AltTab_IsWindowEnabled); + VnPatchDelayIAT(hAltTab, "uxtheme.dll", "OpenThemeData", AltTab_OpenThemeData); + VnPatchDelayIAT(hAltTab, "uxtheme.dll", "DrawThemeTextEx", AltTab_DrawThemeTextEx); + HRESULT(*pDllGetClassObject)(REFCLSID, REFIID, LPVOID) = GetProcAddress(hAltTab, "DllGetClassObject"); + IClassFactory* pFactory = NULL; + if (pDllGetClassObject && SUCCEEDED(pDllGetClassObject(&CLSID_AltTabSSO, &IID_IClassFactory, &pFactory)) && pFactory) { + if (SUCCEEDED(pFactory->lpVtbl->CreateInstance(pFactory, NULL, &IID_IOleCommandTarget, &pAltTabSSO)) && pAltTabSSO) { + if (SUCCEEDED(pAltTabSSO->lpVtbl->Exec(pAltTabSSO, &CGID_ShellServiceObject, 2, 0, NULL, NULL))) { + printf(">>> Using Windows 7 AltTab\n"); + } + } + pFactory->lpVtbl->Release(pFactory); + } + FreeLibrary(hAltTab); + return 0; + } + return 1; +} + +BOOL WINAPI DllMain( + _In_ HINSTANCE hinstDLL, + _In_ DWORD fdwReason, + _In_ LPVOID lpvReserved +) { + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + hModule = hinstDLL; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} \ No newline at end of file diff --git a/ep_extra_valinet.win7alttab/resource.h b/ep_extra_valinet.win7alttab/resource.h new file mode 100644 index 0000000..7ca31da --- /dev/null +++ b/ep_extra_valinet.win7alttab/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif