Skip to content

Commit 48e1de3

Browse files
committed
Taskbar10: Apply vtable-based hooks to ep_taskbar (valinet#4097)
1 parent df7d604 commit 48e1de3

1 file changed

Lines changed: 103 additions & 88 deletions

File tree

ExplorerPatcher/dllmain.c

Lines changed: 103 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -948,18 +948,29 @@ interface ITaskGroup
948948
CONST_VTBL struct ITaskGroupVtbl* lpVtbl;
949949
};
950950

951-
HRESULT(*CTaskGroup_DoesWindowMatchFunc)(LONG_PTR* task_group, HWND hCompareWnd, ITEMIDLIST* pCompareItemIdList,
952-
WCHAR* pCompareAppId, int* pnMatch, LONG_PTR** p_task_item) = NULL;
953-
HRESULT __stdcall CTaskGroup_DoesWindowMatchHook(LONG_PTR* task_group, HWND hCompareWnd, ITEMIDLIST* pCompareItemIdList,
954-
WCHAR* pCompareAppId, int* pnMatch, LONG_PTR** p_task_item)
955-
{
956-
HRESULT hr = CTaskGroup_DoesWindowMatchFunc(task_group, hCompareWnd, pCompareItemIdList, pCompareAppId, pnMatch, p_task_item);
957-
BOOL bDontGroup = FALSE;
958-
BOOL bPinned = FALSE;
959-
if (bPinnedItemsActAsQuickLaunch && SUCCEEDED(hr) && *pnMatch >= 1 && *pnMatch <= 3) // itemlist or appid match
960-
{
961-
bDontGroup = FALSE;
962-
bPinned = (!task_group[4] || (int)((LONG_PTR*)task_group[4])[0] == 0);
951+
typedef enum tagWINDOWMATCHCONFIDENCE
952+
{
953+
WMC_None,
954+
WMC_MatchAppID,
955+
WMC_MatchShortcutIDListByAppID,
956+
WMC_MatchShortcutIDList,
957+
WMC_MatchWindow,
958+
} WINDOWMATCHCONFIDENCE;
959+
960+
HRESULT(STDMETHODCALLTYPE *CTaskGroup_DoesWindowMatchFunc)(ITaskGroup* pTaskGroup, HWND hCompareWnd, ITEMIDLIST* pCompareItemIdList,
961+
WCHAR* pCompareAppId, WINDOWMATCHCONFIDENCE* pnMatch, LONG_PTR** p_task_item) = NULL;
962+
HRESULT STDMETHODCALLTYPE CTaskGroup_DoesWindowMatchHook(ITaskGroup* pTaskGroup, HWND hCompareWnd, ITEMIDLIST* pCompareItemIdList,
963+
WCHAR* pCompareAppId, WINDOWMATCHCONFIDENCE* pnMatch, LONG_PTR** p_task_item)
964+
{
965+
wprintf(L"CTaskGroup_DoesWindowMatchHook called for hwnd 0x%p\n", hCompareWnd);
966+
HRESULT hr = CTaskGroup_DoesWindowMatchFunc(pTaskGroup, hCompareWnd, pCompareItemIdList, pCompareAppId, pnMatch, p_task_item);
967+
if (bPinnedItemsActAsQuickLaunch && SUCCEEDED(hr)
968+
&& (*pnMatch == WMC_MatchAppID || *pnMatch == WMC_MatchShortcutIDListByAppID || *pnMatch == WMC_MatchShortcutIDList))
969+
{
970+
BOOL bDontGroup = FALSE;
971+
PBYTE _this = (PBYTE)pTaskGroup - 16 /*sizeof(CTaskUnknown)*/;
972+
HDPA hdpaItems = *(HDPA*)(_this + 48 /*offsetof(CTaskGroup, m_hdpaItems)*/);
973+
BOOL bPinned = !hdpaItems || !DPA_GetPtrCount(hdpaItems);
963974
if (bPinned)
964975
{
965976
bDontGroup = TRUE;
@@ -1023,13 +1034,13 @@ typedef struct ITaskBtnGroupVtbl
10231034
HRESULT(STDMETHODCALLTYPE* CancelRemoveItem)(
10241035
ITaskBtnGroup* This);
10251036

1026-
LONG_PTR(STDMETHODCALLTYPE* GetIdealSpan)(
1037+
int(STDMETHODCALLTYPE* GetIdealSpan)(
10271038
ITaskBtnGroup* This,
1028-
LONG_PTR var2,
1029-
LONG_PTR var3,
1030-
LONG_PTR var4,
1031-
LONG_PTR var5,
1032-
LONG_PTR var6);
1039+
int var2,
1040+
int var3,
1041+
int var4,
1042+
int var5,
1043+
int var6);
10331044
// ...
10341045

10351046
END_INTERFACE
@@ -1040,60 +1051,104 @@ interface ITaskBtnGroup
10401051
CONST_VTBL struct ITaskBtnGroupVtbl* lpVtbl;
10411052
};
10421053

1043-
LONG_PTR (*CTaskBtnGroup_GetIdealSpanFunc)(ITaskBtnGroup* _this, LONG_PTR var2, LONG_PTR var3,
1044-
LONG_PTR var4, LONG_PTR var5, LONG_PTR var6) = NULL;
1045-
LONG_PTR __stdcall CTaskBtnGroup_GetIdealSpanHook(ITaskBtnGroup* _this, LONG_PTR var2, LONG_PTR var3,
1046-
LONG_PTR var4, LONG_PTR var5, LONG_PTR var6)
1054+
typedef enum eTBGROUPTYPE
1055+
{
1056+
TBGROUPTYPE_Unknown,
1057+
TBGROUPTYPE_Normal,
1058+
TBGROUPTYPE_Pinned,
1059+
TBGROUPTYPE_Stacked,
1060+
TBGROUPTYPE_Invisible,
1061+
} TBGROUPTYPE;
1062+
1063+
int (STDMETHODCALLTYPE *CTaskBtnGroup_GetIdealSpanFunc)(ITaskBtnGroup* pTaskBtnGroup, int var2, int var3,
1064+
int var4, int var5, int* var6) = NULL;
1065+
int STDMETHODCALLTYPE CTaskBtnGroup_GetIdealSpanHook(ITaskBtnGroup* pTaskBtnGroup, int var2, int var3,
1066+
int var4, int var5, int* var6)
10471067
{
1048-
LONG_PTR ret = NULL;
10491068
BOOL bTypeModified = FALSE;
1050-
int button_group_type = *(unsigned int*)((INT64)_this + 64);
1051-
if (bRemoveExtraGapAroundPinnedItems && button_group_type == 2)
1069+
PBYTE _this = (PBYTE)pTaskBtnGroup - 16 /*sizeof(CTaskUnknown)*/;
1070+
TBGROUPTYPE* pGroupType = (TBGROUPTYPE*)(_this + 80 /*offsetof(CTaskBtnGroup, m_groupType)*/);
1071+
TBGROUPTYPE lastGroupType = *pGroupType;
1072+
if (bRemoveExtraGapAroundPinnedItems && lastGroupType == TBGROUPTYPE_Pinned)
10521073
{
1053-
*(unsigned int*)((INT64)_this + 64) = 4;
1074+
*pGroupType = TBGROUPTYPE_Invisible;
10541075
bTypeModified = TRUE;
10551076
}
1056-
ret = CTaskBtnGroup_GetIdealSpanFunc(_this, var2, var3, var4, var5, var6);
1077+
int ret = CTaskBtnGroup_GetIdealSpanFunc(pTaskBtnGroup, var2, var3, var4, var5, var6);
10571078
if (bRemoveExtraGapAroundPinnedItems && bTypeModified)
10581079
{
1059-
*(unsigned int*)((INT64)_this + 64) = button_group_type;
1080+
*pGroupType = lastGroupType;
10601081
}
10611082
return ret;
10621083
}
10631084

1064-
HRESULT explorer_QISearch(void* that, LPCQITAB pqit, REFIID riid, void** ppv)
1085+
void Win10TaskbarHooks_ConditionalPatchITaskGroupVtbl(ITaskGroupVtbl* pVtbl)
10651086
{
1066-
HRESULT hr = QISearch(that, pqit, riid, ppv);
1067-
if (SUCCEEDED(hr) && IsEqualGUID(pqit[0].piid, &IID_ITaskGroup) && bPinnedItemsActAsQuickLaunch)
1087+
if (bPinnedItemsActAsQuickLaunch)
10681088
{
1069-
ITaskGroup* pTaskGroup = (char*)that + pqit[0].dwOffset;
10701089
DWORD flOldProtect = 0;
1071-
if (VirtualProtect(pTaskGroup->lpVtbl, sizeof(ITaskGroupVtbl), PAGE_EXECUTE_READWRITE, &flOldProtect))
1090+
if (VirtualProtect(pVtbl, sizeof(ITaskGroupVtbl), PAGE_EXECUTE_READWRITE, &flOldProtect))
10721091
{
10731092
if (!CTaskGroup_DoesWindowMatchFunc)
10741093
{
1075-
CTaskGroup_DoesWindowMatchFunc = pTaskGroup->lpVtbl->DoesWindowMatch;
1094+
CTaskGroup_DoesWindowMatchFunc = pVtbl->DoesWindowMatch;
10761095
}
1077-
pTaskGroup->lpVtbl->DoesWindowMatch = CTaskGroup_DoesWindowMatchHook;
1078-
VirtualProtect(pTaskGroup->lpVtbl, sizeof(ITaskGroupVtbl), flOldProtect, &flOldProtect);
1096+
pVtbl->DoesWindowMatch = CTaskGroup_DoesWindowMatchHook;
1097+
VirtualProtect(pVtbl, sizeof(ITaskGroupVtbl), flOldProtect, &flOldProtect);
10791098
}
10801099
}
1081-
else if (SUCCEEDED(hr) && IsEqualGUID(pqit[0].piid, &IID_ITaskBtnGroup) && bRemoveExtraGapAroundPinnedItems)
1100+
}
1101+
1102+
void Win10TaskbarHooks_ConditionalPatchITaskBtnGroupVtbl(ITaskBtnGroupVtbl* pVtbl)
1103+
{
1104+
if (bRemoveExtraGapAroundPinnedItems)
10821105
{
1083-
ITaskBtnGroup* pTaskBtnGroup = (char*)that + pqit[0].dwOffset;
10841106
DWORD flOldProtect = 0;
1085-
if (VirtualProtect(pTaskBtnGroup->lpVtbl, sizeof(ITaskBtnGroupVtbl), PAGE_EXECUTE_READWRITE, &flOldProtect))
1107+
if (VirtualProtect(pVtbl, sizeof(ITaskBtnGroupVtbl), PAGE_EXECUTE_READWRITE, &flOldProtect))
10861108
{
10871109
if (!CTaskBtnGroup_GetIdealSpanFunc)
10881110
{
1089-
CTaskBtnGroup_GetIdealSpanFunc = pTaskBtnGroup->lpVtbl->GetIdealSpan;
1111+
CTaskBtnGroup_GetIdealSpanFunc = pVtbl->GetIdealSpan;
10901112
}
1091-
pTaskBtnGroup->lpVtbl->GetIdealSpan = CTaskBtnGroup_GetIdealSpanHook;
1092-
VirtualProtect(pTaskBtnGroup->lpVtbl, sizeof(ITaskBtnGroupVtbl), flOldProtect, &flOldProtect);
1113+
pVtbl->GetIdealSpan = CTaskBtnGroup_GetIdealSpanHook;
1114+
VirtualProtect(pVtbl, sizeof(ITaskBtnGroupVtbl), flOldProtect, &flOldProtect);
1115+
}
1116+
}
1117+
}
1118+
1119+
HRESULT explorer_QISearch(void* that, LPCQITAB pqit, REFIID riid, void** ppv)
1120+
{
1121+
HRESULT hr = QISearch(that, pqit, riid, ppv);
1122+
if (SUCCEEDED(hr))
1123+
{
1124+
if (IsEqualGUID(pqit[0].piid, &IID_ITaskGroup))
1125+
{
1126+
ITaskGroup* pTaskGroup = (char*)that + pqit[0].dwOffset;
1127+
Win10TaskbarHooks_ConditionalPatchITaskGroupVtbl(pTaskGroup->lpVtbl);
1128+
}
1129+
else if (IsEqualGUID(pqit[0].piid, &IID_ITaskBtnGroup))
1130+
{
1131+
ITaskBtnGroup* pTaskBtnGroup = (char*)that + pqit[0].dwOffset;
1132+
Win10TaskbarHooks_ConditionalPatchITaskBtnGroupVtbl(pTaskBtnGroup->lpVtbl);
10931133
}
10941134
}
10951135
return hr;
10961136
}
1137+
1138+
void Win10TaskbarHooks_PatchEPTaskbarVtables(HMODULE hModule)
1139+
{
1140+
ITaskGroupVtbl* pTaskGroupVtbl = (ITaskGroupVtbl*)GetProcAddress(hModule, "??_7CTaskGroup@@6BITaskGroup@@@");
1141+
if (pTaskGroupVtbl)
1142+
{
1143+
Win10TaskbarHooks_ConditionalPatchITaskGroupVtbl(pTaskGroupVtbl);
1144+
}
1145+
1146+
ITaskBtnGroupVtbl* pTaskBtnGroupVtbl = (ITaskBtnGroupVtbl*)GetProcAddress(hModule, "??_7CTaskBtnGroup@@6BITaskBtnGroup@@@");
1147+
if (pTaskBtnGroupVtbl)
1148+
{
1149+
Win10TaskbarHooks_ConditionalPatchITaskBtnGroupVtbl(pTaskBtnGroupVtbl);
1150+
}
1151+
}
10971152
#endif
10981153
#pragma endregion
10991154

@@ -8389,12 +8444,6 @@ __declspec(dllexport) HRESULT explorer_CoCreateInstanceHook(REFCLSID rclsid, LPU
83898444
}
83908445
return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv);
83918446
}
8392-
8393-
bool(*DisableWin10TaskbarIsEnabledFunc)(void* _this);
8394-
bool DisableWin10TaskbarIsEnabledHook(void* _this)
8395-
{
8396-
return false;
8397-
}
83988447
#endif
83998448
#pragma endregion
84008449

@@ -10823,45 +10872,6 @@ DWORD Inject(BOOL bIsExplorer)
1082310872
if (IsWindows11Version22H2OrHigher())
1082410873
{
1082510874
TryToFindExplorerOffsets(hExplorer, &miExplorer, symbols_PTRS.explorer_PTRS);
10826-
10827-
#if 0
10828-
if (global_rovi.dwBuildNumber >= 26002)
10829-
{
10830-
#if defined(_M_X64)
10831-
// Please Microsoft 🙏
10832-
// 48 8B ?? 78 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 0F 85
10833-
// ^^^^^^^^^^^
10834-
// 26040.1000: C28AE
10835-
// 26052.1000: BF052
10836-
// 26058.1000: BEFA2
10837-
// 26080.1 : 11795C
10838-
PBYTE match = FindPattern(
10839-
hExplorer,
10840-
miExplorer.SizeOfImage,
10841-
"\x48\x8B\x00\x78\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x84\xC0\x0F\x85",
10842-
"xx?xxxx????x????xxxx"
10843-
);
10844-
if (match)
10845-
{
10846-
match += 11;
10847-
match += 5 + *(int*)(match + 1);
10848-
}
10849-
#elif defined(_M_ARM64)
10850-
PBYTE match = NULL;
10851-
#endif
10852-
if (match)
10853-
{
10854-
DisableWin10TaskbarIsEnabledFunc = match;
10855-
printf("wil::details::FeatureImpl<__WilFeatureTraits_Feature_DisableWin10Taskbar>::__private_IsEnabled() = %llX\n", match - (PBYTE)hExplorer);
10856-
10857-
funchook_prepare(
10858-
funchook,
10859-
(void**)&DisableWin10TaskbarIsEnabledFunc,
10860-
DisableWin10TaskbarIsEnabledHook
10861-
);
10862-
}
10863-
}
10864-
#endif
1086510875
}
1086610876

1086710877
const WCHAR* pszTaskbarDll = GetTaskbarDllChecked(&symbols_PTRS);
@@ -10883,7 +10893,10 @@ DWORD Inject(BOOL bIsExplorer)
1088310893
VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegCreateKeyExW", explorer_RegCreateKeyExW);
1088410894
VnPatchIAT(hExplorer, "API-MS-WIN-SHCORE-REGISTRY-L1-1-0.DLL", "SHGetValueW", explorer_SHGetValueW);
1088510895
VnPatchIAT(hExplorer, "user32.dll", "LoadMenuW", explorer_LoadMenuW);
10886-
VnPatchIAT(hExplorer, "api-ms-win-core-shlwapi-obsolete-l1-1-0.dll", "QISearch", explorer_QISearch);
10896+
if (bOldTaskbar == 1)
10897+
{
10898+
VnPatchIAT(hExplorer, "api-ms-win-core-shlwapi-obsolete-l1-1-0.dll", "QISearch", explorer_QISearch);
10899+
}
1088710900
if (IsOS(OS_ANYSERVER)) VnPatchIAT(hExplorer, "api-ms-win-shcore-sysinfo-l1-1-0.dll", "IsOS", explorer_IsOS);
1088810901
if (IsWindows11Version22H2OrHigher()) VnPatchDelayIAT(hExplorer, "ext-ms-win-rtcore-ntuser-window-ext-l1-1-0.dll", "CreateWindowExW", Windows11v22H2_explorer_CreateWindowExW);
1088910902
}
@@ -11078,6 +11091,8 @@ DWORD Inject(BOOL bIsExplorer)
1107811091
VnPatchIAT(hMyTaskbar, "user32.dll", MAKEINTRESOURCEA(2005), explorer_SetChildWindowNoActivateHook);
1107911092

1108011093
VnPatchIAT(hMyTaskbar, "uxtheme.dll", MAKEINTRESOURCEA(126), PeopleBand_DrawTextWithGlowHook);
11094+
11095+
Win10TaskbarHooks_PatchEPTaskbarVtables(hMyTaskbar);
1108111096
}
1108211097

1108311098
HANDLE hCombase = LoadLibraryW(L"combase.dll");

0 commit comments

Comments
 (0)