1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-11-23 23:21:08 +01:00

Refactoring

This commit is contained in:
Valentin Radu 2021-10-01 01:26:10 +03:00
parent ad9395ce6d
commit 227ae4d0a4
24 changed files with 3447 additions and 3635 deletions

View File

@ -2,6 +2,23 @@
This document includes the same release notes as in the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section on GitHub. This document includes the same release notes as in the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section on GitHub.
## 22000.194.0.20
Tested on build: 22000.194.
* Huge code refactoring, improved memory patching
* Updated README with better description of the software and how to use it
* Drastically reduced the number of symbols required (around 40MB to download, instead of over 400MB previously)
* Improved Start menu and search positioning, now it is not necessary to have the DLL in `C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy`, please remove it from there.
* Skin "Bluetooth" pop-up menu
* Option to hide the search bar in File Explorer completely
* Option to disable the control center button in the taskbar
* Removed the option to disable the modern search box in File Explorer. Instead, you now run a command which disables it globally on your user account (works in "Open" dialogs as well); read [here](https://github.com/valinet/ExplorerPatcher#disable-the-modern-search-box-in-File-Explorer)
* Removed the option to disable the immersive (new) context menu in File Explorer. Instead, you now run a command which disables it globally on your user account; read [here](https://github.com/valinet/ExplorerPatcher#disable-the-immersive-context-menu)
* Ability to disable command bar is described [here](https://github.com/valinet/ExplorerPatcher#disable-the-command-bar-in-File-Explorer)
* Option to apply Mica effect on File Explorer windows (requires `StartIsBack64.dll`), read [here](https://github.com/valinet/ExplorerPatcher#configuration)
* Option to skin system tray icons to match Windows 11 style (requires `StartisBack64.dll`), read [here](https://github.com/valinet/ExplorerPatcher#configuration)
## 22449.1000.0.18 ## 22449.1000.0.18
Tested on the following builds: 22449.1000, 22000.176, 22000.1. Tested on the following builds: 22449.1000, 22000.176, 22000.1.

View File

@ -0,0 +1,200 @@
#include "ArchiveMenu.h"
DWORD ArchiveMenuThread(ArchiveMenuThreadParams* params)
{
Sleep(1000);
printf("Started \"Archive menu\" thread.\n");
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
return 0;
}
WNDCLASS wc = { 0 };
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = params->wndProc;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = L"ArchiveMenuWindowExplorer";
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
RegisterClass(&wc);
*(params->hWnd) = params->CreateWindowInBand(
0,
L"ArchiveMenuWindowExplorer",
0,
WS_POPUP,
0,
0,
0,
0,
0,
0,
GetModuleHandle(NULL),
NULL,
7
);
if (!*(params->hWnd))
{
return 0;
}
ITaskbarList* pTaskList = NULL;
hr = CoCreateInstance(
&__uuidof_TaskbarList,
NULL,
CLSCTX_ALL,
&__uuidof_ITaskbarList,
(void**)(&pTaskList)
);
if (FAILED(hr))
{
return 0;
}
hr = pTaskList->lpVtbl->HrInit(pTaskList);
if (FAILED(hr))
{
return 0;
}
ShowWindow(*(params->hWnd), SW_SHOW);
hr = pTaskList->lpVtbl->DeleteTab(pTaskList, *(params->hWnd));
if (FAILED(hr))
{
return 0;
}
hr = pTaskList->lpVtbl->Release(pTaskList);
if (FAILED(hr))
{
return 0;
}
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
printf("Ended \"Archive menu\" thread.\n");
}
LRESULT CALLBACK ArchiveMenuWndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)(
HMENU h1,
HMENU h2,
HWND a3,
unsigned int a4,
void* data
),
void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)(
HMENU _this,
HMENU hWnd,
HWND a3
)
)
{
LRESULT result;
if (uMsg == WM_COPYDATA)
{
COPYDATASTRUCT* st = lParam;
HWND srcWnd = wParam;
POINT pt;
GetCursorPos(&pt);
HWND prevhWnd = GetForegroundWindow();
SetForegroundWindow(hWnd);
HMENU hMenu = CreatePopupMenu();
TCHAR buffer[MAX_PATH + 100];
TCHAR filename[MAX_PATH];
ZeroMemory(filename, MAX_PATH * sizeof(TCHAR));
memcpy(filename, st->lpData, wcslen(st->lpData) * sizeof(TCHAR));
PathUnquoteSpacesW(filename);
PathRemoveExtensionW(filename);
PathStripPathW(filename);
wsprintf(buffer, EXTRACT_NAME, filename);
InsertMenu(hMenu, 0, MF_BYPOSITION | MF_STRING, 1, buffer);
InsertMenu(hMenu, 0, MF_BYPOSITION | MF_STRING, 2, OPEN_NAME);
INT64* unknown_array = calloc(4, sizeof(INT64));
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc(
hMenu,
hWnd,
&(pt),
0xc,
unknown_array
);
BOOL res = TrackPopupMenu(
hMenu,
TPM_RETURNCMD,
pt.x - 15,
pt.y - 15,
0,
hWnd,
0
);
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc(
hMenu,
hWnd,
&(pt)
);
free(unknown_array);
SetForegroundWindow(prevhWnd);
if (res == 1 || res == 2)
{
ZeroMemory(buffer, (MAX_PATH + 100) * sizeof(TCHAR));
if (res == 2)
{
wsprintf(buffer, OPEN_CMD, st->lpData);
//wprintf(L"%s\n%s\n\n", st->lpData, buffer);
}
else if (res == 1)
{
TCHAR path[MAX_PATH + 1], path_orig[MAX_PATH + 1];
ZeroMemory(path, (MAX_PATH + 1) * sizeof(TCHAR));
ZeroMemory(path_orig, (MAX_PATH + 1) * sizeof(TCHAR));
memcpy(path, st->lpData, wcslen(st->lpData) * sizeof(TCHAR));
memcpy(path_orig, st->lpData, wcslen(st->lpData) * sizeof(TCHAR));
PathUnquoteSpacesW(path_orig);
PathRemoveExtensionW(path_orig);
wsprintf(buffer, EXTRACT_CMD, path_orig, path);
//wprintf(L"%s\n%s\n\n", st->lpData, buffer);
}
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
BOOL b = CreateProcess(
NULL,
buffer,
NULL,
NULL,
TRUE,
CREATE_UNICODE_ENVIRONMENT,
NULL,
NULL,
&si,
&pi
);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
DestroyMenu(hMenu);
ShowWindow(hWnd, SW_HIDE);
return 0;
}
else if (uMsg == WM_CLOSE)
{
return 0;
}
return 1;
}

View File

@ -0,0 +1,64 @@
#ifndef _H_ARCHIVEMENU_H_
#define _H_ARCHIVEMENU_H_
#include <initguid.h>
#include <Windows.h>
#include <Shlobj_core.h>
#define OPEN_NAME L"&Open archive"
#define EXTRACT_NAME L"&Extract to \"%s\\\""
#define OPEN_CMD L"\"C:\\Program Files\\7-Zip\\7zFM.exe\" %s"
#define EXTRACT_CMD L"\"C:\\Program Files\\7-Zip\\7zG.exe\" x -o\"%s\" -spe %s"
DEFINE_GUID(__uuidof_TaskbarList,
0x56FDF344,
0xFD6D, 0x11d0, 0x95, 0x8A,
0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90
);
DEFINE_GUID(__uuidof_ITaskbarList,
0x56FDF342,
0xFD6D, 0x11d0, 0x95, 0x8A,
0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90
);
typedef struct _ArchiveMenuThreadParams
{
HWND* hWnd;
WNDPROC wndProc;
HWND(WINAPI* CreateWindowInBand)(
_In_ DWORD dwExStyle,
_In_opt_ ATOM atom,
_In_opt_ LPCWSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int X,
_In_ int Y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam,
DWORD band
);
} ArchiveMenuThreadParams;
DWORD ArchiveMenuThread(ArchiveMenuThreadParams* params);
LRESULT CALLBACK ArchiveMenuWndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam,
INT64(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)(
HMENU h1,
HMENU h2,
HWND a3,
unsigned int a4,
void* data
),
void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)(
HMENU _this,
HMENU hWnd,
HWND a3
)
);
#endif

View File

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 22449,1000,0,18 FILEVERSION 22000,194,0,20
PRODUCTVERSION 22449,1000,0,18 PRODUCTVERSION 22000,194,0,20
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "VALINET Solutions SRL" VALUE "CompanyName", "VALINET Solutions SRL"
VALUE "FileDescription", "ExplorerPatcher" VALUE "FileDescription", "ExplorerPatcher"
VALUE "FileVersion", "22449.1000.0.18" VALUE "FileVersion", "22000.194.0.20"
VALUE "InternalName", "ExplorerPatcher.dll" VALUE "InternalName", "ExplorerPatcher.dll"
VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved." VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved."
VALUE "OriginalFilename", "ExplorerPatcher.dll" VALUE "OriginalFilename", "ExplorerPatcher.dll"
VALUE "ProductName", "ExplorerPatcher" VALUE "ProductName", "ExplorerPatcher"
VALUE "ProductVersion", "22449.1000.0.18" VALUE "ProductVersion", "22000.194.0.20"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -193,10 +193,26 @@
</PreBuildEvent> </PreBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ArchiveMenu.c" />
<ClCompile Include="dllmain.c" /> <ClCompile Include="dllmain.c" />
<ClCompile Include="HideExplorerSearchBar.c" />
<ClCompile Include="SettingsMonitor.c" />
<ClCompile Include="StartMenu.c" />
<ClCompile Include="StartupSound.c" />
<ClCompile Include="symbols.c" />
<ClCompile Include="utility.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ArchiveMenu.h" />
<ClInclude Include="dxgi_imp.h" />
<ClInclude Include="HideExplorerSearchBar.h" />
<ClInclude Include="hooking.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="SettingsMonitor.h" />
<ClInclude Include="StartMenu.h" />
<ClInclude Include="StartupSound.h" />
<ClInclude Include="symbols.h" />
<ClInclude Include="utility.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="ExplorerPatcher.rc" /> <ResourceCompile Include="ExplorerPatcher.rc" />

View File

