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"