Skip to content

Commit

Permalink
Fixes #2 (Win+X combination is now handled and opens the power user m…
Browse files Browse the repository at this point in the history
…enu)
  • Loading branch information
valinet committed Aug 13, 2021
1 parent 9de9b01 commit c850e50
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 23 deletions.
8 changes: 4 additions & 4 deletions ExplorerPatcher/ExplorerPatcher.rc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 22000,1,0,3
PRODUCTVERSION 22000,1,0,3
FILEVERSION 22000,1,0,4
PRODUCTVERSION 22000,1,0,4
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "VALINET Solutions SRL"
VALUE "FileDescription", "ExplorerPatcher Daemon"
VALUE "FileVersion", "22000.1.0.3"
VALUE "FileVersion", "22000.1.0.4"
VALUE "InternalName", "ExplorerPatcher.exe"
VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved."
VALUE "OriginalFilename", "ExplorerPatcher.exe"
VALUE "ProductName", "ExplorerPatcher"
VALUE "ProductVersion", "22000.1.0.3"
VALUE "ProductVersion", "22000.1.0.4"
END
END
BLOCK "VarFileInfo"
Expand Down
8 changes: 4 additions & 4 deletions ExplorerPatcherLibrary/ExplorerPatcherLibrary.rc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 22000,1,0,3
PRODUCTVERSION 22000,1,0,3
FILEVERSION 22000,1,0,4
PRODUCTVERSION 22000,1,0,4
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "VALINET Solutions SRL"
VALUE "FileDescription", "ExplorerPatcher Library"
VALUE "FileVersion", "22000.1.0.3"
VALUE "FileVersion", "22000.1.0.4"
VALUE "InternalName", "ExplorerPatcherLibrary.dll"
VALUE "LegalCopyright", "Copyright (C) 2006-2021 VALINET Solutions SRL. All rights reserved."
VALUE "OriginalFilename", "ExplorerPatcherLibrary.dll"
VALUE "ProductName", "WinOverview"
VALUE "ProductVersion", "22000.1.0.3"
VALUE "ProductVersion", "22000.1.0.4"
END
END
BLOCK "VarFileInfo"
Expand Down
122 changes: 112 additions & 10 deletions ExplorerPatcherLibrary/dllmain.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
funchook_t* funchook = NULL;
HMODULE hModule = NULL;
HWND messageWindow = NULL;


HANDLE hIsWinXShown = NULL;
INT64 lockEnsureWinXHotkeyOnlyOnce;