@ -18,6 +18,33 @@
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="hooking.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ArchiveMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StartupSound.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dxgi_imp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SettingsMonitor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="HideExplorerSearchBar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StartMenu.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="symbols.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utility.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="ExplorerPatcher.rc"> <ResourceCompile Include="ExplorerPatcher.rc">
@ -28,5 +55,26 @@
<ClCompile Include="dllmain.c"> <ClCompile Include="dllmain.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ArchiveMenu.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StartupSound.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SettingsMonitor.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="HideExplorerSearchBar.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StartMenu.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="symbols.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utility.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,121 @@
#include "HideExplorerSearchBar.h"
HWND FindChildWindow(
HWND hwndParent,
wchar_t* lpszClass
)
{
HWND hwnd = FindWindowEx(
hwndParent,
NULL,
lpszClass,
NULL
);
if (hwnd == NULL)
{
HWND hwndChild = FindWindowEx(
hwndParent,
NULL,
NULL,
NULL
);
while (hwndChild != NULL && hwnd == NULL)
{
hwnd = FindChildWindow(
hwndChild,
lpszClass
);
if (hwnd == NULL)
{
hwndChild = FindWindowEx(
hwndParent,
hwndChild,
NULL,
NULL
);
}
}
}
return hwnd;
}
VOID HideExplorerSearchBar(HWND hWnd)
{
HWND band = NULL, rebar = NULL;
band = FindChildWindow(
hWnd,
(wchar_t*)L"TravelBand"
);
if (!band)
{
return;
}
rebar = GetParent(band);
if (!rebar)
{
return;
}
int idx = 0;
idx = (int)SendMessage(
rebar,
RB_IDTOINDEX,
4,
0
);
if (idx >= 0)
{
SendMessage(
rebar,
RB_SHOWBAND,
idx,
FALSE
);
}
idx = (int)SendMessage(
rebar,
RB_IDTOINDEX,
5,
0
);
if (idx >= 0)
{
SendMessage(
rebar,
RB_SHOWBAND,
idx,
TRUE
);
}
RedrawWindow(
rebar,
NULL,
NULL,
RDW_UPDATENOW | RDW_ALLCHILDREN
);
}
LRESULT HideExplorerSearchBarSubClass(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
UINT_PTR uIdSubclass,
DWORD_PTR dwRefData
)
{
switch (uMsg)
{
case WM_PARENTNOTIFY:
if ((WORD)wParam == 1)
{
HideExplorerSearchBar(hWnd);
}
break;
case WM_DESTROY:
RemoveWindowSubclass(hWnd, HideExplorerSearchBarSubClass, (UINT_PTR)HideExplorerSearchBarSubClass);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

View File

@ -0,0 +1,24 @@
#ifndef _H_HIDEEXPLORERSEARCHBAR_H_
#define _H_HIDEEXPLORERSEARCHBAR_H_
#include <Windows.h>
#include <commctrl.h>
#pragma comment(lib, "Comctl32.lib")
// https://stackoverflow.com/questions/30141592/how-do-i-find-a-handle-inside-a-control
HWND FindChildWindow(
HWND hwndParent,
wchar_t* lpszClass
);
// https://github.com/Open-Shell/Open-Shell-Menu/blob/master/Src/ClassicExplorer/ExplorerBHO.cpp
VOID HideExplorerSearchBar(HWND hWnd);
LRESULT HideExplorerSearchBarSubClass(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
UINT_PTR uIdSubclass,
DWORD_PTR dwRefData
);
#endif

View File

@ -0,0 +1,318 @@
#include "SettingsMonitor.h"
DWORD MonitorSettingsChanges(SettingsChangeParameters* params)
{
HMODULE hModule = LoadLibraryW(L"Shlwapi.dll");
if (hModule)
{
FARPROC SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(hModule, "SHRegGetValueFromHKCUHKLM");
DWORD dwSize = sizeof(DWORD);
LONG lRes = ERROR_SUCCESS;
HKEY hKeyCU, hKeyLM;
dwSize = sizeof(DWORD);
DWORD dwInitialTaskbarAl = 0, dwTaskbarAl = 0, dwInitialTaskbarAlWas = 0;
if (!SHRegGetValueFromHKCUHKLMFunc || SHRegGetValueFromHKCUHKLMFunc(
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
TEXT("TaskbarAl"),
SRRF_RT_REG_DWORD,
NULL,
&dwInitialTaskbarAl,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS)
{
dwInitialTaskbarAl = 0;
}
else
{
dwInitialTaskbarAlWas = 1;
}
dwSize = sizeof(DWORD);
DWORD dwInitialMaximumFrequentApps = 6, dwMaximumFrequentApps = 6, dwInitialMaximumFrequentAppsWas = 0;
if (!SHRegGetValueFromHKCUHKLMFunc || SHRegGetValueFromHKCUHKLMFunc(
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
TEXT("Start_MaximumFrequentApps"),
SRRF_RT_REG_DWORD,
NULL,
&dwInitialMaximumFrequentApps,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS)
{
dwInitialMaximumFrequentApps = 6;
}
else
{
dwInitialMaximumFrequentAppsWas = 1;
}
while (TRUE)
{
lRes = RegOpenKeyExW(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
0,
KEY_READ,
&hKeyCU
);
if (lRes != ERROR_SUCCESS)
{
return 0;
}
HANDLE hEvHKCU = CreateEvent(NULL, FALSE, FALSE, NULL);
RegNotifyChangeKeyValue(
hKeyCU,
FALSE,
REG_NOTIFY_CHANGE_LAST_SET,
hEvHKCU,
TRUE
);
lRes = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
0,
KEY_READ,
&hKeyLM
);
if (lRes != ERROR_SUCCESS)
{
return 0;
}
HANDLE hEvHKLM = CreateEvent(NULL, FALSE, FALSE, NULL);
RegNotifyChangeKeyValue(
hKeyLM,
FALSE,
REG_NOTIFY_CHANGE_LAST_SET,
hEvHKLM,
TRUE
);
printf("!!! Setup monitor %d %d\n", hEvHKCU, hEvHKLM);
HANDLE hEvents[2];
hEvents[0] = hEvHKCU;
hEvents[1] = hEvHKLM;
DWORD rv = WaitForMultipleObjects(
2,
hEvents,
FALSE,
INFINITE
);
if (rv == WAIT_OBJECT_0)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyCU,
TEXT("TaskbarAl"),
0,
NULL,
&dwTaskbarAl,
&dwSize
);
if (lRes != ERROR_SUCCESS && dwInitialTaskbarAlWas)
{
if (params->TaskbarAlChangedCallback)
{
void* p = 0;
if (params->TaskbarAlChangedCallbackData)
{
p = params->TaskbarAlChangedCallbackData;
}
params->TaskbarAlChangedCallback(p, dwTaskbarAl);
}
else
{
exit(0);
}
dwInitialTaskbarAl = dwTaskbarAl;
}
if (lRes == ERROR_SUCCESS && dwTaskbarAl != dwInitialTaskbarAl)
{
if (params->TaskbarAlChangedCallback)
{
void* p = 0;
if (params->TaskbarAlChangedCallbackData)
{
p = params->TaskbarAlChangedCallbackData;
}
params->TaskbarAlChangedCallback(p, dwTaskbarAl);
}
else
{
exit(0);
}
dwInitialTaskbarAl = dwTaskbarAl;
}
if (params->isStartMenuExperienceHost)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyCU,
TEXT("Start_MaximumFrequentApps"),
0,
NULL,
&dwMaximumFrequentApps,
&dwSize
);
if (lRes != ERROR_SUCCESS && dwInitialMaximumFrequentAppsWas)
{
if (params->Start_MaximumRecentAppsChangedCallback)
{
void* p = 0;
if (params->Start_MaximumRecentAppsChangedCallbackData)
{
p = params->Start_MaximumRecentAppsChangedCallbackData;
}
params->Start_MaximumRecentAppsChangedCallback(p, dwMaximumFrequentApps);
}
else
{
exit(0);
}
dwInitialMaximumFrequentApps = dwMaximumFrequentApps;
}
if (lRes == ERROR_SUCCESS && dwMaximumFrequentApps != dwInitialMaximumFrequentApps)
{
if (params->Start_MaximumRecentAppsChangedCallback)
{
void* p = 0;
if (params->Start_MaximumRecentAppsChangedCallbackData)
{
p = params->Start_MaximumRecentAppsChangedCallbackData;
}
params->Start_MaximumRecentAppsChangedCallback(p, dwMaximumFrequentApps);
}
else
{
exit(0);
}
dwInitialMaximumFrequentApps = dwMaximumFrequentApps;
}
}
}
else if (rv == WAIT_OBJECT_0 + 1)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyCU,
TEXT("TaskbarAl"),
0,
NULL,
&dwTaskbarAl,
&dwSize
);
if (lRes != ERROR_SUCCESS)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyLM,
TEXT("TaskbarAl"),
0,
NULL,
&dwTaskbarAl,
&dwSize
);
if (lRes != ERROR_SUCCESS && dwInitialTaskbarAlWas)
{
if (params->TaskbarAlChangedCallback)
{
void* p = 0;
if (params->TaskbarAlChangedCallbackData)
{
p = params->TaskbarAlChangedCallbackData;
}
params->TaskbarAlChangedCallback(p, dwTaskbarAl);
}
else
{
exit(0);
}
dwInitialTaskbarAl = dwTaskbarAl;
}
if (lRes == ERROR_SUCCESS && dwTaskbarAl != dwInitialTaskbarAl)
{
if (params->TaskbarAlChangedCallback)
{
void* p = 0;
if (params->TaskbarAlChangedCallbackData)
{
p = params->TaskbarAlChangedCallbackData;
}
params->TaskbarAlChangedCallback(p, dwTaskbarAl);
}
else
{
exit(0);
}
dwInitialTaskbarAl = dwTaskbarAl;
}
}
if (params->isStartMenuExperienceHost)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyCU,
TEXT("Start_MaximumFrequentApps"),
0,
NULL,
&dwMaximumFrequentApps,
&dwSize
);
if (lRes != ERROR_SUCCESS)
{
dwSize = sizeof(DWORD);
lRes = RegQueryValueExW(
hKeyLM,
TEXT("Start_MaximumFrequentApps"),
0,
NULL,
&dwMaximumFrequentApps,
&dwSize
);
if (lRes != ERROR_SUCCESS && dwInitialMaximumFrequentAppsWas)
{
if (params->Start_MaximumRecentAppsChangedCallback)
{
void* p = 0;
if (params->Start_MaximumRecentAppsChangedCallbackData)
{
p = params->Start_MaximumRecentAppsChangedCallbackData;
}
params->Start_MaximumRecentAppsChangedCallback(p, dwMaximumFrequentApps);
}
else
{
exit(0);
}
dwInitialMaximumFrequentApps = dwMaximumFrequentApps;
}
if (lRes == ERROR_SUCCESS && dwMaximumFrequentApps != dwInitialMaximumFrequentApps)
{
if (params->Start_MaximumRecentAppsChangedCallback)
{
void* p = 0;
if (params->Start_MaximumRecentAppsChangedCallbackData)
{
p = params->Start_MaximumRecentAppsChangedCallbackData;
}
params->Start_MaximumRecentAppsChangedCallback(p, dwMaximumFrequentApps);
}
else
{
exit(0);
}
dwInitialMaximumFrequentApps = dwMaximumFrequentApps;
}
}
}
}
CloseHandle(hEvHKCU);
CloseHandle(hEvHKLM);
RegCloseKey(hKeyCU);
RegCloseKey(hKeyLM);
}
}
}

View File

@ -0,0 +1,16 @@
#ifndef _H_SETTINGSMONITOR_H_
#define _H_SETTINGSMONITOR_H_
#include <Windows.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
typedef struct _SettingsChangeParameters
{
BOOL isStartMenuExperienceHost;
void (*TaskbarAlChangedCallback)(INT64, DWORD);
void* TaskbarAlChangedCallbackData;
void (*Start_MaximumRecentAppsChangedCallback)(INT64, DWORD);
void* Start_MaximumRecentAppsChangedCallbackData;
} SettingsChangeParameters;
DWORD MonitorSettingsChanges(SettingsChangeParameters* params);
#endif

192
ExplorerPatcher/StartMenu.c Normal file
View File

