diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72400451c..79070fbb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
This document includes the same release notes as in the [Releases](https://github.com/valinet/ExplorerPatcher/releases) section on GitHub.
+## 22621.2428.59
+
+Tested on OS builds 22000.2416, 22621.2428, 23555.1000, and 23560.1000.
+
+#### Details
+
+##### 1
+
+* Taskbar10: Fixed Control Center and Toast Center positioning on build 25951 (Canary). (dca0b3a)
+* Taskbar10: Fixed start menu position when the taskbar is at the left or right side on Moment 4 builds. (a57471f)
+* Taskbar10: Fixed the Windows 10 taskbar background patch to not crash anymore on build 25951 (Canary). (b52bd79)
+* Taskbar10: Made taskbar fonts (when using classic theme mitigations) more accurate (thanks @aubymori). (8fc53a1)
+* Start10: Fixed a bug where certain texts in the Windows 10 Start menu stayed in English. (c6a7d3f, ed251e9)
+* Start10: Properly fixed start menu showing/hiding along with its original animations on builds 22000.65+. (7e2f768)
+* GUI: Fixed a bug where "Remember last used section" doesn't remember the current page after being enabled. (dcf72bb)
+* Symbols: Reworked how symbols are managed so that symbols don't need to be successfully downloaded in succession. (8412bd6)
+
## 22621.2361.58
Tested on OS builds 22000.2416, 22621.1, 22621.2134, 22621.2361, 22631.2338, and 23545.1000.
diff --git a/ExplorerPatcher/ExplorerPatcher.rc b/ExplorerPatcher/ExplorerPatcher.rc
index 1e1f3a878..3e006d955 100644
Binary files a/ExplorerPatcher/ExplorerPatcher.rc and b/ExplorerPatcher/ExplorerPatcher.rc differ
diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj
index 694321193..b8c1b5bd2 100644
--- a/ExplorerPatcher/ExplorerPatcher.vcxproj
+++ b/ExplorerPatcher/ExplorerPatcher.vcxproj
@@ -96,7 +96,7 @@
true
true
true
- NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ NDEBUG;_CONSOLE;WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions)
true
$(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\Detours\include;%(AdditionalIncludeDirectories)
MultiThreaded
@@ -126,7 +126,7 @@
true
true
true
- NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ NDEBUG;_CONSOLE;WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions)
true
$(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;$(SolutionDir)libs\funchook\distorm\include;$(SolutionDir)libs\Detours\include;%(AdditionalIncludeDirectories)
MultiThreaded
diff --git a/ExplorerPatcher/GUI.c b/ExplorerPatcher/GUI.c
index a3a48be91..c6f8045b5 100644
--- a/ExplorerPatcher/GUI.c
+++ b/ExplorerPatcher/GUI.c
@@ -1624,7 +1624,7 @@ static BOOL GUI_Build(HDC hDC, HWND hwnd, POINT pt)
}
else
{
- BeginExplorerRestart();
+ BeginExplorerRestart(NULL);
}
}
Sleep(100);
diff --git a/ExplorerPatcher/RefreshedStyles.xbf b/ExplorerPatcher/RefreshedStyles.xbf
new file mode 100644
index 000000000..68f84fcf4
Binary files /dev/null and b/ExplorerPatcher/RefreshedStyles.xbf differ
diff --git a/ExplorerPatcher/StartMenuSettings.cpp b/ExplorerPatcher/StartMenuSettings.cpp
index b0866a8f8..94cda734c 100644
--- a/ExplorerPatcher/StartMenuSettings.cpp
+++ b/ExplorerPatcher/StartMenuSettings.cpp
@@ -26,7 +26,7 @@ static std::vector GlobalStartData_GetPlacesFromRegistry()
std::vector places;
DWORD dwSize;
- HRESULT hr = RegGetValueW(
+ LSTATUS lRes = RegGetValueW(
HKEY_CURRENT_USER,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Start",
L"VisiblePlaces",
@@ -35,11 +35,11 @@ static std::vector GlobalStartData_GetPlacesFromRegistry()
nullptr,
&dwSize
);
- if (FAILED(hr) || dwSize == 0)
+ if (lRes != ERROR_SUCCESS || dwSize == 0)
return places;
places.resize(dwSize / sizeof(winrt::guid));
- hr = RegGetValueW(
+ lRes = RegGetValueW(
HKEY_CURRENT_USER,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Start",
L"VisiblePlaces",
@@ -48,7 +48,7 @@ static std::vector GlobalStartData_GetPlacesFromRegistry()
places.data(),
&dwSize
);
- if (FAILED(hr))
+ if (lRes != ERROR_SUCCESS)
places.clear();
return places;
diff --git a/ExplorerPatcher/def.h b/ExplorerPatcher/def.h
index 3b1d683ea..ba61dc290 100644
--- a/ExplorerPatcher/def.h
+++ b/ExplorerPatcher/def.h
@@ -1,8 +1,8 @@
#ifndef _H_DEF_H_
#define _H_DEF_H_
#define APPID L"Microsoft.Windows.Explorer"
-#define REGPATH "SOFTWARE\\ExplorerPatcher"
-#define REGPATH_OLD "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ExplorerPatcher"
+#define REGPATH "Software\\ExplorerPatcher"
+#define REGPATH_OLD "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ExplorerPatcher"
#define REGPATH_STARTMENU REGPATH_OLD
#define SPECIAL_FOLDER CSIDL_PROGRAM_FILES
#define SPECIAL_FOLDER_LEGACY CSIDL_APPDATA
diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c
index 3076329c6..d9e963c6f 100644
--- a/ExplorerPatcher/dllmain.c
+++ b/ExplorerPatcher/dllmain.c
@@ -4296,6 +4296,7 @@ INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHo
#pragma region "Enable old taskbar"
#ifdef _WIN64
+HRESULT(*explorer_RoGetActivationFactoryFunc)(HSTRING activatableClassId, GUID* iid, void** factory);
HRESULT explorer_RoGetActivationFactoryHook(HSTRING activatableClassId, GUID* iid, void** factory)
{
PCWSTR StringRawBuffer = WindowsGetStringRawBuffer(activatableClassId, 0);
@@ -4312,7 +4313,7 @@ HRESULT explorer_RoGetActivationFactoryHook(HSTRING activatableClassId, GUID* ii
return S_OK;
}
}
- return RoGetActivationFactory(activatableClassId, iid, factory);
+ return explorer_RoGetActivationFactoryFunc(activatableClassId, iid, factory);
}
FARPROC explorer_GetProcAddressHook(HMODULE hModule, const CHAR* lpProcName)
@@ -8062,27 +8063,15 @@ HRESULT explorer_DrawThemeTextEx(
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &ncm, 0);
HFONT hFont = NULL;
- if (bIsActiveUnhovered)
+ if (bIsActiveUnhovered || bIsActiveHovered)
{
- hFont = CreateFontIndirectW(&(ncm.lfCaptionFont));
- }
- else if (bIsInactiveUnhovered)
- {
- hFont = CreateFontIndirectW(&(ncm.lfMenuFont));
- }
- else if (bIsActiveHovered)
- {
- hFont = CreateFontIndirectW(&(ncm.lfCaptionFont));
- }
- else if (bIsInactiveHovered)
- {
- hFont = CreateFontIndirectW(&(ncm.lfMenuFont));
+ ncm.lfCaptionFont.lfWeight = FW_BOLD;
}
else
{
- hFont = CreateFontIndirectW(&(ncm.lfMenuFont));
- //wprintf(L"DrawThemeTextEx %d %d %s\n", iPartId, iStateId, pszText);
+ ncm.lfCaptionFont.lfWeight = FW_NORMAL;
}
+ hFont = CreateFontIndirectW(&(ncm.lfCaptionFont));
if (iPartId == 5 && iStateId == 0) // clock
{
@@ -9693,6 +9682,15 @@ int RtlQueryFeatureConfigurationHook(UINT32 featureId, int sectionType, INT64* c
break;
}
#endif
+ case 44656322: // ID44656322
+ {
+ if (bOldTaskbar)
+ {
+ // Fixes start menu positioning when the taskbar is at the left or right side
+ buffer->enabledState = FEATURE_ENABLED_STATE_DISABLED;
+ }
+ break;
+ }
}
return rv;
}
@@ -10446,7 +10444,10 @@ BOOL explorer_IsOS(DWORD dwOS)
void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
{
// We read from the file instead of from memory because other tweak software might've modified the functions we're looking for
- HANDLE hFile = CreateFileW(L"twinui.pcshell.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ WCHAR wszPath[MAX_PATH];
+ GetSystemDirectoryW(wszPath, MAX_PATH);
+ wcscat_s(wszPath, MAX_PATH, L"\\twinui.pcshell.dll");
+ HANDLE hFile = CreateFileW(wszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Failed to open twinui.pcshell.dll\n");
@@ -10647,7 +10648,7 @@ static void PatchAppResolver()
if (match)
{
match += 5;
- match = match + 5 + *(int*)(match + 1);
+ match += 5 + *(int*)(match + 1);
AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc = match;
printf("CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart() = %llX\n", match - (PBYTE)hAppResolver);
}
@@ -10677,6 +10678,381 @@ static void PatchStartTileData()
#pragma endregion
+#pragma region "Fix Windows 10 start menu animation on 22000.65+"
+#ifdef _WIN64
+static struct
+{
+ int startExperienceManager_singleViewShellExperience;
+ int startExperienceManager_singleViewShellExperienceEventHandler;
+ int startExperienceManager_openingAnimation;
+ int startExperienceManager_closingAnimation;
+ int startExperienceManager_bMaybeFullScreenMode;
+} g_SMAnimationPatchOffsets;
+
+enum EDGEUI_TRAYSTUCKPLACE {};
+enum DWMTRANSITION_TARGET {};
+
+HRESULT(*CStartExperienceManager_GetMonitorInformationFunc)(void* _this, void* experience, RECT* a3, enum EDGEUI_TRAYSTUCKPLACE* pTsp, bool* a5, RECT* a6, HMONITOR* a7);
+HRESULT(*CExperienceManagerAnimationHelper_BeginFunc)(void* _this, void*, enum DWMTRANSITION_TARGET, const RECT*, const RECT*, const RECT*, const RECT*, const RECT*);
+HRESULT(*CExperienceManagerAnimationHelper_EndFunc)(void* _this);
+
+HRESULT(*OnViewCloakingFunc)(void* eventHandler, void* experience);
+HRESULT OnViewCloakingHook(void* eventHandler, void* experience)
+{
+ PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperienceEventHandler;
+ bool bMaybeFullScreenMode = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bMaybeFullScreenMode);
+ if (bMaybeFullScreenMode)
+ return S_OK;
+
+ RECT rc;
+ enum EDGEUI_TRAYSTUCKPLACE tsp;
+ bool bUnknown;
+ RECT rc2;
+ HMONITOR hMonitor;
+ HRESULT hr = CStartExperienceManager_GetMonitorInformationFunc(_this, experience, &rc, &tsp, &bUnknown, &rc2, &hMonitor);
+ if (FAILED(hr))
+ return hr;
+
+ enum DWMTRANSITION_TARGET target = 0x51;
+ if (*(bool*)((PBYTE)experience + 0x34))
+ target = 0x52;
+ else if (tsp == 0)
+ target = 0x4D;
+ else if (tsp == 1)
+ target = 0x4F;
+ else if (tsp == 2)
+ target = 0x4E;
+ else if (tsp == 3)
+ target = 0x50;
+
+ hr = CExperienceManagerAnimationHelper_BeginFunc(
+ _this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation,
+ *(void**)((PBYTE)experience + 0x18), // viewWrapper
+ target | 0x200000u, NULL, NULL, NULL, NULL, &rc);
+
+ return hr;
+}
+
+// Note: `void* experience` is never valid because the compiler optimized out the argument passing. At least on 22621.1992
+HRESULT CStartExperienceManager_GetMonitorInformationHook(void* _this, void* experience, RECT* a3, enum EDGEUI_TRAYSTUCKPLACE* pTsp, bool* a5, RECT* a6, HMONITOR* a7)
+{
+ HRESULT hr = CStartExperienceManager_GetMonitorInformationFunc(_this, experience, a3, pTsp, a5, a6, a7);
+ // We add code to OnViewUncloaking through this function
+ if (SUCCEEDED(hr) && *(PBYTE)_ReturnAddress() == 0x85 && *((PBYTE)_ReturnAddress() + 1) == 0xC0 && *((PBYTE)_ReturnAddress() + 2) == 0x78)
+ {
+ experience = (PBYTE)_this + g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience;
+ enum DWMTRANSITION_TARGET target = 0x51;
+ if (*(bool*)((PBYTE)experience + 0x34))
+ target = 0x52;
+ else if (*pTsp == 0)
+ target = 0x4E;
+ else if (*pTsp == 1)
+ target = 0x50;
+ else if (*pTsp == 2)
+ target = 0x4D;
+ else if (*pTsp == 3)
+ target = 0x4F;
+ CExperienceManagerAnimationHelper_BeginFunc(
+ (PBYTE)_this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation,
+ *(void**)((PBYTE)experience + 0x18), // viewWrapper
+ target | 0x200000u, NULL, NULL, NULL, NULL, a3);
+ return E_FAIL; // Don't invoke ReportUsage() called in OnViewUncloaking
+ }
+ return hr;
+}
+
+HRESULT(*OnViewUncloakingFunc)(void* eventHandler, void* experience);
+
+HRESULT(*OnViewUncloakedFunc)(void* eventHandler, void* experience);
+HRESULT OnViewUncloakedHook(void* eventHandler, void* experience)
+{
+ PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperienceEventHandler;
+ CExperienceManagerAnimationHelper_EndFunc(_this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation);
+ return S_OK;
+}
+
+BOOL FixStartMenuAnimation(LPMODULEINFO mi)
+{
+ // The idea here is to re-add the code that got removed in 22000.65+. We can see that "STest03" is the feature flag
+ // that experiments with the new start menu. So, because in 22000.51 one can enable the old start menu with proper
+ // behavior by setting the Start_ShowClassicMode registry value to 1, and there is a convenient function called
+ // `StartDocked::ShouldUseStartDocked()`, we crosscheck the removed code and piece together a patch for proper
+ // animations on 22000.65+.
+
+ // ### Offset of SingleViewShellExperience instance and its event handler
+ // ```
+ // 48 8D 8E ?? ?? ?? ?? 44 8D 45 ?? 48 8D 56 ?? E8
+ // ^^^^^^^^^^^ SVSE ^^ SVSEEH
+ // ```
+ // Ref: CStartExperienceManager::CStartExperienceManager()
+ PBYTE match1 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x48\x8D\x8E\x00\x00\x00\x00\x44\x8D\x45\x00\x48\x8D\x56\x00\xE8",
+ "xxx????xxx?xxx?x"
+ );
+ if (match1)
+ {
+ g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience = *(int*)(match1 + 3);
+ g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperienceEventHandler = (int)*(char*)(match1 + 14);
+ printf("[SMA] match1 = %llX\n", match1 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### Offsets of Animation Helpers
+ // ```
+ // 40 88 AE ?? ?? ?? ?? C7 86 ?? ?? ?? ?? 38 00 00 00
+ // ^^^^^^^^^^^ AH1
+ // ```
+ // Ref: CStartExperienceManager::CStartExperienceManager()
+ // AH2 is located right after AH1. AH is 32 bytes
+ PBYTE match2 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x40\x88\xAE\x00\x00\x00\x00\xC7\x86\x00\x00\x00\x00\x38\x00\x00\x00",
+ "xxx????xx????xxxx"
+ );
+ if (match2)
+ {
+ g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation = *(int*)(match2 + 3);
+ g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation = g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation + 32;
+ printf("[SMA] match2 = %llX\n", match2 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### Offset of bMaybeFullScreenMode
+ // ```
+ // 80 B9 ?? ?? ?? ?? 00 0F 85 ?? ?? ?? ?? 45 33 C0 B2 01
+ // ^^^^^^^^^^^ bMaybeFullScreenMode
+ // ```
+ // Ref: CStartExperienceManager::OnViewHidden()
+ // TODO Broke on 25951 Canary
+ PBYTE match3 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x80\xB9\x00\x00\x00\x00\x00\x0F\x85\x00\x00\x00\x00\x45\x33\xC0\xB2\x01",
+ "xx????xxx????xxxxx"
+ );
+ if (match3)
+ {
+ g_SMAnimationPatchOffsets.startExperienceManager_bMaybeFullScreenMode = g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperienceEventHandler + *(int*)(match3 + 2);
+ printf("[SMA] match3 = %llX\n", match3 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### Offset of CStartExperienceManager::GetMonitorInformation()
+ // ```
+ // E8 ?? ?? ?? ?? 8B ?? 85 C0 0F 88 ?? ?? ?? ?? C6 44 24
+ // ^^^^^^^^^^^
+ // ```
+ // Ref: CStartExperienceManager::PositionMenu()
+ PBYTE match4 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\xE8\x00\x00\x00\x00\x8B\x00\x85\xC0\x0F\x88\x00\x00\x00\x00\xC6\x44\x24",
+ "x????x?xxxx????xxx"
+ );
+ if (match4)
+ {
+ match4 += 5 + *(int*)(match4 + 1);
+ CStartExperienceManager_GetMonitorInformationFunc = match4;
+ printf("[SMA] CStartExperienceManager::GetMonitorInformation() = %llX\n", match4 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### Offset of CExperienceManagerAnimationHelper::Begin()
+ // ```
+ // 44 8B C7 E8 ?? ?? ?? ?? 85 C0 79 19
+ // ^^^^^^^^^^^
+ // ```
+ // Ref: CJumpViewExperienceManager::OnViewUncloaking()
+ PBYTE match5 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x44\x8B\xC7\xE8\x00\x00\x00\x00\x85\xC0\x79\x19",
+ "xxxx????xxxx"
+ );
+ if (match5)
+ {
+ match5 += 3;
+ match5 += 5 + *(int*)(match5 + 1);
+ CExperienceManagerAnimationHelper_BeginFunc = match5;
+ printf("[SMA] CExperienceManagerAnimationHelper::Begin() = %llX\n", match5 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### Offset of CExperienceManagerAnimationHelper::End()
+ // ```
+ // 40 53 48 83 EC 20 80 39 00 74
+ // ```
+ PBYTE match6 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x40\x53\x48\x83\xEC\x20\x80\x39\x00\x74",
+ "xxxxxxxxxx"
+ );
+ if (match6)
+ {
+ CExperienceManagerAnimationHelper_EndFunc = match6;
+ printf("[SMA] CExperienceManagerAnimationHelper::End() = %llX\n", match6 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### CStartExperienceManager::Hide()
+ // ```
+ // 74 ?? ?? 03 00 00 00 44 88
+ // ^^ Turn jz into jmp
+ // ```
+ // Perform on exactly two matches
+ PBYTE match7a = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x74\x00\x00\x03\x00\x00\x00\x44\x88",
+ "x??xxxxxx"
+ );
+ PBYTE match7b = NULL;
+ if (match7a)
+ {
+ printf("[SMA] match7a in CStartExperienceManager::Hide() = %llX\n", match7a - (PBYTE)mi->lpBaseOfDll);
+ match7b = FindPattern(
+ match7a + 14,
+ mi->SizeOfImage - (match7a + 14 - (PBYTE)mi->lpBaseOfDll),
+ "\x74\x00\x00\x03\x00\x00\x00\x44\x88",
+ "x??xxxxxx"
+ );
+ if (match7b)
+ {
+ printf("[SMA] match7b in CStartExperienceManager::Hide() = %llX\n", match7b - (PBYTE)mi->lpBaseOfDll);
+ }
+ }
+
+ // ### CStartExperienceManager::OnViewCloaking()
+ // ```
+ // 48 83 EC 28 80 B9 ?? ?? ?? ?? 00 75 ?? 45 33 C0
+ // ```
+ // Just hook
+ // TODO: Broke on 25951 Canary
+ PBYTE match8 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x48\x83\xEC\x28\x80\xB9\x00\x00\x00\x00\x00\x75\x00\x45\x33\xC0",
+ "xxxxxx????xx?xxx"
+ );
+ if (match8)
+ {
+ OnViewCloakingFunc = match8;
+ printf("[SMA] CStartExperienceManager::OnViewCloaking() = %llX\n", match8 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### CStartExperienceManager::OnViewHidden()
+ // ```
+ // 80 B9 ?? ?? ?? ?? 00 0F 85 ?? ?? ?? ?? 45 33 C0 B2 01
+ // ^^ Start overwriting here. 17 bytes, rest NOP
+ // ```
+ // TODO Broke on 25951 Canary
+ PBYTE match9 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x80\xB9\x00\x00\x00\x00\x00\x0F\x85\x00\x00\x00\x00\x45\x33\xC0\xB2\x01",
+ "xx????xxx????xxxxx"
+ );
+ if (match9)
+ {
+ printf("[SMA] match9 in CStartExperienceManager::OnViewHidden() = %llX\n", match9 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ // ### CStartExperienceManager::OnViewUncloaked()
+ // ```
+ // 48 83 EC 28 45 33 C0 48 8D 0D ?? ?? ?? ?? B2 01 E8 ?? ?? ?? ?? 33 C0
+ // ```
+ // Just hook
+ // TODO: Broke on 25951 Canary
+ PBYTE match10 = FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x48\x83\xEC\x28\x45\x33\xC0\x48\x8D\x0D\x00\x00\x00\x00\xB2\x01\xE8\x00\x00\x00\x00\x33\xC0",
+ "xxxxxxxxxx????xxx????xx"
+ );
+ if (match10)
+ {
+ OnViewUncloakedFunc = match10;
+ printf("[SMA] CStartExperienceManager::OnViewUncloaked() = %llX\n", match10 - (PBYTE)mi->lpBaseOfDll);
+ }
+
+ if (!match1 || !match2 || !match3 || !match4 || !match5 || !match6 || !match7a || !match7b || !match8 || !match9 || !match10)
+ {
+ printf("[SMA] Not all offsets were found, cannot perform patch\n");
+ return FALSE;
+ }
+
+ int rv = funchook_prepare(
+ funchook,
+ (void**)&CStartExperienceManager_GetMonitorInformationFunc,
+ CStartExperienceManager_GetMonitorInformationHook
+ );
+ if (rv != 0)
+ {
+ printf("Failed to hook CStartExperienceManager::GetMonitorInformation(). rv = %d\n", rv);
+ }
+
+ DWORD dwOldProtect = 0;
+ if (VirtualProtect(match7a + 11, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect))
+ {
+ match7a[0] = 0xEB;
+ VirtualProtect(match7a + 11, 1, dwOldProtect, &dwOldProtect);
+
+ dwOldProtect = 0;
+ if (VirtualProtect(match7b + 11, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect))
+ {
+ match7b[0] = 0xEB;
+ VirtualProtect(match7b + 11, 1, dwOldProtect, &dwOldProtect);
+ }
+ }
+
+ rv = funchook_prepare(
+ funchook,
+ (void**)&OnViewCloakingFunc,
+ OnViewCloakingHook
+ );
+ if (rv != 0)
+ {
+ printf("Failed to hook CStartExperienceManager::OnViewCloaking(). rv = %d\n", rv);
+ }
+
+ PBYTE begin = match9 + 13;
+ PBYTE end = begin + 17;
+
+ // Craft the code to call End()
+ BYTE code[] = {
+ // lea rcx, [rbx+] ; rbx is the `this`, offset to closingAnimation
+ 0x48, 0x8D, 0x8B, 0x11, 0x11, 0x11, 0x11,
+ // call CExperienceManagerAnimationHelper::End
+ 0xE8, 0x22, 0x22, 0x22, 0x22,
+ };
+
+ *(int*)(code + 3) = -g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperienceEventHandler + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation;
+ *(int*)(code + 8) = (int)((PBYTE)CExperienceManagerAnimationHelper_EndFunc - (begin + sizeof(code)));
+
+ PBYTE nopBegin = begin + sizeof(code);
+
+ dwOldProtect = 0;
+ if (VirtualProtect(begin, end - begin, PAGE_EXECUTE_READWRITE, &dwOldProtect))
+ {
+ memcpy(begin, code, sizeof(code));
+ memset(nopBegin, 0x90, end - nopBegin);
+ VirtualProtect(begin, end - begin, dwOldProtect, &dwOldProtect);
+ }
+
+ rv = funchook_prepare(
+ funchook,
+ (void**)&OnViewUncloakedFunc,
+ OnViewUncloakedHook
+ );
+ if (rv != 0)
+ {
+ printf("Failed to hook CStartExperienceManager::OnViewUncloaked(). rv = %d\n", rv);
+ }
+
+ return TRUE;
+}
+#endif
+#pragma endregion
+
+
DWORD Inject(BOOL bIsExplorer)
{
#if defined(DEBUG) | defined(_DEBUG)
@@ -11009,7 +11385,9 @@ DWORD Inject(BOOL bIsExplorer)
{
VnPatchIAT(hExplorer, "user32.dll", (LPCSTR)2005, explorer_SetChildWindowNoActivateHook);
VnPatchDelayIAT(hExplorer, "ext-ms-win-rtcore-ntuser-window-ext-l1-1-0.dll", "SendMessageW", explorer_SendMessageW);
- VnPatchIAT(hExplorer, "api-ms-win-core-libraryloader-l1-2-0.dll", "GetProcAddress", explorer_GetProcAddressHook);
+ // A certain configuration update in 23560.1000 broke this method, this didn't get called with
+ // "RoGetActivationFactory" anymore. We're now hooking RoGetActivationFactory directly.
+ // VnPatchIAT(hExplorer, "api-ms-win-core-libraryloader-l1-2-0.dll", "GetProcAddress", explorer_GetProcAddressHook);
VnPatchIAT(hExplorer, "shell32.dll", "ShellExecuteW", explorer_ShellExecuteW);
VnPatchIAT(hExplorer, "shell32.dll", "ShellExecuteExW", explorer_ShellExecuteExW);
VnPatchIAT(hExplorer, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegGetValueW", explorer_RegGetValueW);
@@ -11315,17 +11693,53 @@ DWORD Inject(BOOL bIsExplorer)
printf("Failed to hook PenMenuSystemTrayManager::GetDynamicSystemTrayHeightForMonitor(). rv = %d\n", rv);
}
}
+
+ if ((global_rovi.dwBuildNumber > 22000 || global_rovi.dwBuildNumber == 22000 && global_ubr >= 65) // Allow on 22000.65+
+ && global_rovi.dwBuildNumber < 25000 // But not on 25xxx (yet)
+ && dwStartShowClassicMode)
+ {
+ // Make sure crash counter is enabled. If one of the patches make Explorer crash while the start menu is open,
+ // we don't want to softlock the user. The system reopens the start menu if Explorer terminates while it's open.
+ DWORD crashCounterDisabled = 0, dwTCSize = sizeof(DWORD);
+ RegGetValueW(HKEY_CURRENT_USER, _T(REGPATH), L"CrashCounterDisabled", RRF_RT_DWORD, NULL, &crashCounterDisabled, &dwTCSize); dwTCSize = sizeof(DWORD);
+ if (crashCounterDisabled != 0 && crashCounterDisabled != 1) crashCounterDisabled = 0;
+
+ if (!crashCounterDisabled)
+ {
+ FixStartMenuAnimation(&miTwinuiPcshell);
+ }
+ }
#endif
VnPatchIAT(hTwinuiPcshell, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegGetValueW", twinuipcshell_RegGetValueW);
printf("Setup twinui.pcshell functions done\n");
- if (IsWindows11Version22H2OrHigher())
+ if (IsWindows11())
{
HANDLE hCombase = LoadLibraryW(L"combase.dll");
- // Fixed a bug that crashed Explorer when a folder window was opened after a first one was closed on OS builds 22621+
- VnPatchIAT(hCombase, "api-ms-win-core-libraryloader-l1-2-0.dll", "LoadLibraryExW", Windows11v22H2_combase_LoadLibraryExW);
+ if (bOldTaskbar)
+ {
+ // Hook RoGetActivationFactory() for old taskbar
+ explorer_RoGetActivationFactoryFunc = GetProcAddress(hCombase, "RoGetActivationFactory");
+ if (explorer_RoGetActivationFactoryFunc)
+ {
+ rv = funchook_prepare(
+ funchook,
+ (void**)&explorer_RoGetActivationFactoryFunc,
+ explorer_RoGetActivationFactoryHook
+ );
+ }
+ if (rv != 0)
+ {
+ printf("Failed to hook RoGetActivationFactory(). rv = %d\n", rv);
+ }
+ }
+ if (IsWindows11Version22H2OrHigher())
+ {
+ // Fixed a bug that crashed Explorer when a folder window was opened after a first one was closed on OS builds 22621+
+ VnPatchIAT(hCombase, "api-ms-win-core-libraryloader-l1-2-0.dll", "LoadLibraryExW", Windows11v22H2_combase_LoadLibraryExW);
+ }
printf("Setup combase functions done\n");
}
@@ -12166,6 +12580,96 @@ LSTATUS StartUI_RegGetValueW(HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue, DWORD
return RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData);
}
+typedef enum Parser_XamlBufferType
+{
+ XBT_Text,
+ XBT_Binary,
+ XBT_MemoryMappedResource
+} Parser_XamlBufferType;
+
+typedef struct Parser_XamlBuffer
+{
+ unsigned int m_count;
+ Parser_XamlBufferType m_bufferType;
+ const unsigned __int8* m_buffer;
+} Parser_XamlBuffer;
+
+static BOOL StartMenu_FillParserBuffer(Parser_XamlBuffer* pBuffer, int resourceId)
+{
+ HRSRC hRscr = FindResource(hModule, MAKEINTRESOURCE(resourceId), RT_RCDATA);
+ if (!hRscr)
+ return FALSE;
+
+ HGLOBAL hgRscr = LoadResource(hModule, hRscr);
+ if (!hgRscr)
+ return FALSE;
+
+ pBuffer->m_buffer = LockResource(hgRscr);
+ pBuffer->m_count = SizeofResource(hModule, hRscr);
+ pBuffer->m_bufferType = XBT_Binary;
+ return TRUE;
+}
+
+Parser_XamlBuffer g_EmptyRefreshedStylesXbfBuffer;
+
+HRESULT(*CCoreServices_TryLoadXamlResourceHelperFunc)(void* _this, void* pUri, bool* pfHasBinaryFile, void** ppMemory, Parser_XamlBuffer* pBuffer, void** ppPhysicalUri);
+HRESULT CCoreServices_TryLoadXamlResourceHelperHook(void* _this, void* pUri, bool* pfHasBinaryFile, void** ppMemory, Parser_XamlBuffer* pBuffer, void** ppPhysicalUri)
+{
+ HRESULT(*Clone)(void* _this, void** ppUri); // index 3
+ HRESULT(*GetPath)(void* _this, unsigned int* pBufferLength, wchar_t* pszBuffer); // index 12
+ void** vtable = *(void***)pUri;
+ Clone = vtable[3];
+ GetPath = vtable[12];
+ wchar_t thePath[MAX_PATH];
+ unsigned int len = MAX_PATH;
+ GetPath(pUri, &len, thePath);
+ // OutputDebugStringW(thePath); OutputDebugStringW(L"<<<<<\n");
+
+ if (!wcscmp(thePath, L"/JumpViewUI/RefreshedStyles.xaml"))
+ {
+ *pfHasBinaryFile = true;
+ *pBuffer = g_EmptyRefreshedStylesXbfBuffer;
+ if (ppPhysicalUri)
+ Clone(pUri, ppPhysicalUri);
+ return pBuffer->m_buffer ? S_OK : E_FAIL;
+ }
+
+ return CCoreServices_TryLoadXamlResourceHelperFunc(_this, pUri, pfHasBinaryFile, ppMemory, pBuffer, ppPhysicalUri);
+}
+
+static BOOL StartMenu_FixContextMenuXbfHijackMethod()
+{
+ LoadLibraryW(L"Windows.UI.Xaml.dll");
+ HANDLE hWindowsUIXaml = GetModuleHandleW(L"Windows.UI.Xaml.dll");
+ MODULEINFO mi;
+ GetModuleInformation(GetCurrentProcess(), hWindowsUIXaml, &mi, sizeof(mi));
+
+ if (!StartMenu_FillParserBuffer(&g_EmptyRefreshedStylesXbfBuffer, IDR_REFRESHEDSTYLES_XBF))
+ return FALSE;
+
+ // 49 89 43 C8 E8 ?? ?? ?? ?? 85 C0
+ // ^^^^^^^^^^^
+ // Ref: CCoreServices::LoadXamlResource()
+ PBYTE match = FindPattern(
+ mi.lpBaseOfDll,
+ mi.SizeOfImage,
+ "\x49\x89\x43\xC8\xE8\x00\x00\x00\x00\x85\xC0",
+ "xxxxx????xx"
+ );
+ if (!match)
+ return FALSE;
+
+ match += 4;
+ match += 5 + *(int*)(match + 1);
+ CCoreServices_TryLoadXamlResourceHelperFunc = match;
+ funchook_prepare(
+ funchook,
+ (void**)&CCoreServices_TryLoadXamlResourceHelperFunc,
+ CCoreServices_TryLoadXamlResourceHelperHook
+ );
+ return TRUE;
+}
+
LSTATUS StartUI_RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
{
if (wcsstr(lpSubKey, L"$start.tilegrid$windows.data.curatedtilecollection.tilecollection\\Current"))
@@ -12213,7 +12717,8 @@ int Start_SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
HRESULT hr = IsThreadCoreWindowVisible(&bIsWindowVisible);
if (SUCCEEDED(hr))
{
- if (IsWindows11()) ShowWindow(hWnd, bIsWindowVisible ? SW_SHOW : SW_HIDE);
+ if (global_rovi.dwBuildNumber >= 25000 && dwStartShowClassicMode)
+ ShowWindow(hWnd, bIsWindowVisible ? SW_SHOW : SW_HIDE);
DWORD TaskbarAl = InterlockedAdd(&dwTaskbarAl, 0);
if (bIsWindowVisible && (!TaskbarAl ? (dwStartShowClassicMode ? StartUI_EnableRoundedCornersApply : StartDocked_DisableRecommendedSectionApply) : 1))
{
@@ -12797,13 +13302,17 @@ DWORD InjectStartMenu()
PatchAppResolver();
PatchStartTileData();
- // Redirects to pri files from 22000.51 which work with the legacy menu
- LoadLibraryW(L"MrmCoreR.dll");
- HANDLE hMrmCoreR = GetModuleHandleW(L"MrmCoreR.dll");
- VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "CreateFileW", StartUI_CreateFileW);
- VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "GetFileAttributesExW", StartUI_GetFileAttributesExW);
- VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "FindFirstFileW", StartUI_FindFirstFileW);
- VnPatchIAT(hMrmCoreR, "api-ms-win-core-registry-l1-1-0.dll", "RegGetValueW", StartUI_RegGetValueW);
+ // Fixes context menu crashes
+ if (!StartMenu_FixContextMenuXbfHijackMethod()) {
+ // Fallback to the old method, but we'll have broken localization
+ // Redirects to pri files from 22000.51 which work with the legacy menu
+ LoadLibraryW(L"MrmCoreR.dll");
+ HANDLE hMrmCoreR = GetModuleHandleW(L"MrmCoreR.dll");
+ VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "CreateFileW", StartUI_CreateFileW);
+ VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "GetFileAttributesExW", StartUI_GetFileAttributesExW);
+ VnPatchIAT(hMrmCoreR, "api-ms-win-core-file-l1-1-0.dll", "FindFirstFileW", StartUI_FindFirstFileW);
+ VnPatchIAT(hMrmCoreR, "api-ms-win-core-registry-l1-1-0.dll", "RegGetValueW", StartUI_RegGetValueW);
+ }
// Enables "Show more tiles" setting
LoadLibraryW(L"Windows.CloudStore.dll");
diff --git a/ExplorerPatcher/fmemopen.h b/ExplorerPatcher/fmemopen.h
index 3c337ee88..630d6df6f 100644
--- a/ExplorerPatcher/fmemopen.h
+++ b/ExplorerPatcher/fmemopen.h
@@ -5,5 +5,15 @@
#include
#include
#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
FILE* fmemopen(void* buf, size_t len, const char* type);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
\ No newline at end of file
diff --git a/ExplorerPatcher/getline.h b/ExplorerPatcher/getline.h
index 6760bc1e4..123d9734e 100644
--- a/ExplorerPatcher/getline.h
+++ b/ExplorerPatcher/getline.h
@@ -5,8 +5,16 @@
#include
typedef SSIZE_T ssize_t;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
ssize_t getdelim(char** buf, size_t* bufsiz, int delimiter, FILE* fp);
ssize_t getline(char** buf, size_t* bufsiz, FILE* fp);
+#ifdef __cplusplus
+}
+#endif
+
#endif
\ No newline at end of file
diff --git a/ExplorerPatcher/osutility.h b/ExplorerPatcher/osutility.h
index 833b6484c..de3c8be24 100644
--- a/ExplorerPatcher/osutility.h
+++ b/ExplorerPatcher/osutility.h
@@ -20,6 +20,10 @@
#endif
#define DWMWA_MICA_EFFFECT 1029
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern RTL_OSVERSIONINFOW global_rovi;
extern DWORD32 global_ubr;
@@ -94,4 +98,9 @@ inline BOOL IsWindows11Version22H2Build2361OrHigher()
if (global_rovi.dwBuildNumber > 22621) return TRUE;
return global_rovi.dwBuildNumber == 22621 && global_ubr >= 2361;
}
+
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/ExplorerPatcher/resource.h b/ExplorerPatcher/resource.h
index 57986c4dc..2e86782dd 100644
--- a/ExplorerPatcher/resource.h
+++ b/ExplorerPatcher/resource.h
@@ -16,6 +16,7 @@
#define IDS_UNINSTALL_ERROR_TEXT 112
#define IDS_OPERATION_NONE 113
#define IDR_REGISTRY2 114
+#define IDR_REFRESHEDSTYLES_XBF 115
#define IDS_DRIVECATEGORY_HARDDISKDRIVES 40000
#define IDS_DRIVECATEGORY_REMOVABLESTORAGE 40001
#define IDS_DRIVECATEGORY_OTHER 40002
diff --git a/ExplorerPatcher/utility.c b/ExplorerPatcher/utility.c
index c39cfb1ad..d702a0be6 100644
--- a/ExplorerPatcher/utility.c
+++ b/ExplorerPatcher/utility.c
@@ -163,7 +163,7 @@ LRESULT CALLBACK BalloonWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
return 0;
}
-__declspec(dllexport) CALLBACK ZZTestBalloon(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
+__declspec(dllexport) int CALLBACK ZZTestBalloon(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int nCmdShow)
{
TCHAR* lpwszCmdLine = calloc((strlen(lpszCmdLine) + 1), sizeof(TCHAR));
if (!lpwszCmdLine) exit(0);
@@ -199,6 +199,8 @@ __declspec(dllexport) CALLBACK ZZTestBalloon(HWND hWnd, HINSTANCE hInstance, LPS
TranslateMessage(&msg);
DispatchMessage(&msg);
}
+
+ return 0;
}
const wchar_t TestToastXML[] =
@@ -212,7 +214,7 @@ L" \r\n"
L" \r\n"
L"