From 6023718b959941eccc586aa81c9eeab4e5998385 Mon Sep 17 00:00:00 2001 From: Amrsatrio Date: Sun, 24 Sep 2023 19:52:48 +0700 Subject: [PATCH] Taskbar11: Fixed a bug that crashed `explorer.exe` when right clicking the new taskbar on Windows 11 builds with "Never combine" on the new taskbar --- ExplorerPatcher/dllmain.c | 78 +++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index e819131..a1a0165 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -2411,6 +2411,8 @@ LRESULT CALLBACK Shell_TrayWndMouseProc( return CallNextHookEx(Shell_TrayWndMouseHook, nCode, wParam, lParam); } +PBYTE g_pTrayUIHost; + INT64 Shell_TrayWndSubclassProc( _In_ HWND hWnd, _In_ UINT uMsg, @@ -2492,29 +2494,25 @@ INT64 Shell_TrayWndSubclassProc( } DeleteMenu(hSubMenu, 424, MF_BYCOMMAND); // Lock the taskbar DeleteMenu(hSubMenu, 425, MF_BYCOMMAND); // Lock all taskbars - HWND hShellTray_Wnd = FindWindowExW(NULL, NULL, L"Shell_TrayWnd", NULL); - INT64* CTrayInstance = (BYTE*)(GetWindowLongPtrW(hShellTray_Wnd, 0)); // -> CTray - const unsigned int TRAYUI_OFFSET_IN_CTRAY = 110; - uintptr_t TrayUIInstance = *((INT64*)CTrayInstance + TRAYUI_OFFSET_IN_CTRAY) + 8; - if (TrayUIInstance) + if (g_pTrayUIHost) { - int offset = 656; - if (IsWindows11Version22H2OrHigher()) offset = 640; - if (IsWindows11Version22H2Build2134OrHigher()) offset = 648; - if ((*(unsigned __int8(__fastcall**)(INT64))(**(INT64**)(TrayUIInstance + offset) + 104i64))(*(INT64*)(TrayUIInstance + offset))) + void** pTrayUIHostVtbl = *(void***)g_pTrayUIHost; + BOOL (*ShouldDeleteContextMenuUndo)(PBYTE) = pTrayUIHostVtbl[13]; + UINT (*GetContextMenuUndoResourceId)(PBYTE) = pTrayUIHostVtbl[14]; + + if (ShouldDeleteContextMenuUndo(g_pTrayUIHost)) { - DeleteMenu(hSubMenu, 0x1A0u, 0); + DeleteMenu(hSubMenu, 416, MF_BYCOMMAND); } else { - WCHAR Buffer[MAX_PATH]; - WCHAR v40[MAX_PATH]; - WCHAR NewItem[MAX_PATH]; - LoadStringW(GetModuleHandleW(NULL), 0x216u, Buffer, 64); - UINT v22 = (*(__int64(__fastcall**)(INT64))(**(INT64**)(TrayUIInstance + offset) + 112i64))(*(INT64*)(TrayUIInstance + offset)); - LoadStringW(GetModuleHandleW(NULL), v22, v40, 96); - swprintf_s(NewItem, 0xA0ui64, Buffer, v40); - ModifyMenuW(hSubMenu, 0x1A0u, 0, 0x1A0ui64, NewItem); + WCHAR wszTemplate[64]; + WCHAR wszCommand[96]; + WCHAR wszMenu[160]; + LoadStringW(GetModuleHandleW(NULL), 534, wszTemplate, 64); + LoadStringW(GetModuleHandleW(NULL), GetContextMenuUndoResourceId(g_pTrayUIHost), wszCommand, 96); + swprintf_s(wszMenu, 160, wszTemplate, wszCommand); + ModifyMenuW(hSubMenu, 416, MF_BYCOMMAND, 416, wszMenu); } } else @@ -10715,6 +10713,8 @@ DWORD Inject(BOOL bIsExplorer) HANDLE hExplorer = GetModuleHandleW(NULL); + MODULEINFO miExplorer; + GetModuleInformation(GetCurrentProcess(), hExplorer, &miExplorer, sizeof(MODULEINFO)); SetChildWindowNoActivateFunc = GetProcAddress(GetModuleHandleW(L"user32.dll"), (LPCSTR)2005); if (bOldTaskbar) { @@ -10784,7 +10784,29 @@ DWORD Inject(BOOL bIsExplorer) VnPatchIAT(hExplorer, "dwmapi.dll", "DwmUpdateThumbnailProperties", explorer_DwmUpdateThumbnailPropertiesHook); PatchExplorer_UpdateWindowAccentProperties(); } - + if (IsWindows11()) + { + // Find a pointer to ITrayUIHost needed to have a working Windows 10 taskbar context menu on Windows 11 taskbar + // Ref: CTray::Init() + // 4C 8D 05 ? ? ? ? 48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B 8D + // ^^^^^^^ + PBYTE match = FindPattern( + hExplorer, + miExplorer.SizeOfImage, + "\x4C\x8D\x05\x00\x00\x00\x00\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\x8D", + "xxx????xxx????x????xxx" + ); + if (match) + { + match += 7; + g_pTrayUIHost = match + 7 + *(int*)(match + 3); + printf("ITrayUIHost = %llX\n", g_pTrayUIHost - (PBYTE)hExplorer); + } + else + { + printf("Failed to find ITrayUIHost, the custom Windows 11 taskbar context menu will not have the undo function\n"); + } + } HANDLE hShcore = LoadLibraryW(L"shcore.dll"); SHWindowsPolicy = GetProcAddress(hShcore, (LPCSTR)190); @@ -10857,7 +10879,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\x4D\x8B\xCF\x4D\x8B\xC4\x8B\xD6\x48\x8B\x49\x08\xE8\x00\x00\x00\x00\xE9", "xxxxxxxxxxxxx????x" ); @@ -10873,7 +10895,7 @@ DWORD Inject(BOOL bIsExplorer) // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 30 49 8B D8 48 8B FA 48 8B F1 49 83 20 00 41 B0 03 B2 01 PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x30\x49\x8B\xD8\x48\x8B\xFA\x48\x8B\xF1\x49\x83\x20\x00\x41\xB0\x03\xB2\x01", "xxxx?xxxx?xxxxxxxxxxxxxxxxxxxxxxx" ); @@ -10890,7 +10912,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x0F\xB7\xC8\xE8\x00\x00\x00\x00\xF7\xD8", "x????x????xxxx????xx" ); @@ -10907,7 +10929,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\xE8\x00\x00\x00\x00\x85\xDB\x74\x29", "x????xxxx" ); @@ -10923,7 +10945,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\xE8\x00\x00\x00\x00\x90\x49\x8D\x56\x38\x49\x8B\xCE", "x????xxxxxxxx" ); @@ -10939,7 +10961,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\xE8\x00\x00\x00\x00\x90\x48\x8D\x56\x38\x48\x8B\xCE", "x????xxxxxxxx" ); @@ -10954,7 +10976,7 @@ DWORD Inject(BOOL bIsExplorer) // 48 83 EC 28 41 B0 03 B2 01 PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\x48\x83\xEC\x28\x41\xB0\x03\xB2\x01", "xxxxxxxxx" ); @@ -10971,7 +10993,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\x4C\x89\x74\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\xE8\x00\x00\x00\x00\x8B", "xxxx??x??x?xxxxxx????x" ); @@ -10989,7 +11011,7 @@ DWORD Inject(BOOL bIsExplorer) // ^^^^^^^ PBYTE match = FindPattern( hTwinuiPcshell, - miTwinuiPcshell.lpBaseOfDll, + miTwinuiPcshell.SizeOfImage, "\x4C\x89\x74\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\xE8\x00\x00\x00\x00\x90", "xxxx??x??x?xxxxxx????x" );