@ -0,0 +1,192 @@
#include "StartMenu.h"
void OpenStartOnMonitor(HMONITOR monitor)
{
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))
{
IImmersiveMonitorService* pMonitorService = NULL;
IUnknown_QueryService(
pImmersiveShell,
&SID_IImmersiveMonitorService,
&IID_IImmersiveMonitorService,
&pMonitorService
);
if (pMonitorService)
{
IUnknown* pMonitor = NULL;
pMonitorService->lpVtbl->GetFromHandle(
pMonitorService,
monitor,
&pMonitor
);
IImmersiveLauncher10RS* pLauncher = NULL;
IUnknown_QueryService(
pImmersiveShell,
&SID_ImmersiveLauncher,
&IID_IImmersiveLauncher10RS,
&pLauncher
);
if (pLauncher)
{
BOOL bIsVisible = FALSE;
pLauncher->lpVtbl->IsVisible(pLauncher, &bIsVisible);
if (SUCCEEDED(hr))
{
if (!bIsVisible)
{
if (pMonitor)
{
pLauncher->lpVtbl->ConnectToMonitor(pLauncher, pMonitor);
}
pLauncher->lpVtbl->ShowStartView(pLauncher, 11, 0);
}
else
{
pLauncher->lpVtbl->Dismiss(pLauncher);
}
}
pLauncher->lpVtbl->Release(pLauncher);
}
if (pMonitor)
{
pMonitor->lpVtbl->Release(pMonitor);
}
pMonitorService->lpVtbl->Release(pMonitorService);
}
pImmersiveShell->lpVtbl->Release(pImmersiveShell);
}
}
LRESULT CALLBACK OpenStartOnCurentMonitorThreadHook(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if (code == HC_ACTION && wParam)
{
MSG* msg = (MSG*)lParam;
if (GetSystemMetrics(SM_CMONITORS) >= 2 && msg->message == WM_SYSCOMMAND && (msg->wParam & 0xFFF0) == SC_TASKLIST)
{
DWORD dwStatus = 0;
DWORD dwSize = sizeof(DWORD);
HMODULE hModule = GetModuleHandle(TEXT("Shlwapi.dll"));
FARPROC SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(hModule, "SHRegGetValueFromHKCUHKLM");
if (!SHRegGetValueFromHKCUHKLMFunc || SHRegGetValueFromHKCUHKLMFunc(
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage"),
TEXT("MonitorOverride"),
SRRF_RT_REG_DWORD,
NULL,
&dwStatus,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS || dwStatus == 1)
{
goto finish;
}
DWORD pts = GetMessagePos();
POINT pt;
pt.x = GET_X_LPARAM(pts);
pt.y = GET_Y_LPARAM(pts);
HMONITOR monitor = MonitorFromPoint(
pt,
MONITOR_DEFAULTTONULL
);
OpenStartOnMonitor(monitor);
msg->message = WM_NULL;
}
}
finish:
return CallNextHookEx(NULL, code, wParam, lParam);
}
DWORD OpenStartOnCurentMonitorThread(OpenStartOnCurentMonitorThreadParams* unused)
{
HANDLE hEvent = CreateEvent(0, 0, 0, L"ShellDesktopSwitchEvent");
if (!hEvent)
{
printf("Failed to start \"Open Start on current monitor\" thread.\n");
return 0;
}
WaitForSingleObject(
hEvent,
INFINITE
);
printf("Started \"Open Start on current monitor\" thread.\n");
HWND g_ProgWin = FindWindowEx(
NULL,
NULL,
L"Progman",
NULL
);
DWORD progThread = GetWindowThreadProcessId(
g_ProgWin,
NULL
);
HHOOK g_ProgHook = SetWindowsHookEx(
WH_GETMESSAGE,
OpenStartOnCurentMonitorThreadHook,
NULL,
progThread
);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
printf("Ended \"Open Start on current monitor\" thread.\n");
}
DWORD OpenStartAtLogonThread(OpenStartAtLogonThreadParams* unused)
{
HANDLE hEvent = CreateEvent(0, 0, 0, L"ShellDesktopSwitchEvent");
if (!hEvent)
{
printf("Failed to start \"Open Start at Logon\" thread.\n");
return 0;
}
WaitForSingleObject(
hEvent,
INFINITE
);
printf("Started \"Open Start at Logon\" thread.\n");
DWORD dwStatus = 0;
DWORD dwSize = sizeof(DWORD);
HMODULE hModule = GetModuleHandle(TEXT("Shlwapi"));
FARPROC SHRegGetValueFromHKCUHKLMFunc = GetProcAddress(hModule, "SHRegGetValueFromHKCUHKLM");
if (!SHRegGetValueFromHKCUHKLMFunc || SHRegGetValueFromHKCUHKLMFunc(
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartPage"),
TEXT("OpenAtLogon"),
SRRF_RT_REG_DWORD,
NULL,
&dwStatus,
(LPDWORD)(&dwSize)
) != ERROR_SUCCESS || dwStatus == 0)
{
return 0;
}
POINT pt;
pt.x = 0;
pt.y = 0;
HMONITOR monitor = MonitorFromPoint(
pt,
MONITOR_DEFAULTTOPRIMARY
);
OpenStartOnMonitor(monitor);
printf("Ended \"Open Start at Logon\" thread.\n");
}

177
ExplorerPatcher/StartMenu.h Normal file
View File

@ -0,0 +1,177 @@
#ifndef _H_STARTMENU_H_
#define _H_STARTMENU_H_
#include <initguid.h>
#include <Windows.h>
#include <windowsx.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
DEFINE_GUID(CLSID_ImmersiveShell,
0xc2f03a33,
0x21f5, 0x47fa, 0xb4, 0xbb,
0x15, 0x63, 0x62, 0xa2, 0xf2, 0x39
);
DEFINE_GUID(SID_IImmersiveMonitorService,
0x47094e3a,
0x0cf2, 0x430f, 0x80, 0x6f,
0xcf, 0x9e, 0x4f, 0x0f, 0x12, 0xdd
);
DEFINE_GUID(IID_IImmersiveMonitorService,
0x4d4c1e64,
0xe410, 0x4faa, 0xba, 0xfa,
0x59, 0xca, 0x06, 0x9b, 0xfe, 0xc2
);
DEFINE_GUID(SID_ImmersiveLauncher,
0x6f86e01c,
0xc649, 0x4d61, 0xbe, 0x23,
0xf1, 0x32, 0x2d, 0xde, 0xca, 0x9d
);
DEFINE_GUID(IID_IImmersiveLauncher10RS,
0xd8d60399,
0xa0f1, 0xf987, 0x55, 0x51,
0x32, 0x1f, 0xd1, 0xb4, 0x98, 0x64
);
typedef interface IImmersiveMonitorService IImmersiveMonitorService;
typedef struct IImmersiveMonitorServiceVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
IImmersiveMonitorService* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
IImmersiveMonitorService* This);
ULONG(STDMETHODCALLTYPE* Release)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method3)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method4)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method5)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* GetFromHandle)(
IImmersiveMonitorService* This,
/* [in] */ HMONITOR hMonitor,
_COM_Outptr_ IUnknown** ppvObject);
HRESULT(STDMETHODCALLTYPE* method6)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* method7)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* QueryService)(
IImmersiveMonitorService* This,
HMONITOR hMonitor,
GUID*,
GUID*,
void** ppvObject
);
HRESULT(STDMETHODCALLTYPE* method9)(
IImmersiveMonitorService* This);
HRESULT(STDMETHODCALLTYPE* QueryServiceFromWindow)(
IImmersiveMonitorService* This,
HWND hWnd,
GUID* a3,
GUID* a4,
void** ppvObject
);
END_INTERFACE
} IImmersiveMonitorServiceVtbl;
interface IImmersiveMonitorService
{
CONST_VTBL struct IImmersiveMonitorServiceVtbl* lpVtbl;
};
typedef interface IImmersiveLauncher10RS IImmersiveLauncher10RS;
typedef struct IImmersiveLauncher10RSVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
IImmersiveLauncher10RS* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
IImmersiveLauncher10RS* This);
ULONG(STDMETHODCALLTYPE* Release)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* ShowStartView)(
IImmersiveLauncher10RS* This,
/* [in] */ int method,
/* [in] */ int flags);
HRESULT(STDMETHODCALLTYPE* Dismiss)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method5)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method6)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* IsVisible)(
IImmersiveLauncher10RS* This,
/* [in] */ BOOL* ret);
HRESULT(STDMETHODCALLTYPE* method8)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* method9)(
IImmersiveLauncher10RS* This);
HRESULT(STDMETHODCALLTYPE* ConnectToMonitor)(
IImmersiveLauncher10RS* This,
/* [in] */ IUnknown* monitor);
HRESULT(STDMETHODCALLTYPE* GetMonitor)(
IImmersiveLauncher10RS* This,
/* [in] */ IUnknown** monitor);
END_INTERFACE
} IImmersiveLauncher10RSVtbl;
interface IImmersiveLauncher10RS
{
CONST_VTBL struct IImmersiveLauncher10RSVtbl* lpVtbl;
};
void OpenStartOnMonitor(HMONITOR monitor);
// Slightly tweaked version of function available in Open Shell
// (Open-Shell-Menu\Src\StartMenu\StartMenuHelper\StartMenuHelper.cpp)
LRESULT CALLBACK OpenStartOnCurentMonitorThreadHook(
int code,
WPARAM wParam,
LPARAM lParam
);
typedef DWORD OpenStartOnCurentMonitorThreadParams;
DWORD OpenStartOnCurentMonitorThread(OpenStartOnCurentMonitorThreadParams* unused);
typedef DWORD OpenStartAtLogonThreadParams;
DWORD OpenStartAtLogonThread(OpenStartAtLogonThreadParams* unused);
#endif

View File

@ -0,0 +1,29 @@
#include "StartupSound.h"
DWORD PlayStartupSound(PlayStartupSoundParams* unused)
{
Sleep(2000);
printf("Started \"Play startup sound\" thread.\n");
HRESULT hr = CoInitialize(NULL);
// this checks Software\\Microsoft\\Windows\\CurrentVersion\\Authentication\\LogonUI\\LogonSoundPlayed
// and then plays the startup sound
AuthUILogonSound* ppv;
hr = CoCreateInstance(
&__uuidof_AuthUILogonSound,
NULL,
CLSCTX_INPROC_SERVER,
&__uuidof_IAuthUILogonSound,
&ppv
);
if (SUCCEEDED(hr))
{
ppv->lpVtbl->PlayIfNecessary(ppv, 1);
ppv->lpVtbl->Release(ppv);
}
printf("Ended \"Play startup sound\" thread.\n");
return 0;
}

View File

