From 725d5ad18f5df2426010a52fb2b80de1305256be Mon Sep 17 00:00:00 2001 From: Valentin Radu Date: Thu, 18 Nov 2021 18:20:17 +0200 Subject: [PATCH] 22000.318.38: * Functional Windows 10 network flyout * Functional Windows 10 battery flyout * Implemented support for Windows 7 battery flyout (#274) --- CHANGELOG.md | 15 + ExplorerPatcher/ExplorerPatcher.vcxproj | 2 + .../ExplorerPatcher.vcxproj.filters | 6 + ExplorerPatcher/ImmersiveFlyouts.c | 146 ++++++ ExplorerPatcher/ImmersiveFlyouts.h | 196 ++++++++ ExplorerPatcher/dllmain.c | 438 ++++++++++++++++-- ExplorerPatcher/settings.reg | 59 +-- ep_setup/ep_setup.c | 9 + version.h | 8 +- 9 files changed, 813 insertions(+), 66 deletions(-) create mode 100644 ExplorerPatcher/ImmersiveFlyouts.c create mode 100644 ExplorerPatcher/ImmersiveFlyouts.h diff --git a/CHANGELOG.md b/CHANGELOG.md index b35b45f..66e4fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ This document includes the same release notes as in the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section on GitHub. +## 22000.318.38 + +Tested on build 22000.318 and 22000.346 (currently in Windows Insider beta and release preview channels). + +#### New features + +* Functional Windows 10 network flyout +* Functional Windows 10 battery flyout +* Implemented support for Windows 7 battery flyout (#274) + +#### Feature enhancements + +* Improved reliability when invoking Control Center (`Win`+`A`) when the taskbar icon is disabled (the icon should now not reappear anymore sometimes) (#242) +* Small reorganization of some options in "Properties" + ## 22000.318.37 Tested on build 22000.318 and 22000.346 (currently in Windows Insider beta and release preview channels). diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj index 8422394..02665f6 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj @@ -246,6 +246,7 @@ true + true @@ -298,6 +299,7 @@ + diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj.filters b/ExplorerPatcher/ExplorerPatcher.vcxproj.filters index fdca619..2c72f79 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj.filters +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj.filters @@ -114,6 +114,9 @@ Header Files\internal + + Header Files + @@ -184,6 +187,9 @@ Source Files + + Source Files + diff --git a/ExplorerPatcher/ImmersiveFlyouts.c b/ExplorerPatcher/ImmersiveFlyouts.c new file mode 100644 index 0000000..d66c4a1 --- /dev/null +++ b/ExplorerPatcher/ImmersiveFlyouts.c @@ -0,0 +1,146 @@ +#include "ImmersiveFlyouts.h" + +void InvokeActionCenter() +{ + HRESULT hr = S_OK; + IUnknown* pImmersiveShell = NULL; + hr = CoCreateInstance( + &CLSID_ImmersiveShell, + NULL, + CLSCTX_NO_CODE_DOWNLOAD | CLSCTX_LOCAL_SERVER, + &IID_IServiceProvider, + &pImmersiveShell + ); + if (SUCCEEDED(hr)) + { + IShellExperienceManagerFactory* pShellExperienceManagerFactory = NULL; + IUnknown_QueryService( + pImmersiveShell, + &CLSID_ShellExperienceManagerFactory, + &CLSID_ShellExperienceManagerFactory, + &pShellExperienceManagerFactory + ); + if (pShellExperienceManagerFactory) + { + HSTRING_HEADER hstringHeader; + HSTRING hstring = NULL; + hr = WindowsCreateStringReference( + L"Windows.Internal.ShellExperience.ControlCenter", + (UINT32)(sizeof(L"Windows.Internal.ShellExperience.ControlCenter") / sizeof(wchar_t) - 1), + &hstringHeader, + &hstring + ); + if (hstring) + { + IUnknown* pIntf = NULL; + pShellExperienceManagerFactory->lpVtbl->GetExperienceManager( + pShellExperienceManagerFactory, + hstring, + &pIntf + ); + if (pIntf) + { + IActionCenterOrControlCenterExperienceManager* pControlCenterExperienceManager = NULL; + pIntf->lpVtbl->QueryInterface(pIntf, &IID_ControlCenterExperienceManager, &pControlCenterExperienceManager); + if (pControlCenterExperienceManager) + { + pControlCenterExperienceManager->lpVtbl->HotKeyInvoked(pControlCenterExperienceManager, 0); + pControlCenterExperienceManager->lpVtbl->Release(pControlCenterExperienceManager); + } + } + WindowsDeleteString(hstring); + } + pShellExperienceManagerFactory->lpVtbl->Release(pShellExperienceManagerFactory); + } + pImmersiveShell->lpVtbl->Release(pImmersiveShell); + } +} + +void InvokeFlyout(BOOL bAction, DWORD dwWhich) +{ + HRESULT hr = S_OK; + IUnknown* pImmersiveShell = NULL; + hr = CoCreateInstance( + &CLSID_ImmersiveShell, + NULL, + CLSCTX_NO_CODE_DOWNLOAD | CLSCTX_LOCAL_SERVER, + &IID_IServiceProvider, + &pImmersiveShell + ); + if (SUCCEEDED(hr)) + { + IShellExperienceManagerFactory* pShellExperienceManagerFactory = NULL; + IUnknown_QueryService( + pImmersiveShell, + &CLSID_ShellExperienceManagerFactory, + &CLSID_ShellExperienceManagerFactory, + &pShellExperienceManagerFactory + ); + if (pShellExperienceManagerFactory) + { + HSTRING_HEADER hstringHeader; + HSTRING hstring = NULL; + WCHAR* pwszStr = NULL; + switch (dwWhich) + { + case INVOKE_FLYOUT_NETWORK: + pwszStr = L"Windows.Internal.ShellExperience.NetworkFlyout"; + break; + case INVOKE_FLYOUT_CLOCK: + pwszStr = L"Windows.Internal.ShellExperience.TrayClockFlyout"; + break; + case INVOKE_FLYOUT_BATTERY: + pwszStr = L"Windows.Internal.ShellExperience.TrayBatteryFlyout"; + break; + case INVOKE_FLYOUT_SOUND: + pwszStr = L"Windows.Internal.ShellExperience.MtcUvc"; + break; + } + hr = WindowsCreateStringReference( + pwszStr, + pwszStr ? wcslen(pwszStr) : 0, + &hstringHeader, + &hstring + ); + if (hstring) + { + IUnknown* pIntf = NULL; + pShellExperienceManagerFactory->lpVtbl->GetExperienceManager( + pShellExperienceManagerFactory, + hstring, + &pIntf + ); + if (pIntf) + { + IExperienceManager* pExperienceManager = NULL; + pIntf->lpVtbl->QueryInterface( + pIntf, + dwWhich == INVOKE_FLYOUT_NETWORK ? &IID_NetworkFlyoutExperienceManager : + (dwWhich == INVOKE_FLYOUT_CLOCK ? &IID_TrayClockFlyoutExperienceManager : + (dwWhich == INVOKE_FLYOUT_BATTERY ? &IID_TrayBatteryFlyoutExperienceManager : + (dwWhich == INVOKE_FLYOUT_SOUND ? &IID_TrayMtcUvcFlyoutExperienceManager : &IID_IUnknown))), + &pExperienceManager + ); + if (pExperienceManager) + { + RECT rc; + SetRect(&rc, 0, 0, 0, 0); + if (bAction == INVOKE_FLYOUT_SHOW) + { + pExperienceManager->lpVtbl->ShowFlyout(pExperienceManager, &rc, NULL); + } + else if (bAction == INVOKE_FLYOUT_HIDE) + { + pExperienceManager->lpVtbl->HideFlyout(pExperienceManager); + } + pExperienceManager->lpVtbl->Release(pExperienceManager); + } + + } + WindowsDeleteString(hstring); + } + pShellExperienceManagerFactory->lpVtbl->Release(pShellExperienceManagerFactory); + } + pImmersiveShell->lpVtbl->Release(pImmersiveShell); + } +} diff --git a/ExplorerPatcher/ImmersiveFlyouts.h b/ExplorerPatcher/ImmersiveFlyouts.h new file mode 100644 index 0000000..947320f --- /dev/null +++ b/ExplorerPatcher/ImmersiveFlyouts.h @@ -0,0 +1,196 @@ +#ifndef _H_IMMERSIVEFLYOUTS_H_ +#define _H_IMMERSIVEFLYOUTS_H_ +#include +#include +#include "utility.h" + +DEFINE_GUID(IID_TrayBatteryFlyoutExperienceManager, + 0x0a73aedc, + 0x1c68, 0x410d, 0x8d, 0x53, + 0x63, 0xaf, 0x80, 0x95, 0x1e, 0x8f +); +DEFINE_GUID(IID_TrayClockFlyoutExperienceManager, + 0xb1604325, + 0x6b59, 0x427b, 0xbf, 0x1b, + 0x80, 0xa2, 0xdb, 0x02, 0xd3, 0xd8 +); +DEFINE_GUID(IID_TrayMtcUvcFlyoutExperienceManager, + 0x7154c95d, + 0xc519, 0x49bd, 0xa9, 0x7e, + 0x64, 0x5b, 0xbf, 0xab, 0xE1, 0x11 +); +DEFINE_GUID(IID_NetworkFlyoutExperienceManager, + 0xC9DDC674, + 0xB44B, 0x4C67, 0x9D, 0x79, + 0x2B, 0x23, 0x7D, 0x9B, 0xE0, 0x5A +); +typedef interface IExperienceManager IExperienceManager; + +typedef struct IExperienceManagerVtbl // : IInspectable +{ + BEGIN_INTERFACE + + HRESULT(STDMETHODCALLTYPE* QueryInterface)( + IExperienceManager* This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void** ppvObject); + + ULONG(STDMETHODCALLTYPE* AddRef)( + IExperienceManager* This); + + ULONG(STDMETHODCALLTYPE* Release)( + IExperienceManager* This); + + HRESULT(STDMETHODCALLTYPE* GetIids)( + IExperienceManager* This, + ULONG* iidCount, + IID** iids); + + HRESULT(STDMETHODCALLTYPE* GetRuntimeClassName)( + IExperienceManager* This, + HSTRING* className); + + HRESULT(STDMETHODCALLTYPE* GetTrustLevel)( + IExperienceManager* This, + TrustLevel* trustLevel); + + HRESULT(STDMETHODCALLTYPE* ShowFlyout)( + IExperienceManager* This, + /* [in] */ RECT* rect, + /* [in] */ HWND hWnd); + + HRESULT(STDMETHODCALLTYPE* HideFlyout)( + IExperienceManager* This); + + END_INTERFACE +} IExperienceManagerVtbl; + +interface IExperienceManager +{ + CONST_VTBL struct IExperienceManagerVtbl* lpVtbl; +}; + +DEFINE_GUID(CLSID_ShellExperienceManagerFactory, + 0x2E8FCB18, + 0xA0EE, 0x41AD, 0x8E, 0xF8, + 0x77, 0xFB, 0x3A, 0x37, 0x0C, 0xA5 +); +typedef interface IShellExperienceManagerFactory IShellExperienceManagerFactory; + +typedef struct IShellExperienceManagerFactoryVtbl // : IInspectable +{ + BEGIN_INTERFACE + + HRESULT(STDMETHODCALLTYPE* QueryInterface)( + IShellExperienceManagerFactory* This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void** ppvObject); + + ULONG(STDMETHODCALLTYPE* AddRef)( + IShellExperienceManagerFactory* This); + + ULONG(STDMETHODCALLTYPE* Release)( + IShellExperienceManagerFactory* This); + + HRESULT(STDMETHODCALLTYPE* GetIids)( + IShellExperienceManagerFactory* This, + ULONG* iidCount, + IID** iids); + + HRESULT(STDMETHODCALLTYPE* GetRuntimeClassName)( + IShellExperienceManagerFactory* This, + HSTRING* className); + + HRESULT(STDMETHODCALLTYPE* GetTrustLevel)( + IShellExperienceManagerFactory* This, + TrustLevel* trustLevel); + + HRESULT(STDMETHODCALLTYPE* GetExperienceManager)( + IShellExperienceManagerFactory* This, + /* [in] */ HSTRING* experience, + _COM_Outptr_ IInspectable** ppvObject); + + END_INTERFACE +} IShellExperienceManagerFactoryVtbl; + +interface IShellExperienceManagerFactory +{ + CONST_VTBL struct IShellExperienceManagerFactoryVtbl* lpVtbl; +}; + +DEFINE_GUID(IID_ActionCenterExperienceManager, + 0xdec04b18, + 0x357e, 0x41d8, 0x9b, 0x71, + 0xb9, 0x91, 0x24, 0x3b, 0xea, 0x34 +); +DEFINE_GUID(IID_ControlCenterExperienceManager, + 0xd669a58e, + 0x6b18, 0x4d1d, 0x90, 0x04, + 0xa8, 0x86, 0x2a, 0xdb, 0x0a, 0x20 +); +typedef interface IActionCenterOrControlCenterExperienceManager IActionCenterOrControlCenterExperienceManager; + +typedef struct IActionCenterOrControlCenterExperienceManagerVtbl // : IInspectable +{ + BEGIN_INTERFACE + + HRESULT(STDMETHODCALLTYPE* QueryInterface)( + IActionCenterOrControlCenterExperienceManager* This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void** ppvObject); + + ULONG(STDMETHODCALLTYPE* AddRef)( + IActionCenterOrControlCenterExperienceManager* This); + + ULONG(STDMETHODCALLTYPE* Release)( + IActionCenterOrControlCenterExperienceManager* This); + + HRESULT(STDMETHODCALLTYPE* GetIids)( + IActionCenterOrControlCenterExperienceManager* This, + ULONG* iidCount, + IID** iids); + + HRESULT(STDMETHODCALLTYPE* GetRuntimeClassName)( + IActionCenterOrControlCenterExperienceManager* This, + HSTRING* className); + + HRESULT(STDMETHODCALLTYPE* GetTrustLevel)( + IActionCenterOrControlCenterExperienceManager* This, + TrustLevel* trustLevel); + + HRESULT(STDMETHODCALLTYPE* HotKeyInvoked)( + IActionCenterOrControlCenterExperienceManager* This, + /* [in] */ void* kind); + + HRESULT(STDMETHODCALLTYPE* Show)( // only in control center + IActionCenterOrControlCenterExperienceManager* This, + HSTRING hstringUnknown, + void* bSupressAnimations, + void* dwUnknown_ShouldBeOne); + + HRESULT(STDMETHODCALLTYPE* Hide)( // only in control center + IActionCenterOrControlCenterExperienceManager* This, + HSTRING hstringUnknown, + void* bSupressAnimations); + + END_INTERFACE +} IActionCenterOrControlCenterExperienceManagerVtbl; + +interface IActionCenterOrControlCenterExperienceManager +{ + CONST_VTBL struct IActionCenterOrControlCenterExperienceManagerVtbl* lpVtbl; +}; + +void InvokeActionCenter(); + +#define INVOKE_FLYOUT_SHOW 1 +#define INVOKE_FLYOUT_HIDE 2 +#define INVOKE_FLYOUT_NETWORK 1 +#define INVOKE_FLYOUT_CLOCK 2 +#define INVOKE_FLYOUT_BATTERY 3 +#define INVOKE_FLYOUT_SOUND 4 +void InvokeFlyout(BOOL bAction, DWORD dwWhich); +#endif \ No newline at end of file diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index fd47f7b..23419f6 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -122,6 +122,7 @@ DWORD S_Icon_Dark_Widgets = 0; #endif #include "SettingsMonitor.h" #include "HideExplorerSearchBar.h" +#include "ImmersiveFlyouts.h" #include "updates.h" DWORD dwUpdatePolicy = UPDATE_POLICY_DEFAULT; @@ -461,9 +462,60 @@ POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight, BOO return point; } +void TerminateShellExperienceHost() +{ + WCHAR wszKnownPath[MAX_PATH]; + GetWindowsDirectoryW(wszKnownPath, MAX_PATH); + wcscat_s(wszKnownPath, MAX_PATH, L"\\SystemApps\\ShellExperienceHost_cw5n1h2txyewy\\ShellExperienceHost.exe"); + HANDLE hSnapshot = NULL; + PROCESSENTRY32 pe32; + ZeroMemory(&pe32, sizeof(PROCESSENTRY32)); + pe32.dwSize = sizeof(PROCESSENTRY32); + hSnapshot = CreateToolhelp32Snapshot( + TH32CS_SNAPPROCESS, + 0 + ); + if (Process32First(hSnapshot, &pe32) == TRUE) + { + do + { + if (!wcscmp(pe32.szExeFile, TEXT("ShellExperienceHost.exe"))) + { + HANDLE hProcess = OpenProcess( + PROCESS_QUERY_LIMITED_INFORMATION | + PROCESS_TERMINATE, + FALSE, + pe32.th32ProcessID + ); + if (hProcess) + { + TCHAR wszProcessPath[MAX_PATH]; + DWORD dwLength = MAX_PATH; + QueryFullProcessImageNameW( + hProcess, + 0, + wszProcessPath, + &dwLength + ); + if (!_wcsicmp(wszProcessPath, wszKnownPath)) + { + TerminateProcess(hProcess, 0); + } + CloseHandle(hProcess); + hProcess = NULL; + } + } + } while (Process32Next(hSnapshot, &pe32) == TRUE); + if (hSnapshot) + { + CloseHandle(hSnapshot); + } + } +} + long long elapsedCheckForeground = 0; HANDLE hCheckForegroundThread = NULL; -DWORD CheckForegroundThread(wchar_t* wszClassName) +DWORD CheckForegroundThread(DWORD dwMode) { printf("Started \"Check foreground window\" thread.\n"); UINT i = 0; @@ -471,7 +523,7 @@ DWORD CheckForegroundThread(wchar_t* wszClassName) { wchar_t text[200]; GetClassNameW(GetForegroundWindow(), text, 200); - if (!wcscmp(text, wszClassName)) + if (!wcscmp(text, L"Windows.UI.Core.CoreWindow")) { break; } @@ -483,13 +535,18 @@ DWORD CheckForegroundThread(wchar_t* wszClassName) { wchar_t text[200]; GetClassNameW(GetForegroundWindow(), text, 200); - if (wcscmp(text, wszClassName)) + if (wcscmp(text, L"Windows.UI.Core.CoreWindow")) { break; } Sleep(100); } elapsedCheckForeground = milliseconds_now(); + if (!dwMode) + { + RegDeleteKeyW(HKEY_CURRENT_USER, _T(SEH_REGPATH)); + TerminateShellExperienceHost(); + } printf("Ended \"Check foreground window\" thread.\n"); return 0; } @@ -498,6 +555,10 @@ void LaunchNetworkTargets(DWORD dwTarget) { // very helpful: https://www.tenforums.com/tutorials/3123-clsid-key-guid-shortcuts-list-windows-10-a.html if (!dwTarget) + { + InvokeFlyout(INVOKE_FLYOUT_SHOW, INVOKE_FLYOUT_NETWORK); + } + else if (dwTarget == 5) { ShellExecuteW( NULL, @@ -1287,7 +1348,9 @@ INT64 Shell_TrayWndSubclassProc( } else if (uMsg == WM_HOTKEY && wParam == 500 && lParam == MAKELPARAM(MOD_WIN, 0x41)) { - if (lpShouldDisplayCCButton) + InvokeActionCenter(); + return 0; + /*if (lpShouldDisplayCCButton) { *lpShouldDisplayCCButton = 1; } @@ -1296,7 +1359,7 @@ INT64 Shell_TrayWndSubclassProc( { *lpShouldDisplayCCButton = bHideControlCenterButton; } - return lRes; + return lRes;*/ } else if (uMsg == WM_DISPLAYCHANGE) { @@ -2121,6 +2184,62 @@ BOOL sndvolsso_TrackPopupMenuExHook( } return b; } +long long stobject_TrackPopupMenuExElapsed = 0; +BOOL stobject_TrackPopupMenuExHook( + HMENU hMenu, + UINT uFlags, + int x, + int y, + HWND hWnd, + LPTPMPARAMS lptpm +) +{ + long long elapsed = milliseconds_now() - stobject_TrackPopupMenuExElapsed; + BOOL b = FALSE; + if (elapsed > POPUPMENU_SAFETOREMOVE_TIMEOUT || !bFlyoutMenus) + { + if (bCenterMenus) + { + PopupMenuAdjustCoordinatesAndFlags(&x, &y, &uFlags); + } + INT64* unknown_array = NULL; + POINT pt; + if (bSkinMenus) + { + unknown_array = calloc(4, sizeof(INT64)); + pt.x = x; + pt.y = y; + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( + hMenu, + hWnd, + &(pt), + 0xc, + unknown_array + ); + SetWindowSubclass(hWnd, OwnerDrawSubclassProc, OwnerDrawSubclassProc, 0); + } + b = TrackPopupMenuEx( + hMenu, + uFlags | TPM_RIGHTBUTTON, + x, + y, + hWnd, + lptpm + ); + stobject_TrackPopupMenuExElapsed = milliseconds_now(); + if (bSkinMenus) + { + RemoveWindowSubclass(hWnd, OwnerDrawSubclassProc, OwnerDrawSubclassProc); + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( + hMenu, + hWnd, + &(pt) + ); + free(unknown_array); + } + } + return b; +} long long stobject_TrackPopupMenuElapsed = 0; BOOL stobject_TrackPopupMenuHook( HMENU hMenu, @@ -2326,18 +2445,104 @@ HWND WINAPI explorerframe_SHCreateWorkerWindowHook( #pragma endregion +#pragma region "Fix battery flyout" +#ifdef _WIN64 +LSTATUS stobject_RegGetValueW( + HKEY hkey, + LPCWSTR lpSubKey, + LPCWSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData +) +{ + if (!lstrcmpW(lpValue, L"UseWin32BatteryFlyout")) + { + if (SHRegGetValueFromHKCUHKLMFunc) + { + return SHRegGetValueFromHKCUHKLMFunc( + lpSubKey, + lpValue, + SRRF_RT_REG_DWORD, + pdwType, + pvData, + pcbData + ); + } + } + return RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); +} + +HRESULT stobject_CoCreateInstanceHook( + REFCLSID rclsid, + LPUNKNOWN pUnkOuter, + DWORD dwClsContext, + REFIID riid, + LPVOID* ppv +) +{ + DWORD dwVal = 0, dwSize = sizeof(DWORD); + if (IsEqualGUID(rclsid, &CLSID_ImmersiveShell) && + IsEqualGUID(riid, &IID_IServiceProvider) && + SHRegGetValueFromHKCUHKLMFunc && SHRegGetValueFromHKCUHKLMFunc( + TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ImmersiveShell"), + TEXT("UseWin32BatteryFlyout"), + SRRF_RT_REG_DWORD, + NULL, + &dwVal, + (LPDWORD)(&dwSize) + ) == ERROR_SUCCESS) + { + if (!dwVal) + { + if (hCheckForegroundThread) + { + WaitForSingleObject(hCheckForegroundThread, INFINITE); + CloseHandle(hCheckForegroundThread); + hCheckForegroundThread = NULL; + } + HKEY hKey = NULL; + if (RegCreateKeyExW( + HKEY_CURRENT_USER, + _T(SEH_REGPATH), + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_READ, + NULL, + &hKey, + NULL + ) == ERROR_SUCCESS) + { + RegCloseKey(hKey); + } + TerminateShellExperienceHost(); + hCheckForegroundThread = CreateThread( + 0, + 0, + CheckForegroundThread, + dwVal, + 0, + 0 + ); + } + } + return CoCreateInstance( + rclsid, + pUnkOuter, + dwClsContext, + riid, + ppv + ); +} +#endif +#pragma endregion + + + #pragma region "Show WiFi networks on network icon click" #ifdef _WIN64 -DEFINE_GUID(GUID_c2f03a33_21f5_47fa_b4bb_156362a2f239, - 0xc2f03a33, - 0x21f5, 0x47fa, 0xb4, 0xbb, - 0x15, 0x63, 0x62, 0xa2, 0xf2, 0x39 -); -DEFINE_GUID(GUID_6d5140c1_7436_11ce_8034_00aa006009fa, - 0x6d5140c1, - 0x7436, 0x11ce, 0x80, 0x34, - 0x00, 0xaa, 0x00, 0x60, 0x09, 0xfa -); HRESULT pnidui_CoCreateInstanceHook( REFCLSID rclsid, LPUNKNOWN pUnkOuter, @@ -2347,8 +2552,8 @@ HRESULT pnidui_CoCreateInstanceHook( ) { DWORD dwVal = 0, dwSize = sizeof(DWORD); - if (IsEqualGUID(rclsid, &GUID_c2f03a33_21f5_47fa_b4bb_156362a2f239) && - IsEqualGUID(riid, &GUID_6d5140c1_7436_11ce_8034_00aa006009fa) && + if (IsEqualGUID(rclsid, &CLSID_ImmersiveShell) && + IsEqualGUID(riid, &IID_IServiceProvider) && SHRegGetValueFromHKCUHKLMFunc && SHRegGetValueFromHKCUHKLMFunc( TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Control Panel\\Settings\\Network"), TEXT("ReplaceVan"), @@ -2358,30 +2563,68 @@ HRESULT pnidui_CoCreateInstanceHook( (LPDWORD)(&dwSize) ) == ERROR_SUCCESS) { - if (dwVal != 0) + if (dwVal) { - LaunchNetworkTargets(dwVal); + if (dwVal == 5) + { + if (hCheckForegroundThread) + { + WaitForSingleObject(hCheckForegroundThread, INFINITE); + CloseHandle(hCheckForegroundThread); + hCheckForegroundThread = NULL; + } + if (milliseconds_now() - elapsedCheckForeground > CHECKFOREGROUNDELAPSED_TIMEOUT) + { + LaunchNetworkTargets(dwVal); + hCheckForegroundThread = CreateThread( + 0, + 0, + CheckForegroundThread, + dwVal, + 0, + 0 + ); + } + } + else + { + LaunchNetworkTargets(dwVal); + } return E_NOINTERFACE; } - if (hCheckForegroundThread) - { - WaitForSingleObject(hCheckForegroundThread, INFINITE); - CloseHandle(hCheckForegroundThread); - hCheckForegroundThread = NULL; - } - if (milliseconds_now() - elapsedCheckForeground > CHECKFOREGROUNDELAPSED_TIMEOUT) + else { - LaunchNetworkTargets(dwVal); + if (hCheckForegroundThread) + { + WaitForSingleObject(hCheckForegroundThread, INFINITE); + CloseHandle(hCheckForegroundThread); + hCheckForegroundThread = NULL; + } + HKEY hKey = NULL; + if (RegCreateKeyExW( + HKEY_CURRENT_USER, + _T(SEH_REGPATH), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ, + NULL, + &hKey, + NULL + ) == ERROR_SUCCESS) + { + RegCloseKey(hKey); + } + TerminateShellExperienceHost(); hCheckForegroundThread = CreateThread( - 0, - 0, + 0, + 0, CheckForegroundThread, - L"Windows.UI.Core.CoreWindow", - 0, + dwVal, + 0, 0 ); } - return E_NOINTERFACE; } return CoCreateInstance( rclsid, @@ -2471,7 +2714,7 @@ INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHo hWnd = FindWindowExW(hWnd, NULL, L"ClockButton", NULL); if (hWnd) { - if (ShouldShowLegacyClockExperience()) + if (ShouldShowLegacyClockExperience() == 1) { if (!FindWindowW(L"ClockFlyoutWindow", NULL)) { @@ -2482,6 +2725,11 @@ INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHo return PostMessageW(FindWindowW(L"ClockFlyoutWindow", NULL), WM_CLOSE, 0, 0); } } + else if (ShouldShowLegacyClockExperience() == 2) + { + ToggleNotificationsFlyout(); + return 0; + } INT64* CTrayInstance = (BYTE*)(GetWindowLongPtrW(hShellTray_Wnd, 0)); // -> CTray void* ClockButtonInstance = (BYTE*)(GetWindowLongPtrW(hWnd, 0)); // -> ClockButton @@ -5135,7 +5383,10 @@ DWORD Inject(BOOL bIsExplorer) HANDLE hStobject = LoadLibraryW(L"stobject.dll"); + VnPatchIAT(hStobject, "api-ms-win-core-registry-l1-1-0.dll", "RegGetValueW", stobject_RegGetValueW); + VnPatchIAT(hStobject, "api-ms-win-core-com-l1-1-0.dll", "CoCreateInstance", stobject_CoCreateInstanceHook); VnPatchDelayIAT(hStobject, "user32.dll", "TrackPopupMenu", stobject_TrackPopupMenuHook); + VnPatchDelayIAT(hStobject, "user32.dll", "TrackPopupMenuEx", stobject_TrackPopupMenuExHook); #ifdef USE_PRIVATE_INTERFACES if (bSkinIcons) { @@ -6035,6 +6286,110 @@ void InjectStartMenu() #endif } +void InjectShellExperienceHost() +{ +#ifdef _WIN64 + HKEY hKey; + if (RegOpenKeyW(HKEY_CURRENT_USER, _T(SEH_REGPATH), &hKey)) + { + return; + } + HMODULE hQA = LoadLibraryW(L"Windows.UI.QuickActions.dll"); + if (hQA) + { + PIMAGE_DOS_HEADER dosHeader = hQA; + if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) + { + PIMAGE_NT_HEADERS64 ntHeader = (PIMAGE_NT_HEADERS64)((u_char*)dosHeader + dosHeader->e_lfanew); + if (ntHeader->Signature == IMAGE_NT_SIGNATURE) + { + char* pSEHPatchArea = NULL; + char seh_pattern1[14] = + { + // mov al, 1 + 0xB0, 0x01, + // jmp + 2 + 0xEB, 0x02, + // xor al, al + 0x32, 0xC0, + // add rsp, 0x20 + 0x48, 0x83, 0xC4, 0x20, + // pop rdi + 0x5F, + // pop rsi + 0x5E, + // pop rbx + 0x5B, + // ret + 0xC3 + }; + char seh_off = 12; + char seh_pattern2[5] = + { + // mov r8b, 3 + 0x41, 0xB0, 0x03, + // mov dl, 1 + 0xB2, 0x01 + }; + BOOL bTwice = FALSE; + PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeader); + for (unsigned int i = 0; i < ntHeader->FileHeader.NumberOfSections; ++i) + { + if (section->Characteristics & IMAGE_SCN_CNT_CODE) + { + if (section->SizeOfRawData && !bTwice) + { + DWORD dwOldProtect; + VirtualProtect(hQA + section->VirtualAddress, section->SizeOfRawData, PAGE_EXECUTE_READWRITE, &dwOldProtect); + char* pCandidate = NULL; + while (TRUE) + { + pCandidate = memmem( + !pCandidate ? hQA + section->VirtualAddress : pCandidate, + !pCandidate ? section->SizeOfRawData : (uintptr_t)section->SizeOfRawData - (uintptr_t)(pCandidate - (hQA + section->VirtualAddress)), + seh_pattern1, + sizeof(seh_pattern1) + ); + if (!pCandidate) + { + break; + } + char* pCandidate2 = pCandidate - seh_off - sizeof(seh_pattern2); + if (pCandidate2 > section->VirtualAddress) + { + if (memmem(pCandidate2, sizeof(seh_pattern2), seh_pattern2, sizeof(seh_pattern2))) + { + if (!pSEHPatchArea) + { + pSEHPatchArea = pCandidate; + } + else + { + bTwice = TRUE; + } + } + } + pCandidate += sizeof(seh_pattern1); + } + VirtualProtect(hQA + section->VirtualAddress, section->SizeOfRawData, dwOldProtect, &dwOldProtect); + } + } + section++; + } + if (pSEHPatchArea && !bTwice) + { + DWORD dwOldProtect; + VirtualProtect(pSEHPatchArea, sizeof(seh_pattern1), PAGE_EXECUTE_READWRITE, &dwOldProtect); + pSEHPatchArea[2] = 0x90; + pSEHPatchArea[3] = 0x90; + VirtualProtect(pSEHPatchArea, sizeof(seh_pattern1), dwOldProtect, &dwOldProtect); + } + } + } + } +#endif +} + #define DLL_INJECTION_METHOD_DXGI 0 #define DLL_INJECTION_METHOD_COM 1 #define DLL_INJECTION_METHOD_START_INJECTION 2 @@ -6082,9 +6437,14 @@ HRESULT EntryPoint(DWORD dwMethod) wcscat_s(wszStartExpectedPath, MAX_PATH, L"\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\StartMenuExperienceHost.exe"); BOOL bIsThisStartMEH = !_wcsicmp(exePath, wszStartExpectedPath); + TCHAR wszShellExpectedPath[MAX_PATH]; + GetWindowsDirectoryW(wszShellExpectedPath, MAX_PATH); + wcscat_s(wszShellExpectedPath, MAX_PATH, L"\\SystemApps\\ShellExperienceHost_cw5n1h2txyewy\\ShellExperienceHost.exe"); + BOOL bIsThisShellEH = !_wcsicmp(exePath, wszShellExpectedPath); + if (dwMethod == DLL_INJECTION_METHOD_DXGI) { - if (!(bIsThisExplorer || bIsThisStartMEH)) + if (!(bIsThisExplorer || bIsThisStartMEH || bIsThisShellEH)) { return E_NOINTERFACE; } @@ -6095,7 +6455,7 @@ HRESULT EntryPoint(DWORD dwMethod) SetupDXGIImportFunctions(LoadLibraryW(wszRealDXGIPath)); #endif } - if (dwMethod == DLL_INJECTION_METHOD_COM && (bIsThisExplorer || bIsThisStartMEH)) + if (dwMethod == DLL_INJECTION_METHOD_COM && (bIsThisExplorer || bIsThisStartMEH || bIsThisShellEH)) { return E_NOINTERFACE; } @@ -6117,6 +6477,12 @@ HRESULT EntryPoint(DWORD dwMethod) IncrementDLLReferenceCount(hModule); bInstanced = TRUE; } + else if (bIsThisShellEH) + { + InjectShellExperienceHost(); + IncrementDLLReferenceCount(hModule); + bInstanced = TRUE; + } else if (dwMethod == DLL_INJECTION_METHOD_COM) { Inject(FALSE); @@ -6128,7 +6494,7 @@ HRESULT EntryPoint(DWORD dwMethod) } #ifdef _WIN64 -// for explorer.exe +// for explorer.exe and ShellExperienceHost.exe __declspec(dllexport) HRESULT DXGIDeclareAdapterRemovalSupport() { EntryPoint(DLL_INJECTION_METHOD_DXGI); diff --git a/ExplorerPatcher/settings.reg b/ExplorerPatcher/settings.reg index 9dbd9e8..56965d8 100644 --- a/ExplorerPatcher/settings.reg +++ b/ExplorerPatcher/settings.reg @@ -10,6 +10,10 @@ "OldTaskbar"=dword:00000001 ;y More taskbar options in the Settings app 🡕 ;ms-settings:taskbar +;y Customize notification area icons 🡕 +;shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} +;y Customize system icons in the notification area 🡕 +;shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons ;t The following settings only apply to the Windows 10 taskbar: [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced] ;c 3 Combine taskbar icons on main taskbar @@ -46,14 +50,8 @@ [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ExplorerPatcher] ;b Show separators between toolbars * "ToolbarSeparators"=dword:00000000 -;t -;t ;T System tray -;y Customize notification area icons 🡕 -;shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} -;y Customize system icons in the notification area 🡕 -;shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced] ;b Show seconds in the clock "ShowSecondsInSystemClock"=dword:00000000 @@ -72,17 +70,41 @@ [HKEY_CURRENT_USER\Software\Microsoft\TabletTip\1.7] ;b Show touch keyboard button * "TipbandDesiredVisibility"=dword:00000000 +[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ExplorerPatcher] +;a Choosing 'Open Network && Internet settings' when right clicking the +;c 3 network icon should open: +;x 0 Network section in the Settings app (default) +;x 1 Network and Sharing Center in Control Panel +;x 2 Network Connections in Control Panel +"ReplaceNetwork"=dword:00000000 +;t When clicking a system icon in the tray, open: +[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Control Panel\Settings\Network] +;c 6 Network +;x 5 Windows 11 WiFi flyout +;x 0 Windows 10 flyout (default) +;x 2 Windows 8 flyout +;x 1 Network section in the Settings app +;x 3 Network and Sharing Center in Control Panel +;x 4 Network Connections in Control Panel +"ReplaceVan"=dword:00000000 [HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\MTCUVC] -;i Use legacy volume flyout +;c 2 Sound +;x 1 Windows 10 flyout (default) +;x 0 Windows 7 flyout "EnableMtcUvc"=dword:00000001 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell] -;c 3 Clock flyout style -;x 2 Windows 11 -;x 0 Windows 10 (default) +;c 3 Clock +;x 2 Windows 11 flyout +;x 0 Windows 10 flyout (default) ;x 1 Windows 7 "UseWin32TrayClockExperience"=dword:00000000 +[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ImmersiveShell] +;c 2 Battery +;x 0 Windows 10 flyout (default) +;x 1 Windows 7 +"UseWin32BatteryFlyout"=dword:00000000 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ExplorerPatcher] -;c 6 Language switcher flyout style * +;c 6 Language switcher * ;x 0 Windows 11 (default) ;x 1 Windows 10 ;x 2 "LOGONUI" @@ -90,21 +112,6 @@ ;x 4 "SETTINGSPANE" ;x 5 "OOBE" "IMEStyle"=dword:00000000 -[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ExplorerPatcher] -;a Choosing 'Open Network && Internet settings' when right clicking the -;c 3 network icon should open: -;x 0 Network section in the Settings app (default) -;x 1 Network and Sharing Center in Control Panel -;x 2 Network Connections in Control Panel -"ReplaceNetwork"=dword:00000000 -[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Control Panel\Settings\Network] -;c 5 Network icon should open -;x 0 WiFi list (default) -;x 1 Network section in the Settings app -;x 2 Windows 8 network flyout -;x 3 Network and Sharing Center in Control Panel -;x 4 Network Connections in Control Panel -"ReplaceVan"=dword:00000000 ;T File Explorer [-HKEY_CURRENT_USER\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32] diff --git a/ep_setup/ep_setup.c b/ep_setup/ep_setup.c index 83d36fd..dbf05ab 100644 --- a/ep_setup/ep_setup.c +++ b/ep_setup/ep_setup.c @@ -523,6 +523,15 @@ int WINAPI wWinMain( bOk = InstallResource(bInstall, hInstance, IDR_EP_AMD64, wszPath); } if (bOk) + { + bOk = GetWindowsDirectoryW(wszPath, MAX_PATH); + } + if (bOk) + { + wcscat_s(wszPath, MAX_PATH, L"\\SystemApps\\ShellExperienceHost_cw5n1h2txyewy\\dxgi.dll"); + bOk = InstallResource(bInstall, hInstance, IDR_EP_AMD64, wszPath); + } + if (bOk) { SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\" _T(SETUP_UTILITY_NAME)); diff --git a/version.h b/version.h index fe9e456..5c599ae 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define VER_MAJOR 22000 #define VER_MINOR 318 -#define VER_BUILD_HI 37 -#define VER_BUILD_LO 5 +#define VER_BUILD_HI 38 +#define VER_BUILD_LO 0 #define VER_FLAGS VS_FF_PRERELEASE @@ -12,5 +12,5 @@ #define VER_STR(arg) #arg // The String form of the version numbers -#define VER_FILE_STRING VALUE "FileVersion", "22000.318.37.5" -#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.318.37.5" +#define VER_FILE_STRING VALUE "FileVersion", "22000.318.38.0" +#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.318.38.0"