static HWND(WINAPI* CreateWindowInBand)(
_In_ DWORD dwExStyle,
Expand Down Expand Up @@ -85,6 +85,12 @@ static INT64(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProc)(
BOOL* a5
);

static INT64(*CTray_HandleGlobalHotkeyFunc)(
void* _this,
unsigned int a2,
unsigned int a3
);

DEFINE_GUID(IID_ILauncherTipContextMenu,
0xb8c1db5f,
0xcbb3, 0x48bc, 0xaf, 0xd9,
Expand Down Expand Up @@ -249,7 +255,7 @@ interface IImmersiveLauncher10RS



HANDLE hThread;


LRESULT CALLBACK CLauncherTipContextMenu_WndProc(
_In_ HWND hWnd,
Expand Down Expand Up @@ -434,7 +440,7 @@ DWORD ShowLauncherTipContextMenu(
0
);
free(params);
hThread = NULL;
hIsWinXShown = NULL;
return 0;
}

Expand All @@ -443,7 +449,7 @@ INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
POINT* pt
)
{
if (hThread)
if (hIsWinXShown)
{
goto finalize;
}
Expand Down Expand Up @@ -510,7 +516,7 @@ INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
params->_this = _this;
params->point = point;
params->iunk = iunk;
hThread = CreateThread(
hIsWinXShown = CreateThread(
0,
0,
ShowLauncherTipContextMenu,
Expand All @@ -523,24 +529,106 @@ INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(
return CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt);
}

INT64 CTray_HandleGlobalHotkeyHook(
void* _this,
unsigned int a2,
unsigned int a3
)
{
if (a2 == 590 && IsDesktopInputContextFunc(_this, a2))
{
// this works just fine but is hacky because using
// the proper way does not work for some reason
// see https://github.com/valinet/ExplorerPatcher/issues/3
if (hIsWinXShown)
{
INPUT ip[2];
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wScan = 0;
ip[0].ki.time = 0;
ip[0].ki.dwExtraInfo = 0;
ip[0].ki.wVk = VK_ESCAPE;
ip[0].ki.dwFlags = 0;
ip[1].type = INPUT_KEYBOARD;
ip[1].ki.wScan = 0;
ip[1].ki.time = 0;
ip[1].ki.dwExtraInfo = 0;
ip[1].ki.wVk = VK_ESCAPE;
ip[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(2, ip, sizeof(INPUT));
return 0;
}

InterlockedExchange64(&lockEnsureWinXHotkeyOnlyOnce, 1);

HWND hWnd = GetForegroundWindow();
HWND g_ProgWin = FindWindowEx(
NULL,
NULL,
L"Progman",
NULL
);
SetForegroundWindow(g_ProgWin);

INPUT ip[4];
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wScan = 0;
ip[0].ki.time = 0;
ip[0].ki.dwExtraInfo = 0;
ip[0].ki.wVk = VK_LWIN;
ip[0].ki.dwFlags = 0;
ip[1].type = INPUT_KEYBOARD;
ip[1].ki.wScan = 0;
ip[1].ki.time = 0;
ip[1].ki.dwExtraInfo = 0;
ip[1].ki.wVk = 0x51; // 0x46;
ip[1].ki.dwFlags = 0;
ip[2].type = INPUT_KEYBOARD;
ip[2].ki.wScan = 0;
ip[2].ki.time = 0;
ip[2].ki.dwExtraInfo = 0;
ip[2].ki.wVk = 0x51; // 0x46;
ip[2].ki.dwFlags = KEYEVENTF_KEYUP;
ip[3].type = INPUT_KEYBOARD;
ip[3].ki.wScan = 0;
ip[3].ki.time = 0;
ip[3].ki.dwExtraInfo = 0;
ip[3].ki.wVk = VK_LWIN;
ip[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, ip, sizeof(INPUT));

SetForegroundWindow(hWnd);

return 0;
}
return CTray_HandleGlobalHotkeyFunc(
_this,
a2,
a3
);
}

HRESULT CImmersiveHotkeyNotification_OnMessageHook(
void* _this,
INT64 msg,
INT wParam,
INT64 lParam
)
{
if (wParam == 28 && IsDesktopInputContextFunc(_this, msg)) // 15
if (InterlockedExchange64(&lockEnsureWinXHotkeyOnlyOnce, 0) &&
wParam == 30 && // 28, 15
IsDesktopInputContextFunc(_this, msg)
)
{
IUnknown* pMonitor;
IUnknown* pMonitor = NULL;
HRESULT hr = CImmersiveHotkeyNotification_GetMonitorForHotkeyNotificationFunc(
(char*)_this - 0x68,
&pMonitor,
0
);
if (SUCCEEDED(hr))
{
IUnknown* pMenu;
IUnknown* pMenu = NULL;
IUnknown_QueryService(
pMonitor,
&IID_ILauncherTipContextMenu,
Expand Down Expand Up @@ -650,7 +738,7 @@ LRESULT CALLBACK OpenStartOnCurentMonitorThreadHook(
);

HRESULT hr = S_OK;
IUnknown* pImmersiveShell;
IUnknown* pImmersiveShell = NULL;
hr = CoCreateInstance(
&CLSID_ImmersiveShell,
NULL,
Expand Down Expand Up @@ -780,6 +868,20 @@ __declspec(dllexport) DWORD WINAPI main(
);


HANDLE hExplorer = GetModuleHandle(NULL);
CTray_HandleGlobalHotkeyFunc = (INT64(*)(void*, unsigned int, unsigned int))
((uintptr_t)hExplorer + 0x117F8);
rv = funchook_prepare(
funchook,
(void**)&CTray_HandleGlobalHotkeyFunc,
CTray_HandleGlobalHotkeyHook
);
if (rv != 0)
{
FreeLibraryAndExitThread(hModule, rv);
return rv;
}


HANDLE hUser32 = GetModuleHandle(L"user32.dll");

Expand Down
5 changes: 0 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ To install, save the executable in a safe directory, run it once as an administr

The application does not currently offer a way to configure its behavior. In the mean time, I recommend commenting out whatever you do not like and compile your own executable, as described below (instructions are very simple).

## Known issues

* The power user menu (Win+X menu) is unskinned - it has the default menu appearance from Windows 11 instead of the look the clock, taskbar etc context menus get; at the moment, I think it boils down to correctly calling `ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu`, but unfortunately I've yet to do it correctly
* The power user menu (Win+X menu) is mapped to Win+F for the moment, as I've yet to have the time to investigate where exactly Win+X is handled (i.e. it is not in `CImmersiveHotkeyNotification::OnMessage`)

## License

Hooking is done using the excellent [funchook](https://github.com/kubo/funchook) library (GPLv2 with linking exception), which in turn is powered by the [diStorm3](https://github.com/gdabah/distorm/) (3-clause BSD) disassembler. Thus, I am offering this under GNU General Public License Version 2.0, which I believe is compatible.
Expand Down

0 comments on commit c850e50

Please sign in to comment.