@ -0,0 +1,50 @@
#ifndef _H_STARTUPSOUND_H_
#define _H_STARTUPSOUND_H_
#include <initguid.h>
#include <Windows.h>
DEFINE_GUID(__uuidof_AuthUILogonSound,
0x0A0D018EE,
0x1100, 0x4389, 0xAB, 0x44,
0x46, 0x4F, 0xAF, 0x00, 0x12, 0x88
);
DEFINE_GUID(__uuidof_IAuthUILogonSound,
0xc35243ea,
0x4cfc, 0x435a, 0x91, 0xc2,
0x9d, 0xbd, 0xec, 0xbf, 0xfc, 0x95
);
typedef interface AuthUILogonSound AuthUILogonSound;
typedef struct AuthUILogonSoundVtbl
{
BEGIN_INTERFACE
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
AuthUILogonSound* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
ULONG(STDMETHODCALLTYPE* AddRef)(
AuthUILogonSound* This);
ULONG(STDMETHODCALLTYPE* Release)(
AuthUILogonSound* This);
HRESULT(STDMETHODCALLTYPE* PlayIfNecessary)(
AuthUILogonSound* This,
/* [in] */ INT64 a1);
END_INTERFACE
} AuthUILogonSoundVtbl;
interface AuthUILogonSound
{
CONST_VTBL struct AuthUILogonSoundVtbl* lpVtbl;
};
typedef DWORD PlayStartupSoundParams;
DWORD PlayStartupSound(PlayStartupSoundParams* unused);
#endif

File diff suppressed because it is too large Load Diff

120
ExplorerPatcher/dxgi_imp.h Normal file
View File

@ -0,0 +1,120 @@
#ifndef _H_DXGI_IMP_H_
#define _H_DXGI_IMP_H_
#include <Windows.h>
static HRESULT(*ApplyCompatResolutionQuirkingFunc)(void*, void*);
__declspec(dllexport) HRESULT ApplyCompatResolutionQuirking(void* p1, void* p2)
{
return ApplyCompatResolutionQuirkingFunc(p1, p2);
}
static HRESULT(*CompatStringFunc)(void*, void*, void*, BOOL);
__declspec(dllexport) HRESULT CompatString(void* p1, void* p2, void* p3, BOOL p4)
{
return CompatStringFunc(p1, p2, p3, p4);
}
static HRESULT(*CompatValueFunc)(void*, void*);
__declspec(dllexport) HRESULT CompatValue(void* p1, void* p2)
{
return CompatValueFunc(p1, p2);
}
static HRESULT(*CreateDXGIFactoryFunc)(void*, void**);
__declspec(dllexport) HRESULT CreateDXGIFactory(void* p1, void** p2)
{
return CreateDXGIFactoryFunc(p1, p2);
}
static HRESULT(*CreateDXGIFactory1Func)(void*, void**);
__declspec(dllexport) HRESULT CreateDXGIFactory1(void* p1, void** p2)
{
return CreateDXGIFactory1Func(p1, p2);
}
static HRESULT(*CreateDXGIFactory2Func)(UINT, void*, void**);
__declspec(dllexport) HRESULT CreateDXGIFactory2(UINT p1, void* p2, void** p3)
{
return CreateDXGIFactory2Func(p1, p2, p3);
}
static HRESULT(*DXGID3D10CreateDeviceFunc)();
__declspec(dllexport) HRESULT DXGID3D10CreateDevice() {
return DXGID3D10CreateDeviceFunc();
}
static HRESULT(*DXGID3D10CreateLayeredDeviceFunc)();
__declspec(dllexport) HRESULT DXGID3D10CreateLayeredDevice()
{
return DXGID3D10CreateLayeredDeviceFunc();
}
static HRESULT(*DXGID3D10GetLayeredDeviceSizeFunc)();
__declspec(dllexport) HRESULT DXGID3D10GetLayeredDeviceSize()
{
return DXGID3D10GetLayeredDeviceSizeFunc();
}
static HRESULT(*DXGID3D10RegisterLayersFunc)();
__declspec(dllexport) HRESULT DXGID3D10RegisterLayers()
{
return DXGID3D10RegisterLayersFunc();
}
static HRESULT(*DXGIDeclareAdapterRemovalSupportFunc)();
__declspec(dllexport) HRESULT DXGIDeclareAdapterRemovalSupport()
{
return DXGIDeclareAdapterRemovalSupportFunc();
}
static HRESULT(*DXGIDumpJournalFunc)(void*);
__declspec(dllexport) HRESULT DXGIDumpJournal(void* p1)
{
return DXGIDumpJournalFunc(p1);
}
static HRESULT(*DXGIGetDebugInterface1Func)(UINT, void*, void**);
__declspec(dllexport) HRESULT DXGIGetDebugInterface1(UINT p1, void* p2, void* p3)
{
return DXGIGetDebugInterface1Func(p1, p2, p3);
}
static HRESULT(*DXGIReportAdapterConfigurationFunc)();
__declspec(dllexport) HRESULT DXGIReportAdapterConfiguration(void* p1)
{
return DXGIReportAdapterConfigurationFunc(p1);
}
static HRESULT(*PIXBeginCaptureFunc)(INT64, void*);
__declspec(dllexport) HRESULT PIXBeginCapture(INT64 p1, void* p2)
{
return PIXBeginCaptureFunc(p1, p2);
}
static HRESULT(*PIXEndCaptureFunc)();
__declspec(dllexport) HRESULT PIXEndCapture()
{
return PIXEndCaptureFunc();
}
static HRESULT(*PIXGetCaptureStateFunc)();
__declspec(dllexport) HRESULT PIXGetCaptureState()
{
return PIXGetCaptureState();
}
static HRESULT(*SetAppCompatStringPointerFunc)(SIZE_T, void*);
__declspec(dllexport) HRESULT SetAppCompatStringPointer(SIZE_T p1, void* p2)
{
return SetAppCompatStringPointerFunc(p1, p2);
}
static HRESULT(*UpdateHMDEmulationStatusFunc)(char);
__declspec(dllexport) HRESULT UpdateHMDEmulationStatus(char p1)
{
return UpdateHMDEmulationStatusFunc(p1);
}
inline void SetupDXGIImportFunctions(HMODULE hModule)
{
ApplyCompatResolutionQuirkingFunc = (HRESULT(*)(void*, void*))GetProcAddress(hModule, "ApplyCompatResolutionQuirking");
CompatStringFunc = (HRESULT(*)(void*, void*, void*, BOOL))GetProcAddress(hModule, "CompatString");
CompatValueFunc = (HRESULT(*)(void*, void*))GetProcAddress(hModule, "CompatValue");
CreateDXGIFactoryFunc = (HRESULT(*)(void*, void**))GetProcAddress(hModule, "CreateDXGIFactory");
CreateDXGIFactory1Func = (HRESULT(*)(void*, void**))GetProcAddress(hModule, "CreateDXGIFactory1");
CreateDXGIFactory2Func = (HRESULT(*)(UINT, void*, void**))GetProcAddress(hModule, "CreateDXGIFactory2");
DXGID3D10CreateDeviceFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGID3D10CreateDevice");
DXGID3D10CreateLayeredDeviceFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGID3D10CreateLayeredDevice");
DXGID3D10GetLayeredDeviceSizeFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGID3D10GetLayeredDeviceSize");
DXGID3D10RegisterLayersFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGID3D10RegisterLayers");
DXGIDeclareAdapterRemovalSupportFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGIDeclareAdapterRemovalSupport");
DXGIDumpJournalFunc = (HRESULT(*)(void*))GetProcAddress(hModule, "DXGIDumpJournal");
DXGIGetDebugInterface1Func = (HRESULT(*)(UINT, void*, void**))GetProcAddress(hModule, "DXGIGetDebugInterface1");
DXGIReportAdapterConfigurationFunc = (HRESULT(*)())GetProcAddress(hModule, "DXGIReportAdapterConfiguration");
PIXBeginCaptureFunc = (HRESULT(*)(INT64, void*))GetProcAddress(hModule, "PIXBeginCapture");
PIXEndCaptureFunc = (HRESULT(*)())GetProcAddress(hModule, "PIXEndCapture");
PIXGetCaptureStateFunc = (HRESULT(*)())GetProcAddress(hModule, "PIXGetCaptureState");
SetAppCompatStringPointerFunc = (HRESULT(*)(SIZE_T, void*))GetProcAddress(hModule, "SetAppCompatStringPointer");
UpdateHMDEmulationStatusFunc = (HRESULT(*)(char))GetProcAddress(hModule, "UpdateHMDEmulationStatus");
}
#endif

64
ExplorerPatcher/hooking.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef _H_HOOKING_H_
#define _H_HOOKING_H_
#ifndef _M_AMD64
#ifndef _M_ARM64
#error This application only supports the amd64 or ARM64 architectures. Compilation aborted.
#endif
#endif
#define STRAT_REPLACE_ANY_TYPE_OF_JUMP_WITH_NOP 0
#define STRAT_REPLACE_ANY_TYPE_OF_JUMP_WITH_ALWAYS_JUMP 1
#define HOOK_WITH_FUNCHOOK 0
#define HOOK_WITH_DETOURS 1
#define HOW_TO_HOOK HOOK_WITH_FUNCHOOK
#if HOW_TO_HOOK == HOOK_WITH_FUNCHOOK
#ifdef _M_ARM64
#error Cannot compile for ARM64 using funchook. Change the source to hook with Detours and try again. Compilation aborted.
#endif
#include <funchook.h>
#include <distorm.h>
#pragma comment(lib, "funchook.lib")
#pragma comment(lib, "Psapi.lib") // required by funchook
#pragma comment(lib, "distorm.lib")
#elif HOW_TO_HOOK == HOOK_WITH_DETOURS
#include <detours.h>
#pragma comment(lib, "detours.lib")
void* funchook_create(void)
{
return 1;
}
int funchook_uninstall(
void* _this,
int flags
)
{
return 0;
}
int funchook_destroy(void* _this)
{
return 0;
}
int funchook_prepare(
void* funchook,
void** target_func,
void* hook_func
)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(target_func, hook_func);
return DetourTransactionCommit();
}
int funchook_install(
void* funchook,
int flags
)
{
return 0;
}
#endif
#if HOW_TO_HOOK == HOOK_WITH_FUNCHOOK
funchook_t* funchook = 0;
#elif HOW_TO_HOOK == HOOK_WITH_DETOURS
void* funchook = 0;
#endif
#endif

641
ExplorerPatcher/symbols.c Normal file
View File

@ -0,0 +1,641 @@
#include "symbols.h"
const char* twinui_pcshell_SN[TWINUI_PCSHELL_SB_CNT] = {
TWINUI_PCSHELL_SB_0,
TWINUI_PCSHELL_SB_1,
TWINUI_PCSHELL_SB_2,
TWINUI_PCSHELL_SB_3,
TWINUI_PCSHELL_SB_4,
TWINUI_PCSHELL_SB_5,
TWINUI_PCSHELL_SB_6,
TWINUI_PCSHELL_SB_7
};
const char* startdocked_SN[STARTDOCKED_SB_CNT] = {
STARTDOCKED_SB_0,
STARTDOCKED_SB_1,
STARTDOCKED_SB_2,
STARTDOCKED_SB_3,
STARTDOCKED_SB_4
};
const wchar_t DownloadSymbolsXML[] =
L"<toast displayTimestamp=\"2021-08-29T00:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"short\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Unable to find symbols for OS version %s]]></text>\r\n"
L" <text><![CDATA[Downloading and applying symbol information, please wait...]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
const wchar_t DownloadOKXML[] =
L"<toast displayTimestamp=\"2021-08-29T01:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"short\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Symbols downloaded and applied successfully!]]></text>\r\n"
L" <text><![CDATA[Now, please wait while dynamic Explorer patching is done...]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
const wchar_t InstallOK[] =
L"<toast displayTimestamp=\"2021-08-29T01:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"long\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[Installation succeeded!]]></text>\r\n"
L" <text><![CDATA[This notification will not show again until the next OS build update.]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
DWORD DownloadSymbols(DownloadSymbolsParams* params)
{
TCHAR* wszSettingsPath = params->wszSettingsPath;
HMODULE hModule = params->hModule;
Sleep(3000);
printf("Started \"Download symbols\" thread.\n");
RTL_OSVERSIONINFOW rovi;
DWORD32 ubr = VnGetOSVersionAndUBR(&rovi);
TCHAR szReportedVersion[MAX_PATH + 1];
ZeroMemory(
szReportedVersion,
(MAX_PATH + 1) * sizeof(TCHAR)
);
wsprintf(
szReportedVersion,
L"%d.%d.%d.%d",
rovi.dwMajorVersion,
rovi.dwMinorVersion,
rovi.dwBuildNumber,
ubr
);
TCHAR buffer[sizeof(DownloadSymbolsXML) / sizeof(wchar_t) + 30];
ZeroMemory(
buffer,
(sizeof(DownloadSymbolsXML) / sizeof(wchar_t) + 30) * sizeof(TCHAR)
);
wsprintf(
buffer,
DownloadSymbolsXML,
szReportedVersion
);
HRESULT hr = S_OK;
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
hr = String2IXMLDocument(
buffer,
wcslen(buffer),
&inputXml,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
hr = ShowToastMessage(
inputXml,
APPID,
sizeof(APPID) / sizeof(TCHAR) - 1,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
DWORD dwRet = 0;
char szSettingsPath[MAX_PATH + 1];
ZeroMemory(
szSettingsPath,
(MAX_PATH + 1) * sizeof(char)
);
wcstombs_s(
&dwRet,
szSettingsPath,
MAX_PATH + 1,
wszSettingsPath,
MAX_PATH + 1
);
PathRemoveFileSpecA(szSettingsPath);
CreateDirectoryA(szSettingsPath, NULL);
strcat_s(
szSettingsPath,
MAX_PATH + 1,
"\\"
);
printf("Downloading to \"%s\".\n", szSettingsPath);
symbols_addr symbols_PTRS;
ZeroMemory(
&symbols_PTRS,
sizeof(symbols_addr)
);
char twinui_pcshell_sb_dll[MAX_PATH];
ZeroMemory(
twinui_pcshell_sb_dll,
(MAX_PATH) * sizeof(char)
);
GetSystemDirectoryA(
twinui_pcshell_sb_dll,
MAX_PATH
);
strcat_s(
twinui_pcshell_sb_dll,
MAX_PATH,
"\\"
);
strcat_s(
twinui_pcshell_sb_dll,
MAX_PATH,
TWINUI_PCSHELL_SB_NAME
);
strcat_s(
twinui_pcshell_sb_dll,
MAX_PATH,
".dll"
);
printf("Downloading symbols for \"%s\"...\n", twinui_pcshell_sb_dll);
if (VnDownloadSymbols(
NULL,
twinui_pcshell_sb_dll,
szSettingsPath,
MAX_PATH
))
{
FreeLibraryAndExitThread(
hModule,
4
);
return 4;
}
printf("Reading symbols...\n");
if (VnGetSymbols(
szSettingsPath,
symbols_PTRS.twinui_pcshell_PTRS,
twinui_pcshell_SN,
TWINUI_PCSHELL_SB_CNT
))
{
printf("Hooking Win+C is not available for this build.\n");
if (VnGetSymbols(
szSettingsPath,
symbols_PTRS.twinui_pcshell_PTRS,
twinui_pcshell_SN,
TWINUI_PCSHELL_SB_CNT - 1
))
{
FreeLibraryAndExitThread(
hModule,
5
);
return 5;
}
}
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_0),
symbols_PTRS.twinui_pcshell_PTRS[0],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_1),
symbols_PTRS.twinui_pcshell_PTRS[1],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_2),
symbols_PTRS.twinui_pcshell_PTRS[2],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_3),
symbols_PTRS.twinui_pcshell_PTRS[3],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_4),
symbols_PTRS.twinui_pcshell_PTRS[4],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_5),
symbols_PTRS.twinui_pcshell_PTRS[5],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_6),
symbols_PTRS.twinui_pcshell_PTRS[6],
wszSettingsPath
);
VnWriteUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_7),
symbols_PTRS.twinui_pcshell_PTRS[7],
wszSettingsPath
);
char startdocked_sb_dll[MAX_PATH];
ZeroMemory(
startdocked_sb_dll,
(MAX_PATH) * sizeof(char)
);
GetWindowsDirectoryA(
startdocked_sb_dll,
MAX_PATH
);
strcat_s(
startdocked_sb_dll,
MAX_PATH,
"\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\"
);
strcat_s(
startdocked_sb_dll,
MAX_PATH,
STARTDOCKED_SB_NAME
);
strcat_s(
startdocked_sb_dll,
MAX_PATH,
".dll"
);
printf("Downloading symbols for \"%s\"...\n", startdocked_sb_dll);
if (VnDownloadSymbols(
NULL,
startdocked_sb_dll,
szSettingsPath,
MAX_PATH
))
{
FreeLibraryAndExitThread(
hModule,
6
);
return 6;
}
printf("Reading symbols...\n");
if (VnGetSymbols(
szSettingsPath,
symbols_PTRS.startdocked_PTRS,
startdocked_SN,
STARTDOCKED_SB_CNT
))
{
printf("error...\n");
FreeLibraryAndExitThread(
hModule,
7
);
return 7;
}
VnWriteUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_0),
symbols_PTRS.startdocked_PTRS[0],
wszSettingsPath
);
VnWriteUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_1),
symbols_PTRS.startdocked_PTRS[1],
wszSettingsPath
);
VnWriteUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_2),
symbols_PTRS.startdocked_PTRS[2],
wszSettingsPath
);
VnWriteUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_3),
symbols_PTRS.startdocked_PTRS[3],
wszSettingsPath
);
VnWriteUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_4),
symbols_PTRS.startdocked_PTRS[4],
wszSettingsPath
);
VnWriteString(
TEXT("OS"),
TEXT("Build"),
szReportedVersion,
wszSettingsPath
);
if (symbols_PTRS.twinui_pcshell_PTRS[0])
{
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
HRESULT hr = String2IXMLDocument(
InstallOK,
wcslen(InstallOK),
&inputXml,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
hr = ShowToastMessage(
inputXml,
APPID,
sizeof(APPID) / sizeof(TCHAR) - 1,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
}
else
{
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml2 = NULL;
hr = String2IXMLDocument(
DownloadOKXML,
wcslen(DownloadOKXML),
&inputXml2,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
hr = ShowToastMessage(
inputXml2,
APPID,
sizeof(APPID) / sizeof(TCHAR) - 1,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
}
Sleep(4000);
TCHAR wszExplorerPath[MAX_PATH + 1];
wszExplorerPath[0] = L'\"';
GetSystemDirectory(wszExplorerPath + 1, MAX_PATH);
wcscat_s(wszExplorerPath, MAX_PATH + 1, L"\\rundll32.exe\" \"");
GetModuleFileName(hModule, wszExplorerPath + wcslen(wszExplorerPath), MAX_PATH - wcslen(wszExplorerPath));
wcscat_s(wszExplorerPath, MAX_PATH, L"\",ZZLaunchExplorer");
wprintf(L"Command to launch: \" %s \"\n.", wszExplorerPath);
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
BOOL b = CreateProcess(
NULL,
wszExplorerPath,
NULL,
NULL,
TRUE,
CREATE_UNICODE_ENVIRONMENT,
NULL,
NULL,
&si,
&pi
);
FreeConsole();
TerminateProcess(
OpenProcess(
PROCESS_TERMINATE,
FALSE,
GetCurrentProcessId()
),
EXIT_CODE_EXPLORER
);
}
BOOL LoadSymbols(symbols_addr* symbols_PTRS, TCHAR* wszSettingsPath)
{
symbols_PTRS->twinui_pcshell_PTRS[0] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_0),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[1] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_1),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[2] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_2),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[3] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_3),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[4] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_4),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[5] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_5),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[6] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_6),
0,
wszSettingsPath
);
symbols_PTRS->twinui_pcshell_PTRS[7] = VnGetUInt(
TEXT(TWINUI_PCSHELL_SB_NAME),
TEXT(TWINUI_PCSHELL_SB_7),
0,
wszSettingsPath
);
HKEY hKeySettings;
DWORD dwDisposition;
RegCreateKeyExW(
HKEY_CURRENT_USER,
TEXT(REGPATH_OTHERS) L"\\" TEXT(STARTDOCKED_SB_NAME),
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKeySettings,
&dwDisposition
);
symbols_PTRS->startdocked_PTRS[0] = VnGetUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_0),
0,
wszSettingsPath
);
if (hKeySettings)
{
RegSetValueExW(
hKeySettings,
TEXT(STARTDOCKED_SB_0),
0,
REG_DWORD,
&(symbols_PTRS->startdocked_PTRS[0]),
sizeof(DWORD)
);
}
symbols_PTRS->startdocked_PTRS[1] = VnGetUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_1),
0,
wszSettingsPath
);
if (hKeySettings)
{
RegSetValueExW(
hKeySettings,
TEXT(STARTDOCKED_SB_1),
0,
REG_DWORD,
&(symbols_PTRS->startdocked_PTRS[1]),
sizeof(DWORD)
);
}
symbols_PTRS->startdocked_PTRS[2] = VnGetUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_2),
0,
wszSettingsPath
);
if (hKeySettings)
{
RegSetValueExW(
hKeySettings,
TEXT(STARTDOCKED_SB_2),
0,
REG_DWORD,
&(symbols_PTRS->startdocked_PTRS[2]),
sizeof(DWORD)
);
}
symbols_PTRS->startdocked_PTRS[3] = VnGetUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_3),
0,
wszSettingsPath
);
if (hKeySettings)
{
RegSetValueExW(
hKeySettings,
TEXT(STARTDOCKED_SB_3),
0,
REG_DWORD,
&(symbols_PTRS->startdocked_PTRS[3]),
sizeof(DWORD)
);
}
symbols_PTRS->startdocked_PTRS[4] = VnGetUInt(
TEXT(STARTDOCKED_SB_NAME),
TEXT(STARTDOCKED_SB_4),
0,
wszSettingsPath
);
if (hKeySettings)
{
RegSetValueExW(
hKeySettings,
TEXT(STARTDOCKED_SB_4),
0,
REG_DWORD,
&(symbols_PTRS->startdocked_PTRS[4]),
sizeof(DWORD)
);
}
if (hKeySettings)
{
RegCloseKey(hKeySettings);
}
BOOL bNeedToDownload = FALSE;
for (UINT i = 0; i < sizeof(symbols_addr) / sizeof(DWORD); ++i)
{
if (!((DWORD*)symbols_PTRS)[i] &&
(((DWORD*)symbols_PTRS) + i) != symbols_PTRS->twinui_pcshell_PTRS + TWINUI_PCSHELL_SB_CNT - 1
)
{
bNeedToDownload = TRUE;
}
}
RTL_OSVERSIONINFOW rovi;
DWORD32 ubr = VnGetOSVersionAndUBR(&rovi);
TCHAR szReportedVersion[MAX_PATH + 1];
ZeroMemory(
szReportedVersion,
(MAX_PATH + 1) * sizeof(TCHAR)
);
TCHAR szStoredVersion[MAX_PATH + 1];
ZeroMemory(
szStoredVersion,
(MAX_PATH + 1) * sizeof(TCHAR)
);
wsprintf(
szReportedVersion,
L"%d.%d.%d.%d",
rovi.dwMajorVersion,
rovi.dwMinorVersion,
rovi.dwBuildNumber,
ubr
);
VnGetString(
TEXT("OS"),
TEXT("Build"),
szStoredVersion,
MAX_PATH,
MAX_PATH,
NULL,
wszSettingsPath
);
if (!bNeedToDownload)
{
bNeedToDownload = wcscmp(szReportedVersion, szStoredVersion);
}
return bNeedToDownload;
}

47
ExplorerPatcher/symbols.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef _H_SYMBOLS_H_
#define _H_SYMBOLS_H_
#include <Windows.h>
#define _LIBVALINET_INCLUDE_UNIVERSAL
#include <valinet/universal/toast/toast.h>
#include <valinet/utility/osversion.h>
#include <roapi.h>
#include "utility.h"
#define EXIT_CODE_EXPLORER 1
#define REGPATH_OTHERS "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ExplorerPatcher"
#define SYMBOLS_RELATIVE_PATH "\\ExplorerPatcher\\settings.ini"
#define TWINUI_PCSHELL_SB_NAME "twinui.pcshell"
#define TWINUI_PCSHELL_SB_0 "CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc"
#define TWINUI_PCSHELL_SB_1 "CLauncherTipContextMenu::GetMenuItemsAsync"
#define TWINUI_PCSHELL_SB_2 "ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu"
#define TWINUI_PCSHELL_SB_3 "ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu"
#define TWINUI_PCSHELL_SB_4 "CLauncherTipContextMenu::_ExecuteShutdownCommand"
#define TWINUI_PCSHELL_SB_5 "CLauncherTipContextMenu::_ExecuteCommand"
#define TWINUI_PCSHELL_SB_6 "CLauncherTipContextMenu::ShowLauncherTipContextMenu"
#define TWINUI_PCSHELL_SB_7 "winrt::Windows::Internal::Shell::implementation::MeetAndChatManager::OnMessage" // should be always last
#define TWINUI_PCSHELL_SB_CNT 8
#define STARTDOCKED_SB_NAME "StartDocked"
#define STARTDOCKED_SB_0 "StartDocked::LauncherFrame::ShowAllApps" // UNUSED
#define STARTDOCKED_SB_1 "StartDocked::LauncherFrame::ShowAllApps"
#define STARTDOCKED_SB_2 "StartDocked::LauncherFrame::OnVisibilityChanged"
#define STARTDOCKED_SB_3 "StartDocked::SystemListPolicyProvider::GetMaximumFrequentApps"
#define STARTDOCKED_SB_4 "StartDocked::StartSizingFrame::StartSizingFrame"
#define STARTDOCKED_SB_CNT 5
#pragma pack(push, 1)
typedef struct symbols_addr
{
DWORD twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT];
DWORD startdocked_PTRS[STARTDOCKED_SB_CNT];
} symbols_addr;
#pragma pack(pop)
typedef struct _DownloadSymbolsParams
{
TCHAR* wszSettingsPath;
HMODULE hModule;
} DownloadSymbolsParams;
DWORD DownloadSymbols(DownloadSymbolsParams* params);
BOOL LoadSymbols(symbols_addr* symbols_PTRS, TCHAR* wszSettingsPath);
#endif

358
ExplorerPatcher/utility.c Normal file
View File

@ -0,0 +1,358 @@
#include "utility.h"
#pragma region "Weird stuff"
INT64 nimpl4_1(INT64 a1, DWORD* a2)
{
*a2 = 1;
return 0;
}
INT64 nimpl4_0(INT64 a1, DWORD* a2)
{
*a2 = 0;
return 0;
}
__int64 __fastcall nimpl2(__int64 a1, uintptr_t* a2)
{
__int64 v2; // rax
v2 = a1 + 8;
if (!a1)
v2 = 0i64;
*a2 = v2;
return 0i64;
}
ULONG nimpl3()
{
return 1;
}
HRESULT nimpl()
{
return E_NOTIMPL;
}
HRESULT nimpl1(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1; // rcx
if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;
*a3 = v4;
return S_OK;
}
HRESULT nimpl1_2(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1 - sizeof(__int64); // rcx
if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;
*a3 = v4;
return S_OK;
}
HRESULT nimpl1_3(__int64 a1, uintptr_t* a2, uintptr_t* a3)
{
__int64 v4 = a1 - 2 * sizeof(__int64); // rcx
if (*a2 != 0x5FADCA5C34A95314i64 || a2[1] != 0xC1661118901A7CAEui64)
return E_NOTIMPL;
*a3 = v4;
return S_OK;
}
__int64 nimpl4(__int64 a1, __int64 a2, __int64 a3, BYTE* a4)
{
*a4 = 0;
return 0i64;
}
const IActivationFactoryVtbl _IActivationFactoryVtbl = {
.QueryInterface = nimpl1,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl2
};
const IActivationFactoryVtbl _IActivationFactoryVtbl2 = {
.QueryInterface = nimpl1_2,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl
};
const IActivationFactoryVtbl _IActivationFactoryVtbl3 = {
.QueryInterface = nimpl1_3,
.AddRef = nimpl3,
.Release = nimpl3,
.GetIids = nimpl,
.GetRuntimeClassName = nimpl,
.GetTrustLevel = nimpl,
.ActivateInstance = nimpl4
};
const IActivationFactoryAA XamlExtensionsFactory = {
.lpVtbl = &_IActivationFactoryVtbl,
.lpVtbl2 = &_IActivationFactoryVtbl2,
.lpVtbl3 = &_IActivationFactoryVtbl3
};
#pragma endregion
void printf_guid(GUID guid)
{
printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
LRESULT CALLBACK BalloonWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CREATE)
{
LPCREATESTRUCT lpCs = lParam;
NOTIFYICONDATA ni = { 0 };
ni.cbSize = sizeof(ni);
ni.hWnd = hWnd;
ni.uID = 1;
ni.uFlags = NIF_INFO;
ni.dwInfoFlags = NIIF_INFO;
ni.uTimeout = 2000;
_tcscpy_s(ni.szInfo, _countof(ni.szInfo), lpCs->lpCreateParams);
_tcscpy_s(ni.szInfoTitle, _countof(ni.szInfoTitle), _T("ExplorerPatcher"));
Shell_NotifyIcon(NIM_ADD, &ni);
free(lpCs->lpCreateParams);
exit(0);
}
else
{
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
__declspec(dllexport) CALLBACK ZZTestBalloon(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{
TCHAR* lpwszCmdLine = calloc((strlen(lpszCmdLine) + 1), sizeof(TCHAR));
if (!lpwszCmdLine) exit(0);
size_t numChConv = 0;
mbstowcs_s(&numChConv, lpwszCmdLine, strlen(lpszCmdLine) + 1, lpszCmdLine, strlen(lpszCmdLine) + 1);
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = BalloonWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"ExplorerPatcherBalloon";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
return 0;
}
hwnd = CreateWindowEx(0, L"ExplorerPatcherBalloon", L"",
0, 0, 0, 0, 0,
HWND_MESSAGE, NULL, hInstance, lpwszCmdLine);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
const wchar_t TestToastXML[] =
L"<toast displayTimestamp=\"2021-08-29T00:00:00.000Z\" scenario=\"reminder\" "
L"activationType=\"protocol\" launch=\"https://github.com/valinet/ExplorerPatcher\" duration=\"%s\">\r\n"
L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[%s]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n"
L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n";
__declspec(dllexport) CALLBACK ZZTestToast(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{
TCHAR* lpwszCmdLine = calloc((strlen(lpszCmdLine) + 1), sizeof(TCHAR));
if (!lpwszCmdLine) exit(0);
size_t numChConv = 0;
mbstowcs_s(&numChConv, lpwszCmdLine, strlen(lpszCmdLine) + 1, lpszCmdLine, strlen(lpszCmdLine) + 1);
TCHAR* buffer = calloc((sizeof(TestToastXML) / sizeof(wchar_t) + strlen(lpszCmdLine) + 10), sizeof(TCHAR));
if (buffer)
{
wsprintf(
buffer,
TestToastXML,
L"short",
lpwszCmdLine
);
HRESULT hr = S_OK;
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
hr = String2IXMLDocument(
buffer,
wcslen(buffer),
&inputXml,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
hr = ShowToastMessage(
inputXml,
APPID,
sizeof(APPID) / sizeof(TCHAR) - 1,
#ifdef DEBUG
stdout
#else
NULL
#endif
);
free(buffer);
}
free(lpwszCmdLine);
}
__declspec(dllexport) CALLBACK ZZLaunchExplorer(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{
Sleep(100);
TCHAR wszExplorerPath[MAX_PATH + 1];
GetWindowsDirectory(wszExplorerPath, MAX_PATH + 1);
wcscat_s(wszExplorerPath, MAX_PATH + 1, L"\\explorer.exe");
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
BOOL b = CreateProcess(
NULL,
wszExplorerPath,
NULL,
NULL,
TRUE,
CREATE_UNICODE_ENVIRONMENT,
NULL,
NULL,
&si,
&pi
);
FreeConsole();
TerminateProcess(
OpenProcess(
PROCESS_TERMINATE,
FALSE,
GetCurrentProcessId()
),
0
);
}
__declspec(dllexport) CALLBACK ZZLaunchExplorerDelayed(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{
Sleep(2000);
ZZLaunchExplorer(hWnd, hInstance, lpszCmdLine, nCmdShow);
}
POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight)
{
if (lpBottom) *lpBottom = FALSE;
if (lpRight) *lpRight = FALSE;
POINT point;
point.x = 0;
point.y = 0;
POINT ptCursor;
GetCursorPos(&ptCursor);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
HWND hWnd = GetMonitorInfoFromPointForTaskbarFlyoutActivation(
ptCursor,
MONITOR_DEFAULTTOPRIMARY,
&mi
);
if (hWnd)
{
RECT rc;
GetWindowRect(hWnd, &rc);
if (rc.left - mi.rcMonitor.left == 0)
{
if (bUseRcWork)
{
point.x = mi.rcWork.left;
}
else
{
point.x = mi.rcMonitor.left;
}
if (rc.top - mi.rcMonitor.top == 0)
{
if (bUseRcWork)
{
point.y = mi.rcWork.top;
}
else
{
point.y = mi.rcMonitor.top;
}
}
else
{
if (lpBottom) *lpBottom = TRUE;
if (bUseRcWork)
{
point.y = mi.rcWork.bottom;
}
else
{
point.y = mi.rcMonitor.bottom;
}
}
}
else
{
if (lpRight) *lpRight = TRUE;
if (bUseRcWork)
{
point.x = mi.rcWork.right;
}
else
{
point.x = mi.rcMonitor.right;
}
if (rc.top - mi.rcMonitor.top == 0)
{
if (bUseRcWork)
{
point.y = mi.rcWork.top;
}
else
{
point.y = mi.rcMonitor.top;
}
}
else
{
if (lpBottom) *lpBottom = TRUE;
if (bUseRcWork)
{
point.y = mi.rcWork.bottom;
}
else
{
point.y = mi.rcMonitor.bottom;
}
}
}
}
return point;
}

45
ExplorerPatcher/utility.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef _H_UTILITY_H_
#define _H_UTILITY_H_
#include <Windows.h>
#include <tchar.h>
#include <windows.data.xml.dom.h>
#include <Shlobj_core.h>
#define _LIBVALINET_INCLUDE_UNIVERSAL
#include <valinet/universal/toast/toast.h>
#define APPID L"Microsoft.Windows.Explorer"
#pragma region "Weird stuff"
INT64 nimpl4_1(INT64 a1, DWORD* a2);
INT64 nimpl4_0(INT64 a1, DWORD* a2);
__int64 __fastcall nimpl2(__int64 a1, uintptr_t* a2);
ULONG nimpl3();
HRESULT nimpl();
HRESULT nimpl1(__int64 a1, uintptr_t* a2, uintptr_t* a3);
HRESULT nimpl1_2(__int64 a1, uintptr_t* a2, uintptr_t* a3);
HRESULT nimpl1_3(__int64 a1, uintptr_t* a2, uintptr_t* a3);
__int64 nimpl4(__int64 a1, __int64 a2, __int64 a3, BYTE* a4);
typedef struct _IActivationFactoryAA
{
CONST_VTBL struct IActivationFactoryVtbl* lpVtbl;
struct IActivationFactoryVtbl* lpVtbl2;
struct IActivationFactoryVtbl* lpVtbl3;
} IActivationFactoryAA;
extern const IActivationFactoryAA XamlExtensionsFactory;
#pragma endregion
// https://stackoverflow.com/questions/1672677/print-a-guid-variable
void printf_guid(GUID guid);
LRESULT CALLBACK BalloonWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
__declspec(dllexport) CALLBACK ZZTestBalloon(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow);
__declspec(dllexport) CALLBACK ZZTestToast(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow);
__declspec(dllexport) CALLBACK ZZLaunchExplorer(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow);
__declspec(dllexport) CALLBACK ZZLaunchExplorerDelayed(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow);
POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight);
#endif

201
README.md
View File

@ -1,80 +1,181 @@
# Explorer Patcher for Windows 11 # Explorer Patcher for Windows 11
This application aims to bring back a productive working environment on Windows 11, by restoring dormant functionalities from Windows 10 in the newest OS builds. This project aims to bring back a productive working environment on Windows 11.
The well-known [StartIsBack](https://www.startisback.com/) application recently introduced support for Windows 11. Currently, regarding Windows 11 functionality, it offers the same features as this patcher, plus all the functionalities from the older releases of the software; thus the differences between the two at the moment, besides their internal implementation (probably) resort in the cost, licensing, support and development model: StartIsBack is a paid app, proprietary, closed source and comes with support, while ExplorerPatcher is free ([gratis and libre - as in free beer and free speech](https://en.wikipedia.org/wiki/Gratis_versus_libre)), open source and is provided as-is, with support offered in a best-effort attempt. <details>
<summary>About ExplorerPatcher and StartIsBack</summary>
The well-known [StartIsBack](https://www.startisback.com/) application recently introduced support for Windows 11. Currently, regarding Windows 11 functionality, it offers the same features as this patcher, plus all the functionalities from the older releases of the software; thus the differences between the two at the moment, besides their internal implementation (probably) resort in the cost, licensing, support and development model: StartIsBack is a paid app, proprietary, closed source and comes with support, while ExplorerPatcher is free ([gratis and libre - as in free beer and free speech](https://en.wikipedia.org/wiki/Gratis_versus_libre)), open source and is provided as-is, with support offered in a best-effort attempt.
ExplorerPatcher is offered more like a tool for people to study the source code and the techniques used, to learn and adapt it in order and to enable people to build each on top of the work of the others. The aim is to benefit both the community and its users. You are encouraged to take a look at the source and adapt it to your needs. While the source and the application in its current form will always be available here, I cannot make any guarantes over how long it will work in newer Windows 11 builds. Thus, these things being considered, if you would like, you can check out the beta test for StartIsBack [here](http://startisback.com/tbd/) and report any issues and make suggestions to its developer. It will probably mature in a release that will be better supported from a consumer point of view than ExplorerPatcher. ExplorerPatcher is offered more like a tool for people to study the source code and the techniques used, to learn and adapt it in order and to enable people to build each on top of the work of the others. The aim is to benefit both the community and its users. You are encouraged to take a look at the source and adapt it to your needs. While the source and the application in its current form will always be available here, I cannot make any guarantes over how long it will work in newer Windows 11 builds. Thus, these things being considered, if you would like, you can check out the beta test for StartIsBack [here](http://startisback.com/tbd/) and report any issues and make suggestions to its developer. It will probably mature in a release that will be better supported from a consumer point of view than ExplorerPatcher.
</details>
Current functionality enabled by this patcher includes:
* use the classic taskbar from Windows 10 (without the nasty effects of `UndockingDisabled`)
* restores the classic power user menu (`Win+X`) when using the classic taskbar
* ability for the Start menu and search to align to the left when using the classic taskbar (it follows the setting `Left`/`Center` in `Settings\Personalization\Taskbar\Taskbar behaviors\Taskbar alignment`)
* ability for the Start menu to show the app list by default when opening
* ability to customize the maximum number of "Most used" apps displayed in the app list in Start
* ability to show the Start menu on the monitor containing the cursor when you press the Windows key*
* disable the new context menus in File Explorer and restore the classic ones
* disable the "modern search box" in File Explorer and revert to the proper working one from initial Windows 10 builds (or from Windows 7 and 8)
* skin the "Safe to Remove Hardware" pop-up to match the context menus of the taskbar
* disables the logon delay which happened if you were to enable the classic taskbar using `UndockingDisabled`
* play log on sound, if enabled
It has been developed on and tested to work against the latest builds, 22000.176 and 22449.1000 (Insider Preview). It should work on newer builds as well as long as the internal structure does not change too much (hopefully Microsoft won't remove all the legacy code).
A changelog is available [here](https://github.com/valinet/ExplorerPatcher/blob/master/CHANGELOG.md).
A detailed description of how this works is available on my web site [here](https://valinet.ro/2021/08/09/Restore-Windows-11-to-working-Windows-10-UI.html).
The application comes in the form of a dynamic-link library (DLL). Precompiled binaries are available in [Releases](https://github.com/valinet/ExplorerPatcher/releases).
Screenshots: [<1>](https://gist.githubusercontent.com/valinet/d0f72ff09773702584e77c46065b95e0/raw/94036ed3e38218b87744a29ae5c40b06be637daf/ep_img0.png) [<2>](https://user-images.githubusercontent.com/6503598/131937638-d513ca72-ead7-459b-a8ce-619fb302b7da.png) Screenshots: [<1>](https://gist.githubusercontent.com/valinet/d0f72ff09773702584e77c46065b95e0/raw/94036ed3e38218b87744a29ae5c40b06be637daf/ep_img0.png) [<2>](https://user-images.githubusercontent.com/6503598/131937638-d513ca72-ead7-459b-a8ce-619fb302b7da.png)
(*) There is a bug currently in Windows 11 22000.176 where search may not open properly on other monitors. This is not because of this patcher, and will probably (hopefully) be fixed by Microsoft in a future build. ## dxgi.dll - the patcher
In the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section, you will find a download for a DLL called `dxgi.dll`. It has been tested on the latest stable build of Windows 11 (22000.194), but it may work just fine on newer builds too. This is the runtime part of the application. You need to place this DLL in the following location: `C:\Windows`. This will enable the following functionality:
## Installation * use the classic taskbar from Windows 10 (without the nasty effects of `UndockingDisabled`)
* restores the classic power user menu (`Win+X`) when using the classic taskbar
* Start menu follows the taskbar alignment setting (`Left`/`Center`) specified in `Settings\Personalization\Taskbar\Taskbar behaviors\Taskbar alignment`
* ability to show the Start menu on the monitor containing the cursor when pressing the Windows key
* skin "Safe to Remove Hardware" and "Bluetooth" popup menus
* play log on sound, if enabled
* option to hide the search bar in File Explorer
* option to disable the control center button in the taskbar
Simply copy the downloaded DLL named `dxgi.dll` to `%windir%` (usually `C:\Windows`) and restart Explorer. Additionally, you can place the DLL in the following location: `C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy` to enable additional functionality:
At first launch, the application will notify you about missing symbols and will automatically download them from Microsoft. When this is done, a notification will show informing you that everything's done and Explorer will restart and display the old taskbar. Note that for those with relevant toast display turned off, this process may be done automatically without any notification. Normally giving it 5 mins will suffice. * show the "All apps" list by default when opening the Start menu
* customize the maximum number of "Most used" apps displayed in the "All apps" list in Start
After Explorer restarts, the classic taskbar will be available and fully functioning, but you will notice the system tray misses the status icons. Those can be easily enabled by opening `Run` and going to `%windir%\explorer.exe shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons` and enabling each system icon you wish from there. For a list of other useful registry settings that can help you make the most out of this application, like disabling taskbar grouping, read [here](https://github.com/valinet/ExplorerPatcher/issues/9). Also, if you place the `StartIsBack64.dll` file from StartIsBack(TBD) Preview 2 in the folder `%appdata%\ExplorerPatcher` (create if it does not exist), the following additional features will be enabled:
After you get the classic taskbar working, to make it work with the Start menu and search and enable related functionality, copy the DLL to the following 2 locations as well: * option to apply Mica effect on File Explorer windows
* option to skin system tray icons to match Windows 11 style
* `C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy` After you have completed the above setup, make sure you have an active Internet connection and restart the Explorer process using Task Manager or by issuing the following command: `taskkill /f /im explorer.exe`. Once File Explorer restarts, some necessary files (symbol files) will be downloaded from Microsoft (around 50MB). This should be relatively quick, depending on your Internet connection speed. When this is done, File Explorer will restart again and will be ready for use. Notifications should show up informing you about the progress, and you can also use Task Manager to watch for network activity. This process only happens when a new Windows 11 build is installed on the machine.
* `C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy`
After that is done, kill both `StartMenuExperienceHost.exe` and `SearchHost.exe` from Task Manager, or simply log out and back in or restart the computer. Now, the classic taskbar should be enabled. Still, there is some more setup to do, depending on your preferences.
Two of the applets in the system tray do not work in this mode: battery and network. To replace the battery applet, I recommend the much more capable [Battery Mode](https://en.bmode.tarcode.ru/) application which has very good integration and allows showing both classic power modes and Windows 10 power schemes (better battery, better performance etc), changing the display brightness (for laptop screens AND monitors) etc. To replace the network icon, I recommend using the control center to switch networks and keep the legacy icon only as an indicator. You can also have it open the "Network" section in the Settings app as described [here](https://winaero.com/change-network-icon-click-action-in-windows-10). ### Enable system tray icons
As you have noticed, some system tray icons are missing (for example, the clock, notification center button, network, battery, sound etc). To enable these icons, open the following using Run:
If you want to disable the blue highlight in the context menu and return to the classic gray highlight from early Windows 11 builds, read [here](https://github.com/valinet/ExplorerPatcher/issues/18). Also, if you want to disable the rounded corners of the windows in Windows 11, I recommend you one of my other utilities available [here](https://github.com/valinet/Win11DisableRoundedCorners). ```
%windir%\explorer.exe shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9}\SystemIcons
```
Downloaded symbols and application configuration is saved in the `%appdata%\ExplorerPatcher` folder. In the window that appears, toggle to `On` whatever icons you would like to have enabled in the taskbar.
To uninstall, simply delete `dxgi.dll` from all the directories above. If you get a "file in use" error when attempting to do so, simply rename it everywhere to `dxgia.dll`, reboot the computer and then delete the renamed DLL. ### Show labels for taskbar buttons
One of the great features the old taskbar had was the ability to ungroup the taskbar buttons, showing a button with a label for each window that the user currently has open. To enable this functionality, run either of the following commands, depending on your preference.
#### A note on antivirus false positives #### Ungroup icons on all taskbars
The DLL you download may trigger a false positive alert in your antivirus program. This is fairly normal, a sign that the product you are using is decently capable, since it features detection methods a bit more advanced than what was state of the art in 1999. The program being flagged is usually done through heuristic analysis, not via a database of know viruses. That means that the antivirus program thinks that due to the nature of the code in this application, it likely may be a virus, a program that the user does not really mean to run. Injecting code into other executables is rarely done by legitimate programs. One such kind of legitimate programs is this patcher, that you deliberately choose to run and let it alter Explorer's code and memory in a controlled manner so that you achieve a certain effect. Thus, this patcher falls in the category of false positives: your antivirus thought such a program was not something you meant to run, but that's not the case this time. ```
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /f /v "NoTaskGrouping" /t REG_DWORD /d 1
```
If you still feel a bit iffy running this, then that's why the source code is available on the web site. You can take a look and even compile the DLL yourself and make an informed decision when running the software. Never run untrusted binaries from questionable sources, especially when you lack access to the source code and a way to reproduce that binary. #### Ungroup icons on main taskbar only
#### How does this work? ```
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /f /v "TaskbarGlomLevel" /t REG_DWORD /d 2
```
#### Ungroup icons on secondary taskbars
```
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /f /v "MMTaskbarGlomLevel" /t REG_DWORD /d 2
```
In the commands above, change `2` to `0` for "Always combine" and `2` to `1` for "Combine when taskbar is full`.
### Disable the immersive context menu
As you probably have noticed, Windows 11 introduced a simplified context menu in File Explorer. To get to the old menu which contains all entries from shell extensions, one has to click on "Show more options" or type Shift+F10. To disable this new menu, run the following command:
```
reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve
```
To restore back the immersive menu, run:
```
reg.exe delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
```
### Disable the command bar in File Explorer
In Windows 11, File Explorer comes with a command bar instead of the traditional ribbon. To disable this and get back the ribbon, run the following command:
```
reg.exe add "HKCU\Software\Classes\CLSID\{d93ed569-3b3e-4bff-8355-3c44f6a52bb5}\InprocServer32" /f /ve
```
To restore back the command bar, run:
```
reg.exe delete "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}" /f
```
If you want to get back the command bar from Windows 7, after enabling back the ribbon, [OldNewExplorer](https://msfn.org/board/topic/170375-oldnewexplorer-119/) will allow you to do so, and many more options, like drive ungrouping in This PC, as it used to be prior to Windows 8.1.
### Disable the modern search box in File Explorer
In Windows 10 1903, Microsoft introduced a new search box in File Explorer. This new search control is clunky, does not search automatically and usually is kind of broken. The old search box remains available, but only in Control Panel windows. To enable it on all File Explorer windows, run the following command:
```
reg.exe add "HKCU\Software\Classes\CLSID\{1d64637d-31e9-4b06-9124-e83fb178ac6e}\TreatAs" /f /ve /t REG_SZ /d "{64bc32b5-4eec-4de7-972d-bd8bd0324537}"
```
To restore the modern search box, run:
```
reg.exe delete "HKCU\Software\Classes\CLSID\{1d64637d-31e9-4b06-9124-e83fb178ac6e}" /f
```
Also, in the next section, which desribes the configuration options for the software, you will learn about how to disable the search box altogether, should you want to.
### Fix the battery applet
As you will notice, the battery flyout in the taskbar is broken in Windows 11. You can replace it with a much better alternative called [Battery Mode](https://en.bmode.tarcode.ru/) which has all the stock options and more.
### Disable blue highlight in menus
To disable the blue highlight in the context menu and return to the classic gray highlight from early Windows 11 builds, read [here](https://github.com/valinet/ExplorerPatcher/issues/18).
### Disable window rounded corners
You can try one of my other utilities available [here](https://github.com/valinet/Win11DisableRoundedCorners).
## Configuration
Now that you have set up the basic stuff, you can choose to enable additional settings to enhance the experience even more. For this, edit the file `%appdata%\ExplorerPatcher\settings.ini` and add the following section to it (change to `0` the setting that you do not want to enable):
```
[General]
HideExplorerSearchBar=1
HideControlCenterButton=1
MicaEffectOnTitlebar=1
SkinMenus=1
SkinIcons=1
AllocConsole=1
```
* `HideExplorerSearchBar` completely removes the search box in File Explorer
* `HideControlCenterButton` disables the Control Center button and its associated shortcut key (`Win`+`A`)
* `MicaEffectOnTitlebar` enables Mica effect on File Explorer windows (requires `StartIsBack64.dll`)
* `SkinMenus` applies the immersive skin to "Safe to Remove Hardware" and "Bluetooth" pop-up menus
* `SkinIcons` applies Windows 11 icon skins to taskbar buttons (requires `StartIsBack64.dll`)
* `AllocConsole` will display a console window (for debugging purposes)
Also, if you chose to place the patcher in `C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy` as well, use the following commands to configure Start menu options:
* Open Start menu to "All apps" directly (replace with 0 to disable)
```
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\StartPage /f /v "MakeAllAppsDefault" /t REG_DWORD /d 1
```
* Show only 4 most recent apps (change the number to customize)
```
reg.exe add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced /f /v "Start_MaximumFrequentApps" /t REG_DWORD /d 4
```
## More configuration
Even more registry configuration settings are described in the following document, make sure to take a look on it [here](https://github.com/valinet/ExplorerPatcher/issues/9).
## Uninstallation
To uninstall, rename the DLL in the locations where you placed it from `dxgi.dll` to `dxgio.dll`. Then, reboot the computer and delete the `dxgio.dll` file from the locations where it is placed. You can also then safely delete the `%appdata%\ExplorerPatcher` directory as well.
## More details
A changelog is available [here](https://github.com/valinet/ExplorerPatcher/blob/master/CHANGELOG.md).
<details>
<summary>How does this work?</summary>
A detailed description of how this works is available on my web site [here](https://valinet.ro/2021/08/09/Restore-Windows-11-to-working-Windows-10-UI.html).
The way the application gets loaded is by exploiting the DLL search order in Windows. I take advantage of the fact that Explorer is one of the few system processes located in `%windir%` and not in `%windir%\System32`, so it does not affect most apps. Also, `%windir%` is not first in the search path. Read more about this technique [here](https://itm4n.github.io/windows-dll-hijacking-clarified/). The main advantage here is that you do not have to keep an extra process running in the memory; plus, due to the diverse nature of how Explorer is launched, hooking it can be difficult. The way the application gets loaded is by exploiting the DLL search order in Windows. I take advantage of the fact that Explorer is one of the few system processes located in `%windir%` and not in `%windir%\System32`, so it does not affect most apps. Also, `%windir%` is not first in the search path. Read more about this technique [here](https://itm4n.github.io/windows-dll-hijacking-clarified/). The main advantage here is that you do not have to keep an extra process running in the memory; plus, due to the diverse nature of how Explorer is launched, hooking it can be difficult.
I picked `dxgi.dll` because it is not on the `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs` list, because it has few exports and is loaded very early by Explorer, when calling the `DXGIDeclareAdapterRemovalSupport()` function. I picked `dxgi.dll` because it is not on the `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs` list, because it has few exports and is loaded very early by Explorer, when calling the `DXGIDeclareAdapterRemovalSupport()` function.
</details>
## Configuration <details>
<summary>A note on antivirus false positives</summary>
The DLL you download may trigger a false positive alert in your antivirus program. This is fairly normal, a sign that the product you are using is decently capable, since it features detection methods a bit more advanced than what was state of the art in 1999. The program being flagged is usually done through heuristic analysis, not via a database of know viruses. That means that the antivirus program thinks that due to the nature of the code in this application, it likely may be a virus, a program that the user does not really mean to run. Injecting code into other executables is rarely done by legitimate programs. One such kind of legitimate programs is this patcher, that you deliberately choose to run and let it alter Explorer's code and memory in a controlled manner so that you achieve a certain effect. Thus, this patcher falls in the category of false positives: your antivirus thought such a program was not something you meant to run, but that's not the case this time.
The `settings.ini` file contains, among the offsets for the various hooked/exploited functions, a few parameters that you can tweak: If you still feel a bit iffy running this, then that's why the source code is available on the web site. You can take a look and even compile the DLL yourself and make an informed decision when running the software. Never run untrusted binaries from questionable sources, especially when you lack access to the source code and a way to reproduce that binary.
</details>
* `General\AllowImmersiveContextMenus = 1` will show the new context menus in Explorer instead of the legacy one
* `General\AllowModernSearchBox = 1` will leave the modern search box enabled in File Explorer
* `General\AllocConsole = 1` will show a console when the application runs (useful for diagnostics).
The rest of the parameters that you can tweak and have them work with the application are located in the registry and are described [here](https://github.com/valinet/ExplorerPatcher/issues/9).
## License ## License

View File

@ -0,0 +1,23 @@
[General]
AllocConsole=0
HideExplorerSearchBar=0
HideControlCenterButton=0
MicaEffectOnTitlebar=0
SkinMenus=1
SkinIcons=1
[twinui.pcshell]
CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc=2183030
CLauncherTipContextMenu::GetMenuItemsAsync=6072240
ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu=6242504
ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu=6244560
CLauncherTipContextMenu::_ExecuteShutdownCommand=6131272
CLauncherTipContextMenu::_ExecuteCommand=6130436
CLauncherTipContextMenu::ShowLauncherTipContextMenu=6077440
winrt::Windows::Internal::Shell::implementation::MeetAndChatManager::OnMessage=313504
[StartDocked]
StartDocked::LauncherFrame::ShowAllApps=1609404
StartDocked::LauncherFrame::OnVisibilityChanged=1601824
StartDocked::SystemListPolicyProvider::GetMaximumFrequentApps=15376
StartDocked::StartSizingFrame::StartSizingFrame=1444588
[OS]
Build=10.0.22000.194

@ -1 +1 @@
Subproject commit b8aefade48424ff76db4509f347cc52557ca2d5e Subproject commit 3244bfa5646ceba0756f7330d60aad919c3aa584