diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbd94a35a..3b4276b8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -91,32 +91,32 @@ jobs: run: | BuildDependencies%BUILD_CONFIGURATION%.bat - # - name: Download ep_taskbar - # uses: robinraju/release-downloader@v1 - # with: - # repository: ExplorerPatcher/ep_taskbar_releases - # fileName: ep_taskbar.*.dll - # latest: true - # out-file-path: build/Release + - name: Download ep_taskbar + uses: robinraju/release-downloader@v1 + with: + repository: ExplorerPatcher/ep_taskbar_releases + fileName: ep_taskbar.*.dll + latest: true + out-file-path: build/Release # build/Release/ep_taskbar.*.amd64.dll -> build/Release/x64/ep_taskbar.*.dll # build/Release/ep_taskbar.*.arm64.dll -> build/Release/ARM64/ep_taskbar.*.dll - # - name: Move ep_taskbar - # shell: bash - # run: | - # if ls build/Release/ep_taskbar.*.amd64.dll 1> /dev/null 2>&1; then - # mkdir -p build/Release/x64 - # for file in build/Release/ep_taskbar.*.amd64.dll; do - # mv "$file" "build/Release/x64/$(basename "$file" .amd64.dll).dll" - # done - # fi - # - # if ls build/Release/ep_taskbar.*.arm64.dll 1> /dev/null 2>&1; then - # mkdir -p build/Release/ARM64 - # for file in build/Release/ep_taskbar.*.arm64.dll; do - # mv "$file" "build/Release/ARM64/$(basename "$file" .arm64.dll).dll" - # done - # fi + - name: Move ep_taskbar + shell: bash + run: | + if ls build/Release/ep_taskbar.*.amd64.dll 1> /dev/null 2>&1; then + mkdir -p build/Release/x64 + for file in build/Release/ep_taskbar.*.amd64.dll; do + mv "$file" "build/Release/x64/$(basename "$file" .amd64.dll).dll" + done + fi + + if ls build/Release/ep_taskbar.*.arm64.dll 1> /dev/null 2>&1; then + mkdir -p build/Release/ARM64 + for file in build/Release/ep_taskbar.*.arm64.dll; do + mv "$file" "build/Release/ARM64/$(basename "$file" .arm64.dll).dll" + done + fi - name: Build EP IA-32 if: github.event.inputs.config == '' @@ -179,7 +179,7 @@ jobs: build/Release/ # build/Release/x64/ep_setup.exe -> build/Release/ep_setup.exe - # build/Release/ARM64/ep_setup.exe -> build/Release/ep_setup.arm64.exe + # build/Release/ARM64/ep_setup.exe -> build/Release/ep_setup_arm64.exe - name: Stage files for release if: github.ref == 'refs/heads/master' && github.event.inputs.ref == '' shell: bash @@ -188,7 +188,7 @@ jobs: cp build/Release/x64/ep_setup.exe build/Release/ep_setup.exe fi if [ -d "build/Release/ARM64" ] && ls build/Release/ARM64/ep_setup.exe 1> /dev/null 2>&1; then - cp build/Release/ARM64/ep_setup.exe build/Release/ep_setup.arm64.exe + cp build/Release/ARM64/ep_setup.exe build/Release/ep_setup_arm64.exe fi - name: Generate release name @@ -221,7 +221,7 @@ jobs: body: ${{ steps.release_description.outputs.data }} files: | build/Release/ep_setup.exe - build/Release/ep_setup.arm64.exe + build/Release/ep_setup_arm64.exe env: GITHUB_TOKEN: ${{ secrets.PAT }} @@ -237,6 +237,6 @@ jobs: body: ${{ steps.release_description.outputs.data }} files: | build/Release/ep_setup.exe - build/Release/ep_setup.arm64.exe + build/Release/ep_setup_arm64.exe env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9850447f8..fccd85537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,18 +15,46 @@ Tested on OS builds 19045.4598, 22621.3296, 22621.3810, 26120.961, and 26244.500 ##### 2 +
+ * Taskbar10: Due to false positive antivirus detections, the new taskbar implementation is no longer bundled in the setup program. (48c2a75) * If you want to use the new taskbar implementation, you can download the appropriate DLL for your system from the [Releases](https://github.com/ExplorerPatcher/ep_taskbar_releases/releases/latest) page of its releases repository, and then manually putting it in `C:\Program Files\ExplorerPatcher` without the architecture specifier. * For example, for 226xx builds on x64-based systems, download `ep_taskbar.2.amd64.dll`, rename to `ep_taskbar.2.dll`, and lastly put it in `C:\Program Files\ExplorerPatcher`. +
+ ##### 3 * Introduced support for ARM64 devices. (992b3a6, 2e4e4f5, b76c0e4, c9884b2, 57f63ad, 78788ec, 4799b4b, 5d0d218) * These builds are only tested on and made to work with 24H2 ARM64 builds. Older ARM64 Windows versions than 24H2 may not work as expected. - * An ARM64 device to support the making and testing of ARM64 builds is not cheap, so please consider [donating @Amrsatrio via Ko-fi](https://ko-fi.com/amrsatrio) to recoup the costs. * Added an "Update now" button into update notifications for easier updating. (2b9c747, 8c16a9a) * Revised how files are packed in ep_setup for smaller size and easier maintenance. (30579b0, b253625, 04fd2b7, db54ce9, 126c024, c0201ff) -* ⚠️ **Note for users with the pre-release versions enabled:** Versions before this one will not be able to update to this version or later versions due to the updater code of previous versions not supporting multiple binaries in one GitHub release. Please manually update by downloading the appropriate binary from this page. +* EP's taskbar implementation for 24H2 is now available in [its releases repository](https://github.com/ExplorerPatcher/ep_taskbar_releases/releases/latest), as `ep_taskbar.5.dll`. If you want to try this out, follow the steps explained above. + +##### 4 + +With this update, ExplorerPatcher is now officially compatible and supported on Windows 11 24H2 🥳🎉 + +* Start10: Now works again on 24H2 and 226xx.3930+. (755f101, 7e0f7eb, b473114) +* Taskbar10: EP's taskbar DLLs are now included again in the setup files. (d9595fc) +* Taskbar10: Network icon now shows again on 24H2. (7e0f7eb, b473114) +* Start10: Fixed positioning when the taskbar is not placed at the bottom, on 24H2 and latest 22H2/23H2 builds. (de2532d, ea5881f) +* Taskbar10: Fixed taskbar jump list flyout positioning when the taskbar is not placed at the bottom, on latest 22H2/23H2/24H2 builds. (39609e4) +* Setup: Updated the code for dealing with locked files, this should reduce the chances of getting setup failures due to locked files. (7e0f7eb) +* ep_taskbar: Fixed tray icons not being saved. +* ep_taskbar: Removed the Copilot button on 22H2. + +ℹ️ **Important note:** Please include the following folders in your antivirus' exclusion list to prevent issues due to false positive detections: +* `C:\Program Files\ExplorerPatcher` +* `%APPDATA%\ExplorerPatcher` + +For Defender, you can run the following script in PowerShell as an administrator: +```ps1 +Add-MpPreference -ExclusionPath "C:\Program Files\ExplorerPatcher" +Add-MpPreference -ExclusionPath "$env:APPDATA\ExplorerPatcher" +``` + +**A little request from us:** Because the development of EP's taskbar implementation took a lot of effort for 8 consecutive months, and that an ARM64 device to support the making and testing of ARM64 builds is not cheap, it would be really, really appreciated if you can [donate @Amrsatrio via Ko-fi](https://ko-fi.com/amrsatrio) 🙏 ## 22621.3527.65 diff --git a/ExplorerPatcher-L10N b/ExplorerPatcher-L10N index 0d154eba1..17f644775 160000 --- a/ExplorerPatcher-L10N +++ b/ExplorerPatcher-L10N @@ -1 +1 @@ -Subproject commit 0d154eba13317cd33530968224b39ba94260e20b +Subproject commit 17f644775baae0d920a0c2722d89102a6bdcf620 diff --git a/ExplorerPatcher/ArchiveMenu.h b/ExplorerPatcher/ArchiveMenu.h index ee388659b..9ad3da97d 100644 --- a/ExplorerPatcher/ArchiveMenu.h +++ b/ExplorerPatcher/ArchiveMenu.h @@ -4,6 +4,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #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" @@ -51,4 +55,8 @@ LRESULT CALLBACK ArchiveMenuWndProc( void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)(HMENU hMenu, HWND hWnd) ); +#ifdef __cplusplus +} +#endif + #endif diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj index 56a526d69..437381bf8 100644 --- a/ExplorerPatcher/ExplorerPatcher.vcxproj +++ b/ExplorerPatcher/ExplorerPatcher.vcxproj @@ -256,6 +256,9 @@ true + + true + true diff --git a/ExplorerPatcher/StartMenu.h b/ExplorerPatcher/StartMenu.h index 51001d9d9..ddc8e8ac4 100644 --- a/ExplorerPatcher/StartMenu.h +++ b/ExplorerPatcher/StartMenu.h @@ -179,42 +179,6 @@ interface IImmersiveLauncher10RS CONST_VTBL struct IImmersiveLauncher10RSVtbl* lpVtbl; }; -DEFINE_GUID(IID_ILauncherTipContextMenu, - 0xb8c1db5f, - 0xcbb3, 0x48bc, 0xaf, 0xd9, - 0xce, 0x6b, 0x88, 0x0c, 0x79, 0xed -); - -typedef interface ILauncherTipContextMenu ILauncherTipContextMenu; - -typedef struct ILauncherTipContextMenuVtbl -{ - BEGIN_INTERFACE - - HRESULT(STDMETHODCALLTYPE* QueryInterface)( - ILauncherTipContextMenu* This, - /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ - _COM_Outptr_ void** ppvObject); - - ULONG(STDMETHODCALLTYPE* AddRef)( - ILauncherTipContextMenu* This); - - ULONG(STDMETHODCALLTYPE* Release)( - ILauncherTipContextMenu* This); - - HRESULT(STDMETHODCALLTYPE* ShowLauncherTipContextMenu)( - ILauncherTipContextMenu* This, - /* [in] */ POINT* pt); - - END_INTERFACE -} ILauncherTipContextMenuVtbl; - -interface ILauncherTipContextMenu -{ - CONST_VTBL struct ILauncherTipContextMenuVtbl* lpVtbl; -}; - void OpenStartOnMonitor(HMONITOR monitor); // Slightly tweaked version of function available in Open Shell diff --git a/ExplorerPatcher/TwinUIPatches.cpp b/ExplorerPatcher/TwinUIPatches.cpp new file mode 100644 index 000000000..149f612dd --- /dev/null +++ b/ExplorerPatcher/TwinUIPatches.cpp @@ -0,0 +1,3274 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "ArchiveMenu.h" +#include "utility.h" +#include "hooking.h" +#include "symbols.h" + +using namespace Microsoft::WRL; + + +#pragma region "Types and utilities" + +DEFINE_GUID(SID_EdgeUi, 0x0D189B30, 0xF12B, 0x4B13, 0x94, 0xCF, 0x53, 0xCB, 0x0E, 0x0E, 0x24, 0x0D); // 0d189b30-f12b-4b13-94cf-53cb0e0e240d + +interface IImmersiveApplication; +interface IEdgeUiInvocationProvider; + +enum EDGEUI_COMPONENT +{ + EUICMP_UNKNOWN = -1, + EUICMP_SWITCHER = 0, + EUICMP_CHARMSBAR, + EUICMP_APPBAR, + EUICMP_TASKBAR, + EUICMP_TITLEBAR, + EUICMP_TABLETMODEVIEWMANAGER, + EUICMP_ACTIONCENTER, + EUICMP_TOTALCOUNT, +}; + +enum DISMISSED_UI_FLAGS +{ + DUF_NONE = 0x0, + DUF_FORCEOBSERVATIONOFF = 0x1, +}; + +enum EDGEUI_TRAYSTUCKPLACE +{ + EUITSP_UNKNOWN = -1, + EUITSP_LEFT = 0, + EUITSP_TOP, + EUITSP_RIGHT, + EUITSP_BOTTOM, +}; + +MIDL_INTERFACE("6e6c3c52-5a5e-4b4b-a0f8-7fe12621a93e") +IEdgeUiManager : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetTargetApplicationFromPoint(POINT, int, IImmersiveApplication**) = 0; + virtual HRESULT STDMETHODCALLTYPE DismissedUI(EDGEUI_COMPONENT, DISMISSED_UI_FLAGS) = 0; + virtual HRESULT STDMETHODCALLTYPE HandleEdgeGesturePrefChanged(HWND) = 0; + virtual HRESULT STDMETHODCALLTYPE DiscreteInvokeForApp(EDGEUI_COMPONENT, IImmersiveApplication*) = 0; + virtual HRESULT STDMETHODCALLTYPE BeginInputObservation(EDGEUI_COMPONENT) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRegionForCornerOrEdge(EDGEUI_COMPONENT, HRGN*) = 0; + virtual HRESULT STDMETHODCALLTYPE NotifyTrayStuckPlaceChanged(EDGEUI_TRAYSTUCKPLACE) = 0; + virtual HRESULT STDMETHODCALLTYPE GetTrayStuckPlace(EDGEUI_TRAYSTUCKPLACE*) = 0; + virtual HRESULT STDMETHODCALLTYPE NotifyTraySearchBoxVisibilityChanged(BOOL) = 0; + virtual HRESULT STDMETHODCALLTYPE GetTraySearchBoxVisibility(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE NotifyPearlRectChanged(RECT) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPearlRect(RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE UpdateEdgeWindowZorder() = 0; + virtual HRESULT STDMETHODCALLTYPE ShowStandardSystemOverlays(IImmersiveApplication*) = 0; + virtual HRESULT STDMETHODCALLTYPE OverrideInvocation(IEdgeUiInvocationProvider*) = 0; + virtual HRESULT STDMETHODCALLTYPE NotifyAutohideImmuneWorkAreaMayHaveChanged(RECT) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAutohideImmuneWorkArea(RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE TaskbarRaised() = 0; + virtual HRESULT STDMETHODCALLTYPE GetTrayRect(RECT*) = 0; +}; + +enum IMMERSIVE_MONITOR_FILTER_FLAGS +{ + IMMERSIVE_MONITOR_FILTER_FLAGS_NONE = 0x0, + IMMERSIVE_MONITOR_FILTER_FLAGS_DISABLE_TRAY = 0x1, +}; + +DEFINE_ENUM_FLAG_OPERATORS(IMMERSIVE_MONITOR_FILTER_FLAGS); + +MIDL_INTERFACE("880b26f8-9197-43d0-8045-8702d0d72000") +IImmersiveMonitor : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetIdentity(DWORD*) = 0; + virtual HRESULT STDMETHODCALLTYPE ConnectObject(IUnknown*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetHandle(HMONITOR*) = 0; + virtual HRESULT STDMETHODCALLTYPE IsConnected(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPrimary(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE IsImmersiveDisplayDevice(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetDisplayRect(RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetOrientation(DWORD*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetWorkArea(RECT*) = 0; + virtual HRESULT STDMETHODCALLTYPE IsEqual(IImmersiveMonitor*, BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE IsImmersiveCapable(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetEffectiveDpi(UINT*, UINT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFilterFlags(IMMERSIVE_MONITOR_FILTER_FLAGS*) = 0; +}; + +DEFINE_GUID(SID_IImmersiveMonitorService, 0x47094E3A, 0x0CF2, 0x430F, 0x80, 0x6F, 0xCF, 0x9E, 0x4F, 0x0F, 0x12, 0xDD); // 47094e3a-0cf2-430f-806f-cf9e4f0f12dd + +enum IMMERSIVE_MONITOR_MOVE_DIRECTION +{ + IMMD_PREVIOUS, + IMMD_NEXT, +}; + +interface IImmersiveMonitorFilter; + +MIDL_INTERFACE("4d4c1e64-e410-4faa-bafa-59ca069bfec2") +IImmersiveMonitorManager : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE GetCount(UINT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetConnectedCount(UINT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetAt(UINT, IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFromHandle(HMONITOR, IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetFromIdentity(DWORD, IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetImmersiveProxyMonitor(IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryService(HMONITOR, REFGUID, REFGUID, void**) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryServiceByIdentity(DWORD, REFGUID, REFGUID, void**) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryServiceFromWindow(HWND, REFGUID, REFGUID, void**) = 0; + virtual HRESULT STDMETHODCALLTYPE QueryServiceFromPoint(const POINT*, REFGUID, REFGUID, void**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetNextImmersiveMonitor(IMMERSIVE_MONITOR_MOVE_DIRECTION, IImmersiveMonitor*, IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMonitorArray(IObjectArray**) = 0; + virtual HRESULT STDMETHODCALLTYPE SetFilter(IImmersiveMonitorFilter*) = 0; +}; + +DEFINE_GUID(SID_ImmersiveLauncher, 0x6F86E01C, 0xC649, 0x4D61, 0xBE, 0x23, 0xF1, 0x32, 0x2D, 0xDE, 0xCA, 0x9D); // 6f86e01c-c649-4d61-be23-f1322ddeca9d + +enum IMMERSIVELAUNCHERSHOWMETHOD +{ + ILSM_INVALID = 0, + ILSM_HSHELLTASKMAN = 1, + ILSM_IMMERSIVEBACKGROUND = 4, + ILSM_APPCLOSED = 6, + ILSM_STARTBUTTON = 11, + ILSM_RETAILDEMO_EDUCATIONAPP = 12, + ILSM_BACK = 13, + ILSM_SESSIONONUNLOCK = 14, +}; + +enum IMMERSIVELAUNCHERSHOWFLAGS +{ + ILSF_NONE = 0x0, + ILSF_IGNORE_SET_FOREGROUND_ERROR = 0x4, +}; + +DEFINE_ENUM_FLAG_OPERATORS(IMMERSIVELAUNCHERSHOWFLAGS); + +enum IMMERSIVELAUNCHERDISMISSMETHOD +{ + ILDM_INVALID = 0, + ILDM_HSHELLTASKMAN = 1, + ILDM_STARTCHARM = 2, + ILDM_BACKGESTURE = 3, + ILDM_ESCAPEKEY = 4, + ILDM_SHOWDESKTOP = 5, + ILDM_STARTTIP = 6, + ILDM_GENERIC_NONANIMATING = 7, + ILDM_SEARCH_OPENING = 8, + ILDM_DRAG = 9, +}; + +MIDL_INTERFACE("d8d60399-a0f1-f987-5551-321fd1b49864") +IImmersiveLauncher : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE ShowStartView(IMMERSIVELAUNCHERSHOWMETHOD, IMMERSIVELAUNCHERSHOWFLAGS) = 0; + virtual HRESULT STDMETHODCALLTYPE Dismiss(IMMERSIVELAUNCHERDISMISSMETHOD) = 0; + virtual HRESULT STDMETHODCALLTYPE DismissToLastDesktopApplication(IMMERSIVELAUNCHERDISMISSMETHOD) = 0; + virtual HRESULT STDMETHODCALLTYPE DismissSynchronouslyWithoutTransition() = 0; + virtual HRESULT STDMETHODCALLTYPE IsVisible(BOOL*) = 0; + virtual HRESULT STDMETHODCALLTYPE OnStartButtonPressed(IMMERSIVELAUNCHERSHOWMETHOD, IMMERSIVELAUNCHERDISMISSMETHOD) = 0; + virtual HRESULT STDMETHODCALLTYPE SetForeground() = 0; + virtual HRESULT STDMETHODCALLTYPE ConnectToMonitor(IImmersiveMonitor*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMonitor(IImmersiveMonitor**) = 0; + virtual HRESULT STDMETHODCALLTYPE OnFirstSignAnimationFinished() = 0; + virtual HRESULT STDMETHODCALLTYPE Prelaunch() = 0; +}; + +MIDL_INTERFACE("b8c1db5f-cbb3-48bc-afd9-ce6b880c79ed") +ILauncherTipContextMenu : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE ShowLauncherTipContextMenu(POINT*) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMenuItemsAsync(RECT, IUnknown**) = 0; +}; + +inline BOOL IsBiDiLocale(LCID locale) +{ + int info; + int charsRead = GetLocaleInfoW( + locale, + LOCALE_IREADINGLAYOUT | LOCALE_RETURN_NUMBER, + (LPWSTR)&info, + sizeof(info) / sizeof(WCHAR) + ); + return charsRead > 0 ? info == 1 : false; +} + +BOOL Mirror_IsThreadRTL() +{ + return IsBiDiLocale(GetThreadUILanguage()); +} + +enum ZBID : int; +enum ACCENT_STATE : int; + +class CSingleViewShellExperience; + +class SingleViewShellExperiencePersonality; + +class CSingleViewShellExperience +{ +public: + enum class Border + { + None = 0, + Left = 1, + Top = 2, + Right = 4, + Bottom = 8 + }; + + HRESULT SetPosition(const RECT* rect); + + Wrappers::HString _args; + Wrappers::HString _aumid; + Wrappers::HString _experience; + void* _viewWrapper; + ComPtr _propertySet; + int _viewState; + ABI::Windows::Foundation::Size _desiredSize; + BOOLEAN _fullScreen; + bool _isSessionIdle; + DWORD _pid; + ZBID _zbidDefault; + int _pendingViewAction; + int _pendingViewShowFlags; + int _navLevelOverrideHelper[2]; + wistd::unique_ptr m_personality; + // ... +}; + +class SingleViewShellExperiencePersonality +{ +public: + virtual ~SingleViewShellExperiencePersonality() = 0; + virtual bool IsPersonality(void*) = 0; + virtual HRESULT Initialize(IServiceProvider*) = 0; + virtual HRESULT EnableSessionIdleNotifications(IServiceProvider*) = 0; + virtual HRESULT OnViewWrapperChanged() = 0; + virtual HRESULT ShowView() = 0; + virtual HRESULT HideView() = 0; + virtual HRESULT IsViewVisible(bool*) = 0; + virtual HRESULT SetWindowBand(ZBID) = 0; + virtual HRESULT BringToForeground() = 0; + virtual HRESULT BringToFocus() = 0; + virtual HRESULT ShowBorder(CSingleViewShellExperience::Border, ACCENT_STATE, DWORD, const RECT*) = 0; + virtual HRESULT SetPosition(const RECT*) = 0; +}; + +HRESULT CSingleViewShellExperience::SetPosition(const RECT* rect) +{ + RETURN_HR(m_personality->SetPosition(rect)); +} + +namespace ExperienceManagerUtils +{ + void ScaleByDPI(const ABI::Windows::Foundation::Size* size, int dpi, int* outWidth, int* outHeight) + { + *outWidth = MulDiv((int)size->Width, dpi, 96); + *outHeight = MulDiv((int)size->Height, dpi, 96); + } +} + +#pragma endregion + + +#pragma region "Stuff from dllmain" + +extern "C" +{ + +extern HMODULE hModule; +extern HWND archivehWnd; +extern DWORD bOldTaskbar; +extern DWORD bSkinMenus; +extern DWORD bClockFlyoutOnWinC; +extern DWORD bPropertiesInWinX; +extern DWORD bNoMenuAccelerator; +extern DWORD dwAltTabSettings; +extern DWORD dwSnapAssistSettings; +extern DWORD dwStartShowClassicMode; +extern HANDLE hWin11AltTabInitialized; + +typedef HRESULT(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t)(HMENU hmenu, HWND hWnd, POINT* pptOrigin, unsigned int icmoFlags, void* srgRenderingData); +extern ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc; +typedef void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t)(HMENU hmenu, HWND hwnd); +extern ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc; +typedef LRESULT(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc_t)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +extern CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc_t CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc; + +BOOL VnPatchIAT_NonInline(HMODULE hMod, const char* libName, const char* funcName, uintptr_t hookAddr); +POINT GetDefaultWinXPosition(BOOL bUseRcWork, BOOL* lpBottom, BOOL* lpRight, BOOL bAdjust, BOOL bToRight); +BOOL InvokeClockFlyout(); +void ReportSuccessfulAnimationPatching(); +BOOL IsCrashCounterEnabled(); + +} // extern "C" + +#pragma endregion + + +#pragma region "twinui.pcshell.dll hooks" + +#define LAUNCHERTIP_CLASS_NAME L"LauncherTipWnd" +#define WINX_ADJUST_X 5 +#define WINX_ADJUST_Y 5 + +static INT64(*winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc)(void* _this, INT64 a2, INT a3 ) = nullptr; +static INT64(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)(void* _this, POINT* pt) = nullptr; +static void(*CLauncherTipContextMenu_ExecuteCommandFunc)(void* _this, void* a2) = nullptr; +static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)(void* _this, void* a2) = nullptr; +static INT64(*CLauncherTipContextMenu_GetMenuItemsAsyncFunc)(void* _this, RECT rect, IUnknown** iunk) = nullptr; + +HWND hWinXWnd; +HANDLE hIsWinXShown; +HANDLE hWinXThread; + +extern "C" LRESULT CALLBACK CLauncherTipContextMenu_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result; + + if (hWnd == archivehWnd && !ArchiveMenuWndProc( + hWnd, uMsg, wParam, lParam, + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc, + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc + )) + { + return 0; + } + + if (uMsg == WM_NCCREATE) + { + CREATESTRUCT* pCs = (CREATESTRUCT*)lParam; + if (pCs->lpCreateParams) + { + *((HWND*)((char*)pCs->lpCreateParams + 0x78)) = hWnd; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pCs->lpCreateParams); + result = DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + else + { + result = DefWindowProcW(hWnd, uMsg, wParam, lParam); + //result = 0; + } + } + else + { + void* _this = (void*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); + if ((uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) && + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc && + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc(hWnd, uMsg, wParam, lParam)) + { + result = 0; + } + else + { + result = DefWindowProcW(hWnd, uMsg, wParam, lParam); + } + if (_this) + { + if (uMsg == WM_NCDESTROY) + { + SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0); + *((HWND*)((char*)_this + 0x78)) = nullptr; + } + } + } + return result; +} + +typedef struct +{ + void* _this; + POINT point; + IUnknown* iunk; + BOOL bShouldCenterWinXHorizontally; +} ShowLauncherTipContextMenuParameters; + +DWORD ShowLauncherTipContextMenu(LPVOID lpParams) +{ + ShowLauncherTipContextMenuParameters* params = (ShowLauncherTipContextMenuParameters*)lpParams; + + // Adjust this based on info from: CLauncherTipContextMenu::SetSite + // and CLauncherTipContextMenu::CLauncherTipContextMenu + // 22000.739: 0xe8 + // 22000.778: 0xf0 + // What has happened, between .739 and .778 is that the launcher tip + // context menu object now implements a new interface, ILauncherTipContextMenuMigration; + // thus, members have shifted 8 bytes (one 64-bit value which will hold the + // address of the vtable for this intf at runtime) to the right; + // all this intf seems to do, as of now, is to remove some "obsolete" links + // from the menu (check out "CLauncherTipContextMenu::RunMigrationTasks"); it + // seems you can disable this by setting a DWORD "WinXMigrationLevel" = 1 in + // HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced + int offset_in_class = 0; + if (global_rovi.dwBuildNumber >= 22621 || (global_rovi.dwBuildNumber == 22000 && global_ubr >= 778)) + { + offset_in_class = 8; + } + + static ATOM windowRegistrationAtom = 0; + if (windowRegistrationAtom == 0) + { + WNDCLASS wc = { + .style = CS_DBLCLKS, + .lpfnWndProc = CLauncherTipContextMenu_WndProc, + .hInstance = GetModuleHandleW(nullptr), + .hCursor = LoadCursorW(nullptr, IDC_ARROW), + .hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH), + .lpszClassName = LAUNCHERTIP_CLASS_NAME + }; + ATOM atom = RegisterClassW(&wc); + if (atom) + windowRegistrationAtom = atom; + } + + hWinXWnd = CreateWindowInBand( + 0, + MAKEINTATOM(windowRegistrationAtom), + nullptr, + WS_POPUP, + 0, 0, 0, 0, + nullptr, nullptr, + GetModuleHandle(nullptr), + (char*)params->_this - 0x58, + 7 // ZBID_IMMERSIVE_EDGY + ); + // DO NOT USE ShowWindow here; it breaks the window order + // and renders the desktop toggle unusable; but leave + // SetForegroundWindow as is so that the menu gets dismissed + // when the user clicks outside it + // + // ShowWindow(hWinXWnd, SW_SHOW); + SetForegroundWindow(hWinXWnd); + + HMENU* phMenu = ((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)); + while (!*phMenu) + { + Sleep(1); + } + auto finalize = wil::scope_exit([&]() -> void + { + params->iunk->Release(); + SendMessageW(hWinXWnd, WM_CLOSE, 0, 0); + free(params); + hIsWinXShown = nullptr; + }); + if (!*phMenu) + { + return 0; + } + + TCHAR buffer[260]; + LoadStringW(GetModuleHandleW(L"ExplorerFrame.dll"), 50222, buffer + (bNoMenuAccelerator ? 0 : 1), 260); + if (!bNoMenuAccelerator) + { + buffer[0] = L'&'; + } + wchar_t* p = wcschr(buffer, L'('); + if (p) + { + p--; + if (*p == L' ') + { + *p = 0; + } + else + { + p++; + *p = 0; + } + } + + BOOL bCreatedMenu = FALSE; + MENUITEMINFOW menuInfo; + ZeroMemory(&menuInfo, sizeof(MENUITEMINFOW)); + menuInfo.cbSize = sizeof(MENUITEMINFOW); + menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA; + menuInfo.wID = 3999; + menuInfo.dwItemData = 0; + menuInfo.fType = MFT_STRING; + menuInfo.dwTypeData = buffer; + menuInfo.cch = (UINT)wcslen(buffer); + if (bPropertiesInWinX) + { + InsertMenuItemW( + *phMenu, + GetMenuItemCount(*phMenu) - 1, + TRUE, + &menuInfo + ); + bCreatedMenu = TRUE; + } + + INT64* unknown_array = nullptr; + if (bSkinMenus) + { + unknown_array = (INT64*)calloc(4, sizeof(INT64)); + if (ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc) + { + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( + *phMenu, + hWinXWnd, + &(params->point), + 0xc, + unknown_array + ); + } + } + + BOOL res = TrackPopupMenu( + *phMenu, + TPM_RETURNCMD | TPM_RIGHTBUTTON | (params->bShouldCenterWinXHorizontally ? TPM_CENTERALIGN : 0), + params->point.x, + params->point.y, + 0, + hWinXWnd, + nullptr + ); + + if (bSkinMenus) + { + if (ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc) + { + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( + *phMenu, + hWinXWnd + ); + } + free(unknown_array); + } + + if (bCreatedMenu) + { + RemoveMenu( + *phMenu, + 3999, + MF_BYCOMMAND + ); + } + + if (res > 0) + { + if (bCreatedMenu && res == 3999) + { + LaunchPropertiesGUI(hModule); + } + else if (res < 4000) + { + INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xa8 + offset_in_class - 0x58)) + (INT64)res * 8 - 8); + if (CLauncherTipContextMenu_ExecuteCommandFunc) + { + CLauncherTipContextMenu_ExecuteCommandFunc( + (char*)params->_this - 0x58, + &info + ); + } + } + else + { + INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xc8 + offset_in_class - 0x58)) + ((INT64)res - 4000) * 8); + if (CLauncherTipContextMenu_ExecuteShutdownCommandFunc) + { + CLauncherTipContextMenu_ExecuteShutdownCommandFunc( + (char*)params->_this - 0x58, + &info + ); + } + } + } + + return 0; +} + +INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook( + void* _this, + POINT* pt +) +{ + if (hWinXThread) + { + WaitForSingleObject(hWinXThread, INFINITE); + CloseHandle(hWinXThread); + hWinXThread = nullptr; + } + + if (!hIsWinXShown) + { + BOOL bShouldCenterWinXHorizontally = FALSE; + POINT point; + if (pt) + { + point = *pt; + BOOL bBottom, bRight; + POINT dPt = GetDefaultWinXPosition(FALSE, &bBottom, &bRight, FALSE, FALSE); + POINT posCursor; + GetCursorPos(&posCursor); + RECT rcHitZone; + rcHitZone.left = pt->x - 5; + rcHitZone.right = pt->x + 5; + rcHitZone.top = pt->y - 5; + rcHitZone.bottom = pt->y + 5; + //printf("%d %d = %d %d %d %d\n", posCursor.x, posCursor.y, rcHitZone.left, rcHitZone.right, rcHitZone.top, rcHitZone.bottom); + if (bBottom && IsThemeActive() && PtInRect(&rcHitZone, posCursor) && GetClassWord(WindowFromPoint(point), GCW_ATOM) == RegisterWindowMessageW(L"Start")) + { + HMONITOR hMonitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY); + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hMonitor, &mi); + HWND hWndUnder = WindowFromPoint(*pt); + TCHAR wszClassName[100]; + ZeroMemory(wszClassName, 100); + GetClassNameW(hWndUnder, wszClassName, 100); + if (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd")) + { + hWndUnder = FindWindowEx( + hWndUnder, + nullptr, + L"Start", + nullptr + ); + } + RECT rcUnder; + GetWindowRect(hWndUnder, &rcUnder); + if (mi.rcMonitor.left != rcUnder.left) + { + bShouldCenterWinXHorizontally = TRUE; + point.x = rcUnder.left + (rcUnder.right - rcUnder.left) / 2; + point.y = rcUnder.top; + } + else + { + UINT dpiX, dpiY; + HRESULT hr = GetDpiForMonitor( + hMonitor, + MDT_DEFAULT, + &dpiX, + &dpiY + ); + double dx = dpiX / 96.0, dy = dpiY / 96.0; + BOOL xo = FALSE, yo = FALSE; + if ((int)(point.x - WINX_ADJUST_X * dx) < mi.rcMonitor.left) + { + xo = TRUE; + } + if ((int)(point.y + WINX_ADJUST_Y * dy) > mi.rcMonitor.bottom) + { + yo = TRUE; + } + POINT ptCursor; + GetCursorPos(&ptCursor); + if (xo) + { + ptCursor.x += (int)((WINX_ADJUST_X * 2) * dx); + } + else + { + point.x -= (int)(WINX_ADJUST_X * dx); + } + if (yo) + { + ptCursor.y -= (int)((WINX_ADJUST_Y * 2) * dy); + } + else + { + point.y += (int)(WINX_ADJUST_Y * dy); + } + SetCursorPos(ptCursor.x, ptCursor.y); + } + } + } + else + { + point = GetDefaultWinXPosition(FALSE, nullptr, nullptr, TRUE, FALSE); + } + + IUnknown* iunk = nullptr; + if (CLauncherTipContextMenu_GetMenuItemsAsyncFunc) + { + RECT rc = { 0 }; + CLauncherTipContextMenu_GetMenuItemsAsyncFunc(_this, rc, &iunk); + } + if (iunk) + { + iunk->AddRef(); + + ShowLauncherTipContextMenuParameters* params = (ShowLauncherTipContextMenuParameters*)malloc(sizeof(ShowLauncherTipContextMenuParameters)); + params->_this = _this; + params->point = point; + params->iunk = iunk; + params->bShouldCenterWinXHorizontally = bShouldCenterWinXHorizontally; + hIsWinXShown = CreateThread(nullptr, 0, ShowLauncherTipContextMenu, params, 0, nullptr); + hWinXThread = hIsWinXShown; + } + } + if (CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc) + { + return CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt); + } + return 0; +} + +extern "C" void ToggleLauncherTipContextMenu() +{ + if (hIsWinXShown) + { + SendMessageW(hWinXWnd, WM_CLOSE, 0, 0); + return; + } + + HWND hWnd = FindWindowExW(nullptr, nullptr, L"Shell_TrayWnd", nullptr); + if (!hWnd) + return; + + hWnd = FindWindowExW(hWnd, nullptr, L"Start", nullptr); + if (!hWnd) + return; + + POINT pt = GetDefaultWinXPosition(FALSE, nullptr, nullptr, TRUE, FALSE); + // Finally implemented a variation of + // https://github.com/valinet/ExplorerPatcher/issues/3 + // inspired by how the real Start button activates this menu + // (CPearl::_GetLauncherTipContextMenu) + // This also works when auto hide taskbar is on (#63) + ComPtr pImmersiveShell; + if (SUCCEEDED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImmersiveShell)))) + { + ComPtr pMonitorService; + if (SUCCEEDED(pImmersiveShell->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&pMonitorService)))) + { + ComPtr pMenu; + if (SUCCEEDED(pMonitorService->QueryServiceFromWindow(hWnd, __uuidof(ILauncherTipContextMenu), IID_PPV_ARGS(&pMenu)))) + { + pMenu->ShowLauncherTipContextMenu(&pt); + } + } + } +} + +LSTATUS twinuipcshell_RegGetValueW( + HKEY hkey, + LPCWSTR lpSubKey, + LPCWSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData +) +{ + LSTATUS lRes = RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + + if (!lstrcmpW(lpValue, L"AltTabSettings")) + { + if (lRes == ERROR_SUCCESS && *(DWORD*)pvData) + { + if (*(DWORD*)pvData == 3) + { + *(DWORD*)pvData = 0; + } + else + { + *(DWORD*)pvData = 1; + } + } + + if (!bOldTaskbar && hWin11AltTabInitialized) + { + SetEvent(hWin11AltTabInitialized); + CloseHandle(hWin11AltTabInitialized); + hWin11AltTabInitialized = nullptr; + } + + lRes = ERROR_SUCCESS; + } + + return lRes; +} + +INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHook( + void* _this, + INT64 a2, + INT a3 +) +{ + if (!bClockFlyoutOnWinC) + { + if (winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc) + { + return winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc(_this, a2, a3); + } + return 0; + } + if (a2 == 786 && a3 == 107) + { + InvokeClockFlyout(); + } + return 0; +} + +#pragma endregion + + +#pragma region "Enable old Alt+Tab" + +INT64(*twinui_pcshell_IsUndockedAssetAvailableFunc)(INT a1, INT64 a2, INT64 a3, const char* a4); +INT64 twinui_pcshell_IsUndockedAssetAvailableHook(INT a1, INT64 a2, INT64 a3, const char* a4) +{ + // if IsAltTab and AltTabSettings == Windows 10 or sws (Precision Touchpad gesture) + if (a1 == 1 && (dwAltTabSettings == 3 || dwAltTabSettings == 2)) + { + return 0; + } + // if IsSnapAssist and SnapAssistSettings == Windows 10 + else if (a1 == 4 && dwSnapAssistSettings == 3 && !IsWindows11Version22H2OrHigher()) + { + return 0; + } + // else, show Windows 11 style basically + else + { + if (twinui_pcshell_IsUndockedAssetAvailableFunc) + return twinui_pcshell_IsUndockedAssetAvailableFunc(a1, a2, a3, a4); + return 1; + } +} + +INT64(*twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc)(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5); +INT64(*twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc)(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5); +INT64 twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostHook(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5) +{ + if (!twinui_pcshell_IsUndockedAssetAvailableHook(a2, 0, 0, nullptr)) + return twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc(_this, a2, a3, a4, a5); + return twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc(_this, a2, a3, a4, a5); +} + +#pragma endregion + + +#pragma region "Fixes related to the removal of STTest feature flag (22621.2134+)" + +HRESULT(*twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc)(IInspectable* _this, HMONITOR hMonitor, float* outHeight); +HRESULT twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorHook(IInspectable* _this, HMONITOR hMonitor, float* outHeight) +{ + if (bOldTaskbar) + { + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + GetMonitorInfoW(hMonitor, &mi); + *outHeight = (float)(mi.rcMonitor.bottom - mi.rcWork.bottom); + return S_OK; + } + return twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc(_this, hMonitor, outHeight); +} + +static struct +{ + int coroInstance_rcOut; // 22621.1992: 0x10 + int coroInstance_pHardwareConfirmatorHost; // 22621.1992: 0xFD + int hardwareConfirmatorHost_bIsInLockScreen; // 22621.1992: 0xEC +} g_Moment2PatchOffsets; + +#if defined(_M_X64) +inline PBYTE GetTargetOfJzBeforeMe(PBYTE anchor) +{ + // Check big jz + if (*(anchor - 6) == 0x0F && *(anchor - 5) == 0x84) + return anchor + *(int*)(anchor - 4); + // Check small jz + if (*(anchor - 2) == 0x74) + return anchor + *(char*)(anchor - 1); + return nullptr; +} +#endif + +// CActionCenterExperienceManager::GetViewPosition() patcher +BOOL Moment2PatchActionCenter(LPMODULEINFO mi) +{ +#if defined(_M_X64) + // Step 1: + // Scan within the DLL for `*a2 = mi.rcMonitor`. + // ```0F 10 45 ?? F3 0F 7F ?? 80 ?? ?? ?? 00 00 00 // movups - movdqu - cmp``` + // 22621.1992: 7E2F0 + // 22621.2283: 140D5 + PBYTE rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\xF3\x0F\x7F\x00\x80\x00\x00\x00\x00\x00\x00", "xxx?xxx?x???xxx"); + if (!rcMonitorAssignment) return FALSE; + printf("[AC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); + + // 22621.1992 has a different compiled code structure than 22621.2283 therefore we have to use a different approach: + // Short circuiting the `if (26008830 is enabled)`. + // 22621.1992: 7E313 + if (!IsWindows11Version22H2Build2134OrHigher()) // We're on 1413-1992 + { +#if USE_MOMENT_3_FIXES_ON_MOMENT_2 + PBYTE featureCheckJz = rcMonitorAssignment + 35; + if (*featureCheckJz != 0x0F && *(featureCheckJz + 1) != 0x84) return FALSE; + + DWORD dwOldProtect = 0; + PBYTE jzAddr = featureCheckJz + 6 + *(DWORD*)(featureCheckJz + 2); + if (!VirtualProtect(featureCheckJz, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + featureCheckJz[0] = 0xE9; + *(DWORD*)(featureCheckJz + 1) = (DWORD)(jzAddr - featureCheckJz - 5); + VirtualProtect(featureCheckJz, 5, dwOldProtect, &dwOldProtect); + goto done; +#else + return FALSE; +#endif + } + + // Step 2: + // Copy `*a2 = mi.rcMonitor` into right after the first jz starting from step 1. + // Find within couple bytes from step 1: + // ```48 8D // lea``` + // Then offset the first ?? so that it points to mi.rcWork which is 16 bytes after mi.rcMonitor. + // 22621.2283: 140E6 + PBYTE blockBegin = (PBYTE)FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); + if (!blockBegin) return FALSE; + printf("[AC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); + + // Step 3: + // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after + // the 8 bytes `rcMonitor = mi.rcWork` we've written. + PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); + if (!blockEnd) return FALSE; + printf("[AC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); + + // Execution + DWORD dwOldProtect = 0; + if (!VirtualProtect(blockBegin, 8 /**a2 = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + + // Step 2 + memcpy(blockBegin, rcMonitorAssignment, 8); + blockBegin[3] += offsetof(MONITORINFO, rcWork) - offsetof(MONITORINFO, rcMonitor); + + // Step 3 + PBYTE jmpToEnd = blockBegin + 8; + jmpToEnd[0] = 0xE9; + *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); + + VirtualProtect(blockBegin, 8 + 5, dwOldProtect, &dwOldProtect); + goto done; + +done: + printf("[AC] Patched!\n"); + return TRUE; +#else + return FALSE; +#endif +} + +// CControlCenterExperienceManager::PositionView() patcher +BOOL Moment2PatchControlCenter(LPMODULEINFO mi) +{ +#if defined(_M_X64) + // Step 1: + // Scan within the DLL for `rcMonitor = mi.rcMonitor`. + // ```0F 10 44 24 ?? F3 0F 7F 44 24 ?? 80 // movups - movdqu - cmp``` + // 22621.1992: 4B35B + // 22621.2283: 65C5C + PBYTE rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x44\x24\x00\xF3\x0F\x7F\x44\x24\x00\x80", "xxxx?xxxxx?x"); + if (!rcMonitorAssignment) return FALSE; + printf("[CC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); + + // Step 2: + // Scan within the function for the 10 bytes long `rcMonitor = mi.rcWork`. + // This pattern applies to both ControlCenter and ToastCenter. + // ```0F 10 45 ?? F3 0F 7F 44 24 ?? 48 // movups - movdqu - test``` + // 22621.1992: 4B3FD and 4B418 (The second one is compiled out in later builds) + // 22621.2283: 65CE6 + PBYTE rcWorkAssignment = (PBYTE)FindPattern(rcMonitorAssignment + 1, 256, "\x0F\x10\x45\x00\xF3\x0F\x7F\x44\x24\x00\x48", "xxx?xxxxx?x"); + if (!rcWorkAssignment) return FALSE; + printf("[CC] rcWorkAssignment = %llX\n", rcWorkAssignment - (PBYTE)mi->lpBaseOfDll); + + // Step 3: + // Copy the `rcMonitor = mi.rcWork` into right after the first jz starting from step 1. + // Find within couple bytes from step 1: + // ```48 8D // lea``` + // 22621.1992: 4B373 + // 22621.2283: 65C74 + PBYTE blockBegin = (PBYTE)FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); + if (!blockBegin) return FALSE; + printf("[CC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); + + // Step 4: + // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after + // the 10 bytes `rcMonitor = mi.rcWork` we've written. + PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); + if (!blockEnd) return FALSE; + printf("[CC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); + + // Execution + DWORD dwOldProtect = 0; + if (!VirtualProtect(blockBegin, 10 /*rcMonitor = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + + // Step 2 + memcpy(blockBegin, rcWorkAssignment, 10); + + // Step 3 + PBYTE jmpToEnd = blockBegin + 10; + jmpToEnd[0] = 0xE9; + *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); + + VirtualProtect(blockBegin, 10 + 5, dwOldProtect, &dwOldProtect); + + printf("[CC] Patched!\n"); + return TRUE; +#else + return FALSE; +#endif +} + +// CToastCenterExperienceManager::PositionView() patcher +BOOL Moment2PatchToastCenter(LPMODULEINFO mi) +{ +#if defined(_M_X64) + // Step 1: + // Scan within the DLL for `rcMonitor = mi.rcMonitor`. + // + // Pattern 1: + // Will have a match if CToastCenterExperienceManager::ShouldShowWithinWorkArea() is present. + // ```0F 10 45 ?? ?? 0F 7F 44 24 ?? 48 8B CF // movups - movdqu - mov``` + // 22621.1992: 40CE8 + // 22621.2283: 501DB + // + // Pattern 2: + // Will have a match if CToastCenterExperienceManager::ShouldShowWithinWorkArea() is inlined. + // ```0F 10 45 ?? ?? 0F 7F 44 24 ?? 44 38 // movups - movdqu - cmp``` + // 25951.1000: 36B2C4 + // + // Pattern 3: + // Same as pattern 1, but different length of the movdqu instruction. + // ```0F 10 45 ?? ?? 0F 7F 45 ?? 48 8B CF // movups - movdqu - mov``` + // 22621.3066: 3DC340 + // + // Pattern 4: + // Same as pattern 2, but different length of the movdqu instruction. + // ```0F 10 45 ?? ?? 0F 7F 45 ?? 44 38 // movups - movdqu - cmp``` + // No matches yet, just in case. + int assignmentSize = 10; + PBYTE rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x44\x24\x00\x48\x8B\xCF", "xxx??xxxx?xxx"); + if (!rcMonitorAssignment) + { + rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x44\x24\x00\x44\x38", "xxx??xxxx?xx"); + if (!rcMonitorAssignment) + { + assignmentSize = 9; + rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x45\x00\x48\x8B\xCF", "xxx??xxx?xxx"); + if (!rcMonitorAssignment) + { + rcMonitorAssignment = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x45\x00\x44\x38", "xxx??xxx?xx"); + if (!rcMonitorAssignment) return FALSE; + } + } + } + printf("[TC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); + + // Step 2: + // Copy the `rcMonitor = mi.rcMonitor` into right after the first jz starting from step 1. + // Find within couple bytes from step 1: + // ```48 8D // lea``` + // Then offset the first ?? so that it points to mi.rcWork which is 16 bytes after mi.rcMonitor. + // 22621.1992: 40D02 + // 22621.2283: 501F5 + PBYTE blockBegin = (PBYTE)FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); + if (!blockBegin) return FALSE; + printf("[TC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); + + // Step 3: + // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after + // the bytes `rcMonitor = mi.rcWork` we've written. + // + // Note: We are skipping EdgeUI calls here. + PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); + if (!blockEnd) return FALSE; + printf("[TC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); + + // Execution + DWORD dwOldProtect = 0; + if (!VirtualProtect(blockBegin, assignmentSize /*rcMonitor = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + + // Step 2 + memcpy(blockBegin, rcMonitorAssignment, assignmentSize); + blockBegin[3] += offsetof(MONITORINFO, rcWork) - offsetof(MONITORINFO, rcMonitor); + + // Step 3 + PBYTE jmpToEnd = blockBegin + assignmentSize; + jmpToEnd[0] = 0xE9; + *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); + + VirtualProtect(blockBegin, assignmentSize + 5, dwOldProtect, &dwOldProtect); + + printf("[TC] Patched!\n"); + return TRUE; +#else + return FALSE; +#endif +} + +// TaskViewFrame::RuntimeClassInitialize() patcher +BOOL Moment2PatchTaskView(LPMODULEINFO mi) +{ +#if defined(_M_X64) + /*** + If we're using the old taskbar, it'll be stuck in an infinite loading since it's waiting for the new one to respond. + Let's safely skip those by NOPing the `TaskViewFrame::UpdateWorkAreaAsync()` and `WaitForCompletion()` calls, and + turning off the COM object cleanup. + + Step 1: + Scan within the DLL to find the beginning, which is the preparation of the 1st call. + It should be 4C 8B or 4D 8B (mov r8, ...). + For the patterns, they're +1 from the result since it can be either of those. + + Pattern 1: + ```8B ?? 48 8D 55 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8``` + 22621.1992: 7463C + 22621.2134: 3B29C + + Pattern 2: + ```8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8``` + 22621.2283: 24A1D2 + + Step 2: + In place of the 1st call's call op (E8), overwrite it with a code to set the value of the com_ptr passed into the + 2nd argument (rdx) to 0. This is to skip the cleanup that happens right after the 2nd call. + ```48 C7 02 00 00 00 00 mov qword ptr [rdx], 0``` + Start from -13 of the byte after 2nd call's end. + 22621.1992: 74646 + 22621.2134: 3B2A6 + 22621.2283: 24A1DD + + Step 3: + NOP the rest of the 2nd call. + + Summary: + ``` + 48 8B ?? 48 8D 55 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // Pattern 1 + 48 8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // Pattern 2 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ + 1st: TaskViewFrame::UpdateWorkAreaAsync() 2nd: WaitForCompletion() + 48 8B ?? 48 8D 54 24 ?? 48 8B ?? 48 C7 02 00 00 00 00 90 90 90 90 90 90 // Result according to Pattern 2 + -------------------------------- xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxx + We need rdx Step 2 Step 3 + ``` + + Notes: + - In 22621.1992 and 22621.2134, `~AsyncOperationCompletedHandler()` is inlined, while it is not in 22621.2283. We + can see `unconditional_release_ref()` calls right in `RuntimeClassInitialize()` of 1992 and 2134. + - In 22621.2134, there is `33 FF xor edi, edi` before the jz for the inlined cleanup. The value of edi is used in + two more cleanup calls after our area of interest (those covered by twoCallsLength), therefore we can't just NOP + everything. And I think detecting such things is too much work. + ***/ + + int twoCallsLength = 1 + 18 + 4; // 4C/4D + pattern length + 4 bytes for the 2nd call's call address + PBYTE firstCallPrep = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x55\x00\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxx?xx?x????xxxx"); + if (!firstCallPrep) + { + twoCallsLength += 1; // Add 1 to the pattern length + firstCallPrep = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x54\x24\x00\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxxx?xx?x????xxxx"); + if (!firstCallPrep) return FALSE; + } + firstCallPrep -= 1; // Point to the 4C/4D + printf("[TV] firstCallPrep = %llX\n", firstCallPrep - (PBYTE)mi->lpBaseOfDll); + + PBYTE firstCallCall = firstCallPrep + twoCallsLength - 13; + printf("[TV] firstCallCall = %llX\n", firstCallCall - (PBYTE)mi->lpBaseOfDll); + + PBYTE nopBegin = firstCallCall + 7; + + // Execution + DWORD dwOldProtect = 0; + if (!VirtualProtect(firstCallPrep, twoCallsLength, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + const BYTE step2Payload[] = { 0x48, 0xC7, 0x02, 0x00, 0x00, 0x00, 0x00 }; + memcpy(firstCallCall, step2Payload, sizeof(step2Payload)); + memset(nopBegin, 0x90, twoCallsLength - (nopBegin - firstCallPrep)); + VirtualProtect(firstCallPrep, twoCallsLength, dwOldProtect, &dwOldProtect); + + printf("[TV] Patched!\n"); + return TRUE; +#else + return FALSE; +#endif +} + +// Reimplementation of HardwareConfirmatorHost::GetDisplayRect() +void WINAPI HardwareConfirmatorShellcode(PBYTE pCoroInstance) +{ + PBYTE pHardwareConfirmatorHost = *(PBYTE*)(pCoroInstance + g_Moment2PatchOffsets.coroInstance_pHardwareConfirmatorHost); + + RECT rc; + HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTOPRIMARY); + + ComPtr pImmersiveShell; + if (SUCCEEDED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pImmersiveShell)))) + { + ComPtr pMonitorService; + if (SUCCEEDED(pImmersiveShell->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&pMonitorService)))) + { + ComPtr pEdgeUiManager; + if (SUCCEEDED(pMonitorService->QueryService(hMonitor, SID_EdgeUi, IID_PPV_ARGS(&pEdgeUiManager)))) + { + if (*(pHardwareConfirmatorHost + g_Moment2PatchOffsets.hardwareConfirmatorHost_bIsInLockScreen)) + { + // Lock screen + MONITORINFO mi; + mi.cbSize = sizeof(MONITORINFO); + if (GetMonitorInfoW(hMonitor, &mi)) + rc = mi.rcMonitor; + } + else + { + // Desktop + LOG_IF_FAILED(pEdgeUiManager->GetAutohideImmuneWorkArea(&rc)); + } + + ABI::Windows::Foundation::Rect* out = (ABI::Windows::Foundation::Rect*)(pCoroInstance + g_Moment2PatchOffsets.coroInstance_rcOut); + out->X = (float)rc.left; + out->Y = (float)rc.top; + out->Width = (float)(rc.right - rc.left); + out->Height = (float)(rc.bottom - rc.top); + } + } + } +} + +// [HardwareConfirmatorHost::GetDisplayRectAsync$_ResumeCoro$1() patcher +BOOL Moment2PatchHardwareConfirmator(LPMODULEINFO mi) +{ +#if defined(_M_X64) + // Find required offsets + + // pHardwareConfirmatorHost and bIsInLockScreen: + // Find in GetDisplayRectAsync$_ResumeCoro$1, inside `case 4:` + // + // 48 8B 83 ED 00 00 00 mov rax, [rbx+0EDh] + // ^^^^^^^^^^^ pHardwareConfirmatorHost + // 8A 80 EC 00 00 00 mov al, [rax+0ECh] + // ^^^^^^^^^^^ bIsInLockScreen + // + // if ( ADJ(this)->pHardwareConfirmatorHost->bIsInLockScreen ) + // if ( *(_BYTE *)(*(_QWORD *)(this + 237) + 236i64) ) // 22621.2283 + // ^ HCH ^ bIsInLockScreen + // + // 22621.2134: 1D55D + PBYTE match1 = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x48\x8B\x83\x00\x00\x00\x00\x8A\x80", "xxx????xx"); + printf("[HC] match1 = %llX\n", match1 - (PBYTE)mi->lpBaseOfDll); + if (!match1) return FALSE; + g_Moment2PatchOffsets.coroInstance_pHardwareConfirmatorHost = *(int*)(match1 + 3); + g_Moment2PatchOffsets.hardwareConfirmatorHost_bIsInLockScreen = *(int*)(match1 + 9); + + // coroInstance_rcOut: + // Also in GetDisplayRectAsync$_ResumeCoro$1, through `case 4:` + // We also use this as the point to jump to, which is the code to set the rect and finish the coroutine. + // + // v27 = *(_OWORD *)(this + 16); + // *(_OWORD *)(this - 16) = v27; + // if ( winrt_suspend_handler ) ... + // + // 0F 10 43 10 movups xmm0, xmmword ptr [rbx+10h] + // ^^ coroInstance_rcOut + // 0F 11 84 24 D0 00 00 00 movups [rsp+158h+var_88], xmm0 + // + // 22621.2134: 1D624 + PBYTE match2 = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x43\x00\x0F\x11\x84\x24", "xxx?xxxx"); + printf("[HC] match2 = %llX\n", match2 - (PBYTE)mi->lpBaseOfDll); + if (!match2) return FALSE; + g_Moment2PatchOffsets.coroInstance_rcOut = *(match2 + 3); + + // Find where to put the shellcode + // We'll overwrite from this position: + // + // *(_OWORD *)(this + 32) = 0i64; + // *(_QWORD *)(this + 48) = MonitorFromRect((LPCRECT)(this + 32), 1u); + // + // 22621.2134: 1D21E + PBYTE writeAt = (PBYTE)FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x48\x8D\x4B\x00\x0F", "xxx?x"); + if (!writeAt) return FALSE; + printf("[HC] writeAt = %llX\n", writeAt - (PBYTE)mi->lpBaseOfDll); + + // In 22621.2134+, after our jump location there is a cleanup for something we skipped. NOP them. + // From match2, bytes +17 until +37, which is 21 bytes to be NOP'd. + // 22621.2134: 1D635-1D64A + PBYTE cleanupBegin = nullptr, cleanupEnd = nullptr; + if (IsWindows11Version22H2Build2134OrHigher()) + { + cleanupBegin = match2 + 17; + cleanupEnd = match2 + 38; // Exclusive + printf("[HC] cleanup = %llX-%llX\n", cleanupBegin - (PBYTE)mi->lpBaseOfDll, cleanupEnd - (PBYTE)mi->lpBaseOfDll); + if (*cleanupBegin != 0x49 || *cleanupEnd != 0x90 /*Already NOP here*/) return FALSE; + } + + // Craft the shellcode + BYTE shellcode[] = { + // lea rcx, [rbx+0] ; rbx is the `this` which is the instance of the coro, we pass it to our function + 0x48, 0x8D, 0x0B, + // mov rax, 1111111111111111h ; placeholder for the address of HardwareConfirmatorShellcode + 0x48, 0xB8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + // call rax + 0xFF, 0xD0 + }; + + uintptr_t pattern = 0x1111111111111111; + *(uintptr_t*)(memmem(shellcode, sizeof(shellcode), &pattern, sizeof(uintptr_t))) = (uintptr_t)HardwareConfirmatorShellcode; + + // Execution + DWORD dwOldProtect = 0; + SIZE_T totalSize = sizeof(shellcode) + 5; + if (!VirtualProtect(writeAt, totalSize, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + memcpy(writeAt, shellcode, sizeof(shellcode)); + PBYTE jmpLoc = writeAt + sizeof(shellcode); + jmpLoc[0] = 0xE9; + *(DWORD*)(jmpLoc + 1) = (DWORD)(match2 - jmpLoc - 5); + VirtualProtect(writeAt, totalSize, dwOldProtect, &dwOldProtect); + + if (cleanupBegin) + { + dwOldProtect = 0; + if (!VirtualProtect(cleanupBegin, cleanupEnd - cleanupBegin, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; + memset(cleanupBegin, 0x90, cleanupEnd - cleanupBegin); + VirtualProtect(cleanupBegin, cleanupEnd - cleanupBegin, dwOldProtect, &dwOldProtect); + } + + printf("[HC] Patched!\n"); + return TRUE; +#else + return FALSE; +#endif +} + +#pragma endregion + + +#pragma region "Fix broken Windows 10 start menu positioning issues caused by 44656322" + +// Reverts 44656322's effects on the start menu +extern "C" HRESULT CStartExperienceManager_GetMonitorInformationHook(void* _this, CSingleViewShellExperience* experience, RECT* rcOutWorkArea, EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor) +{ + *rcOutWorkArea = {}; + *outTrayStuckPlace = EUITSP_BOTTOM; + *bOutRtl = false; + if (hOutMonitor) + *hOutMonitor = nullptr; + + ComPtr spImmersiveShellServiceProvider; + RETURN_IF_FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&spImmersiveShellServiceProvider))); + + ComPtr spImmersiveLauncher; + RETURN_IF_FAILED(spImmersiveShellServiceProvider->QueryService(SID_ImmersiveLauncher, IID_PPV_ARGS(&spImmersiveLauncher))); + + ComPtr spImmersiveMonitor; + HRESULT hr = spImmersiveLauncher->GetMonitor(&spImmersiveMonitor); + if (FAILED(hr)) + return hr; + + HMONITOR hMonitor = nullptr; + if (hOutMonitor) + hr = spImmersiveMonitor->GetHandle(&hMonitor); + + if (FAILED(hr)) + return hr; + + ComPtr spEdgeUiManager; + hr = IUnknown_QueryService(spImmersiveMonitor.Get(), SID_EdgeUi, IID_PPV_ARGS(&spEdgeUiManager)); + if (FAILED(hr)) + return hr; + + EDGEUI_TRAYSTUCKPLACE trayStuckPlace; + RETURN_IF_FAILED(spEdgeUiManager->GetTrayStuckPlace(&trayStuckPlace)); + + HWND hwndTray = FindWindowW(L"Shell_TrayWnd", nullptr); + + RECT rcWork; + if (hwndTray && GetPropW(hwndTray, L"IsAutoHideEnabled")) + { + RETURN_IF_FAILED(spEdgeUiManager->GetAutohideImmuneWorkArea(&rcWork)); + } + else + { + RETURN_IF_FAILED(spImmersiveMonitor->GetWorkArea(&rcWork)); + } + + *rcOutWorkArea = rcWork; + *outTrayStuckPlace = trayStuckPlace; + *bOutRtl = Mirror_IsThreadRTL() != FALSE; + if (hOutMonitor) + *hOutMonitor = hMonitor; + + return S_OK; +} + +#pragma endregion + + +#pragma region "Fix Windows 10 start menu animation on 22000.65+" + +static struct +{ + int startExperienceManager_IStartExperienceManager; + int startExperienceManager_SingleViewShellExperienceEventHandler; + int startExperienceManager_singleViewShellExperience; + int startExperienceManager_openingAnimation; + int startExperienceManager_closingAnimation; + int startExperienceManager_bTransitioningToCortana; +} g_SMAnimationPatchOffsets; + +// Names taken from Windows.UI.Xaml.pdb, only defining the used ones +enum DWMTRANSITION_TARGET +{ + DWMTARGET_LAUNCHERFLYOUTTOLEFT = 0x4D, + DWMTARGET_LAUNCHERFLYOUTTORIGHT = 0x4E, + DWMTARGET_LAUNCHERFLYOUTTOTOP = 0x4F, + DWMTARGET_LAUNCHERFLYOUTTOBOTTOM = 0x50, + DWMTARGET_LAUNCHERFLYOUT = 0x51, + DWMTARGET_LAUNCHERFULLSCREEN = 0x52, +}; + +DEFINE_ENUM_FLAG_OPERATORS(DWMTRANSITION_TARGET); + +extern HRESULT CStartExperienceManager_GetMonitorInformationHook(void* _this, CSingleViewShellExperience* experience, RECT* rcOutWorkArea, EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor); +HRESULT(*CStartExperienceManager_GetMonitorInformationFunc)(void* _this, void* experience, RECT* rcOutWorkArea, EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor); +HRESULT(*CExperienceManagerAnimationHelper_BeginFunc)(void* _this, void* pViewWrapper, DWMTRANSITION_TARGET target, const RECT* prcBeginSource, const RECT* prcBeginDestination, const RECT* prcEndSource, const RECT* prcEndDestination, const RECT* prcClip); +HRESULT(*CExperienceManagerAnimationHelper_EndFunc)(void* _this); + +HRESULT(*CStartExperienceManager_OnViewUncloakingFunc)(void* eventHandler, CSingleViewShellExperience* pSender); +HRESULT CStartExperienceManager_OnViewUncloakingHook(void* eventHandler, CSingleViewShellExperience* pSender) +{ + PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; + + RECT rcWorkArea; + EDGEUI_TRAYSTUCKPLACE tsp; + bool bRtl; + if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationHook(_this, pSender, &rcWorkArea, &tsp, &bRtl, NULL)) && dwStartShowClassicMode) + { + DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT; + if (pSender->_fullScreen) + target = DWMTARGET_LAUNCHERFULLSCREEN; + else if (tsp == EUITSP_LEFT) + target = DWMTARGET_LAUNCHERFLYOUTTORIGHT; + else if (tsp == EUITSP_TOP) + target = DWMTARGET_LAUNCHERFLYOUTTOBOTTOM; + else if (tsp == EUITSP_RIGHT) + target = DWMTARGET_LAUNCHERFLYOUTTOLEFT; + else if (tsp == EUITSP_BOTTOM) + target = DWMTARGET_LAUNCHERFLYOUTTOTOP; + + CExperienceManagerAnimationHelper_BeginFunc( + _this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation, + pSender->_viewWrapper, + (DWMTRANSITION_TARGET)(target | 0x200000), nullptr, nullptr, nullptr, nullptr, &rcWorkArea); + } + + if (global_rovi.dwBuildNumber >= 25169) + { + // Patch hardcoded EUITSP_BOTTOM present in the original function with the correct value +#if defined(_M_X64) + static int* rgpConstants[2]; + if (!rgpConstants[0] && rgpConstants[0] != (int*)-1) + { + // 03 00 00 00 + PBYTE match = (PBYTE)FindPattern(CStartExperienceManager_OnViewUncloakingFunc, 80, "\x03\x00\x00\x00", "xxxx"); + rgpConstants[0] = match ? (int*)match : (int*)-1; + if (match) + { + match = (PBYTE)FindPattern(match + 4, 40, "\x03\x00\x00\x00", "xxxx"); + rgpConstants[1] = match ? (int*)match : (int*)-1; + } + } + for (int i = 0; i < ARRAYSIZE(rgpConstants); i++) + { + if (rgpConstants[i] && rgpConstants[i] != (int*)-1) + { + DWORD dwOldProtect; + if (VirtualProtect(rgpConstants[i], 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + *rgpConstants[i] = tsp; + VirtualProtect(rgpConstants[i], 4, dwOldProtect, &dwOldProtect); + } + } + } +#elif defined(_M_ARM64) + static DWORD* rgpInsnMovs[2]; + if (!rgpInsnMovs[0] && rgpInsnMovs[0] != (DWORD*)-1) + { + // 68 00 80 52 + PBYTE match = (PBYTE)FindPattern(CStartExperienceManager_OnViewUncloakingFunc, 160, "\x68\x00\x80\x52", "xxxx"); + rgpInsnMovs[0] = match ? (DWORD*)match : (DWORD*)-1; + if (match) + { + match = (PBYTE)FindPattern(match + 4, 40, "\x68\x00\x80\x52", "xxxx"); + rgpInsnMovs[1] = match ? (DWORD*)match : (DWORD*)-1; + } + } + for (int i = 0; i < ARRAYSIZE(rgpInsnMovs); i++) + { + if (rgpInsnMovs[i] && rgpInsnMovs[i] != (DWORD*)-1) + { + DWORD dwOldProtect; + if (VirtualProtect(rgpInsnMovs[i], 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + if (ARM64_IsInRange(tsp, 16)) + { + DWORD insn = *rgpInsnMovs[i]; + int imm16Mask = ((1 << 16) - 1) << 5; + insn &= ~imm16Mask; // clear imm16 + insn |= (tsp << 5) & imm16Mask; // set imm16 + *rgpInsnMovs[i] = insn; + } + VirtualProtect(rgpInsnMovs[i], 4, dwOldProtect, &dwOldProtect); + } + } + } +#endif + } + + return CStartExperienceManager_OnViewUncloakingFunc(eventHandler, pSender); +} + +HRESULT(*CStartExperienceManager_OnViewUncloakedFunc)(void* eventHandler, CSingleViewShellExperience* pSender); +HRESULT CStartExperienceManager_OnViewUncloakedHook(void* eventHandler, CSingleViewShellExperience* pSender) +{ + PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; + + if (dwStartShowClassicMode) + { + CExperienceManagerAnimationHelper_EndFunc(_this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation); + } + + return CStartExperienceManager_OnViewUncloakedFunc(eventHandler, pSender); +} + +HRESULT(*CStartExperienceManager_OnViewCloakingFunc)(void* eventHandler, CSingleViewShellExperience* pSender); +HRESULT CStartExperienceManager_OnViewCloakingHook(void* eventHandler, CSingleViewShellExperience* pSender) +{ + PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; + + bool bTransitioningToCortana = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); + if (!bTransitioningToCortana && dwStartShowClassicMode) + { + RECT rcWorkArea; + EDGEUI_TRAYSTUCKPLACE tsp; + bool bRtl; + HMONITOR hMonitor; + if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationHook(_this, pSender, &rcWorkArea, &tsp, &bRtl, &hMonitor))) + { + DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT; + if (pSender->_fullScreen) + target = DWMTARGET_LAUNCHERFULLSCREEN; + else if (tsp == EUITSP_LEFT) + target = DWMTARGET_LAUNCHERFLYOUTTOLEFT; + else if (tsp == EUITSP_TOP) + target = DWMTARGET_LAUNCHERFLYOUTTOTOP; + else if (tsp == EUITSP_RIGHT) + target = DWMTARGET_LAUNCHERFLYOUTTORIGHT; + else if (tsp == EUITSP_BOTTOM) + target = DWMTARGET_LAUNCHERFLYOUTTOBOTTOM; + + CExperienceManagerAnimationHelper_BeginFunc( + _this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation, + pSender->_viewWrapper, + (DWMTRANSITION_TARGET)(target | 0x200000), nullptr, nullptr, nullptr, nullptr, &rcWorkArea); + } + } + + return CStartExperienceManager_OnViewCloakingFunc(eventHandler, pSender); +} + +HRESULT(*CStartExperienceManager_OnViewHiddenFunc)(void* eventHandler, CSingleViewShellExperience* pSender); +HRESULT CStartExperienceManager_OnViewHiddenHook(void* eventHandler, CSingleViewShellExperience* pSender) +{ + PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; + + bool bTransitioningToCortana = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); + if (!bTransitioningToCortana && dwStartShowClassicMode) + { + CExperienceManagerAnimationHelper_EndFunc(_this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation); + } + + return CStartExperienceManager_OnViewHiddenFunc(eventHandler, pSender); +} + +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+. + + g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager = 0x28; + g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler = 0x60; + + // ### CStartExperienceManager::`vftable'{for `SingleViewShellExperienceEventHandler'} +#if defined(_M_X64) + // ``` + // 48 89 46 48 48 8D 05 ?? ?? ?? ?? 48 89 46 60 48 8D 4E 68 E8 + // ^^^^^^^^^^^ + // ``` + // Ref: CStartExperienceManager::CStartExperienceManager() + PBYTE matchVtable = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x48\x89\x46\x48\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x46\x60\x48\x8D\x4E\x68\xE8", + "xxxxxxx????xxxxxxxxx" + ); + if (matchVtable) + { + matchVtable += 4; + matchVtable += 7 + *(int*)(matchVtable + 3); + } +#elif defined(_M_ARM64) + // ``` + // 69 22 04 A9 ?? ?? 00 ?? 08 81 ?? 91 60 A2 01 91 68 32 00 F9 + // ^^^^^^^^^^^+^^^^^^^^^^^ + PBYTE matchVtable = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x69\x22\x04\xA9\x00\x00\x00\x00\x08\x81\x00\x91\x60\xA2\x01\x91\x68\x32\x00\xF9", + "xxxx??x?xx?xxxxxxxxx" + ); + if (matchVtable) + { + matchVtable += 4; + matchVtable = (PBYTE)ARM64_DecodeADRL((UINT_PTR)matchVtable, *(DWORD*)matchVtable, *(DWORD*)(matchVtable + 4)); + } +#endif + if (matchVtable) + { + printf("[SMA] matchVtable = %llX\n", matchVtable - (PBYTE)mi->lpBaseOfDll); + } + + // ### Offset of SingleViewShellExperience instance and its event handler +#if defined(_M_X64) + // ``` + // 48 8D 8E ?? ?? ?? ?? 44 8D 45 41 48 8D 56 60 E8 + // ^^^^^^^^^^^ SVSE ^^ SVSEEH (hardcoded to 0x60, included in pattern for sanity check) + // ``` + // Ref: CStartExperienceManager::CStartExperienceManager() + PBYTE matchSingleViewShellExperienceFields = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x48\x8D\x8E\x00\x00\x00\x00\x44\x8D\x45\x41\x48\x8D\x56\x60\xE8", + "xxx????xxxxxxxxx" + ); + if (matchSingleViewShellExperienceFields) + { + g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience = *(int*)(matchSingleViewShellExperienceFields + 3); + } +#elif defined(_M_ARM64) + // ``` + // 22 08 80 52 61 82 01 91 60 ?? ?? 91 ?? ?? ?? ?? 1F 20 03 D5 + // ^^^SVSEEH^^ ^^^^^^^^^^^ SVSE + // ``` + // Ref: CStartExperienceManager::CStartExperienceManager() + PBYTE matchSingleViewShellExperienceFields = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x22\x08\x80\x52\x61\x82\x01\x91\x60\x00\x00\x91\x00\x00\x00\x00\x1F\x20\x03\xD5", + "xxxxxxxxx??x????xxxx" + ); + if (matchSingleViewShellExperienceFields) + { + g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience = (int)ARM64_DecodeADD(*(DWORD*)(matchSingleViewShellExperienceFields + 8)); + } +#endif + if (matchSingleViewShellExperienceFields) + { + printf("[SMA] matchSingleViewShellExperienceFields = %llX\n", matchSingleViewShellExperienceFields - (PBYTE)mi->lpBaseOfDll); + } + + // ### Offsets of Animation Helpers + PBYTE matchAnimationHelperFields = nullptr; +#if defined(_M_X64) + // ``` + // 40 88 AE ?? ?? ?? ?? C7 86 ?? ?? ?? ?? 38 00 00 00 + // ^^^^^^^^^^^ AH1 + // ``` + // Ref: CStartExperienceManager::CStartExperienceManager() + // AH2 is located right after AH1. AH is 32 bytes + if (matchSingleViewShellExperienceFields) + { + matchAnimationHelperFields = (PBYTE)FindPattern( + matchSingleViewShellExperienceFields + 16, + 128, + "\x40\x88\xAE\x00\x00\x00\x00\xC7\x86\x00\x00\x00\x00\x38\x00\x00\x00", + "xxx????xx????xxxx" + ); + } + if (matchAnimationHelperFields) + { + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation = *(int*)(matchAnimationHelperFields + 3); + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation = g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation + 32; + } +#elif defined(_M_ARM64) + // ``` + // 08 07 80 52 7F ?? ?? 39 68 ?? ?? B9 + // ^^^^^^^^^^^ AH1 + // ``` + // Ref: CStartExperienceManager::CStartExperienceManager() + // AH2 is located right after AH1. AH is 32 bytes + if (matchSingleViewShellExperienceFields) + { + matchAnimationHelperFields = (PBYTE)FindPattern( + matchSingleViewShellExperienceFields + 20, + 128, + "\x08\x07\x80\x52\x7F\x00\x00\x39\x68\x00\x00\xB9", + "xxxxx??xx??x" + ); + } + if (matchAnimationHelperFields) + { + int openingAnimation = (int)ARM64_DecodeSTRBIMM(*(DWORD*)(matchAnimationHelperFields + 4)); + if (openingAnimation != -1) + { + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation = openingAnimation; + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation = g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation + 32; + } + else + { + matchAnimationHelperFields = nullptr; + } + } +#endif + if (matchAnimationHelperFields) + { + printf( + "[SMA] matchAnimationHelperFields = %llX, +0x%X, +0x%X\n", + matchAnimationHelperFields - (PBYTE)mi->lpBaseOfDll, + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation, + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation + ); + } + + // ### Offset of bTransitioningToCortana +#if defined(_M_X64) + // ``` + // 80 B9 ?? ?? ?? ?? 00 75 ?? 48 83 C1 D8 + // ^^^^^^^^^^^ bTransitioningToCortana + // ``` + // Ref: CStartExperienceManager::DimStart() + PBYTE matchTransitioningToCortanaField = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x80\xB9\x00\x00\x00\x00\x00\x75\x00\x48\x83\xC1\xD8", + "xx????xx?xxxx" + ); + if (matchTransitioningToCortanaField) + { + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana = g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager + *(int*)(matchTransitioningToCortanaField + 2); + } +#elif defined(_M_ARM64) + // ``` + // ?? ?? ?? 39 E8 00 00 35 ?? ?? ?? ?? 01 ?? ?? 91 22 00 80 52 + // ^^^^^^^^^^^ bTransitioningToCortana + // ``` + // Ref: CStartExperienceManager::DimStart() + PBYTE matchTransitioningToCortanaField = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x39\xE8\x00\x00\x35\x00\x00\x00\x00\x01\x00\x00\x91\x22\x00\x80\x52", + "xxxxx????x??xxxxx" + ); + if (matchTransitioningToCortanaField) + { + int off = (int)ARM64_DecodeLDRBIMM(*(DWORD*)(matchTransitioningToCortanaField - 3)); + if (off != -1) + { + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana = g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager + off; + } + else + { + matchTransitioningToCortanaField = nullptr; + } + } +#endif + if (matchTransitioningToCortanaField) + { + printf("[SMA] matchTransitioningToCortanaField = %llX, +0x%X\n", matchTransitioningToCortanaField - (PBYTE)mi->lpBaseOfDll, g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); + } + + // ### Offset of CStartExperienceManager::GetMonitorInformation() +#if defined(_M_X64) + // ``` + // 48 8B ?? E8 ?? ?? ?? ?? 8B ?? 85 C0 0F 88 ?? ?? ?? ?? C6 44 24 ?? 01 + // ^^^^^^^^^^^ + // ``` + // Ref: CStartExperienceManager::PositionMenu() + PBYTE matchGetMonitorInformation = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x48\x8B\x00\xE8\x00\x00\x00\x00\x8B\x00\x85\xC0\x0F\x88\x00\x00\x00\x00\xC6\x44\x24\x00\x01", + "xx?x????x?xxxx????xxx?x" + ); + if (matchGetMonitorInformation) + { + matchGetMonitorInformation += 3; + matchGetMonitorInformation += 5 + *(int*)(matchGetMonitorInformation + 1); + } +#elif defined(_M_ARM64) + // * Pattern for 261xx: + // ``` + // E2 82 00 91 E1 03 13 AA E0 03 14 AA ?? ?? ?? ?? + // ^^^^^^^^^^^ + // ``` + // * Different patterns needed for 226xx and 262xx+ + // Ref: CStartExperienceManager::PositionMenu() + PBYTE matchGetMonitorInformation = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\xE2\x82\x00\x91\xE1\x03\x13\xAA\xE0\x03\x14\xAA", + "xxxxxxxxxxxx" + ); + if (matchGetMonitorInformation) + { + matchGetMonitorInformation += 12; + matchGetMonitorInformation = (PBYTE)ARM64_FollowBL((DWORD*)matchGetMonitorInformation); + } +#endif + if (matchGetMonitorInformation) + { + CStartExperienceManager_GetMonitorInformationFunc = (decltype(CStartExperienceManager_GetMonitorInformationFunc))matchGetMonitorInformation; + printf("[SMA] CStartExperienceManager::GetMonitorInformation() = %llX\n", matchGetMonitorInformation - (PBYTE)mi->lpBaseOfDll); + } + + // ### Offset of CExperienceManagerAnimationHelper::Begin() +#if defined(_M_X64) + // * Pattern 1, used when all arguments are available: + // ``` + // 44 8B C7 E8 ?? ?? ?? ?? 85 C0 79 19 + // ^^^^^^^^^^^ + // ``` + // * Pattern 2, used when a4, a5, and a6 are optimized out (e.g. 26020, 26058): + // ``` + // 44 8B C7 48 8D 8B ?? ?? ?? ?? E8 ?? ?? ?? ?? 85 C0 79 19 + // ^^^^^^^^^^^ + // ``` + // Ref: CJumpViewExperienceManager::OnViewUncloaking() + PBYTE matchAnimationBegin = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x44\x8B\xC7\xE8\x00\x00\x00\x00\x85\xC0\x79\x19", + "xxxx????xxxx" + ); + if (matchAnimationBegin) + { + matchAnimationBegin += 3; + matchAnimationBegin += 5 + *(int*)(matchAnimationBegin + 1); + } + else + { + matchAnimationBegin = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x44\x8B\xC7\x48\x8D\x8B\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x85\xC0\x79\x19", + "xxxxxx????x????xxxx" + ); + if (matchAnimationBegin) + { + matchAnimationBegin += 10; + matchAnimationBegin += 5 + *(int*)(matchAnimationBegin + 1); + } + } +#elif defined(_M_ARM64) + // * Pattern 1, used when all arguments are available: + // ``` + // Not implemented + // + // ``` + // * Pattern 2, used when a4, a5, and a6 are optimized out (e.g. 26020, 26058): + // ``` + // 82 02 0B 32 67 ?? ?? 91 60 ?? ?? 91 ?? ?? ?? ?? E3 03 00 2A + // ^^^^^^^^^^^ + // ``` + // Ref: CJumpViewExperienceManager::OnViewUncloaking() + PBYTE matchAnimationBegin = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x82\x02\x0B\x32\x67\x00\x00\x91\x60\x00\x00\x91\x00\x00\x00\x00\xE3\x03\x00\x2A", + "xxxxx??xx??x????xxxx" + ); + if (matchAnimationBegin) + { + matchAnimationBegin += 12; + matchAnimationBegin = (PBYTE)ARM64_FollowBL((DWORD*)matchAnimationBegin); + } +#endif + if (matchAnimationBegin) + { + CExperienceManagerAnimationHelper_BeginFunc = (decltype(CExperienceManagerAnimationHelper_BeginFunc))matchAnimationBegin; + printf("[SMA] CExperienceManagerAnimationHelper::Begin() = %llX\n", matchAnimationBegin - (PBYTE)mi->lpBaseOfDll); + } + + // ### Offset of CExperienceManagerAnimationHelper::End() +#if defined(_M_X64) + // ``` + // 40 53 48 83 EC 20 80 39 00 74 + // ``` + PBYTE matchAnimationEnd = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x40\x53\x48\x83\xEC\x20\x80\x39\x00\x74", + "xxxxxxxxxx" + ); +#elif defined(_M_ARM64) + // ``` + // 7F 23 03 D5 F3 0F 1F F8 FD 7B BF A9 FD 03 00 91 08 00 40 39 + // ----------- PACIBSP, don't scan for this because it's everywhere + // ``` + PBYTE matchAnimationEnd = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\xF3\x0F\x1F\xF8\xFD\x7B\xBF\xA9\xFD\x03\x00\x91\x08\x00\x40\x39", + "xxxxxxxxxxxxxxxx" + ); + if (matchAnimationEnd) + { + matchAnimationEnd -= 4; + } +#endif + if (matchAnimationEnd) + { + CExperienceManagerAnimationHelper_EndFunc = (decltype(CExperienceManagerAnimationHelper_EndFunc))matchAnimationEnd; + printf("[SMA] CExperienceManagerAnimationHelper::End() = %llX\n", matchAnimationEnd - (PBYTE)mi->lpBaseOfDll); + } + + // ### CStartExperienceManager::Hide() +#if defined(_M_X64) + // * Pattern 1, mov [rbx+2A3h], r12b: + // ``` + // 74 ?? ?? 03 00 00 00 44 88 + // ^^ Turn jz into jmp + // ``` + // * Pattern 2, mov byte ptr [rbx+2A3h], 1: + // ``` + // 74 ?? ?? 03 00 00 00 C6 83 + // ^^ Turn jz into jmp + // ``` + // Perform on exactly two matches + PBYTE matchHideA = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x74\x00\x00\x03\x00\x00\x00\x44\x88", + "x??xxxxxx" + ); + PBYTE matchHideB = nullptr; + if (matchHideA) + { + printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); + matchHideB = (PBYTE)FindPattern( + matchHideA + 14, + mi->SizeOfImage - (matchHideA + 14 - (PBYTE)mi->lpBaseOfDll), + "\x74\x00\x00\x03\x00\x00\x00\x44\x88", + "x??xxxxxx" + ); + if (matchHideB) + { + printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); + } + } + + if (!matchHideA || !matchHideB) + { + matchHideA = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x74\x00\x00\x03\x00\x00\x00\xC6\x83", + "x??xxxxxx" + ); + matchHideB = nullptr; + if (matchHideA) + { + printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); + matchHideB = (PBYTE)FindPattern( + matchHideA + 14, + mi->SizeOfImage - (matchHideA + 14 - (PBYTE)mi->lpBaseOfDll), + "\x74\x00\x00\x03\x00\x00\x00\xC6\x83", + "x??xxxxxx" + ); + if (matchHideB) + { + printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); + } + } + } +#elif defined(_M_ARM64) + // ``` + // ?? ?? ?? 34 ?? 00 80 52 ?? 8E 0A 39 + // ^^^^^^^^^^^ Turn CBZ into B + // ``` + // Perform on exactly two matches + PBYTE matchHideA = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x34\x00\x00\x80\x52\x00\x8E\x0A\x39", + "x?xxx?xxx" + ); + PBYTE matchHideB = nullptr; + if (matchHideA) + { + matchHideA -= 3; + printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); + matchHideB = (PBYTE)FindPattern( + matchHideA + 12, + mi->SizeOfImage - (matchHideA + 12 - (PBYTE)mi->lpBaseOfDll), + "\x34\x00\x00\x80\x52\x00\x8E\x0A\x39", + "x?xxx?xxx" + ); + if (matchHideB) + { + matchHideB -= 3; + printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); + } + } +#endif + + if (!matchVtable + || !matchSingleViewShellExperienceFields + || !matchAnimationHelperFields + || !matchTransitioningToCortanaField + || !matchGetMonitorInformation + || !matchAnimationBegin + || !matchAnimationEnd + || !matchHideA + || !matchHideB) + { + printf("[SMA] Not all offsets were found, cannot perform patch\n"); + return FALSE; + } + + DWORD dwOldProtect = 0; + + void** vtable = (void**)matchVtable; + void** p_OnViewUncloaking = &vtable[4]; + void** p_OnViewUncloaked = &vtable[5]; + void** p_OnViewCloaking = &vtable[6]; + void** p_OnViewHidden = &vtable[10]; + + // OnViewUncloaking + if (*p_OnViewUncloaking != CStartExperienceManager_OnViewUncloakingHook) + { + CStartExperienceManager_OnViewUncloakingFunc = (decltype(CStartExperienceManager_OnViewUncloakingFunc))*p_OnViewUncloaking; + if (VirtualProtect(p_OnViewUncloaking, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + *p_OnViewUncloaking = CStartExperienceManager_OnViewUncloakingHook; + VirtualProtect(p_OnViewUncloaking, sizeof(void*), dwOldProtect, &dwOldProtect); + } + } + + // OnViewUncloaked + if (*p_OnViewUncloaked != CStartExperienceManager_OnViewUncloakedHook) + { + CStartExperienceManager_OnViewUncloakedFunc = (decltype(CStartExperienceManager_OnViewUncloakedFunc))*p_OnViewUncloaked; + if (VirtualProtect(p_OnViewUncloaked, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + *p_OnViewUncloaked = CStartExperienceManager_OnViewUncloakedHook; + VirtualProtect(p_OnViewUncloaked, sizeof(void*), dwOldProtect, &dwOldProtect); + } + } + + // OnViewCloaking + if (*p_OnViewCloaking != CStartExperienceManager_OnViewCloakingHook) + { + CStartExperienceManager_OnViewCloakingFunc = (decltype(CStartExperienceManager_OnViewCloakingFunc))*p_OnViewCloaking; + if (VirtualProtect(p_OnViewCloaking, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + *p_OnViewCloaking = CStartExperienceManager_OnViewCloakingHook; + VirtualProtect(p_OnViewCloaking, sizeof(void*), dwOldProtect, &dwOldProtect); + } + } + + // OnViewHidden + if (*p_OnViewHidden != CStartExperienceManager_OnViewHiddenHook) + { + CStartExperienceManager_OnViewHiddenFunc = (decltype(CStartExperienceManager_OnViewHiddenFunc))*p_OnViewHidden; + if (VirtualProtect(p_OnViewHidden, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + *p_OnViewHidden = CStartExperienceManager_OnViewHiddenHook; + VirtualProtect(p_OnViewHidden, sizeof(void*), dwOldProtect, &dwOldProtect); + } + } + + if (dwStartShowClassicMode) + { +#if defined(_M_X64) + if (VirtualProtect(matchHideA, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + matchHideA[0] = 0xEB; + VirtualProtect(matchHideA, 1, dwOldProtect, &dwOldProtect); + + dwOldProtect = 0; + if (VirtualProtect(matchHideB, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + matchHideB[0] = 0xEB; + VirtualProtect(matchHideB, 1, dwOldProtect, &dwOldProtect); + } + } +#elif defined(_M_ARM64) + if (VirtualProtect(matchHideA, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + DWORD newInsn = ARM64_CBZWToB(*(DWORD*)matchHideA); + if (newInsn) + *(DWORD*)matchHideA = newInsn; + VirtualProtect(matchHideA, 4, dwOldProtect, &dwOldProtect); + + dwOldProtect = 0; + if (VirtualProtect(matchHideB, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + { + newInsn = ARM64_CBZWToB(*(DWORD*)matchHideB); + if (newInsn) + *(DWORD*)matchHideB = newInsn; + VirtualProtect(matchHideB, 4, dwOldProtect, &dwOldProtect); + } + } +#endif + } + + int rv = -1; + if (CStartExperienceManager_GetMonitorInformationFunc) + { + rv = funchook_prepare( + funchook, + (void**)&CStartExperienceManager_GetMonitorInformationFunc, + CStartExperienceManager_GetMonitorInformationHook + ); + } + if (rv != 0) + { + printf("Failed to hook CStartExperienceManager::GetMonitorInformation(). rv = %d\n", rv); + } + + return TRUE; +} + +#pragma endregion + + +#pragma region "Fix broken taskbar jump list positioning caused by 40874676" + +class RoVariant +{ + enum States + { + StateIsNull = 0, + StateIsObjNoRef = 1, + StateIsObj = 3, + StateIsPV = 7 + }; + + static bool StateHasRefcount(HRESULT hrState) + { + return hrState == StateIsPV || hrState == StateIsObj; + } + + class Accessor + { + IInspectable* _pI; + HRESULT _hrState; + + ABI::Windows::Foundation::IPropertyValue* _PV() const + { + return (ABI::Windows::Foundation::IPropertyValue*)_pI; + } + + HRESULT VerifyPV() const + { + if (_hrState == StateIsPV) + return S_OK; + if (SUCCEEDED(_hrState)) + return TYPE_E_TYPEMISMATCH; + return _hrState; + } + + public: + Accessor(IInspectable* pI, HRESULT hr) : _pI(pI), _hrState(hr) {} + Accessor* operator->() { return this; } + HRESULT get_Type(ABI::Windows::Foundation::PropertyType* type) const; + + #define GETTER(name, type) HRESULT Get##name(type* value) const \ + { \ + if (!value) \ + return E_POINTER; \ + *value = {}; \ + HRESULT hr = VerifyPV(); \ + if (SUCCEEDED(hr)) \ + hr = _PV()->Get##name(value); \ + return hr; \ + } + + GETTER(UInt8, UINT8); + GETTER(Int16, INT16); + GETTER(UInt16, UINT16); + GETTER(Int32, INT32); + GETTER(UInt32, UINT32); + GETTER(Int64, INT64); + GETTER(UInt64, UINT64); + GETTER(Single, float); + GETTER(Double, double); + GETTER(Char16, WCHAR); + GETTER(Boolean, BOOLEAN); + GETTER(String, HSTRING); + GETTER(Guid, GUID); + GETTER(DateTime, ABI::Windows::Foundation::DateTime); + GETTER(TimeSpan, ABI::Windows::Foundation::TimeSpan); + GETTER(Point, ABI::Windows::Foundation::Point); + GETTER(Size, ABI::Windows::Foundation::Size); + GETTER(Rect, ABI::Windows::Foundation::Rect); + + #undef GETTER + + HRESULT GetInspectable(IInspectable** value) const + { + if (!value) + return E_POINTER; + *value = nullptr; + HRESULT hr = _hrState; + if (SUCCEEDED(hr)) + { + if (hr != StateIsNull && (hr == StateIsObj || hr == StateIsObjNoRef)) + { + *value = _pI; + _pI->AddRef(); + hr = S_OK; + } + else + { + hr = TYPE_E_TYPEMISMATCH; + } + } + return hr; + } + + #define GETTER_ARRAY(name, type) HRESULT Get##name##Array(UINT* length, type** value) const \ + { \ + if (!length || !value) \ + return E_POINTER; \ + *length = 0; \ + *value = nullptr; \ + HRESULT hr = VerifyPV(); \ + if (SUCCEEDED(hr)) \ + hr = _PV()->Get##name##Array(length, value); \ + return hr; \ + } + + GETTER_ARRAY(UInt8, UINT8); + GETTER_ARRAY(Int16, INT16); + GETTER_ARRAY(UInt16, UINT16); + GETTER_ARRAY(Int32, INT32); + GETTER_ARRAY(UInt32, UINT32); + GETTER_ARRAY(Int64, INT64); + GETTER_ARRAY(UInt64, UINT64); + GETTER_ARRAY(Single, float); + GETTER_ARRAY(Double, double); + GETTER_ARRAY(Char16, WCHAR); + GETTER_ARRAY(Boolean, BOOLEAN); + GETTER_ARRAY(String, HSTRING); + GETTER_ARRAY(Inspectable, IInspectable*); + GETTER_ARRAY(Guid, GUID); + GETTER_ARRAY(DateTime, ABI::Windows::Foundation::DateTime); + GETTER_ARRAY(TimeSpan, ABI::Windows::Foundation::TimeSpan); + GETTER_ARRAY(Point, ABI::Windows::Foundation::Point); + GETTER_ARRAY(Size, ABI::Windows::Foundation::Size); + GETTER_ARRAY(Rect, ABI::Windows::Foundation::Rect); + + #undef GETTER_ARRAY + }; + + class OutRef + { + RoVariant* _pOwner; + IInspectable* _pI; + + public: + OutRef(RoVariant* pOwner) : _pOwner(pOwner), _pI(nullptr) {} + operator ABI::Windows::Foundation::IPropertyValue**() { return (ABI::Windows::Foundation::IPropertyValue**)&_pI; } + operator IInspectable**() { return &_pI; } + ~OutRef() { _pOwner->Attach(_pI); } + }; + + IInspectable* _pI = nullptr; + HRESULT _hrState = StateIsNull; + +public: + RoVariant() = default; + RoVariant(RoVariant*); + RoVariant(RoVariant&); + RoVariant(ABI::Windows::Foundation::IPropertyValue*, bool); + +private: + RoVariant(IInspectable* pI, bool fAddRefInspectable, bool attach) + { + if (pI) + { + ABI::Windows::Foundation::IPropertyValue* pPV; + HRESULT hr = pI->QueryInterface(IID_PPV_ARGS(&pPV)); + if (SUCCEEDED(hr)) + { + _pI = pPV; + if (attach) + pI->Release(); + _hrState = StateIsPV; + } + else if (hr != E_NOINTERFACE) + { + _pI = nullptr; + _hrState = hr; + if (attach) + pI->Release(); + } + else + { + _pI = pI; + if (fAddRefInspectable && !attach) + _pI->AddRef(); + _hrState = fAddRefInspectable ? StateIsObj : StateIsObjNoRef; + } + } + else + { + _pI = nullptr; + _hrState = StateIsNull; + } + } + +public: + RoVariant(IInspectable* pI, bool attach) + { + RoVariant tmp(pI, true, attach); + Swap(tmp); + } + + RoVariant(void*); + + ~RoVariant() + { + if (_pI && StateHasRefcount(_hrState)) + _pI->Release(); + } + + RoVariant& operator=(RoVariant other) + { + Swap(other); + return *this; + } + + void Swap(RoVariant& other) + { + IInspectable* pI = _pI; + _pI = other._pI; + other._pI = pI; + + HRESULT hrState = _hrState; + _hrState = other._hrState; + other._hrState = hrState; + } + + operator IInspectable*() const { return Get(); } + IInspectable* Get() const { return _pI; } + IInspectable* Detach(); + void Attach(ABI::Windows::Foundation::IPropertyValue*); + + void Attach(IInspectable* pI) + { + RoVariant tmp = RoVariant(pI, true, true); + Swap(tmp); + } + + Accessor operator*() const { return Accessor(_pI, _hrState); } + Accessor operator->() const { return Accessor(_pI, _hrState); } + OutRef operator&() { return ReleaseAndGetAddressOf(); } + + struct USE_INSTEAD_ReleaseAndGetAddressOf + { + }; + + USE_INSTEAD_ReleaseAndGetAddressOf GetAddressOf() { return USE_INSTEAD_ReleaseAndGetAddressOf(); } + OutRef ReleaseAndGetAddressOf() { return OutRef(this); } + bool operator!(); + static RoVariant Wrap(ABI::Windows::Foundation::IPropertyValue*); + static RoVariant Wrap(IInspectable* pI) { return RoVariant(pI, false, false); } + HRESULT CopyTo(ABI::Windows::Foundation::IPropertyValue**); + HRESULT CopyTo(IInspectable**); +}; + +namespace ABI::Windows::UI::Xaml +{ + enum HorizontalAlignment + { + HorizontalAlignment_Left = 0, + HorizontalAlignment_Center = 1, + HorizontalAlignment_Right = 2, + HorizontalAlignment_Stretch = 3, + }; + + enum VerticalAlignment + { + VerticalAlignment_Top = 0, + VerticalAlignment_Center = 1, + VerticalAlignment_Bottom = 2, + VerticalAlignment_Stretch = 3, + }; +} + +HRESULT CJumpViewExperienceManager_CalcWindowPosition( + RECT rcWork, + POINT ptAnchor, + int width, + int height, + ABI::Windows::UI::Xaml::HorizontalAlignment hAlign, + ABI::Windows::UI::Xaml::VerticalAlignment vAlign, + RECT& result) +{ + using namespace ABI::Windows::UI::Xaml; + + if (false) // Feature_40874676 + { + result.bottom = max(min(ptAnchor.y, rcWork.bottom), rcWork.top); + int desiredTop = result.bottom - height; + result.top = max(desiredTop, rcWork.top); + int desiredLeft = ptAnchor.x - (width / 2); + result.left = min(max(desiredLeft, rcWork.left), rcWork.right); + result.right = min(result.left + width, rcWork.right); + return S_OK; + } + + switch (vAlign) + { + case VerticalAlignment_Center: + { + int desiredTopPre = (height / -2) + ptAnchor.y; + result.bottom = min(height + max(desiredTopPre, rcWork.top), rcWork.bottom); + int desiredTop = result.bottom - height; + result.top = max(desiredTop, rcWork.top); + break; + } + case VerticalAlignment_Top: + { + int desiredTopPre = ptAnchor.y; + result.bottom = min(height + max(desiredTopPre, rcWork.top), rcWork.bottom); + int desiredTop = result.bottom - height; + result.top = max(desiredTop, rcWork.top); + break; + } + case VerticalAlignment_Bottom: + { + int top = max(min(ptAnchor.y, rcWork.bottom) - height, rcWork.top); + result.bottom = min(top + height, rcWork.bottom); + result.top = top; + break; + } + default: + { + RETURN_HR(E_NOTIMPL); + } + } + + switch (hAlign) + { + case HorizontalAlignment_Center: + { + int desiredLeftPre = (width / -2) + ptAnchor.x; + result.right = min(width + max(desiredLeftPre, rcWork.left), rcWork.right); + int desiredLeft = result.right - width; + result.left = max(desiredLeft, rcWork.left); + break; + } + case HorizontalAlignment_Left: + { + int desiredLeftPre = ptAnchor.x; + result.right = min(width + max(desiredLeftPre, rcWork.left), rcWork.right); + int desiredLeft = result.right - width; + result.left = max(desiredLeft, rcWork.left); + break; + } + case HorizontalAlignment_Right: + { + result.left = max(min(ptAnchor.x, rcWork.right) - width, rcWork.left); + result.right = min(result.left + width, rcWork.right); + break; + } + default: + { + RETURN_HR(E_NOTIMPL); + } + } + + return S_OK; +} + +HRESULT CJumpViewExperienceManager_GetMonitorInformation(void* _this, POINT ptAnchor, RECT* prcOutWorkArea, UINT* outDpi, EDGEUI_TRAYSTUCKPLACE* outStuckPlace) +{ + HMONITOR hMonitor = MonitorFromPoint(ptAnchor, MONITOR_DEFAULTTONEAREST); + RETURN_LAST_ERROR_IF(hMonitor == INVALID_HANDLE_VALUE); + + MONITORINFO mi = { sizeof(mi) }; + RETURN_IF_WIN32_BOOL_FALSE(GetMonitorInfoW(hMonitor, &mi)); + *prcOutWorkArea = mi.rcWork; + + UINT dpiY; + RETURN_IF_FAILED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, outDpi, &dpiY)); // 884 + + ComPtr spImmersiveShellServiceProvider; + RETURN_IF_FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&spImmersiveShellServiceProvider))); + + ComPtr spImmersiveMonitorManager; + RETURN_IF_FAILED(spImmersiveShellServiceProvider->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&spImmersiveMonitorManager))); // 886 + + ComPtr spEdgeUiManager; + RETURN_IF_FAILED(spImmersiveMonitorManager->QueryService(hMonitor, SID_EdgeUi, IID_PPV_ARGS(&spEdgeUiManager))); // 887 + RETURN_IF_FAILED(spEdgeUiManager->GetTrayStuckPlace(outStuckPlace)); // 888 + + return S_OK; +} + +HRESULT(*CJumpViewExperienceManager_EnsureWindowPositionFunc)(void* _this, CSingleViewShellExperience* experience); +HRESULT CJumpViewExperienceManager_EnsureWindowPositionHook(void* _this, CSingleViewShellExperience* experience) +{ + if (!experience->_viewWrapper) + return S_OK; + + ComPtr> properties; + RETURN_IF_FAILED(experience->_propertySet.As(&properties)); // 813 + + POINT ptAnchor; + { + RoVariant variant; + RETURN_IF_FAILED(properties->Lookup(Wrappers::HStringReference(L"Position").Get(), &variant)); // 816 + + ABI::Windows::Foundation::Point value; + RETURN_IF_FAILED(variant->GetPoint(&value)); // 819 + + ptAnchor.x = (int)value.X; + ptAnchor.y = (int)value.Y; + } + + ABI::Windows::UI::Xaml::HorizontalAlignment hAlign; + { + RoVariant variant; + RETURN_IF_FAILED(properties->Lookup(Wrappers::HStringReference(L"HorizontalAlign").Get(), &variant)); // 828 + + int value; + RETURN_IF_FAILED(variant->GetInt32(&value)); // 831 + hAlign = (ABI::Windows::UI::Xaml::HorizontalAlignment)value; + } + + ABI::Windows::UI::Xaml::VerticalAlignment vAlign; + { + RoVariant variant; + RETURN_IF_FAILED(properties->Lookup(Wrappers::HStringReference(L"VerticalAlign").Get(), &variant)); // 838 + + int value; + RETURN_IF_FAILED(variant->GetInt32(&value)); // 841 + vAlign = (ABI::Windows::UI::Xaml::VerticalAlignment)value; + } + + RECT rcWorkArea; + UINT dpi; + RETURN_IF_FAILED(CJumpViewExperienceManager_GetMonitorInformation( + _this, ptAnchor, &rcWorkArea, &dpi, + (EDGEUI_TRAYSTUCKPLACE*)((PBYTE)_this + 0x1F0))); // 850 + *((RECT*)((PBYTE)_this + 0x200)) = rcWorkArea; + + int width, height; + ExperienceManagerUtils::ScaleByDPI(&experience->_desiredSize, dpi, &width, &height); + RETURN_HR_IF(E_INVALIDARG, width <= 0 || height <= 0); // 860 + + RECT rcPosition; + RETURN_IF_FAILED(CJumpViewExperienceManager_CalcWindowPosition(rcWorkArea, ptAnchor, width, height, hAlign, vAlign, rcPosition)); + RETURN_IF_FAILED(experience->SetPosition(&rcPosition)); + + return S_OK; +} + +BOOL FixJumpViewPositioning(MODULEINFO* mi) +{ + // Offset sanity checks + + // EDGEUI_TRAYSTUCKPLACE CJumpViewExperienceManager::m_trayStuckPlace +#if defined(_M_X64) + // 8B 8B B0 01 00 00 BF 5C 00 00 00 85 C9 + // ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewUncloaking() + PBYTE matchOffsetTrayStuckPlace = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x8B\x8B\xB0\x01\x00\x00\xBF\x5C\x00\x00\x00\x85\xC9", + "xxxxxxxxxxxxx" + ); +#elif defined(_M_ARM64) + // 08 B0 41 B9 89 0B 80 52 + // ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewCloaking() + PBYTE matchOffsetTrayStuckPlace = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x08\xB0\x41\xB9\x89\x0B\x80\x52", + "xxxxxxxx" + ); +#endif + if (matchOffsetTrayStuckPlace) + { + printf("[JVP] matchOffsetTrayStuckPlace = %llX\n", matchOffsetTrayStuckPlace - (PBYTE)mi->lpBaseOfDll); + } + + // RECT CJumpViewExperienceManager::m_rcWorkArea + PBYTE matchOffsetRcWorkArea = nullptr; +#if defined(_M_X64) + // 48 8B 53 70 48 8D 83 C0 01 00 00 + // -- ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewUncloaking() + if (matchOffsetTrayStuckPlace) + { + matchOffsetRcWorkArea = (PBYTE)FindPattern( + matchOffsetTrayStuckPlace + 13, + 256, + "\x48\x8B\x53\x70\x48\x8D\x83\xC0\x01\x00\x00", + "xxxxxxxxxxx" + ); + } +#elif defined(_M_ARM64) + // 01 38 40 F9 07 00 07 91 + // ----------- ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewCloaking() + if (matchOffsetTrayStuckPlace) + { + matchOffsetRcWorkArea = (PBYTE)FindPattern( + matchOffsetTrayStuckPlace + 8, + 128, + "\x01\x38\x40\xF9\x07\x00\x07\x91", + "xxxxxxxx" + ); + } +#endif + if (matchOffsetRcWorkArea) + { + printf("[JVP] matchOffsetRcWorkArea = %llX\n", matchOffsetRcWorkArea - (PBYTE)mi->lpBaseOfDll); + } + + // CJumpViewExperienceManager::EnsureWindowPosition() +#if defined(_M_X64) + // 8D 4E C0 48 8B ?? E8 ?? ?? ?? ?? 8B + // ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewPropertiesChanging() + PBYTE matchEnsureWindowPosition = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\x8D\x4E\xC0\x48\x8B\x00\xE8\x00\x00\x00\x00\x8B", + "xxxxx?x????x" + ); + if (matchEnsureWindowPosition) + { + matchEnsureWindowPosition += 6; + matchEnsureWindowPosition += 5 + *(int*)(matchEnsureWindowPosition + 1); + } +#elif defined(_M_ARM64) + // E1 03 15 AA 80 02 01 D1 ?? ?? ?? ?? F3 03 00 2A + // ^^^^^^^^^^^ + // Ref: CJumpViewExperienceManager::OnViewPropertiesChanging() + PBYTE matchEnsureWindowPosition = (PBYTE)FindPattern( + mi->lpBaseOfDll, + mi->SizeOfImage, + "\xE1\x03\x15\xAA\x80\x02\x01\xD1\x00\x00\x00\x00\xF3\x03\x00\x2A", + "xxxxxxxx????xxxx" + ); + if (matchEnsureWindowPosition) + { + matchEnsureWindowPosition += 8; + matchEnsureWindowPosition = (PBYTE)ARM64_FollowBL((DWORD*)matchEnsureWindowPosition); + } +#endif + if (matchEnsureWindowPosition) + { + printf("[JVP] matchEnsureWindowPosition = %llX\n", matchEnsureWindowPosition - (PBYTE)mi->lpBaseOfDll); + } + + if (!matchOffsetTrayStuckPlace + || !matchOffsetRcWorkArea + || !matchEnsureWindowPosition) + { + printf("[JVP] Not all offsets were found, cannot perform patch\n"); + return FALSE; + } + + CJumpViewExperienceManager_EnsureWindowPositionFunc = (decltype(CJumpViewExperienceManager_EnsureWindowPositionFunc))matchEnsureWindowPosition; + funchook_prepare( + funchook, + (void**)&CJumpViewExperienceManager_EnsureWindowPositionFunc, + CJumpViewExperienceManager_EnsureWindowPositionHook + ); + + return TRUE; +} + +#pragma endregion + + +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 + 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, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("Failed to open twinui.pcshell.dll\n"); + return; + } + + DWORD dwSize = GetFileSize(hFile, nullptr); + PBYTE pFile = (PBYTE)malloc(dwSize); + DWORD dwRead = 0; + if (!ReadFile(hFile, pFile, dwSize, &dwRead, nullptr) || dwRead != dwSize) + { + printf("Failed to read twinui.pcshell.dll\n"); + goto cleanup; + } + + if (IsWindows11()) + { + // All patterns here have been tested to work on: + // - 22621.1, 22621.1992, 22621.2134, 22621.2283, 22621.2359 (RP) + // - 23545.1000 + // - 25951.1000 + + if (!pOffsets[0] || pOffsets[0] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // 48 8B 49 08 E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 89 + // ^^^^^^^^^^^ + // Ref: CMultitaskingViewFrame::v_WndProc() + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x8B\x49\x08\xE8\x00\x00\x00\x00\xE9\x00\x00\x00\x00\x48\x8B\x89", + "xxxxx????x????xxx" + ); + if (match) + { + match += 4; + pOffsets[0] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } +#elif defined(_M_ARM64) + // ?? AE 00 71 ?? ?? 00 54 ?? 06 40 F9 E3 03 ?? AA E2 03 ?? AA E1 03 ?? 2A ?? ?? ?? ?? + // ^^^^^^^^^^^ + // Ref: CMultitaskingViewFrame::v_WndProc() + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\xAE\x00\x71\x00\x00\x00\x54\x00\x06\x40\xF9\xE3\x03\x00\xAA\xE2\x03\x00\xAA\xE1\x03\x00\x2A", + "xxx??xx?xxxxx?xxx?xxx?x" + ); + if (match) + { + match += 23; + pOffsets[0] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); + } +#endif + if (pOffsets[0] && pOffsets[0] != 0xFFFFFFFF) + { + printf("CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc() = %lX\n", pOffsets[0]); + } + } + if ((!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF) || (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF)) + { + UINT_PTR* vtable = nullptr; +#if defined(_M_X64) + // 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 41 18 48 8D 05 ?? ?? ?? ?? 48 89 41 20 48 8D 05 ?? ?? ?? ?? 48 89 41 58 48 8D 05 ?? ?? ?? ?? 48 89 41 60 + // ^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x8D\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x89\x01\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x18\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x20\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x58\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x60", + "xxx????xxxxxxxxx????xxxxxxx????xxxxxxx????xxxxxxx????xxxx" + ); + if (match) + { + match += 35; // Point to 48 + vtable = (UINT_PTR*)(match + 7 + *(int*)(match + 3)); + } +#elif defined(_M_ARM64) + // * Pattern 1 (for 24H2): + // 69 A2 01 A9 ?? ?? 00 ?? 09 ?? ?? 91 ?? ?? 00 ?? 08 ?? ?? 91 69 A2 05 A9 ?? ?? 00 ?? 08 ?? ?? 91 68 36 00 F9 ?? ?? 00 ?? 08 ?? ?? 91 68 3E 00 F9 + // ^^^^^^^^^^^+^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x69\xA2\x01\xA9\x00\x00\x00\x00\x09\x00\x00\x91\x00\x00\x00\x00\x08\x00\x00\x91\x69\xA2\x05\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x36\x00\xF9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x3E\x00\xF9", + "xxxx??x?x??x??x?x??xxxxx??x?x??xxxxx??x?x??xxxxx" + ); + // Patterns for 226xx are not implemented + if (match) + { + match += 4; // Point to ADRP + UINT_PTR vtableRVA = ARM64_DecodeADRL(FileOffsetToRVA(pFile, match - pFile), *(DWORD*)match, *(DWORD*)(match + 4)); + vtable = (UINT_PTR*)((UINT_PTR)pFile + RVAToFileOffset(pFile, vtableRVA)); + } +#endif + if (vtable) + { + if (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF) + { + pOffsets[6] = (DWORD)(vtable[3] - 0x180000000); + } + if (!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF) + { + pOffsets[1] = (DWORD)(vtable[4] - 0x180000000); + } + } + if (pOffsets[6] && pOffsets[6] != 0xFFFFFFFF) + { + printf("CLauncherTipContextMenu::ShowLauncherTipContextMenu() = %lX\n", pOffsets[6]); + } + if (pOffsets[1] && pOffsets[1] != 0xFFFFFFFF) + { + printf("CLauncherTipContextMenu::GetMenuItemsAsync() = %lX\n", pOffsets[1]); + } + } + if (!pOffsets[2] || pOffsets[2] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // Don't worry if this is too long, this works on 17763 and 25951 + // 40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B B5 ? ? ? ? 41 8B C1 + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x40\x55\x53\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x00\x00\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x33\xC4\x48\x89\x85\x00\x00\x00\x00\x4C\x8B\xB5\x00\x00\x00\x00\x41\x8B\xC1", + "xxxxxxxxxxxxxxxxx????xxx????xxx????xxxxxx????xxx????xxx" + ); + if (match) + { + pOffsets[2] = (DWORD)(match - pFile); + } +#elif defined(_M_ARM64) + // 40 F9 43 03 1C 32 E4 03 15 AA ?? ?? FF 97 + // ^^^^^^^^^^^ + // Ref: ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x40\xF9\x43\x03\x1C\x32\xE4\x03\x15\xAA\x00\x00\xFF\x97", + "xxxxxxxxxx??xx" + ); + if (match) + { + match += 10; + pOffsets[2] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); + } +#endif + if (pOffsets[2] && pOffsets[2] != 0xFFFFFFFF) + { + printf("ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() = %lX\n", pOffsets[2]); + } + } + if (!pOffsets[3] || pOffsets[3] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // 48 89 5C 24 ? 48 89 7C 24 ? 55 48 8B EC 48 83 EC 60 48 8B FA 48 8B D9 E8 + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x89\x5C\x24\x00\x48\x89\x7C\x24\x00\x55\x48\x8B\xEC\x48\x83\xEC\x60\x48\x8B\xFA\x48\x8B\xD9\xE8", + "xxxx?xxxx?xxxxxxxxxxxxxxx" + ); + if (match) + { + pOffsets[3] = (DWORD)(match - pFile); + } +#elif defined(_M_ARM64) + // 7F 23 03 D5 F3 53 BF A9 FD 7B BB A9 FD 03 00 91 F3 03 00 AA F4 03 01 AA ?? ?? ?? ?? FF ?? 03 A9 + // ----------- PACIBSP, don't scan for this because it's everywhere + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\xF3\x53\xBF\xA9\xFD\x7B\xBB\xA9\xFD\x03\x00\x91\xF3\x03\x00\xAA\xF4\x03\x01\xAA\x00\x00\x00\x00\xFF\x00\x03\xA9", + "xxxxxxxxxxxxxxxxxxxx????x?xx" + ); + if (match) + { + match -= 4; + pOffsets[3] = (DWORD)FileOffsetToRVA(pFile, match - pFile); + } +#endif + if (pOffsets[3] && pOffsets[3] != 0xFFFFFFFF) + { + printf("ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu() = %lX\n", pOffsets[3]); + } + } + if (!pOffsets[4] || pOffsets[4] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // 48 8B ? E8 ? ? ? ? 4C 8B ? 48 8B ? 48 8B CE E8 ? ? ? ? 90 + // ^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x8B\x00\xE8\x00\x00\x00\x00\x4C\x8B\x00\x48\x8B\x00\x48\x8B\xCE\xE8\x00\x00\x00\x00\x90", + "xx?x????xx?xx?xxxx????x" + ); + if (match) + { + match += 17; + pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } +#elif defined(_M_ARM64) + // 82 62 00 91 ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5 + // ^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x82\x62\x00\x91\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5", + "xxxx?xxxxx?x????xxxx" + ); + if (match) + { + match += 12; + pOffsets[4] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); + } +#endif + if (pOffsets[4] && pOffsets[4] != 0xFFFFFFFF) + { + printf("CLauncherTipContextMenu::_ExecuteShutdownCommand() = %lX\n", pOffsets[4]); + } + } + if (!pOffsets[5] || pOffsets[5] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // 48 8B ? E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90 48 8D 56 ? 48 8B CE + // ^^^^^^^ ------------------- Non-inlined ~::final_suspend() + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90\x48\x8D\x56\x00\x48\x8B\xCE", + "xx?x????xxxxxxx????xxxx?xxx" + ); + if (match) + { + match += 14; + pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } + else + { + // 48 8B ? E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90 48 8B 05 ? ? ? ? 48 + // ^^^^^^^ ------------------- Inlined ~::final_suspend() + match = (PBYTE)FindPattern( + pFile, dwSize, + "\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90\x48\x8B\x05\x00\x00\x00\x00\x48", + "xx?x????xxxxxxx????xxxx????x" + ); + if (match) + { + match += 14; + pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } + } +#elif defined(_M_ARM64) + // 08 09 40 F9 ?? 16 00 F9 ?? ?? ?? ?? ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5 + // ^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\x08\x09\x40\xF9\x00\x16\x00\xF9\x00\x00\x00\x00\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5", + "xxxx?xxx?????xxxxx?x????xxxx" + ); + if (match) + { + match += 20; + pOffsets[5] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); + } +#endif + if (pOffsets[5] && pOffsets[5] != 0xFFFFFFFF) + { + printf("CLauncherTipContextMenu::_ExecuteCommand() = %lX\n", pOffsets[5]); + } + } + if (!pOffsets[7] || pOffsets[7] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // Ref: CMultitaskingViewManager::_CreateMTVHost() + // Inlined GetMTVHostKind() + // 4C 89 74 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE E8 ?? ?? ?? ?? 8B + // ^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\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" + ); + if (match) + { + match += 16; + pOffsets[7] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } + else + { + // Non-inlined GetMTVHostKind() + // 8B CF E8 ?? ?? ?? ?? ?? 89 ?? 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE 83 F8 01 + match = (PBYTE)FindPattern( + pFile, dwSize, + "\x8B\xCF\xE8\x00\x00\x00\x00\x00\x89\x00\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\x83\xF8\x01", + "xxx?????x?x??x??x?xxxxxxxx" + ); + if (match) + { + PBYTE target = nullptr; + DWORD jnzSize = 0; + if (FollowJnz(match + 26, &target, &jnzSize)) + { + match += 26 + jnzSize; + if (match[0] == 0xE8) + { + pOffsets[7] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } + } + } + } +#elif defined(_M_ARM64) + // F3 53 BE A9 F5 5B 01 A9 FD 7B ?? A9 FD 03 00 91 30 00 80 92 F5 03 04 AA B0 ?? 00 F9 F3 03 00 AA BF 02 00 F9 68 2E 40 F9 F6 03 03 AA B3 23 02 A9 ?? ?? 00 B5 + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\xF3\x53\xBE\xA9\xF5\x5B\x01\xA9\xFD\x7B\x00\xA9\xFD\x03\x00\x91\x30\x00\x80\x92\xF5\x03\x04\xAA\xB0\x00\x00\xF9\xF3\x03\x00\xAA\xBF\x02\x00\xF9\x68\x2E\x40\xF9\xF6\x03\x03\xAA\xB3\x23\x02\xA9\x00\x00\x00\xB5", + "xxxxxxxxxx?xxxxxxxxxxxxxx?xxxxxxxxxxxxxxxxxxxxxx??xx" + ); + if (match) + { + pOffsets[7] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile); + } +#endif + if (pOffsets[7] && pOffsets[7] != 0xFFFFFFFF) + { + printf("CMultitaskingViewManager::_CreateXamlMTVHost() = %lX\n", pOffsets[7]); + } + } + if (!pOffsets[8] || pOffsets[8] == 0xFFFFFFFF) + { +#if defined(_M_X64) + // Ref: CMultitaskingViewManager::_CreateMTVHost() + // Inlined GetMTVHostKind() + // 4C 89 74 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE E8 ?? ?? ?? ?? 90 + // ^^^^^^^^^^^ + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\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" + ); + if (match) + { + match += 16; + pOffsets[8] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile); + } + else + { + // Non-inlined GetMTVHostKind() + // 8B CF E8 ?? ?? ?? ?? ?? 89 ?? 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE 83 F8 01 + match = (PBYTE)FindPattern( + pFile, dwSize, + "\x8B\xCF\xE8\x00\x00\x00\x00\x00\x89\x00\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\x83\xF8\x01", + "xxx?????x?x??x??x?xxxxxxxx" + ); + if (match) + { + PBYTE target = nullptr; + DWORD jnzSize = 0; + if (FollowJnz(match + 26, &target, &jnzSize) && target[0] == 0xE8) + { + pOffsets[8] = (DWORD)(target + 5 + *(int*)(target + 1) - pFile); + } + } + } +#elif defined(_M_ARM64) + // F3 53 BC A9 F5 5B 01 A9 F7 13 00 F9 F9 17 00 F9 FB 1B 00 F9 FD 7B BC A9 FD 03 00 91 FF ?? 00 D1 30 00 80 92 FB 03 04 AA + PBYTE match = (PBYTE)FindPattern( + pFile, dwSize, + "\xF3\x53\xBC\xA9\xF5\x5B\x01\xA9\xF7\x13\x00\xF9\xF9\x17\x00\xF9\xFB\x1B\x00\xF9\xFD\x7B\xBC\xA9\xFD\x03\x00\x91\xFF\x00\x00\xD1\x30\x00\x80\x92\xFB\x03\x04\xAA", + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx?xxxxxxxxxx" + ); + if (match) + { + pOffsets[8] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile); + } +#endif + if (pOffsets[8] && pOffsets[8] != 0xFFFFFFFF) + { + printf("CMultitaskingViewManager::_CreateDCompMTVHost() = %lX\n", pOffsets[8]); + } + } + } + +cleanup: + free(pFile); + CloseHandle(hFile); +} + +extern "C" void RunTwinUIPCShellPatches(symbols_addr* symbols_PTRS) +{ + HMODULE hTwinuiPcshell = LoadLibraryW(L"twinui.pcshell.dll"); + MODULEINFO miTwinuiPcshell; + GetModuleInformation(GetCurrentProcess(), hTwinuiPcshell, &miTwinuiPcshell, sizeof(MODULEINFO)); + + // ZeroMemory(symbols_PTRS->twinui_pcshell_PTRS, sizeof(symbols_PTRS->twinui_pcshell_PTRS)); // Uncomment for testing + TryToFindTwinuiPCShellOffsets(symbols_PTRS->twinui_pcshell_PTRS); + + if (symbols_PTRS->twinui_pcshell_PTRS[0] && symbols_PTRS->twinui_pcshell_PTRS[0] != 0xFFFFFFFF) + { + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc = (decltype(CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[0]); + } + + if (symbols_PTRS->twinui_pcshell_PTRS[1] && symbols_PTRS->twinui_pcshell_PTRS[1] != 0xFFFFFFFF) + { + CLauncherTipContextMenu_GetMenuItemsAsyncFunc = (decltype(CLauncherTipContextMenu_GetMenuItemsAsyncFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[1]); + } + + if (symbols_PTRS->twinui_pcshell_PTRS[2] && symbols_PTRS->twinui_pcshell_PTRS[2] != 0xFFFFFFFF) + { + ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc = (decltype(ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[2]); + } + + if (symbols_PTRS->twinui_pcshell_PTRS[3] && symbols_PTRS->twinui_pcshell_PTRS[3] != 0xFFFFFFFF) + { + ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (decltype(ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[3]); + } + + if (symbols_PTRS->twinui_pcshell_PTRS[4] && symbols_PTRS->twinui_pcshell_PTRS[4] != 0xFFFFFFFF) + { + CLauncherTipContextMenu_ExecuteShutdownCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteShutdownCommandFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[4]); + } + + if (symbols_PTRS->twinui_pcshell_PTRS[5] && symbols_PTRS->twinui_pcshell_PTRS[5] != 0xFFFFFFFF) + { + CLauncherTipContextMenu_ExecuteCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteCommandFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[5]); + } + + int rv = -1; + if (symbols_PTRS->twinui_pcshell_PTRS[6] && symbols_PTRS->twinui_pcshell_PTRS[6] != 0xFFFFFFFF) + { + CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc = (decltype(CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[6]); + rv = funchook_prepare( + funchook, + (void**)&CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc, + CLauncherTipContextMenu_ShowLauncherTipContextMenuHook + ); + } + if (rv != 0) + { + printf("Failed to hook CLauncherTipContextMenu::ShowLauncherTipContextMenu(). rv = %d\n", rv); + } + + if (IsWindows11()) + { + rv = -1; + if (symbols_PTRS->twinui_pcshell_PTRS[7] && symbols_PTRS->twinui_pcshell_PTRS[7] != 0xFFFFFFFF) + { + twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc = (decltype(twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[8]); + twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc = (decltype(twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[7]); + rv = funchook_prepare( + funchook, + (void**)&twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc, + twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostHook + ); + } + if (rv != 0) + { + printf("Failed to hook CMultitaskingViewManager::_CreateXamlMTVHost(). rv = %d\n", rv); + } + } + + /*rv = -1; + if (symbols_PTRS->twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1] && symbols_PTRS->twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1] != 0xFFFFFFFF) + { + winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc = (INT64(*)(void*, POINT*)) + ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1]); + rv = funchook_prepare( + funchook, + (void**)&winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc, + winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHook + ); + } + if (rv != 0) + { + printf("Failed to hook winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessage(). rv = %d\n", rv); + }*/ + +#if USE_MOMENT_3_FIXES_ON_MOMENT_2 + // Use this only for testing, since the RtlQueryFeatureConfiguration() hook is perfect. + // Only tested on 22621.1992. + BOOL bPerformMoment2Patches = IsWindows11Version22H2Build1413OrHigher(); +#else + // This is the only way to fix stuff since the flag "26008830" and the code when it's not enabled are gone. + // Tested on: + // - 22621.2134, 22621.2283, 22621.2359 (RP) + // - 23545.1000 + BOOL bPerformMoment2Patches = IsWindows11Version22H2Build2134OrHigher(); +#endif + if (bOldTaskbar != 1) + { + bPerformMoment2Patches = FALSE; + } + if (bPerformMoment2Patches) + { + // Fix flyout placement: Our goal with these patches is to get `mi.rcWork` assigned + Moment2PatchActionCenter(&miTwinuiPcshell); + Moment2PatchControlCenter(&miTwinuiPcshell); + Moment2PatchToastCenter(&miTwinuiPcshell); + + // Fix task view + Moment2PatchTaskView(&miTwinuiPcshell); + + // Fix volume and brightness popups + HMODULE hHardwareConfirmator = LoadLibraryW(L"Windows.Internal.HardwareConfirmator.dll"); + MODULEINFO miHardwareConfirmator; + GetModuleInformation(GetCurrentProcess(), hHardwareConfirmator, &miHardwareConfirmator, sizeof(MODULEINFO)); + Moment2PatchHardwareConfirmator(&miHardwareConfirmator); + + // Fix pen menu +#if defined(_M_X64) + // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 50 49 8B ? 48 81 C1 + PBYTE match = (PBYTE)FindPattern( + hTwinuiPcshell, + miTwinuiPcshell.SizeOfImage, + "\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x50\x49\x8B\x00\x48\x81\xC1", + "xxxx?xxxx?xxxxxxx?xxx" + ); +#elif defined(_M_ARM64) + PBYTE match = nullptr; +#endif + rv = -1; + if (match) + { + twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc = (decltype(twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc))match; + printf("PenMenuSystemTrayManager::GetDynamicSystemTrayHeightForMonitor() = %llX\n", match - (PBYTE)hTwinuiPcshell); + rv = funchook_prepare( + funchook, + (void**)&twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc, + twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorHook + ); + } + if (rv != 0) + { + 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+ + && (bOldTaskbar || 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. + if (IsCrashCounterEnabled()) + { + if (FixStartMenuAnimation(&miTwinuiPcshell)) + { + ReportSuccessfulAnimationPatching(); + } + } + } + + if (IsWindows11Version22H2OrHigher() && bOldTaskbar) + { + // Fix broken taskbar jump list positioning caused by 40874676 + FixJumpViewPositioning(&miTwinuiPcshell); + } + + VnPatchIAT_NonInline(hTwinuiPcshell, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegGetValueW", (uintptr_t)twinuipcshell_RegGetValueW); + printf("Setup twinui.pcshell functions done\n"); +} diff --git a/ExplorerPatcher/def.h b/ExplorerPatcher/def.h index 17c2a385f..865e30ed8 100644 --- a/ExplorerPatcher/def.h +++ b/ExplorerPatcher/def.h @@ -15,7 +15,7 @@ #ifndef _M_ARM64 #define SETUP_UTILITY_NAME "ep_setup.exe" #else -#define SETUP_UTILITY_NAME "ep_setup.arm64.exe" +#define SETUP_UTILITY_NAME "ep_setup_arm64.exe" #endif #define TOAST_BUFSIZ 1536 #define SEH_REGPATH "Control Panel\\Quick Actions\\Control Center\\QuickActionsStateCapture\\ExplorerPatcher" diff --git a/ExplorerPatcher/dllmain.c b/ExplorerPatcher/dllmain.c index a36914e24..0e7e8e303 100644 --- a/ExplorerPatcher/dllmain.c +++ b/ExplorerPatcher/dllmain.c @@ -59,9 +59,6 @@ DWORD32 global_ubr; #pragma comment(lib, "Userenv.lib") #endif -#define WINX_ADJUST_X 5 -#define WINX_ADJUST_Y 5 - #define CHECKFOREGROUNDELAPSED_TIMEOUT 300 #define POPUPMENU_SAFETOREMOVE_TIMEOUT 300 #define POPUPMENU_BLUETOOTH_TIMEOUT 700 @@ -128,8 +125,6 @@ DWORD dwMMTaskbarGlomLevel = MMTASKBARGLOMLEVEL_DEFAULT; HMODULE hModule = NULL; HANDLE hShell32 = NULL; HANDLE hDelayedInjectionThread = NULL; -HANDLE hIsWinXShown = NULL; -HANDLE hWinXThread = NULL; HANDLE hSwsSettingsChanged = NULL; HANDLE hSwsOpacityMaybeChanged = NULL; HANDLE hWin11AltTabInitialized = NULL; @@ -223,7 +218,6 @@ BOOL g_bIsDesktopRaised = FALSE; #include "updates.h" DWORD dwUpdatePolicy = UPDATE_POLICY_DEFAULT; wchar_t* EP_TASKBAR_LENGTH_PROP_NAME = L"EPTBLEN"; -HWND hWinXWnd; #if WITH_MAIN_PATCHER #define MAX_NUM_MONITORS 30 @@ -837,83 +831,6 @@ BOOL ToggleActionCenter() { return PostMessageW(FindWindowExW(NULL, NULL, L"Shell_TrayWnd", NULL), WM_HOTKEY, 500, MAKELPARAM(MOD_WIN, 0x41)); } - -#if WITH_MAIN_PATCHER -void ToggleLauncherTipContextMenu() -{ - if (hIsWinXShown) - { - SendMessage(hWinXWnd, WM_CLOSE, 0, 0); - } - else - { - HWND hWnd = FindWindowEx( - NULL, - NULL, - L"Shell_TrayWnd", - NULL - ); - if (hWnd) - { - hWnd = FindWindowEx( - hWnd, - NULL, - L"Start", - NULL - ); - if (hWnd) - { - POINT pt = GetDefaultWinXPosition(FALSE, NULL, NULL, TRUE, FALSE); - // Finally implemented a variation of - // https://github.com/valinet/ExplorerPatcher/issues/3 - // inspired by how the real Start button activates this menu - // (CPearl::_GetLauncherTipContextMenu) - // This also works when auto hide taskbar is on (#63) - HRESULT hr = S_OK; - IUnknown* pImmersiveShell = NULL; - hr = CoCreateInstance( - &CLSID_ImmersiveShell, - NULL, - CLSCTX_INPROC_SERVER, - &IID_IServiceProvider, - &pImmersiveShell - ); - if (SUCCEEDED(hr)) - { - IImmersiveMonitorService* pMonitorService = NULL; - IUnknown_QueryService( - pImmersiveShell, - &SID_IImmersiveMonitorService, - &IID_IImmersiveMonitorService, - &pMonitorService - ); - if (pMonitorService) - { - ILauncherTipContextMenu* pMenu = NULL; - pMonitorService->lpVtbl->QueryServiceFromWindow( - pMonitorService, - hWnd, - &IID_ILauncherTipContextMenu, - &IID_ILauncherTipContextMenu, - &pMenu - ); - if (pMenu) - { - pMenu->lpVtbl->ShowLauncherTipContextMenu( - pMenu, - &pt - ); - pMenu->lpVtbl->Release(pMenu); - } - pMonitorService->lpVtbl->Release(pMonitorService); - } - pImmersiveShell->lpVtbl->Release(pImmersiveShell); - } - } - } - } -} -#endif #pragma endregion @@ -936,475 +853,46 @@ HRESULT WINAPI windowsudkshellcommon_SLGetWindowsInformationDWORDHook(PCWSTR pws #pragma region "twinui.pcshell.dll hooks" #if WITH_MAIN_PATCHER -#define LAUNCHERTIP_CLASS_NAME L"LauncherTipWnd" -static INT64(*winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc)( - void* _this, - INT64 a2, - INT a3 - ) = NULL; -static INT64(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)( - void* _this, - POINT* pt - ) = NULL; -static void(*CLauncherTipContextMenu_ExecuteCommandFunc)( - void* _this, - int a2 - ) = NULL; -static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)( - void* _this, - void* a2 - ) = NULL; -typedef HRESULT(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t)(HMENU hMenu, HWND hWnd, POINT* pPt, unsigned int options, void* data); -static ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc; -typedef void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t)(HMENU hMenu, HWND hWnd); -static ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc; -static INT64(*CLauncherTipContextMenu_GetMenuItemsAsyncFunc)( - void* _this, - RECT rect, - IUnknown** iunk - ) = NULL; -static INT64(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc)( - HWND hWnd, - int a2, - HWND a3, - int a4, - BOOL* a5 - ) = NULL; - -LRESULT CALLBACK CLauncherTipContextMenu_WndProc( - _In_ HWND hWnd, - _In_ UINT uMsg, - _In_ WPARAM wParam, - _In_ LPARAM lParam -) -{ - LRESULT result; - - if (hWnd == archivehWnd && !ArchiveMenuWndProc( - hWnd, - uMsg, - wParam, - lParam, - ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc, - ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc - )) - { - return 0; - } +typedef HRESULT(*ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t)(HMENU hmenu, HWND hWnd, POINT* pptOrigin, unsigned int icmoFlags, void* srgRenderingData); +ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc; +typedef void(*ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t)(HMENU hmenu, HWND hwnd); +ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc; +typedef LRESULT(*CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc_t)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc_t CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc; - if (uMsg == WM_NCCREATE) - { - CREATESTRUCT* pCs = lParam; - if (pCs->lpCreateParams) - { - *((HWND*)((char*)pCs->lpCreateParams + 0x78)) = hWnd; - SetWindowLongPtr( - hWnd, - GWLP_USERDATA, - pCs->lpCreateParams - ); - result = DefWindowProc( - hWnd, - uMsg, - wParam, - lParam - ); - } - else - { - result = DefWindowProc( - hWnd, - uMsg, - wParam, - lParam - ); - //result = 0; - } - } - else - { - void* _this = GetWindowLongPtr(hWnd, GWLP_USERDATA); - BOOL v12 = FALSE; - if ((uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) && - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc && - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc( - hWnd, - uMsg, - wParam, - lParam, - &v12 - )) - { - result = 0; - } - else - { - result = DefWindowProc( - hWnd, - uMsg, - wParam, - lParam - ); - } - if (_this) - { - if (uMsg == WM_NCDESTROY) - { - SetWindowLongPtrW( - hWnd, - GWLP_USERDATA, - 0 - ); - *((HWND*)((char*)_this + 0x78)) = 0; - } - } - } - return result; -} +extern void ToggleLauncherTipContextMenu(); +extern LRESULT CALLBACK CLauncherTipContextMenu_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +extern void RunTwinUIPCShellPatches(symbols_addr* symbols_PTRS); -typedef struct +BOOL VnPatchIAT_NonInline(HMODULE hMod, const char* libName, const char* funcName, uintptr_t hookAddr) { - void* _this; - POINT point; - IUnknown* iunk; - BOOL bShouldCenterWinXHorizontally; -} ShowLauncherTipContextMenuParameters; -DWORD ShowLauncherTipContextMenu( - ShowLauncherTipContextMenuParameters* params -) -{ - // Adjust this based on info from: CLauncherTipContextMenu::SetSite - // and CLauncherTipContextMenu::CLauncherTipContextMenu - // 22000.739: 0xe8 - // 22000.778: 0xf0 - // What has happened, between .739 and .778 is that the launcher tip - // context menu object now implements a new interface, ILauncherTipContextMenuMigration; - // thus, members have shifted 8 bytes (one 64-bit value which will hold the - // address of the vtable for this intf at runtime) to the right; - // all this intf seems to do, as of now, is to remove some "obsolete" links - // from the menu (check out "CLauncherTipContextMenu::RunMigrationTasks"); it - // seems you can disable this by setting a DWORD "WinXMigrationLevel" = 1 in - // HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced - int offset_in_class = 0; - if (global_rovi.dwBuildNumber >= 22621 || (global_rovi.dwBuildNumber == 22000 && global_ubr >= 778)) - { - offset_in_class = 8; - } - - static ATOM windowRegistrationAtom = 0; - if (windowRegistrationAtom == 0) - { - WNDCLASS wc = { - .style = CS_DBLCLKS, - .lpfnWndProc = CLauncherTipContextMenu_WndProc, - .hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH), - .hInstance = GetModuleHandleW(NULL), - .lpszClassName = LAUNCHERTIP_CLASS_NAME, - .hCursor = LoadCursorW(NULL, IDC_ARROW) - }; - ATOM atom = RegisterClassW(&wc); - if (atom) - windowRegistrationAtom = atom; - } - - hWinXWnd = CreateWindowInBand( - 0, - MAKEINTATOM(windowRegistrationAtom), - 0, - WS_POPUP, - 0, 0, 0, 0, - NULL, NULL, - GetModuleHandle(NULL), - (char*)params->_this - 0x58, - 7 // ZBID_IMMERSIVE_EDGY - ); - // DO NOT USE ShowWindow here; it breaks the window order - // and renders the desktop toggle unusable; but leave - // SetForegroundWindow as is so that the menu gets dismissed - // when the user clicks outside it - // - // ShowWindow(hWinXWnd, SW_SHOW); - SetForegroundWindow(hWinXWnd); - - while (!(*((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)))) - { - Sleep(1); - } - if (!(*((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)))) - { - goto finalize; - } - - TCHAR buffer[260]; - LoadStringW(GetModuleHandleW(L"ExplorerFrame.dll"), 50222, buffer + (bNoMenuAccelerator ? 0 : 1), 260); - if (!bNoMenuAccelerator) - { - buffer[0] = L'&'; - } - wchar_t* p = wcschr(buffer, L'('); - if (p) - { - p--; - if (*p == L' ') - { - *p = 0; - } - else - { - p++; - *p = 0; - } - } - - BOOL bCreatedMenu = FALSE; - MENUITEMINFOW menuInfo; - ZeroMemory(&menuInfo, sizeof(MENUITEMINFOW)); - menuInfo.cbSize = sizeof(MENUITEMINFOW); - menuInfo.fMask = MIIM_ID | MIIM_STRING | MIIM_DATA; - menuInfo.wID = 3999; - menuInfo.dwItemData = 0; - menuInfo.fType = MFT_STRING; - menuInfo.dwTypeData = buffer; - menuInfo.cch = wcslen(buffer); - if (bPropertiesInWinX) - { - InsertMenuItemW( - *((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)), - GetMenuItemCount(*((HMENU*)((char*)params->_this + 0xe8 + offset_in_class))) - 1, - TRUE, - &menuInfo - ); - bCreatedMenu = TRUE; - } - - INT64* unknown_array = NULL; - if (bSkinMenus) - { - unknown_array = calloc(4, sizeof(INT64)); - if (ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc) - { - ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc( - *((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)), - hWinXWnd, - &(params->point), - 0xc, - unknown_array - ); - } - } - - BOOL res = TrackPopupMenu( - *((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)), - TPM_RETURNCMD | TPM_RIGHTBUTTON | (params->bShouldCenterWinXHorizontally ? TPM_CENTERALIGN : 0), - params->point.x, - params->point.y, - 0, - hWinXWnd, - 0 - ); - - if (bSkinMenus) - { - if (ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc) - { - ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc( - *((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)), - hWinXWnd - ); - } - free(unknown_array); - } - - if (bCreatedMenu) - { - RemoveMenu( - *((HMENU*)((char*)params->_this + 0xe8 + offset_in_class)), - 3999, - MF_BYCOMMAND - ); - } - - if (res > 0) - { - if (bCreatedMenu && res == 3999) - { - LaunchPropertiesGUI(hModule); - } - else if (res < 4000) - { - INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xa8 + offset_in_class - 0x58)) + (INT64)res * 8 - 8); - if (CLauncherTipContextMenu_ExecuteCommandFunc) - { - CLauncherTipContextMenu_ExecuteCommandFunc( - (char*)params->_this - 0x58, - &info - ); - } - } - else - { - INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xc8 + offset_in_class - 0x58)) + ((INT64)res - 4000) * 8); - if (CLauncherTipContextMenu_ExecuteShutdownCommandFunc) - { - CLauncherTipContextMenu_ExecuteShutdownCommandFunc( - (char*)params->_this - 0x58, - &info - ); - } - } - } - -finalize: - params->iunk->lpVtbl->Release(params->iunk); - SendMessage( - hWinXWnd, - WM_CLOSE, - 0, - 0 - ); - free(params); - hIsWinXShown = NULL; - return 0; + return VnPatchIAT(hMod, (PSTR)libName, (PSTR)funcName, hookAddr); } -INT64 CLauncherTipContextMenu_ShowLauncherTipContextMenuHook( - void* _this, - POINT* pt -) +void ReportSuccessfulAnimationPatching() { - if (hWinXThread) - { - WaitForSingleObject(hWinXThread, INFINITE); - CloseHandle(hWinXThread); - hWinXThread = NULL; - } - - if (hIsWinXShown) +#if WITH_SMA_PATCH_REPORT + PSID pMainSid = NULL; + GetLogonSid(&pMainSid); + PSID pSecondaySid = NULL; + DeriveAppContainerSidFromAppContainerName(L"Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy", &pSecondaySid); + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + if (PrepareSecurityDescriptor(pMainSid, STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS, pSecondaySid, SYNCHRONIZE, &pSecurityDescriptor)) { - goto finalize; - } - - BOOL bShouldCenterWinXHorizontally = FALSE; - POINT point; - if (pt) - { - point = *pt; - BOOL bBottom, bRight; - POINT dPt = GetDefaultWinXPosition(FALSE, &bBottom, &bRight, FALSE, FALSE); - POINT posCursor; - GetCursorPos(&posCursor); - RECT rcHitZone; - rcHitZone.left = pt->x - 5; - rcHitZone.right = pt->x + 5; - rcHitZone.top = pt->y - 5; - rcHitZone.bottom = pt->y + 5; - //printf("%d %d = %d %d %d %d\n", posCursor.x, posCursor.y, rcHitZone.left, rcHitZone.right, rcHitZone.top, rcHitZone.bottom); - if (bBottom && IsThemeActive() && PtInRect(&rcHitZone, posCursor) && GetClassWord(WindowFromPoint(point), GCW_ATOM) == RegisterWindowMessageW(L"Start")) - { - HMONITOR hMonitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY); - MONITORINFO mi; - mi.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(hMonitor, &mi); - HWND hWndUnder = WindowFromPoint(*pt); - TCHAR wszClassName[100]; - ZeroMemory(wszClassName, 100); - GetClassNameW(hWndUnder, wszClassName, 100); - if (!wcscmp(wszClassName, L"Shell_TrayWnd") || !wcscmp(wszClassName, L"Shell_SecondaryTrayWnd")) - { - hWndUnder = FindWindowEx( - hWndUnder, - NULL, - L"Start", - NULL - ); - } - RECT rcUnder; - GetWindowRect(hWndUnder, &rcUnder); - if (mi.rcMonitor.left != rcUnder.left) - { - bShouldCenterWinXHorizontally = TRUE; - point.x = rcUnder.left + (rcUnder.right - rcUnder.left) / 2; - point.y = rcUnder.top; - } - else - { - UINT dpiX, dpiY; - HRESULT hr = GetDpiForMonitor( - hMonitor, - MDT_DEFAULT, - &dpiX, - &dpiY - ); - double dx = dpiX / 96.0, dy = dpiY / 96.0; - BOOL xo = FALSE, yo = FALSE; - if (point.x - WINX_ADJUST_X * dx < mi.rcMonitor.left) - { - xo = TRUE; - } - if (point.y + WINX_ADJUST_Y * dy > mi.rcMonitor.bottom) - { - yo = TRUE; - } - POINT ptCursor; - GetCursorPos(&ptCursor); - if (xo) - { - ptCursor.x += (WINX_ADJUST_X * 2) * dx; - } - else - { - point.x -= WINX_ADJUST_X * dx; - } - if (yo) - { - ptCursor.y -= (WINX_ADJUST_Y * 2) * dy; - } - else - { - point.y += WINX_ADJUST_Y * dy; - } - SetCursorPos(ptCursor.x, ptCursor.y); - } + SECURITY_ATTRIBUTES SecurityAttributes; + ZeroMemory(&SecurityAttributes, sizeof(SecurityAttributes)); + SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + SecurityAttributes.bInheritHandle = FALSE; + SecurityAttributes.lpSecurityDescriptor = pSecurityDescriptor; + if (CreateMutexW(&SecurityAttributes, FALSE, _T(EPStart10_AnimationsPatched))) + { + printf("[SMA] Advertising successful animations patching.\n"); } + free(pSecurityDescriptor); } - else - { - point = GetDefaultWinXPosition(FALSE, NULL, NULL, TRUE, FALSE); - } - - IUnknown* iunk = NULL; - if (CLauncherTipContextMenu_GetMenuItemsAsyncFunc) - { - RECT rc = { 0 }; - CLauncherTipContextMenu_GetMenuItemsAsyncFunc(_this, rc, &iunk); - } - if (iunk) - { - iunk->lpVtbl->AddRef(iunk); - - ShowLauncherTipContextMenuParameters* params = malloc( - sizeof(ShowLauncherTipContextMenuParameters) - ); - params->_this = _this; - params->point = point; - params->iunk = iunk; - params->bShouldCenterWinXHorizontally = bShouldCenterWinXHorizontally; - hIsWinXShown = CreateThread( - 0, - 0, - ShowLauncherTipContextMenu, - params, - 0, - 0 - ); - hWinXThread = hIsWinXShown; - } -finalize: - if (CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc) - { - return CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt); - } - return 0; + if (pMainSid) free(pMainSid); + if (pSecondaySid) FreeSid(pSecondaySid); +#endif } #endif #pragma endregion @@ -2517,7 +2005,11 @@ INT64 Shell_TrayWndSubclassProc( pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); - HMENU hMenu = LoadMenuW(GetModuleHandle(NULL), MAKEINTRESOURCEW(205)); + HMENU hMenu = LoadMenuW(GetModuleHandleW(NULL), MAKEINTRESOURCEW(205)); + if (!hMenu && g_hMyTaskbar) + { + hMenu = LoadMenuW(g_hMyTaskbar, MAKEINTRESOURCEW(205)); + } if (hMenu) { HMENU hSubMenu = GetSubMenu(hMenu, 0); @@ -3214,25 +2706,13 @@ INT64 OwnerDrawSubclassProc( DWORD_PTR dwRefData ) { - BOOL v12 = FALSE; if ((uMsg == WM_DRAWITEM || uMsg == WM_MEASUREITEM) && CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc && - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc( - hWnd, - uMsg, - wParam, - lParam, - &v12 - )) + CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc(hWnd, uMsg, wParam, lParam)) { return 0; } - return DefSubclassProc( - hWnd, - uMsg, - wParam, - lParam - ); + return DefSubclassProc(hWnd, uMsg, wParam, lParam); } long long explorer_TrackPopupMenuExElapsed = 0; BOOL explorer_TrackPopupMenuExHook( @@ -4390,26 +3870,6 @@ BOOL InvokeClockFlyout() } return FALSE; } -INT64 winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHook( - void* _this, - INT64 a2, - INT a3 -) -{ - if (!bClockFlyoutOnWinC) - { - if (winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc) - { - return winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc(_this, a2, a3); - } - return 0; - } - if (a2 == 786 && a3 == 107) - { - InvokeClockFlyout(); - } - return 0; -} #endif #pragma endregion @@ -8929,71 +8389,33 @@ LSTATUS explorer_RegGetValueW( return lRes; } -LSTATUS twinuipcshell_RegGetValueW( - HKEY hkey, - LPCWSTR lpSubKey, - LPCWSTR lpValue, - DWORD dwFlags, - LPDWORD pdwType, - PVOID pvData, - LPDWORD pcbData +HRESULT (*explorer_SHCreateStreamOnModuleResourceWFunc)( + HMODULE hModule, + LPCWSTR pwszName, + LPCWSTR pwszType, + IStream** ppStream +); + +HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( + HMODULE hModule, + LPCWSTR pwszName, + LPCWSTR pwszType, + IStream** ppStream ) { - LSTATUS lRes = RegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - - if (!lstrcmpW(lpValue, L"AltTabSettings")) - { - if (lRes == ERROR_SUCCESS && *(DWORD*)pvData) - { - if (*(DWORD*)pvData == 3) - { - *(DWORD*)pvData = 0; - } - else - { - *(DWORD*)pvData = 1; - } - } - - if (!bOldTaskbar && hWin11AltTabInitialized) - { - SetEvent(hWin11AltTabInitialized); - CloseHandle(hWin11AltTabInitialized); - hWin11AltTabInitialized = NULL; - } - - lRes = ERROR_SUCCESS; - } - - return lRes; -} - -HRESULT (*explorer_SHCreateStreamOnModuleResourceWFunc)( - HMODULE hModule, - LPCWSTR pwszName, - LPCWSTR pwszType, - IStream** ppStream -); - -HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( - HMODULE hModule, - LPCWSTR pwszName, - LPCWSTR pwszType, - IStream** ppStream -) -{ - wchar_t path[MAX_PATH]; - GetModuleFileNameW(hModule, path, MAX_PATH); - if ((*((WORD*)&(pwszName)+1))) + wchar_t path[MAX_PATH]; + GetModuleFileNameW(hModule, path, MAX_PATH); + if ((*((WORD*)&(pwszName)+1))) { wprintf(L"%s - %s %s\n", path, pwszName, pwszType); } else { - wprintf(L"%s - %d %s\n", path, pwszName, pwszType); + UINT uId = (UINT)(UINT_PTR)pwszName; + wprintf(L"%s - %d %s\n", path, uId, pwszType); IStream* pStream = NULL; - if (pwszName < 124) + if (uId < 124) { if (S_Icon_Dark_TaskView) { @@ -9005,9 +8427,9 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } } } - else if (pwszName >= 151) + else if (uId >= 151) { - if (pwszName < 163) + if (uId < 163) { if (S_Icon_Dark_Search) { @@ -9020,7 +8442,7 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } } - if (pwszName < 201) + if (uId < 201) { if (S_Icon_Light_Search) { @@ -9033,7 +8455,7 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } } - if (pwszName < 213) + if (uId < 213) { if (S_Icon_Dark_Widgets) { @@ -9047,7 +8469,7 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } } - if (pwszName < 251) + if (uId < 251) { if (S_Icon_Light_Widgets) { @@ -9060,7 +8482,7 @@ HRESULT WINAPI explorer_SHCreateStreamOnModuleResourceWHook( } } } - else if (pwszName < 307) + else if (uId < 307) { if (S_Icon_Light_TaskView) { @@ -9977,572 +9399,6 @@ DWORD InjectBasicFunctions(BOOL bIsExplorer, BOOL bInstall) } -#pragma region "Enable old Alt+Tab" -INT64(*twinui_pcshell_IsUndockedAssetAvailableFunc)(INT a1, INT64 a2, INT64 a3, const char* a4); -INT64 twinui_pcshell_IsUndockedAssetAvailableHook(INT a1, INT64 a2, INT64 a3, const char* a4) -{ - // if IsAltTab and AltTabSettings == Windows 10 or sws (Precision Touchpad gesture) - if (a1 == 1 && (dwAltTabSettings == 3 || dwAltTabSettings == 2)) - { - return 0; - } - // if IsSnapAssist and SnapAssistSettings == Windows 10 - else if (a1 == 4 && dwSnapAssistSettings == 3 && !IsWindows11Version22H2OrHigher()) - { - return 0; - } - // else, show Windows 11 style basically - else - { - if (twinui_pcshell_IsUndockedAssetAvailableFunc) - return twinui_pcshell_IsUndockedAssetAvailableFunc(a1, a2, a3, a4); - return 1; - } -} - -INT64(*twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc)(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5); -INT64(*twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc)(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5); -INT64 twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostHook(INT64 _this, unsigned int a2, INT64 a3, INT64 a4, INT64* a5) -{ - if (!twinui_pcshell_IsUndockedAssetAvailableHook(a2, 0, 0, NULL)) - return twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc(_this, a2, a3, a4, a5); - return twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc(_this, a2, a3, a4, a5); -} -#pragma endregion - - -#pragma region "Fixes related to the removal of STTest feature flag (22621.2134+)" -#if WITH_MAIN_PATCHER -HRESULT(*twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc)(IInspectable* _this, HMONITOR hMonitor, float* outHeight); -HRESULT twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorHook(IInspectable* _this, HMONITOR hMonitor, float* outHeight) -{ - if (bOldTaskbar) - { - MONITORINFO mi; - mi.cbSize = sizeof(MONITORINFO); - GetMonitorInfoW(hMonitor, &mi); - *outHeight = (float)(mi.rcMonitor.bottom - mi.rcWork.bottom); - return S_OK; - } - return twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc(_this, hMonitor, outHeight); -} - -static struct -{ - int coroInstance_rcOut; // 22621.1992: 0x10 - int coroInstance_pHardwareConfirmatorHost; // 22621.1992: 0xFD - int hardwareConfirmatorHost_bIsInLockScreen; // 22621.1992: 0xEC -} g_Moment2PatchOffsets; - -#if defined(_M_X64) -inline PBYTE GetTargetOfJzBeforeMe(PBYTE anchor) -{ - // Check big jz - if (*(anchor - 6) == 0x0F && *(anchor - 5) == 0x84) - return anchor + *(int*)(anchor - 4); - // Check small jz - if (*(anchor - 2) == 0x74) - return anchor + *(char*)(anchor - 1); - return NULL; -} -#endif - -// CActionCenterExperienceManager::GetViewPosition() patcher -BOOL Moment2PatchActionCenter(LPMODULEINFO mi) -{ -#if defined(_M_X64) - // Step 1: - // Scan within the DLL for `*a2 = mi.rcMonitor`. - // ```0F 10 45 ?? F3 0F 7F ?? 80 ?? ?? ?? 00 00 00 // movups - movdqu - cmp``` - // 22621.1992: 7E2F0 - // 22621.2283: 140D5 - PBYTE rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\xF3\x0F\x7F\x00\x80\x00\x00\x00\x00\x00\x00", "xxx?xxx?x???xxx"); - if (!rcMonitorAssignment) return FALSE; - printf("[AC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); - - // 22621.1992 has a different compiled code structure than 22621.2283 therefore we have to use a different approach: - // Short circuiting the `if (26008830 is enabled)`. - // 22621.1992: 7E313 - if (!IsWindows11Version22H2Build2134OrHigher()) // We're on 1413-1992 - { -#if USE_MOMENT_3_FIXES_ON_MOMENT_2 - PBYTE featureCheckJz = rcMonitorAssignment + 35; - if (*featureCheckJz != 0x0F && *(featureCheckJz + 1) != 0x84) return FALSE; - - DWORD dwOldProtect = 0; - PBYTE jzAddr = featureCheckJz + 6 + *(DWORD*)(featureCheckJz + 2); - if (!VirtualProtect(featureCheckJz, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - featureCheckJz[0] = 0xE9; - *(DWORD*)(featureCheckJz + 1) = (DWORD)(jzAddr - featureCheckJz - 5); - VirtualProtect(featureCheckJz, 5, dwOldProtect, &dwOldProtect); - goto done; -#else - return FALSE; -#endif - } - - // Step 2: - // Copy `*a2 = mi.rcMonitor` into right after the first jz starting from step 1. - // Find within couple bytes from step 1: - // ```48 8D // lea``` - // Then offset the first ?? so that it points to mi.rcWork which is 16 bytes after mi.rcMonitor. - // 22621.2283: 140E6 - PBYTE blockBegin = FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); - if (!blockBegin) return FALSE; - printf("[AC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); - - // Step 3: - // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after - // the 8 bytes `rcMonitor = mi.rcWork` we've written. - PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); - if (!blockEnd) return FALSE; - printf("[AC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); - - // Execution - DWORD dwOldProtect = 0; - if (!VirtualProtect(blockBegin, 8 /**a2 = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - - // Step 2 - memcpy(blockBegin, rcMonitorAssignment, 8); - blockBegin[3] += offsetof(MONITORINFO, rcWork) - offsetof(MONITORINFO, rcMonitor); - - // Step 3 - PBYTE jmpToEnd = blockBegin + 8; - jmpToEnd[0] = 0xE9; - *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); - - VirtualProtect(blockBegin, 8 + 5, dwOldProtect, &dwOldProtect); - -done: - printf("[AC] Patched!\n"); - return TRUE; -#else - return FALSE; -#endif -} - -// CControlCenterExperienceManager::PositionView() patcher -BOOL Moment2PatchControlCenter(LPMODULEINFO mi) -{ -#if defined(_M_X64) - // Step 1: - // Scan within the DLL for `rcMonitor = mi.rcMonitor`. - // ```0F 10 44 24 ?? F3 0F 7F 44 24 ?? 80 // movups - movdqu - cmp``` - // 22621.1992: 4B35B - // 22621.2283: 65C5C - PBYTE rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x44\x24\x00\xF3\x0F\x7F\x44\x24\x00\x80", "xxxx?xxxxx?x"); - if (!rcMonitorAssignment) return FALSE; - printf("[CC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); - - // Step 2: - // Scan within the function for the 10 bytes long `rcMonitor = mi.rcWork`. - // This pattern applies to both ControlCenter and ToastCenter. - // ```0F 10 45 ?? F3 0F 7F 44 24 ?? 48 // movups - movdqu - test``` - // 22621.1992: 4B3FD and 4B418 (The second one is compiled out in later builds) - // 22621.2283: 65CE6 - PBYTE rcWorkAssignment = FindPattern(rcMonitorAssignment + 1, 256, "\x0F\x10\x45\x00\xF3\x0F\x7F\x44\x24\x00\x48", "xxx?xxxxx?x"); - if (!rcWorkAssignment) return FALSE; - printf("[CC] rcWorkAssignment = %llX\n", rcWorkAssignment - (PBYTE)mi->lpBaseOfDll); - - // Step 3: - // Copy the `rcMonitor = mi.rcWork` into right after the first jz starting from step 1. - // Find within couple bytes from step 1: - // ```48 8D // lea``` - // 22621.1992: 4B373 - // 22621.2283: 65C74 - PBYTE blockBegin = FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); - if (!blockBegin) return FALSE; - printf("[CC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); - - // Step 4: - // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after - // the 10 bytes `rcMonitor = mi.rcWork` we've written. - PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); - if (!blockEnd) return FALSE; - printf("[CC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); - - // Execution - DWORD dwOldProtect = 0; - if (!VirtualProtect(blockBegin, 10 /*rcMonitor = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - - // Step 2 - memcpy(blockBegin, rcWorkAssignment, 10); - - // Step 3 - PBYTE jmpToEnd = blockBegin + 10; - jmpToEnd[0] = 0xE9; - *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); - - VirtualProtect(blockBegin, 10 + 5, dwOldProtect, &dwOldProtect); - - printf("[CC] Patched!\n"); - return TRUE; -#else - return FALSE; -#endif -} - -// CToastCenterExperienceManager::PositionView() patcher -BOOL Moment2PatchToastCenter(LPMODULEINFO mi) -{ -#if defined(_M_X64) - // Step 1: - // Scan within the DLL for `rcMonitor = mi.rcMonitor`. - // - // Pattern 1: - // Will have a match if CToastCenterExperienceManager::ShouldShowWithinWorkArea() is present. - // ```0F 10 45 ?? ?? 0F 7F 44 24 ?? 48 8B CF // movups - movdqu - mov``` - // 22621.1992: 40CE8 - // 22621.2283: 501DB - // - // Pattern 2: - // Will have a match if CToastCenterExperienceManager::ShouldShowWithinWorkArea() is inlined. - // ```0F 10 45 ?? ?? 0F 7F 44 24 ?? 44 38 // movups - movdqu - cmp``` - // 25951.1000: 36B2C4 - // - // Pattern 3: - // Same as pattern 1, but different length of the movdqu instruction. - // ```0F 10 45 ?? ?? 0F 7F 45 ?? 48 8B CF // movups - movdqu - mov``` - // 22621.3066: 3DC340 - // - // Pattern 4: - // Same as pattern 2, but different length of the movdqu instruction. - // ```0F 10 45 ?? ?? 0F 7F 45 ?? 44 38 // movups - movdqu - cmp``` - // No matches yet, just in case. - int assignmentSize = 10; - PBYTE rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x44\x24\x00\x48\x8B\xCF", "xxx??xxxx?xxx"); - if (!rcMonitorAssignment) - { - rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x44\x24\x00\x44\x38", "xxx??xxxx?xx"); - if (!rcMonitorAssignment) - { - assignmentSize = 9; - rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x45\x00\x48\x8B\xCF", "xxx??xxx?xxx"); - if (!rcMonitorAssignment) - { - rcMonitorAssignment = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x45\x00\x00\x0F\x7F\x45\x00\x44\x38", "xxx??xxx?xx"); - if (!rcMonitorAssignment) return FALSE; - } - } - } - printf("[TC] rcMonitorAssignment = %llX\n", rcMonitorAssignment - (PBYTE)mi->lpBaseOfDll); - - // Step 2: - // Copy the `rcMonitor = mi.rcMonitor` into right after the first jz starting from step 1. - // Find within couple bytes from step 1: - // ```48 8D // lea``` - // Then offset the first ?? so that it points to mi.rcWork which is 16 bytes after mi.rcMonitor. - // 22621.1992: 40D02 - // 22621.2283: 501F5 - PBYTE blockBegin = FindPattern(rcMonitorAssignment + 1, 32, "\x48\x8D", "xx"); - if (!blockBegin) return FALSE; - printf("[TC] blockBegin = %llX\n", blockBegin - (PBYTE)mi->lpBaseOfDll); - - // Step 3: - // Exit the block by writing a long jmp into the address referenced by the jz right before step 3, into right after - // the bytes `rcMonitor = mi.rcWork` we've written. - // - // Note: We are skipping EdgeUI calls here. - PBYTE blockEnd = GetTargetOfJzBeforeMe(blockBegin); - if (!blockEnd) return FALSE; - printf("[TC] blockEnd = %llX\n", blockEnd - (PBYTE)mi->lpBaseOfDll); - - // Execution - DWORD dwOldProtect = 0; - if (!VirtualProtect(blockBegin, assignmentSize /*rcMonitor = mi.rcWork*/ + 5 /*jmp*/, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - - // Step 2 - memcpy(blockBegin, rcMonitorAssignment, assignmentSize); - blockBegin[3] += offsetof(MONITORINFO, rcWork) - offsetof(MONITORINFO, rcMonitor); - - // Step 3 - PBYTE jmpToEnd = blockBegin + assignmentSize; - jmpToEnd[0] = 0xE9; - *(DWORD*)(jmpToEnd + 1) = (DWORD)(blockEnd - jmpToEnd - 5); - - VirtualProtect(blockBegin, assignmentSize + 5, dwOldProtect, &dwOldProtect); - - printf("[TC] Patched!\n"); - return TRUE; -#else - return FALSE; -#endif -} - -// TaskViewFrame::RuntimeClassInitialize() patcher -BOOL Moment2PatchTaskView(LPMODULEINFO mi) -{ -#if defined(_M_X64) - /*** - If we're using the old taskbar, it'll be stuck in an infinite loading since it's waiting for the new one to respond. - Let's safely skip those by NOPing the `TaskViewFrame::UpdateWorkAreaAsync()` and `WaitForCompletion()` calls, and - turning off the COM object cleanup. - - Step 1: - Scan within the DLL to find the beginning, which is the preparation of the 1st call. - It should be 4C 8B or 4D 8B (mov r8, ...). - For the patterns, they're +1 from the result since it can be either of those. - - Pattern 1: - ```8B ?? 48 8D 55 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8``` - 22621.1992: 7463C - 22621.2134: 3B29C - - Pattern 2: - ```8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8``` - 22621.2283: 24A1D2 - - Step 2: - In place of the 1st call's call op (E8), overwrite it with a code to set the value of the com_ptr passed into the - 2nd argument (rdx) to 0. This is to skip the cleanup that happens right after the 2nd call. - ```48 C7 02 00 00 00 00 mov qword ptr [rdx], 0``` - Start from -13 of the byte after 2nd call's end. - 22621.1992: 74646 - 22621.2134: 3B2A6 - 22621.2283: 24A1DD - - Step 3: - NOP the rest of the 2nd call. - - Summary: - ``` - 48 8B ?? 48 8D 55 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // Pattern 1 - 48 8B ?? 48 8D 54 24 ?? 48 8B ?? E8 ?? ?? ?? ?? 48 8B 08 E8 ?? ?? ?? ?? // Pattern 2 - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ - 1st: TaskViewFrame::UpdateWorkAreaAsync() 2nd: WaitForCompletion() - 48 8B ?? 48 8D 54 24 ?? 48 8B ?? 48 C7 02 00 00 00 00 90 90 90 90 90 90 // Result according to Pattern 2 - -------------------------------- xxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxx - We need rdx Step 2 Step 3 - ``` - - Notes: - - In 22621.1992 and 22621.2134, `~AsyncOperationCompletedHandler()` is inlined, while it is not in 22621.2283. We - can see `unconditional_release_ref()` calls right in `RuntimeClassInitialize()` of 1992 and 2134. - - In 22621.2134, there is `33 FF xor edi, edi` before the jz for the inlined cleanup. The value of edi is used in - two more cleanup calls after our area of interest (those covered by twoCallsLength), therefore we can't just NOP - everything. And I think detecting such things is too much work. - ***/ - - int twoCallsLength = 1 + 18 + 4; // 4C/4D + pattern length + 4 bytes for the 2nd call's call address - PBYTE firstCallPrep = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x55\x00\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxx?xx?x????xxxx"); - if (!firstCallPrep) - { - twoCallsLength += 1; // Add 1 to the pattern length - firstCallPrep = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x8B\x00\x48\x8D\x54\x24\x00\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\x08\xE8", "x?xxxx?xx?x????xxxx"); - if (!firstCallPrep) return FALSE; - } - firstCallPrep -= 1; // Point to the 4C/4D - printf("[TV] firstCallPrep = %llX\n", firstCallPrep - (PBYTE)mi->lpBaseOfDll); - - PBYTE firstCallCall = firstCallPrep + twoCallsLength - 13; - printf("[TV] firstCallCall = %llX\n", firstCallCall - (PBYTE)mi->lpBaseOfDll); - - PBYTE nopBegin = firstCallCall + 7; - - // Execution - DWORD dwOldProtect = 0; - if (!VirtualProtect(firstCallPrep, twoCallsLength, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - const BYTE step2Payload[] = { 0x48, 0xC7, 0x02, 0x00, 0x00, 0x00, 0x00 }; - memcpy(firstCallCall, step2Payload, sizeof(step2Payload)); - memset(nopBegin, 0x90, twoCallsLength - (nopBegin - firstCallPrep)); - VirtualProtect(firstCallPrep, twoCallsLength, dwOldProtect, &dwOldProtect); - - printf("[TV] Patched!\n"); - return TRUE; -#else - return FALSE; -#endif -} - -DEFINE_GUID(SID_EdgeUi, - 0x0d189b30, - 0x0f12b, 0x4b13, 0x94, 0xcf, - 0x53, 0xcb, 0x0e, 0x0e, 0x24, 0x0d -); - -DEFINE_GUID(IID_IEdgeUiManager, - 0x6e6c3c52, - 0x5a5e, 0x4b4b, 0xa0, 0xf8, - 0x7f, 0xe1, 0x26, 0x21, 0xa9, 0x3e -); - -// Reimplementation of HardwareConfirmatorHost::GetDisplayRect() -void WINAPI HardwareConfirmatorShellcode(PBYTE pCoroInstance) -{ - PBYTE pHardwareConfirmatorHost = *(PBYTE*)(pCoroInstance + g_Moment2PatchOffsets.coroInstance_pHardwareConfirmatorHost); - - RECT rc; - HMONITOR hMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTOPRIMARY); - - HRESULT hr = S_OK; - IUnknown* pImmersiveShell = NULL; - hr = CoCreateInstance( - &CLSID_ImmersiveShell, - NULL, - CLSCTX_LOCAL_SERVER, - &IID_IServiceProvider, - &pImmersiveShell - ); - if (SUCCEEDED(hr)) - { - IImmersiveMonitorService* pMonitorService = NULL; - IUnknown_QueryService( - pImmersiveShell, - &SID_IImmersiveMonitorService, - &IID_IImmersiveMonitorService, - &pMonitorService - ); - if (pMonitorService) - { - IUnknown* pEdgeUiManager = NULL; - pMonitorService->lpVtbl->QueryService( - pMonitorService, - hMonitor, - &SID_EdgeUi, - &IID_IEdgeUiManager, - &pEdgeUiManager - ); - if (pEdgeUiManager) - { - if (*(pHardwareConfirmatorHost + g_Moment2PatchOffsets.hardwareConfirmatorHost_bIsInLockScreen)) - { - // Lock screen - MONITORINFO mi; - mi.cbSize = sizeof(MONITORINFO); - if (GetMonitorInfoW(hMonitor, &mi)) - rc = mi.rcMonitor; - } - else - { - // Desktop - HRESULT(*GetAutohideImmuneWorkArea)(IUnknown*, PRECT) = ((void**)pEdgeUiManager->lpVtbl)[19]; - hr = GetAutohideImmuneWorkArea(pEdgeUiManager, &rc); - } - - __x_ABI_CWindows_CFoundation_CRect* out = pCoroInstance + g_Moment2PatchOffsets.coroInstance_rcOut; - out->X = (float)rc.left; - out->Y = (float)rc.top; - out->Width = (float)(rc.right - rc.left); - out->Height = (float)(rc.bottom - rc.top); - - pEdgeUiManager->lpVtbl->Release(pEdgeUiManager); - } - pMonitorService->lpVtbl->Release(pMonitorService); - } - pImmersiveShell->lpVtbl->Release(pImmersiveShell); - } - - if (FAILED(hr)) - printf("[HardwareConfirmatorShellcode] Failed. 0x%lX\n", hr); -} - -// [HardwareConfirmatorHost::GetDisplayRectAsync$_ResumeCoro$1() patcher -BOOL Moment2PatchHardwareConfirmator(LPMODULEINFO mi) -{ -#if defined(_M_X64) - // Find required offsets - - // pHardwareConfirmatorHost and bIsInLockScreen: - // Find in GetDisplayRectAsync$_ResumeCoro$1, inside `case 4:` - // - // 48 8B 83 ED 00 00 00 mov rax, [rbx+0EDh] - // ^^^^^^^^^^^ pHardwareConfirmatorHost - // 8A 80 EC 00 00 00 mov al, [rax+0ECh] - // ^^^^^^^^^^^ bIsInLockScreen - // - // if ( ADJ(this)->pHardwareConfirmatorHost->bIsInLockScreen ) - // if ( *(_BYTE *)(*(_QWORD *)(this + 237) + 236i64) ) // 22621.2283 - // ^ HCH ^ bIsInLockScreen - // - // 22621.2134: 1D55D - PBYTE match1 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x48\x8B\x83\x00\x00\x00\x00\x8A\x80", "xxx????xx"); - printf("[HC] match1 = %llX\n", match1 - (PBYTE)mi->lpBaseOfDll); - if (!match1) return FALSE; - g_Moment2PatchOffsets.coroInstance_pHardwareConfirmatorHost = *(int*)(match1 + 3); - g_Moment2PatchOffsets.hardwareConfirmatorHost_bIsInLockScreen = *(int*)(match1 + 9); - - // coroInstance_rcOut: - // Also in GetDisplayRectAsync$_ResumeCoro$1, through `case 4:` - // We also use this as the point to jump to, which is the code to set the rect and finish the coroutine. - // - // v27 = *(_OWORD *)(this + 16); - // *(_OWORD *)(this - 16) = v27; - // if ( winrt_suspend_handler ) ... - // - // 0F 10 43 10 movups xmm0, xmmword ptr [rbx+10h] - // ^^ coroInstance_rcOut - // 0F 11 84 24 D0 00 00 00 movups [rsp+158h+var_88], xmm0 - // - // 22621.2134: 1D624 - PBYTE match2 = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x0F\x10\x43\x00\x0F\x11\x84\x24", "xxx?xxxx"); - printf("[HC] match2 = %llX\n", match2 - (PBYTE)mi->lpBaseOfDll); - if (!match2) return FALSE; - g_Moment2PatchOffsets.coroInstance_rcOut = *(match2 + 3); - - // Find where to put the shellcode - // We'll overwrite from this position: - // - // *(_OWORD *)(this + 32) = 0i64; - // *(_QWORD *)(this + 48) = MonitorFromRect((LPCRECT)(this + 32), 1u); - // - // 22621.2134: 1D21E - PBYTE writeAt = FindPattern(mi->lpBaseOfDll, mi->SizeOfImage, "\x48\x8D\x4B\x00\x0F", "xxx?x"); - if (!writeAt) return FALSE; - printf("[HC] writeAt = %llX\n", writeAt - (PBYTE)mi->lpBaseOfDll); - - // In 22621.2134+, after our jump location there is a cleanup for something we skipped. NOP them. - // From match2, bytes +17 until +37, which is 21 bytes to be NOP'd. - // 22621.2134: 1D635-1D64A - PBYTE cleanupBegin = NULL, cleanupEnd = NULL; - if (IsWindows11Version22H2Build2134OrHigher()) - { - cleanupBegin = match2 + 17; - cleanupEnd = match2 + 38; // Exclusive - printf("[HC] cleanup = %llX-%llX\n", cleanupBegin - (PBYTE)mi->lpBaseOfDll, cleanupEnd - (PBYTE)mi->lpBaseOfDll); - if (*cleanupBegin != 0x49 || *cleanupEnd != 0x90 /*Already NOP here*/) return FALSE; - } - - // Craft the shellcode - BYTE shellcode[] = { - // lea rcx, [rbx+0] ; rbx is the `this` which is the instance of the coro, we pass it to our function - 0x48, 0x8D, 0x0B, - // mov rax, 1111111111111111h ; placeholder for the address of HardwareConfirmatorShellcode - 0x48, 0xB8, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - // call rax - 0xFF, 0xD0 - }; - - uintptr_t pattern = 0x1111111111111111; - *(PBYTE*)(memmem(shellcode, sizeof(shellcode), &pattern, sizeof(uintptr_t))) = HardwareConfirmatorShellcode; - - // Execution - DWORD dwOldProtect = 0; - SIZE_T totalSize = sizeof(shellcode) + 5; - if (!VirtualProtect(writeAt, totalSize, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - memcpy(writeAt, shellcode, sizeof(shellcode)); - PBYTE jmpLoc = writeAt + sizeof(shellcode); - jmpLoc[0] = 0xE9; - *(DWORD*)(jmpLoc + 1) = (DWORD)(match2 - jmpLoc - 5); - VirtualProtect(writeAt, totalSize, dwOldProtect, &dwOldProtect); - - if (cleanupBegin) - { - dwOldProtect = 0; - if (!VirtualProtect(cleanupBegin, cleanupEnd - cleanupBegin, PAGE_EXECUTE_READWRITE, &dwOldProtect)) return FALSE; - memset(cleanupBegin, 0x90, cleanupEnd - cleanupBegin); - VirtualProtect(cleanupBegin, cleanupEnd - cleanupBegin, dwOldProtect, &dwOldProtect); - } - - printf("[HC] Patched!\n"); - return TRUE; -#else - return FALSE; -#endif -} -#endif -#pragma endregion - - #pragma region "Enable EP weather on Windows Server SKUs" #if WITH_MAIN_PATCHER BOOL PeopleBand_IsOS(DWORD dwOS) @@ -10580,51 +9436,6 @@ BOOL explorer_IsOS(DWORD dwOS) #pragma region "Find offsets of needed functions when symbols are not available" #if WITH_MAIN_PATCHER -inline BOOL FollowJnz(PBYTE pJnz, PBYTE* pTarget, DWORD* pJnzSize) -{ - // Check big jnz - if (pJnz[0] == 0x0F && pJnz[1] == 0x85) - { - *pTarget = pJnz + 6 + *(int*)(pJnz + 2); - *pJnzSize = 6; - return TRUE; - } - // Check small jnz - if (pJnz[0] == 0x75) - { - *pTarget = pJnz + 2 + *(char*)(pJnz + 1); - *pJnzSize = 2; - return TRUE; - } - return FALSE; -} - -UINT_PTR FileOffsetToRVA(PBYTE pBase, UINT_PTR offset) -{ - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBase; - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pBase + pDosHeader->e_lfanew); - PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders); - for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) - { - if (offset >= pSection->PointerToRawData && offset < pSection->PointerToRawData + pSection->SizeOfRawData) - return offset - pSection->PointerToRawData + pSection->VirtualAddress; - } - return 0; -} - -UINT_PTR RVAToFileOffset(PBYTE pBase, UINT_PTR rva) -{ - PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBase; - PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pBase + pDosHeader->e_lfanew); - PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders); - for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) - { - if (rva >= pSection->VirtualAddress && rva < pSection->VirtualAddress + pSection->Misc.VirtualSize) - return rva - pSection->VirtualAddress + pSection->PointerToRawData; - } - return 0; -} - void TryToFindExplorerOffsets(HANDLE hExplorer, MODULEINFO* pmiExplorer, DWORD* pOffsets) { if (!pOffsets[0] || pOffsets[0] == 0xFFFFFFFF) @@ -10777,1152 +9588,102 @@ void TryToFindExplorerOffsets(HANDLE hExplorer, MODULEINFO* pmiExplorer, DWORD* #endif } } +#endif +#pragma endregion + + +#pragma region "Fix Pin to Start from Explorer not working when using Windows 10 start menu" +#if WITH_MAIN_PATCHER +extern HRESULT AppResolver_StartTileData_RoGetActivationFactory(HSTRING activatableClassId, REFIID iid, void** factory); + +typedef struct CCacheShortcut CCacheShortcut; +extern HRESULT(*AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc)(void* _this, const CCacheShortcut* a2, const void* a3); +extern HRESULT AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStart(void* _this, const CCacheShortcut* a2, const void* a3); -void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets) +static void PatchAppResolver() { - // We read from the file instead of from memory because other tweak software might've modified the functions we're looking for - 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) + HANDLE hAppResolver = LoadLibraryW(L"AppResolver.dll"); + MODULEINFO miAppResolver; + GetModuleInformation(GetCurrentProcess(), hAppResolver, &miAppResolver, sizeof(MODULEINFO)); + + VnPatchDelayIAT(hAppResolver, "api-ms-win-core-winrt-l1-1-0.dll", "RoGetActivationFactory", AppResolver_StartTileData_RoGetActivationFactory); + + // CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart() +#if defined(_M_X64) + // 8B ? 48 8B D3 E8 ? ? ? ? 48 8B 8D + // ^^^^^^^ + // Ref: CAppResolverCacheBuilder::_AddShortcutToCache() + PBYTE match = FindPattern( + hAppResolver, + miAppResolver.SizeOfImage, + "\x8B\x00\x48\x8B\xD3\xE8\x00\x00\x00\x00\x48\x8B\x8D", + "x?xxxx????xxx" + ); + if (match) { - printf("Failed to open twinui.pcshell.dll\n"); - return; + match += 5; + match += 5 + *(int*)(match + 1); } - - DWORD dwSize = GetFileSize(hFile, NULL); - PBYTE pFile = malloc(dwSize); - DWORD dwRead = 0; - if (!ReadFile(hFile, pFile, dwSize, &dwRead, NULL) || dwRead != dwSize) +#elif defined(_M_ARM64) + // 7F 23 03 D5 FD 7B BC A9 F3 53 01 A9 F5 5B 02 A9 F7 1B 00 F9 FD 03 00 91 ?? ?? ?? ?? FF 43 01 D1 F7 03 00 91 30 00 80 92 F0 1A 00 F9 ?? 03 01 AA ?? 03 02 AA FF ?? 00 F9 + // ----------- PACIBSP, don't scan for this because it's everywhere + PBYTE match = FindPattern( + hAppResolver, + miAppResolver.SizeOfImage, + "\xFD\x7B\xBC\xA9\xF3\x53\x01\xA9\xF5\x5B\x02\xA9\xF7\x1B\x00\xF9\xFD\x03\x00\x91\x00\x00\x00\x00\xFF\x43\x01\xD1\xF7\x03\x00\x91\x30\x00\x80\x92\xF0\x1A\x00\xF9\x00\x03\x01\xAA\x00\x03\x02\xAA\xFF\x00\x00\xF9", + "xxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxx?xxx?xxxx?xx" + ); + if (match) { - printf("Failed to read twinui.pcshell.dll\n"); - goto cleanup; + match -= 4; } - - if (IsWindows11()) +#endif + if (match) { - // All patterns here have been tested to work on: - // - 22621.1, 22621.1992, 22621.2134, 22621.2283, 22621.2359 (RP) - // - 23545.1000 - // - 25951.1000 + AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc = match; + printf("CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart() = %llX\n", match - (PBYTE)hAppResolver); + } - if (!pOffsets[0] || pOffsets[0] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // 48 8B 49 08 E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 48 8B 89 - // ^^^^^^^^^^^ - // Ref: CMultitaskingViewFrame::v_WndProc() - PBYTE match = FindPattern( - pFile, dwSize, - "\x48\x8B\x49\x08\xE8\x00\x00\x00\x00\xE9\x00\x00\x00\x00\x48\x8B\x89", - "xxxxx????x????xxx" - ); - if (match) - { - match += 4; - pOffsets[0] = match + 5 + *(int*)(match + 1) - pFile; - } -#elif defined(_M_ARM64) - // ?? AE 00 71 ?? ?? 00 54 ?? 06 40 F9 E3 03 ?? AA E2 03 ?? AA E1 03 ?? 2A ?? ?? ?? ?? - // ^^^^^^^^^^^ - // Ref: CMultitaskingViewFrame::v_WndProc() - PBYTE match = FindPattern( - pFile, dwSize, - "\xAE\x00\x71\x00\x00\x00\x54\x00\x06\x40\xF9\xE3\x03\x00\xAA\xE2\x03\x00\xAA\xE1\x03\x00\x2A", - "xxx??xx?xxxxx?xxx?xxx?x" - ); - if (match) - { - match += 23; - pOffsets[0] = FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); - } -#endif - if (pOffsets[0] && pOffsets[0] != 0xFFFFFFFF) - { - printf("CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc() = %lX\n", pOffsets[0]); - } - } - if ((!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF) || (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF)) - { - UINT_PTR* vtable = NULL; -#if defined(_M_X64) - // 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 41 18 48 8D 05 ?? ?? ?? ?? 48 89 41 20 48 8D 05 ?? ?? ?? ?? 48 89 41 58 48 8D 05 ?? ?? ?? ?? 48 89 41 60 - // ^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\x48\x8D\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x89\x01\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x18\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x20\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x58\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x60", - "xxx????xxxxxxxxx????xxxxxxx????xxxxxxx????xxxxxxx????xxxx" - ); - if (match) - { - match += 35; // Point to 48 - vtable = (UINT_PTR*)(match + 7 + *(int*)(match + 3)); - } -#elif defined(_M_ARM64) - // * Pattern 1 (for 24H2): - // 69 A2 01 A9 ?? ?? 00 ?? 09 ?? ?? 91 ?? ?? 00 ?? 08 ?? ?? 91 69 A2 05 A9 ?? ?? 00 ?? 08 ?? ?? 91 68 36 00 F9 ?? ?? 00 ?? 08 ?? ?? 91 68 3E 00 F9 - // ^^^^^^^^^^^+^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\x69\xA2\x01\xA9\x00\x00\x00\x00\x09\x00\x00\x91\x00\x00\x00\x00\x08\x00\x00\x91\x69\xA2\x05\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x36\x00\xF9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x3E\x00\xF9", - "xxxx??x?x??x??x?x??xxxxx??x?x??xxxxx??x?x??xxxxx" - ); - // Patterns for 226xx are not implemented - if (match) - { - match += 4; // Point to ADRP - UINT_PTR vtableRVA = ARM64_DecodeADRL(FileOffsetToRVA(pFile, match - pFile), *(DWORD*)match, *(DWORD*)(match + 4)); - vtable = (UINT_PTR*)((UINT_PTR)pFile + RVAToFileOffset(pFile, vtableRVA)); - } -#endif - if (vtable) - { - if (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF) - { - pOffsets[6] = (DWORD)(vtable[3] - 0x180000000); - } - if (!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF) - { - pOffsets[1] = (DWORD)(vtable[4] - 0x180000000); - } - } - if (pOffsets[6] && pOffsets[6] != 0xFFFFFFFF) - { - printf("CLauncherTipContextMenu::ShowLauncherTipContextMenu() = %lX\n", pOffsets[6]); - } - if (pOffsets[1] && pOffsets[1] != 0xFFFFFFFF) - { - printf("CLauncherTipContextMenu::GetMenuItemsAsync() = %lX\n", pOffsets[1]); - } - } - if (!pOffsets[2] || pOffsets[2] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // Don't worry if this is too long, this works on 17763 and 25951 - // 40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B B5 ? ? ? ? 41 8B C1 - PBYTE match = FindPattern( - pFile, dwSize, - "\x40\x55\x53\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x00\x00\x00\x00\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\x48\x33\xC4\x48\x89\x85\x00\x00\x00\x00\x4C\x8B\xB5\x00\x00\x00\x00\x41\x8B\xC1", - "xxxxxxxxxxxxxxxxx????xxx????xxx????xxxxxx????xxx????xxx" - ); - if (match) - { - pOffsets[2] = match - pFile; - } -#elif defined(_M_ARM64) - // 40 F9 43 03 1C 32 E4 03 15 AA ?? ?? FF 97 - // ^^^^^^^^^^^ - // Ref: ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() - PBYTE match = FindPattern( - pFile, dwSize, - "\x40\xF9\x43\x03\x1C\x32\xE4\x03\x15\xAA\x00\x00\xFF\x97", - "xxxxxxxxxx??xx" - ); - if (match) - { - match += 10; - pOffsets[2] = FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); - } -#endif - if (pOffsets[2] && pOffsets[2] != 0xFFFFFFFF) - { - printf("ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() = %lX\n", pOffsets[2]); - } - } - if (!pOffsets[3] || pOffsets[3] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // 48 89 5C 24 ? 48 89 7C 24 ? 55 48 8B EC 48 83 EC 60 48 8B FA 48 8B D9 E8 - PBYTE match = FindPattern( - pFile, dwSize, - "\x48\x89\x5C\x24\x00\x48\x89\x7C\x24\x00\x55\x48\x8B\xEC\x48\x83\xEC\x60\x48\x8B\xFA\x48\x8B\xD9\xE8", - "xxxx?xxxx?xxxxxxxxxxxxxxx" - ); - if (match) - { - pOffsets[3] = match - pFile; - } -#elif defined(_M_ARM64) - // 7F 23 03 D5 F3 53 BF A9 FD 7B BB A9 FD 03 00 91 F3 03 00 AA F4 03 01 AA ?? ?? ?? ?? FF ?? 03 A9 - // ----------- PACIBSP, don't scan for this because it's everywhere - PBYTE match = FindPattern( - pFile, dwSize, - "\xF3\x53\xBF\xA9\xFD\x7B\xBB\xA9\xFD\x03\x00\x91\xF3\x03\x00\xAA\xF4\x03\x01\xAA\x00\x00\x00\x00\xFF\x00\x03\xA9", - "xxxxxxxxxxxxxxxxxxxx????x?xx" - ); - if (match) - { - match -= 4; - pOffsets[3] = FileOffsetToRVA(pFile, match - pFile); - } -#endif - if (pOffsets[3] && pOffsets[3] != 0xFFFFFFFF) - { - printf("ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu() = %lX\n", pOffsets[3]); - } - } - if (!pOffsets[4] || pOffsets[4] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // 48 8B ? E8 ? ? ? ? 4C 8B ? 48 8B ? 48 8B CE E8 ? ? ? ? 90 - // ^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\x48\x8B\x00\xE8\x00\x00\x00\x00\x4C\x8B\x00\x48\x8B\x00\x48\x8B\xCE\xE8\x00\x00\x00\x00\x90", - "xx?x????xx?xx?xxxx????x" - ); - if (match) - { - match += 17; - pOffsets[4] = match + 5 + *(int*)(match + 1) - pFile; - } -#elif defined(_M_ARM64) - // 82 62 00 91 ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5 - // ^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\x82\x62\x00\x91\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5", - "xxxx?xxxxx?x????xxxx" - ); - if (match) - { - match += 12; - pOffsets[4] = FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); - } -#endif - if (pOffsets[4] && pOffsets[4] != 0xFFFFFFFF) - { - printf("CLauncherTipContextMenu::_ExecuteShutdownCommand() = %lX\n", pOffsets[4]); - } - } - if (!pOffsets[5] || pOffsets[5] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // 48 8B ? E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90 48 8D 56 ? 48 8B CE - // ^^^^^^^ ------------------- Non-inlined ~::final_suspend() - PBYTE match = FindPattern( - pFile, dwSize, - "\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90\x48\x8D\x56\x00\x48\x8B\xCE", - "xx?x????xxxxxxx????xxxx?xxx" - ); - if (match) - { - match += 14; - pOffsets[5] = match + 5 + *(int*)(match + 1) - pFile; - } - else - { - // 48 8B ? E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90 48 8B 05 ? ? ? ? 48 - // ^^^^^^^ ------------------- Inlined ~::final_suspend() - match = FindPattern( - pFile, dwSize, - "\x48\x8B\x00\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90\x48\x8B\x05\x00\x00\x00\x00\x48", - "xx?x????xxxxxxx????xxxx????x" - ); - if (match) - { - match += 14; - pOffsets[5] = match + 5 + *(int*)(match + 1) - pFile; - } - } -#elif defined(_M_ARM64) - // 08 09 40 F9 ?? 16 00 F9 ?? ?? ?? ?? ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5 - // ^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\x08\x09\x40\xF9\x00\x16\x00\xF9\x00\x00\x00\x00\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5", - "xxxx?xxx?????xxxxx?x????xxxx" - ); - if (match) - { - match += 20; - pOffsets[5] = FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile); - } -#endif - if (pOffsets[5] && pOffsets[5] != 0xFFFFFFFF) - { - printf("CLauncherTipContextMenu::_ExecuteCommand() = %lX\n", pOffsets[5]); - } - } - if (!pOffsets[7] || pOffsets[7] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // Ref: CMultitaskingViewManager::_CreateMTVHost() - // Inlined GetMTVHostKind() - // 4C 89 74 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE E8 ?? ?? ?? ?? 8B - // ^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\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" - ); - if (match) - { - match += 16; - pOffsets[7] = match + 5 + *(int*)(match + 1) - pFile; - } - else - { - // Non-inlined GetMTVHostKind() - // 8B CF E8 ?? ?? ?? ?? ?? 89 ?? 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE 83 F8 01 - match = FindPattern( - pFile, dwSize, - "\x8B\xCF\xE8\x00\x00\x00\x00\x00\x89\x00\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\x83\xF8\x01", - "xxx?????x?x??x??x?xxxxxxxx" - ); - if (match) - { - PBYTE target = NULL; - DWORD jnzSize = 0; - if (FollowJnz(match + 26, &target, &jnzSize)) - { - match += 26 + jnzSize; - if (match[0] == 0xE8) - { - pOffsets[7] = match + 5 + *(int*)(match + 1) - pFile; - } - } - } - } -#elif defined(_M_ARM64) - // F3 53 BE A9 F5 5B 01 A9 FD 7B ?? A9 FD 03 00 91 30 00 80 92 F5 03 04 AA B0 ?? 00 F9 F3 03 00 AA BF 02 00 F9 68 2E 40 F9 F6 03 03 AA B3 23 02 A9 ?? ?? 00 B5 - PBYTE match = FindPattern( - pFile, dwSize, - "\xF3\x53\xBE\xA9\xF5\x5B\x01\xA9\xFD\x7B\x00\xA9\xFD\x03\x00\x91\x30\x00\x80\x92\xF5\x03\x04\xAA\xB0\x00\x00\xF9\xF3\x03\x00\xAA\xBF\x02\x00\xF9\x68\x2E\x40\xF9\xF6\x03\x03\xAA\xB3\x23\x02\xA9\x00\x00\x00\xB5", - "xxxxxxxxxx?xxxxxxxxxxxxxx?xxxxxxxxxxxxxxxxxxxxxx??xx" - ); - if (match) - { - pOffsets[7] = FileOffsetToRVA(pFile, match - 4 - pFile); - } -#endif - if (pOffsets[7] && pOffsets[7] != 0xFFFFFFFF) - { - printf("CMultitaskingViewManager::_CreateXamlMTVHost() = %lX\n", pOffsets[7]); - } - } - if (!pOffsets[8] || pOffsets[8] == 0xFFFFFFFF) - { -#if defined(_M_X64) - // Ref: CMultitaskingViewManager::_CreateMTVHost() - // Inlined GetMTVHostKind() - // 4C 89 74 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE E8 ?? ?? ?? ?? 90 - // ^^^^^^^^^^^ - PBYTE match = FindPattern( - pFile, dwSize, - "\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" - ); - if (match) - { - match += 16; - pOffsets[8] = match + 5 + *(int*)(match + 1) - pFile; - } - else - { - // Non-inlined GetMTVHostKind() - // 8B CF E8 ?? ?? ?? ?? ?? 89 ?? 24 ?? ?? 8B ?? ?? 8B ?? 8B D7 48 8B CE 83 F8 01 - match = FindPattern( - pFile, dwSize, - "\x8B\xCF\xE8\x00\x00\x00\x00\x00\x89\x00\x24\x00\x00\x8B\x00\x00\x8B\x00\x8B\xD7\x48\x8B\xCE\x83\xF8\x01", - "xxx?????x?x??x??x?xxxxxxxx" - ); - if (match) - { - PBYTE target = NULL; - DWORD jnzSize = 0; - if (FollowJnz(match + 26, &target, &jnzSize) && target[0] == 0xE8) - { - pOffsets[8] = target + 5 + *(int*)(target + 1) - pFile; - } - } - } -#elif defined(_M_ARM64) - // F3 53 BC A9 F5 5B 01 A9 F7 13 00 F9 F9 17 00 F9 FB 1B 00 F9 FD 7B BC A9 FD 03 00 91 FF ?? 00 D1 30 00 80 92 FB 03 04 AA - PBYTE match = FindPattern( - pFile, dwSize, - "\xF3\x53\xBC\xA9\xF5\x5B\x01\xA9\xF7\x13\x00\xF9\xF9\x17\x00\xF9\xFB\x1B\x00\xF9\xFD\x7B\xBC\xA9\xFD\x03\x00\x91\xFF\x00\x00\xD1\x30\x00\x80\x92\xFB\x03\x04\xAA", - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx?xxxxxxxxxx" - ); - if (match) - { - pOffsets[8] = FileOffsetToRVA(pFile, match - 4 - pFile); - } -#endif - if (pOffsets[8] && pOffsets[8] != 0xFFFFFFFF) - { - printf("CMultitaskingViewManager::_CreateDCompMTVHost() = %lX\n", pOffsets[8]); - } - } - } - -cleanup: - free(pFile); - CloseHandle(hFile); -} -#endif -#pragma endregion - - -#pragma region "Fix Pin to Start from Explorer not working when using Windows 10 start menu" -#if WITH_MAIN_PATCHER -extern HRESULT AppResolver_StartTileData_RoGetActivationFactory(HSTRING activatableClassId, REFIID iid, void** factory); - -typedef struct CCacheShortcut CCacheShortcut; -extern HRESULT(*AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc)(void* _this, const CCacheShortcut* a2, const void* a3); -extern HRESULT AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStart(void* _this, const CCacheShortcut* a2, const void* a3); - -static void PatchAppResolver() -{ - HANDLE hAppResolver = LoadLibraryW(L"AppResolver.dll"); - MODULEINFO miAppResolver; - GetModuleInformation(GetCurrentProcess(), hAppResolver, &miAppResolver, sizeof(MODULEINFO)); - - VnPatchDelayIAT(hAppResolver, "api-ms-win-core-winrt-l1-1-0.dll", "RoGetActivationFactory", AppResolver_StartTileData_RoGetActivationFactory); - - // CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart() -#if defined(_M_X64) - // 8B ? 48 8B D3 E8 ? ? ? ? 48 8B 8D - // ^^^^^^^ - // Ref: CAppResolverCacheBuilder::_AddShortcutToCache() - PBYTE match = FindPattern( - hAppResolver, - miAppResolver.SizeOfImage, - "\x8B\x00\x48\x8B\xD3\xE8\x00\x00\x00\x00\x48\x8B\x8D", - "x?xxxx????xxx" - ); - if (match) - { - match += 5; - match += 5 + *(int*)(match + 1); - } -#elif defined(_M_ARM64) - // 7F 23 03 D5 FD 7B BC A9 F3 53 01 A9 F5 5B 02 A9 F7 1B 00 F9 FD 03 00 91 ?? ?? ?? ?? FF 43 01 D1 F7 03 00 91 30 00 80 92 F0 1A 00 F9 ?? 03 01 AA ?? 03 02 AA FF ?? 00 F9 - // ----------- PACIBSP, don't scan for this because it's everywhere - PBYTE match = FindPattern( - hAppResolver, - miAppResolver.SizeOfImage, - "\xFD\x7B\xBC\xA9\xF3\x53\x01\xA9\xF5\x5B\x02\xA9\xF7\x1B\x00\xF9\xFD\x03\x00\x91\x00\x00\x00\x00\xFF\x43\x01\xD1\xF7\x03\x00\x91\x30\x00\x80\x92\xF0\x1A\x00\xF9\x00\x03\x01\xAA\x00\x03\x02\xAA\xFF\x00\x00\xF9", - "xxxxxxxxxxxxxxxxxxxx????xxxxxxxxxxxxxxxx?xxx?xxxx?xx" - ); - if (match) - { - match -= 4; - } -#endif - if (match) - { - AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc = match; - printf("CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart() = %llX\n", match - (PBYTE)hAppResolver); - } - - int rv = -1; - if (AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc) - { - rv = funchook_prepare( - funchook, - (void**)&AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc, - AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStart - ); - } - if (rv != 0) - { - printf("Failed to hook CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart(). rv = %d\n", rv); - } -} - -extern HRESULT PatchStartTileDataFurther(HMODULE hModule, BOOL bSMEH); - -static void PatchStartTileData(BOOL bSMEH) -{ - HANDLE hStartTileData = LoadLibraryW(L"StartTileData.dll"); - - VnPatchIAT(hStartTileData, "api-ms-win-core-winrt-l1-1-0.dll", "RoGetActivationFactory", AppResolver_StartTileData_RoGetActivationFactory); - - if (!bSMEH) - return; - - if ((global_rovi.dwBuildNumber >= 22621 && global_rovi.dwBuildNumber <= 22635) && global_ubr >= 3420 - || global_rovi.dwBuildNumber >= 25169) - { - PatchStartTileDataFurther(hStartTileData, bSMEH); - /*HRESULT hr = CoInitialize(NULL); - if (SUCCEEDED(hr)) - { - PatchStartTileDataFurther(hStartTileData, bSMEH); - } - if (hr == S_OK) - { - CoUninitialize(); - }*/ - } -} -#endif -#pragma endregion - - -#pragma region "Fix Windows 10 start menu animation on 22000.65+" -#if WITH_MAIN_PATCHER -static struct -{ - int startExperienceManager_IStartExperienceManager; - int startExperienceManager_SingleViewShellExperienceEventHandler; - int startExperienceManager_singleViewShellExperience; - int startExperienceManager_openingAnimation; - int startExperienceManager_closingAnimation; - int startExperienceManager_bTransitioningToCortana; -} g_SMAnimationPatchOffsets; - -// Names taken from 19041.844 twinui.pdb -enum EDGEUI_TRAYSTUCKPLACE -{ - EUITSP_UNKNOWN = -1, - EUITSP_LEFT = 0, - EUITSP_TOP, - EUITSP_RIGHT, - EUITSP_BOTTOM, -}; - -// Names taken from Windows.UI.Xaml.pdb, only defining the used ones -enum DWMTRANSITION_TARGET -{ - DWMTARGET_LAUNCHERFLYOUTTOLEFT = 0x4D, - DWMTARGET_LAUNCHERFLYOUTTORIGHT = 0x4E, - DWMTARGET_LAUNCHERFLYOUTTOTOP = 0x4F, - DWMTARGET_LAUNCHERFLYOUTTOBOTTOM = 0x50, - DWMTARGET_LAUNCHERFLYOUT = 0x51, - DWMTARGET_LAUNCHERFULLSCREEN = 0x52, -}; - -HRESULT(*CStartExperienceManager_GetMonitorInformationFunc)(void* _this, void* experience, RECT* a3, enum EDGEUI_TRAYSTUCKPLACE* pTsp, bool* a5, 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(*OnViewUncloakingFunc)(void* eventHandler, void* pSender); -HRESULT OnViewUncloakingHook(void* eventHandler, void* pSender) -{ - PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; - - RECT rc; - enum EDGEUI_TRAYSTUCKPLACE tsp; - bool bUnknown; - if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationFunc(_this, pSender, &rc, &tsp, &bUnknown, NULL))) - { - enum DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT; - if (*(bool*)((PBYTE)pSender + 0x34)) - target = DWMTARGET_LAUNCHERFULLSCREEN; - else if (tsp == EUITSP_LEFT) - target = DWMTARGET_LAUNCHERFLYOUTTORIGHT; - else if (tsp == EUITSP_TOP) - target = DWMTARGET_LAUNCHERFLYOUTTOBOTTOM; - else if (tsp == EUITSP_RIGHT) - target = DWMTARGET_LAUNCHERFLYOUTTOLEFT; - else if (tsp == EUITSP_BOTTOM) - target = DWMTARGET_LAUNCHERFLYOUTTOTOP; - - CExperienceManagerAnimationHelper_BeginFunc( - _this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation, - *(void**)((PBYTE)pSender + 0x18), // viewWrapper - target | 0x200000, NULL, NULL, NULL, NULL, &rc); - } - - return OnViewUncloakingFunc(eventHandler, pSender); -} - -HRESULT(*OnViewUncloakedFunc)(void* eventHandler, void* pSender); -HRESULT OnViewUncloakedHook(void* eventHandler, void* pSender) -{ - PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; - - CExperienceManagerAnimationHelper_EndFunc(_this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation); - - return OnViewUncloakedFunc(eventHandler, pSender); -} - -HRESULT(*OnViewCloakingFunc)(void* eventHandler, void* pSender); -HRESULT OnViewCloakingHook(void* eventHandler, void* pSender) -{ - PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; - - bool bTransitioningToCortana = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); - if (!bTransitioningToCortana) - { - RECT rc; - enum EDGEUI_TRAYSTUCKPLACE tsp; - bool bUnknown; - HMONITOR hMonitor; - if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationFunc(_this, pSender, &rc, &tsp, &bUnknown, &hMonitor))) - { - enum DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT; - if (*(bool*)((PBYTE)pSender + 0x34)) - target = DWMTARGET_LAUNCHERFULLSCREEN; - else if (tsp == EUITSP_LEFT) - target = DWMTARGET_LAUNCHERFLYOUTTOLEFT; - else if (tsp == EUITSP_TOP) - target = DWMTARGET_LAUNCHERFLYOUTTOTOP; - else if (tsp == EUITSP_RIGHT) - target = DWMTARGET_LAUNCHERFLYOUTTORIGHT; - else if (tsp == EUITSP_BOTTOM) - target = DWMTARGET_LAUNCHERFLYOUTTOBOTTOM; - - CExperienceManagerAnimationHelper_BeginFunc( - _this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation, - *(void**)((PBYTE)pSender + 0x18), // viewWrapper - target | 0x200000u, NULL, NULL, NULL, NULL, &rc); - } - } - - return OnViewCloakingFunc(eventHandler, pSender); -} - -HRESULT(*OnViewHiddenFunc)(void* eventHandler, void* pSender); -HRESULT OnViewHiddenHook(void* eventHandler, void* pSender) -{ - PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler; - - bool bTransitioningToCortana = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); - if (!bTransitioningToCortana) - { - CExperienceManagerAnimationHelper_EndFunc(_this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation); - } - - return OnViewHiddenFunc(eventHandler, pSender); -} - -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+. - - g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager = 0x28; - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler = 0x60; - - // ### CStartExperienceManager::`vftable'{for `SingleViewShellExperienceEventHandler'} -#if defined(_M_X64) - // ``` - // 48 89 46 48 48 8D 05 ?? ?? ?? ?? 48 89 46 60 48 8D 4E 68 E8 - // ^^^^^^^^^^^ - // ``` - // Ref: CStartExperienceManager::CStartExperienceManager() - PBYTE matchVtable = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x48\x89\x46\x48\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x46\x60\x48\x8D\x4E\x68\xE8", - "xxxxxxx????xxxxxxxxx" - ); - if (matchVtable) - { - matchVtable += 4; - matchVtable += 7 + *(int*)(matchVtable + 3); - } -#elif defined(_M_ARM64) - // ``` - // 69 22 04 A9 ?? ?? 00 ?? 08 81 ?? 91 60 A2 01 91 68 32 00 F9 - // ^^^^^^^^^^^+^^^^^^^^^^^ - PBYTE matchVtable = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x69\x22\x04\xA9\x00\x00\x00\x00\x08\x81\x00\x91\x60\xA2\x01\x91\x68\x32\x00\xF9", - "xxxx??x?xx?xxxxxxxxx" - ); - if (matchVtable) - { - matchVtable += 4; - matchVtable = (PBYTE)ARM64_DecodeADRL((UINT_PTR)matchVtable, *(DWORD*)matchVtable, *(DWORD*)(matchVtable + 4)); - } -#endif - if (matchVtable) - { - printf("[SMA] matchVtable = %llX\n", matchVtable - (PBYTE)mi->lpBaseOfDll); - } - - // ### Offset of SingleViewShellExperience instance and its event handler -#if defined(_M_X64) - // ``` - // 48 8D 8E ?? ?? ?? ?? 44 8D 45 41 48 8D 56 60 E8 - // ^^^^^^^^^^^ SVSE ^^ SVSEEH (hardcoded to 0x60, included in pattern for sanity check) - // ``` - // Ref: CStartExperienceManager::CStartExperienceManager() - PBYTE matchSingleViewShellExperienceFields = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x48\x8D\x8E\x00\x00\x00\x00\x44\x8D\x45\x41\x48\x8D\x56\x60\xE8", - "xxx????xxxxxxxxx" - ); - if (matchSingleViewShellExperienceFields) - { - g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience = *(int*)(matchSingleViewShellExperienceFields + 3); - } -#elif defined(_M_ARM64) - // ``` - // 22 08 80 52 61 82 01 91 60 ?? ?? 91 ?? ?? ?? ?? 1F 20 03 D5 - // ^^^SVSEEH^^ ^^^^^^^^^^^ SVSE - // ``` - // Ref: CStartExperienceManager::CStartExperienceManager() - PBYTE matchSingleViewShellExperienceFields = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x22\x08\x80\x52\x61\x82\x01\x91\x60\x00\x00\x91\x00\x00\x00\x00\x1F\x20\x03\xD5", - "xxxxxxxxx??x????xxxx" - ); - if (matchSingleViewShellExperienceFields) - { - g_SMAnimationPatchOffsets.startExperienceManager_singleViewShellExperience = (int)ARM64_DecodeADD(*(DWORD*)(matchSingleViewShellExperienceFields + 8)); - } -#endif - if (matchSingleViewShellExperienceFields) - { - printf("[SMA] matchSingleViewShellExperienceFields = %llX\n", matchSingleViewShellExperienceFields - (PBYTE)mi->lpBaseOfDll); - } - - // ### Offsets of Animation Helpers - PBYTE matchAnimationHelperFields = NULL; -#if defined(_M_X64) - // ``` - // 40 88 AE ?? ?? ?? ?? C7 86 ?? ?? ?? ?? 38 00 00 00 - // ^^^^^^^^^^^ AH1 - // ``` - // Ref: CStartExperienceManager::CStartExperienceManager() - // AH2 is located right after AH1. AH is 32 bytes - if (matchSingleViewShellExperienceFields) - { - matchAnimationHelperFields = FindPattern( - matchSingleViewShellExperienceFields + 16, - 128, - "\x40\x88\xAE\x00\x00\x00\x00\xC7\x86\x00\x00\x00\x00\x38\x00\x00\x00", - "xxx????xx????xxxx" - ); - } - if (matchAnimationHelperFields) - { - g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation = *(int*)(matchAnimationHelperFields + 3); - g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation = g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation + 32; - } -#elif defined(_M_ARM64) - // ``` - // 08 07 80 52 7F ?? ?? 39 68 ?? ?? B9 - // ^^^^^^^^^^^ AH1 - // ``` - // Ref: CStartExperienceManager::CStartExperienceManager() - // AH2 is located right after AH1. AH is 32 bytes - if (matchSingleViewShellExperienceFields) - { - matchAnimationHelperFields = FindPattern( - matchSingleViewShellExperienceFields + 20, - 128, - "\x08\x07\x80\x52\x7F\x00\x00\x39\x68\x00\x00\xB9", - "xxxxx??xx??x" - ); - } - if (matchAnimationHelperFields) - { - int openingAnimation = (int)ARM64_DecodeSTRBIMM(*(DWORD*)(matchAnimationHelperFields + 4)); - if (openingAnimation != -1) - { - g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation = openingAnimation; - g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation = g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation + 32; - } - else - { - matchAnimationHelperFields = NULL; - } - } -#endif - if (matchAnimationHelperFields) - { - printf( - "[SMA] matchAnimationHelperFields = %llX, +0x%X, +0x%X\n", - matchAnimationHelperFields - (PBYTE)mi->lpBaseOfDll, - g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation, - g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation - ); - } - - // ### Offset of bTransitioningToCortana -#if defined(_M_X64) - // ``` - // 80 B9 ?? ?? ?? ?? 00 75 ?? 48 83 C1 D8 - // ^^^^^^^^^^^ bTransitioningToCortana - // ``` - // Ref: CStartExperienceManager::DimStart() - PBYTE matchTransitioningToCortanaField = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x80\xB9\x00\x00\x00\x00\x00\x75\x00\x48\x83\xC1\xD8", - "xx????xx?xxxx" - ); - if (matchTransitioningToCortanaField) - { - g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana = g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager + *(int*)(matchTransitioningToCortanaField + 2); - } -#elif defined(_M_ARM64) - // ``` - // ?? ?? ?? 39 E8 00 00 35 ?? ?? ?? ?? 01 ?? ?? 91 22 00 80 52 - // ^^^^^^^^^^^ bTransitioningToCortana - // ``` - // Ref: CStartExperienceManager::DimStart() - PBYTE matchTransitioningToCortanaField = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x39\xE8\x00\x00\x35\x00\x00\x00\x00\x01\x00\x00\x91\x22\x00\x80\x52", - "xxxxx????x??xxxxx" - ); - if (matchTransitioningToCortanaField) - { - int off = (int)ARM64_DecodeLDRBIMM(*(DWORD*)(matchTransitioningToCortanaField - 3)); - if (off != -1) - { - g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana = g_SMAnimationPatchOffsets.startExperienceManager_IStartExperienceManager + off; - } - else - { - matchTransitioningToCortanaField = NULL; - } - } -#endif - if (matchTransitioningToCortanaField) - { - printf("[SMA] matchTransitioningToCortanaField = %llX, +0x%X\n", matchTransitioningToCortanaField - (PBYTE)mi->lpBaseOfDll, g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana); - } - - // ### Offset of CStartExperienceManager::GetMonitorInformation() -#if defined(_M_X64) - // ``` - // 48 8B ?? E8 ?? ?? ?? ?? 8B ?? 85 C0 0F 88 ?? ?? ?? ?? C6 44 24 ?? 01 - // ^^^^^^^^^^^ - // ``` - // Ref: CStartExperienceManager::PositionMenu() - PBYTE matchGetMonitorInformation = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x48\x8B\x00\xE8\x00\x00\x00\x00\x8B\x00\x85\xC0\x0F\x88\x00\x00\x00\x00\xC6\x44\x24\x00\x01", - "xx?x????x?xxxx????xxx?x" - ); - if (matchGetMonitorInformation) - { - matchGetMonitorInformation += 3; - matchGetMonitorInformation += 5 + *(int*)(matchGetMonitorInformation + 1); - } -#elif defined(_M_ARM64) - // * Pattern for 261xx: - // ``` - // E2 82 00 91 E1 03 13 AA E0 03 14 AA ?? ?? ?? ?? - // ^^^^^^^^^^^ - // ``` - // * Different patterns needed for 226xx and 262xx+ - // Ref: CStartExperienceManager::PositionMenu() - PBYTE matchGetMonitorInformation = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\xE2\x82\x00\x91\xE1\x03\x13\xAA\xE0\x03\x14\xAA", - "xxxxxxxxxxxx" - ); - if (matchGetMonitorInformation) - { - matchGetMonitorInformation += 12; - matchGetMonitorInformation = (PBYTE)ARM64_FollowBL((DWORD*)matchGetMonitorInformation); - } -#endif - if (matchGetMonitorInformation) - { - CStartExperienceManager_GetMonitorInformationFunc = matchGetMonitorInformation; - printf("[SMA] CStartExperienceManager::GetMonitorInformation() = %llX\n", matchGetMonitorInformation - (PBYTE)mi->lpBaseOfDll); - } - - // ### Offset of CExperienceManagerAnimationHelper::Begin() -#if defined(_M_X64) - // * Pattern 1, used when all arguments are available: - // ``` - // 44 8B C7 E8 ?? ?? ?? ?? 85 C0 79 19 - // ^^^^^^^^^^^ - // ``` - // * Pattern 2, used when a4, a5, and a6 are optimized out (e.g. 26020, 26058): - // ``` - // 44 8B C7 48 8D 8B ?? ?? ?? ?? E8 ?? ?? ?? ?? 85 C0 79 19 - // ^^^^^^^^^^^ - // ``` - // Ref: CJumpViewExperienceManager::OnViewUncloaking() - PBYTE matchAnimationBegin = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x44\x8B\xC7\xE8\x00\x00\x00\x00\x85\xC0\x79\x19", - "xxxx????xxxx" - ); - if (matchAnimationBegin) - { - matchAnimationBegin += 3; - matchAnimationBegin += 5 + *(int*)(matchAnimationBegin + 1); - } - else - { - matchAnimationBegin = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x44\x8B\xC7\x48\x8D\x8B\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x85\xC0\x79\x19", - "xxxxxx????x????xxxx" - ); - if (matchAnimationBegin) - { - matchAnimationBegin += 10; - matchAnimationBegin += 5 + *(int*)(matchAnimationBegin + 1); - } - } -#elif defined(_M_ARM64) - // * Pattern 1, used when all arguments are available: - // ``` - // Not implemented - // - // ``` - // * Pattern 2, used when a4, a5, and a6 are optimized out (e.g. 26020, 26058): - // ``` - // 82 02 0B 32 67 ?? ?? 91 60 ?? ?? 91 ?? ?? ?? ?? E3 03 00 2A - // ^^^^^^^^^^^ - // ``` - // Ref: CJumpViewExperienceManager::OnViewUncloaking() - PBYTE matchAnimationBegin = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x82\x02\x0B\x32\x67\x00\x00\x91\x60\x00\x00\x91\x00\x00\x00\x00\xE3\x03\x00\x2A", - "xxxxx??xx??x????xxxx" - ); - if (matchAnimationBegin) - { - matchAnimationBegin += 12; - matchAnimationBegin = (PBYTE)ARM64_FollowBL((DWORD*)matchAnimationBegin); - } -#endif - if (matchAnimationBegin) - { - CExperienceManagerAnimationHelper_BeginFunc = matchAnimationBegin; - printf("[SMA] CExperienceManagerAnimationHelper::Begin() = %llX\n", matchAnimationBegin - (PBYTE)mi->lpBaseOfDll); - } - - // ### Offset of CExperienceManagerAnimationHelper::End() -#if defined(_M_X64) - // ``` - // 40 53 48 83 EC 20 80 39 00 74 - // ``` - PBYTE matchAnimationEnd = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x40\x53\x48\x83\xEC\x20\x80\x39\x00\x74", - "xxxxxxxxxx" - ); -#elif defined(_M_ARM64) - // ``` - // 7F 23 03 D5 F3 0F 1F F8 FD 7B BF A9 FD 03 00 91 08 00 40 39 - // ----------- PACIBSP, don't scan for this because it's everywhere - // ``` - PBYTE matchAnimationEnd = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\xF3\x0F\x1F\xF8\xFD\x7B\xBF\xA9\xFD\x03\x00\x91\x08\x00\x40\x39", - "xxxxxxxxxxxxxxxx" - ); - if (matchAnimationEnd) - { - matchAnimationEnd -= 4; - } -#endif - if (matchAnimationEnd) - { - CExperienceManagerAnimationHelper_EndFunc = matchAnimationEnd; - printf("[SMA] CExperienceManagerAnimationHelper::End() = %llX\n", matchAnimationEnd - (PBYTE)mi->lpBaseOfDll); - } - - // ### CStartExperienceManager::Hide() -#if defined(_M_X64) - // * Pattern 1, mov [rbx+2A3h], r12b: - // ``` - // 74 ?? ?? 03 00 00 00 44 88 - // ^^ Turn jz into jmp - // ``` - // * Pattern 2, mov byte ptr [rbx+2A3h], 1: - // ``` - // 74 ?? ?? 03 00 00 00 C6 83 - // ^^ Turn jz into jmp - // ``` - // Perform on exactly two matches - PBYTE matchHideA = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x74\x00\x00\x03\x00\x00\x00\x44\x88", - "x??xxxxxx" - ); - PBYTE matchHideB = NULL; - if (matchHideA) + int rv = -1; + if (AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc) { - printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); - matchHideB = FindPattern( - matchHideA + 14, - mi->SizeOfImage - (matchHideA + 14 - (PBYTE)mi->lpBaseOfDll), - "\x74\x00\x00\x03\x00\x00\x00\x44\x88", - "x??xxxxxx" + rv = funchook_prepare( + funchook, + (void**)&AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStartFunc, + AppResolver_CAppResolverCacheBuilder__AddUserPinnedShortcutToStart ); - if (matchHideB) - { - printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); - } - } - - if (!matchHideA || !matchHideB) - { - matchHideA = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x74\x00\x00\x03\x00\x00\x00\xC6\x83", - "x??xxxxxx" - ); - matchHideB = NULL; - if (matchHideA) - { - printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); - matchHideB = FindPattern( - matchHideA + 14, - mi->SizeOfImage - (matchHideA + 14 - (PBYTE)mi->lpBaseOfDll), - "\x74\x00\x00\x03\x00\x00\x00\xC6\x83", - "x??xxxxxx" - ); - if (matchHideB) - { - printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); - } - } } -#elif defined(_M_ARM64) - // ``` - // ?? ?? ?? 34 ?? 00 80 52 ?? 8E 0A 39 - // ^^^^^^^^^^^ Turn CBZ into B - // ``` - // Perform on exactly two matches - PBYTE matchHideA = FindPattern( - mi->lpBaseOfDll, - mi->SizeOfImage, - "\x34\x00\x00\x80\x52\x00\x8E\x0A\x39", - "x?xxx?xxx" - ); - PBYTE matchHideB = NULL; - if (matchHideA) + if (rv != 0) { - matchHideA -= 3; - printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll); - matchHideB = FindPattern( - matchHideA + 12, - mi->SizeOfImage - (matchHideA + 12 - (PBYTE)mi->lpBaseOfDll), - "\x34\x00\x00\x80\x52\x00\x8E\x0A\x39", - "x?xxx?xxx" - ); - if (matchHideB) - { - matchHideB -= 3; - printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll); - } - } -#endif - - if (!matchVtable - || !matchSingleViewShellExperienceFields - || !matchAnimationHelperFields - || !matchTransitioningToCortanaField - || !matchGetMonitorInformation - || !matchAnimationBegin - || !matchAnimationEnd - || !matchHideA - || !matchHideB) - { - printf("[SMA] Not all offsets were found, cannot perform patch\n"); - return FALSE; + printf("Failed to hook CAppResolverCacheBuilder::_AddUserPinnedShortcutToStart(). rv = %d\n", rv); } +} - DWORD dwOldProtect = 0; - - void** vtable = (void**)matchVtable; - void** p_OnViewUncloaking = &vtable[4]; - void** p_OnViewUncloaked = &vtable[5]; - void** p_OnViewCloaking = &vtable[6]; - void** p_OnViewHidden = &vtable[10]; - - // OnViewUncloaking - if (*p_OnViewUncloaking != OnViewUncloakingHook) - { - OnViewUncloakingFunc = *p_OnViewUncloaking; - if (VirtualProtect(p_OnViewUncloaking, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) - { - *p_OnViewUncloaking = OnViewUncloakingHook; - VirtualProtect(p_OnViewUncloaking, sizeof(void*), dwOldProtect, &dwOldProtect); - } - } +extern HRESULT PatchStartTileDataFurther(HMODULE hModule, BOOL bSMEH); - // OnViewUncloaked - if (*p_OnViewUncloaked != OnViewUncloakedHook) - { - OnViewUncloakedFunc = *p_OnViewUncloaked; - if (VirtualProtect(p_OnViewUncloaked, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) - { - *p_OnViewUncloaked = OnViewUncloakedHook; - VirtualProtect(p_OnViewUncloaked, sizeof(void*), dwOldProtect, &dwOldProtect); - } - } +static void PatchStartTileData(BOOL bSMEH) +{ + HANDLE hStartTileData = LoadLibraryW(L"StartTileData.dll"); - // OnViewCloaking - if (*p_OnViewCloaking != OnViewCloakingHook) - { - OnViewCloakingFunc = *p_OnViewCloaking; - if (VirtualProtect(p_OnViewCloaking, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) - { - *p_OnViewCloaking = OnViewCloakingHook; - VirtualProtect(p_OnViewCloaking, sizeof(void*), dwOldProtect, &dwOldProtect); - } - } + VnPatchIAT(hStartTileData, "api-ms-win-core-winrt-l1-1-0.dll", "RoGetActivationFactory", AppResolver_StartTileData_RoGetActivationFactory); - // OnViewHidden - if (*p_OnViewHidden != OnViewHiddenHook) - { - OnViewHiddenFunc = *p_OnViewHidden; - if (VirtualProtect(p_OnViewHidden, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtect)) - { - *p_OnViewHidden = OnViewHiddenHook; - VirtualProtect(p_OnViewHidden, sizeof(void*), dwOldProtect, &dwOldProtect); - } - } + if (!bSMEH) + return; -#if defined(_M_X64) - if (VirtualProtect(matchHideA, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + if ((global_rovi.dwBuildNumber >= 22621 && global_rovi.dwBuildNumber <= 22635) && global_ubr >= 3420 + || global_rovi.dwBuildNumber >= 25169) { - matchHideA[0] = 0xEB; - VirtualProtect(matchHideA, 1, dwOldProtect, &dwOldProtect); - - dwOldProtect = 0; - if (VirtualProtect(matchHideB, 1, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + PatchStartTileDataFurther(hStartTileData, bSMEH); + /*HRESULT hr = CoInitialize(NULL); + if (SUCCEEDED(hr)) { - matchHideB[0] = 0xEB; - VirtualProtect(matchHideB, 1, dwOldProtect, &dwOldProtect); + PatchStartTileDataFurther(hStartTileData, bSMEH); } - } -#elif defined(_M_ARM64) - if (VirtualProtect(matchHideA, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) - { - DWORD newInsn = ARM64_CBZWToB(*(DWORD*)matchHideA); - if (newInsn) - *(DWORD*)matchHideA = newInsn; - VirtualProtect(matchHideA, 4, dwOldProtect, &dwOldProtect); - - dwOldProtect = 0; - if (VirtualProtect(matchHideB, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect)) + if (hr == S_OK) { - newInsn = ARM64_CBZWToB(*(DWORD*)matchHideB); - if (newInsn) - *(DWORD*)matchHideB = newInsn; - VirtualProtect(matchHideB, 4, dwOldProtect, &dwOldProtect); - } + CoUninitialize(); + }*/ } -#endif - - return TRUE; } #endif #pragma endregion @@ -11962,6 +9723,13 @@ void GetCrashCounterSettings(CrashCounterSettings* out) if (out->threshold <= 1 || out->threshold >= 10) out->threshold = 3; } +BOOL IsCrashCounterEnabled() +{ + CrashCounterSettings cfg; + GetCrashCounterSettings(&cfg); + return !cfg.bDisabled; +} + HRESULT InformUserAboutCrashCallback(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData) { if (msg == TDN_HYPERLINK_CLICKED) @@ -12176,7 +9944,7 @@ BOOL CheckExplorerSymbols(symbols_addr* symbols_PTRS) const WCHAR* GetTaskbarDllChecked(symbols_addr* symbols_PTRS) { - if (bOldTaskbar < 2 || !IsWindows11Version22H2OrHigher()) + if (!IsWindows11Version22H2OrHigher()) { return NULL; } @@ -12194,9 +9962,13 @@ const WCHAR* GetTaskbarDllChecked(symbols_addr* symbols_PTRS) return pszTaskbarDll; } +// Behavior based on selected Taskbar style: +// - Windows 11: Load our taskbar DLL with LOAD_LIBRARY_AS_DATAFILE for the old context menu +// - Windows 10: Skip loading +// - Windows 10 (ExplorerPatcher): Load it fully HMODULE PrepareAlternateTaskbarImplementation(symbols_addr* symbols_PTRS, const WCHAR* pszTaskbarDll) { - if (!symbols_PTRS || !pszTaskbarDll) + if (bOldTaskbar == 1 || !symbols_PTRS || !pszTaskbarDll) { return NULL; } @@ -12206,7 +9978,7 @@ HMODULE PrepareAlternateTaskbarImplementation(symbols_addr* symbols_PTRS, const SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, szPath); wcscat_s(szPath, MAX_PATH, _T(APP_RELATIVE_PATH) L"\\"); wcscat_s(szPath, MAX_PATH, pszTaskbarDll); - HMODULE hMyTaskbar = LoadLibraryW(szPath); + HMODULE hMyTaskbar = bOldTaskbar >= 2 ? LoadLibraryW(szPath) : LoadLibraryExW(szPath, NULL, LOAD_LIBRARY_AS_DATAFILE); if (!hMyTaskbar) { wprintf(L"[TB] '%s' not found\n", pszTaskbarDll); @@ -12214,6 +9986,11 @@ HMODULE PrepareAlternateTaskbarImplementation(symbols_addr* symbols_PTRS, const } g_hMyTaskbar = hMyTaskbar; + if (!bOldTaskbar) + { + return NULL; + } + typedef DWORD (*GetVersion_t)(); GetVersion_t GetVersion = (GetVersion_t)GetProcAddress(hMyTaskbar, "GetVersion"); DWORD version = GetVersion ? GetVersion() : 0; @@ -12929,208 +10706,14 @@ DWORD Inject(BOOL bIsExplorer) // DwmExtendFrameIntoClientArea hooked in LoadSettings printf("Setup uxtheme functions done\n"); + RunTwinUIPCShellPatches(&symbols_PTRS); - HANDLE hTwinuiPcshell = LoadLibraryW(L"twinui.pcshell.dll"); - MODULEINFO miTwinuiPcshell; - GetModuleInformation(GetCurrentProcess(), hTwinuiPcshell, &miTwinuiPcshell, sizeof(MODULEINFO)); - - // ZeroMemory(symbols_PTRS.twinui_pcshell_PTRS, sizeof(symbols_PTRS.twinui_pcshell_PTRS)); // Uncomment for testing - TryToFindTwinuiPCShellOffsets(symbols_PTRS.twinui_pcshell_PTRS); - - if (symbols_PTRS.twinui_pcshell_PTRS[0] && symbols_PTRS.twinui_pcshell_PTRS[0] != 0xFFFFFFFF) - { - CImmersiveContextMenuOwnerDrawHelper_s_ContextMenuWndProcFunc = (INT64(*)(HWND, int, HWND, int, BOOL*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[0]); - } - - if (symbols_PTRS.twinui_pcshell_PTRS[1] && symbols_PTRS.twinui_pcshell_PTRS[1] != 0xFFFFFFFF) - { - CLauncherTipContextMenu_GetMenuItemsAsyncFunc = (INT64(*)(void*, RECT, IUnknown**)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[1]); - } - - if (symbols_PTRS.twinui_pcshell_PTRS[2] && symbols_PTRS.twinui_pcshell_PTRS[2] != 0xFFFFFFFF) - { - ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc = (ImmersiveContextMenuHelper_ApplyOwnerDrawToMenu_t) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[2]); - } - - if (symbols_PTRS.twinui_pcshell_PTRS[3] && symbols_PTRS.twinui_pcshell_PTRS[3] != 0xFFFFFFFF) - { - ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenu_t) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[3]); - } - - if (symbols_PTRS.twinui_pcshell_PTRS[4] && symbols_PTRS.twinui_pcshell_PTRS[4] != 0xFFFFFFFF) - { - CLauncherTipContextMenu_ExecuteShutdownCommandFunc = (void(*)(void*, void*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[4]); - } - - if (symbols_PTRS.twinui_pcshell_PTRS[5] && symbols_PTRS.twinui_pcshell_PTRS[5] != 0xFFFFFFFF) - { - CLauncherTipContextMenu_ExecuteCommandFunc = (void(*)(void*, int)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[5]); - } - - rv = -1; - if (symbols_PTRS.twinui_pcshell_PTRS[6] && symbols_PTRS.twinui_pcshell_PTRS[6] != 0xFFFFFFFF) - { - CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc = (INT64(*)(void*, POINT*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[6]); - rv = funchook_prepare( - funchook, - (void**)&CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc, - CLauncherTipContextMenu_ShowLauncherTipContextMenuHook - ); - } - if (rv != 0) - { - printf("Failed to hook CLauncherTipContextMenu::ShowLauncherTipContextMenu(). rv = %d\n", rv); - } - - if (IsWindows11()) - { - rv = -1; - if (symbols_PTRS.twinui_pcshell_PTRS[7] && symbols_PTRS.twinui_pcshell_PTRS[7] != 0xFFFFFFFF) - { - twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc = (INT64(*)(void*, POINT*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[8]); - twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc = (INT64(*)(void*, POINT*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[7]); - rv = funchook_prepare( - funchook, - (void**)&twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc, - twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostHook - ); - } - if (rv != 0) - { - printf("Failed to hook CMultitaskingViewManager::_CreateXamlMTVHost(). rv = %d\n", rv); - } - } - - /*rv = -1; - if (symbols_PTRS.twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1] && symbols_PTRS.twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1] != 0xFFFFFFFF) - { - winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc = (INT64(*)(void*, POINT*)) - ((uintptr_t)hTwinuiPcshell + symbols_PTRS.twinui_pcshell_PTRS[TWINUI_PCSHELL_SB_CNT - 1]); - rv = funchook_prepare( - funchook, - (void**)&winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc, - winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHook - ); - } - if (rv != 0) - { - printf("Failed to hook winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessage(). rv = %d\n", rv); - }*/ - -#if WITH_MAIN_PATCHER -#if USE_MOMENT_3_FIXES_ON_MOMENT_2 - // Use this only for testing, since the RtlQueryFeatureConfiguration() hook is perfect. - // Only tested on 22621.1992. - BOOL bPerformMoment2Patches = IsWindows11Version22H2Build1413OrHigher(); -#else - // This is the only way to fix stuff since the flag "26008830" and the code when it's not enabled are gone. - // Tested on: - // - 22621.2134, 22621.2283, 22621.2359 (RP) - // - 23545.1000 - BOOL bPerformMoment2Patches = IsWindows11Version22H2Build2134OrHigher(); -#endif - if (bOldTaskbar != 1) - { - bPerformMoment2Patches = FALSE; - } - if (bPerformMoment2Patches) - { - // Fix flyout placement: Our goal with these patches is to get `mi.rcWork` assigned - Moment2PatchActionCenter(&miTwinuiPcshell); - Moment2PatchControlCenter(&miTwinuiPcshell); - Moment2PatchToastCenter(&miTwinuiPcshell); - - // Fix task view - Moment2PatchTaskView(&miTwinuiPcshell); - - // Fix volume and brightness popups - HANDLE hHardwareConfirmator = LoadLibraryW(L"Windows.Internal.HardwareConfirmator.dll"); - MODULEINFO miHardwareConfirmator; - GetModuleInformation(GetCurrentProcess(), hHardwareConfirmator, &miHardwareConfirmator, sizeof(MODULEINFO)); - Moment2PatchHardwareConfirmator(&miHardwareConfirmator); - - // Fix pen menu -#if defined(_M_X64) - // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 50 49 8B ? 48 81 C1 - twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc = FindPattern( - hTwinuiPcshell, - miTwinuiPcshell.SizeOfImage, - "\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x50\x49\x8B\x00\x48\x81\xC1", - "xxxx?xxxx?xxxxxxx?xxx" - ); -#endif - rv = -1; - if (twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc) - { - printf("PenMenuSystemTrayManager::GetDynamicSystemTrayHeightForMonitor() = %llX\n", (PBYTE)twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc - (PBYTE)hTwinuiPcshell); - rv = funchook_prepare( - funchook, - (void**)&twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorFunc, - twinui_pcshell_PenMenuSystemTrayManager__GetDynamicSystemTrayHeightForMonitorHook - ); - } - if (rv != 0) - { - 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+ - && 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. - CrashCounterSettings cfg; - GetCrashCounterSettings(&cfg); - if (!cfg.bDisabled) - { - if (FixStartMenuAnimation(&miTwinuiPcshell)) - { -#if WITH_SMA_PATCH_REPORT - PSID pMainSid = NULL; - GetLogonSid(&pMainSid); - PSID pSecondaySid = NULL; - DeriveAppContainerSidFromAppContainerName(L"Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy", &pSecondaySid); - PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; - if (PrepareSecurityDescriptor(pMainSid, STANDARD_RIGHTS_ALL | MUTEX_ALL_ACCESS, pSecondaySid, SYNCHRONIZE, &pSecurityDescriptor)) - { - SECURITY_ATTRIBUTES SecurityAttributes; - ZeroMemory(&SecurityAttributes, sizeof(SecurityAttributes)); - SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - SecurityAttributes.bInheritHandle = FALSE; - SecurityAttributes.lpSecurityDescriptor = pSecurityDescriptor; - if (CreateMutexW(&SecurityAttributes, FALSE, _T(EPStart10_AnimationsPatched))) - { - printf("[SMA] Advertising successful animations patching.\n"); - } - free(pSecurityDescriptor); - } - if (pMainSid) free(pMainSid); - if (pSecondaySid) FreeSid(pSecondaySid); -#endif - } - } - } -#endif - - VnPatchIAT(hTwinuiPcshell, "API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL", "RegGetValueW", twinuipcshell_RegGetValueW); HMODULE hMyTaskbar = PrepareAlternateTaskbarImplementation(&symbols_PTRS, pszTaskbarDll); if (hMyTaskbar) { VnPatchIAT(hMyTaskbar, "user32.dll", "LoadMenuW", explorer_LoadMenuW); VnPatchIAT(hMyTaskbar, "user32.dll", "TrackPopupMenuEx", explorer_TrackPopupMenuExHook); } - printf("Setup twinui.pcshell functions done\n"); - HANDLE hCombase = LoadLibraryW(L"combase.dll"); if (IsWindows11()) @@ -14712,8 +12295,9 @@ DWORD InjectStartMenu() if (dwStartShowClassicMode || !IsWindows11()) { - LoadLibraryW(L"StartUI.dll"); - hStartUI = GetModuleHandleW(L"StartUI.dll"); + hStartUI = LoadLibraryW(L"StartUI.dll"); + if (!hStartUI) + hStartUI = LoadLibraryW(L"StartUI_.dll"); // Fixes hang when Start menu closes VnPatchDelayIAT(hStartUI, "ext-ms-win-ntuser-draw-l1-1-0.dll", "SetWindowRgn", Start_SetWindowRgn); diff --git a/ExplorerPatcher/updates.cpp b/ExplorerPatcher/updates.cpp index 40bf8e7fe..c6154e3a3 100644 --- a/ExplorerPatcher/updates.cpp +++ b/ExplorerPatcher/updates.cpp @@ -275,7 +275,7 @@ BOOL IsUpdateAvailableHelper( jsonStr.c_str(), -1, pszJsonStr, - jsonStr.size() + 1 + (int)(jsonStr.size() + 1) ); } } diff --git a/ExplorerPatcher/utility.c b/ExplorerPatcher/utility.c index 09176680d..2fc049150 100644 --- a/ExplorerPatcher/utility.c +++ b/ExplorerPatcher/utility.c @@ -1330,8 +1330,7 @@ BOOL DownloadFile(LPCWSTR wszURL, DWORD dwSize, LPCWSTR wszPath) exe_buffer = calloc(dwSize, sizeof(char)); if (exe_buffer) { - BOOL bRet = FALSE; - if (bRet = InternetReadFile( + if (InternetReadFile( hConnect, exe_buffer, dwSize - 1, @@ -1342,7 +1341,7 @@ BOOL DownloadFile(LPCWSTR wszURL, DWORD dwSize, LPCWSTR wszPath) _wfopen_s(&f, wszPath, L"wb"); if (f) { - fwrite(exe_buffer, 1, dwRead, f); + bOK = fwrite(exe_buffer, 1, dwRead, f) == dwRead; fclose(f); } } diff --git a/ExplorerPatcher/utility.h b/ExplorerPatcher/utility.h index 94358f65a..d86840241 100644 --- a/ExplorerPatcher/utility.h +++ b/ExplorerPatcher/utility.h @@ -406,7 +406,7 @@ inline RM_UNIQUE_PROCESS GetExplorerApplication() DWORD pid = 0; GetWindowThreadProcessId(hwnd, &pid); - RM_UNIQUE_PROCESS out = { 0, { -1, -1 } }; + RM_UNIQUE_PROCESS out = { 0, { (DWORD)-1, (DWORD)-1 } }; DWORD bytesReturned; WCHAR imageName[MAX_PATH]; // process image name buffer DWORD processIds[2048]; // max 2048 processes (more than enough) @@ -604,6 +604,27 @@ inline BOOL IncrementDLLReferenceCount(HINSTANCE hinst) PVOID FindPattern(PVOID pBase, SIZE_T dwSize, LPCSTR lpPattern, LPCSTR lpMask); +#if _M_X64 +inline BOOL FollowJnz(PBYTE pJnz, PBYTE* pTarget, DWORD* pJnzSize) +{ + // Check big jnz + if (pJnz[0] == 0x0F && pJnz[1] == 0x85) + { + *pTarget = pJnz + 6 + *(int*)(pJnz + 2); + *pJnzSize = 6; + return TRUE; + } + // Check small jnz + if (pJnz[0] == 0x75) + { + *pTarget = pJnz + 2 + *(char*)(pJnz + 1); + *pJnzSize = 2; + return TRUE; + } + return FALSE; +} +#endif + #if _M_ARM64 // https://github.com/CAS-Atlantic/AArch64-Encoding @@ -700,7 +721,7 @@ __forceinline DWORD ARM64_DecodeLDRBIMM(DWORD insnLDRBIMM) inline UINT_PTR ARM64_DecodeADRL(UINT_PTR offset, DWORD insnADRP, DWORD insnADD) { if (!ARM64_IsADRP(insnADRP)) - return NULL; + return 0; UINT_PTR page = ARM64_Align(offset, 0x1000); @@ -857,6 +878,32 @@ inline PVOID FindPattern(PVOID pBase, SIZE_T dwSize, LPCSTR lpPattern, LPCSTR lp return FindPatternHelper(pBase, dwSize, lpPattern, lpMask); } +inline UINT_PTR FileOffsetToRVA(PBYTE pBase, UINT_PTR offset) +{ + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBase; + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pBase + pDosHeader->e_lfanew); + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders); + for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) + { + if (offset >= pSection->PointerToRawData && offset < pSection->PointerToRawData + pSection->SizeOfRawData) + return offset - pSection->PointerToRawData + pSection->VirtualAddress; + } + return 0; +} + +inline UINT_PTR RVAToFileOffset(PBYTE pBase, UINT_PTR rva) +{ + PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBase; + PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)(pBase + pDosHeader->e_lfanew); + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders); + for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++, pSection++) + { + if (rva >= pSection->VirtualAddress && rva < pSection->VirtualAddress + pSection->Misc.VirtualSize) + return rva - pSection->VirtualAddress + pSection->PointerToRawData; + } + return 0; +} + inline HMODULE LoadGuiModule() { wchar_t epGuiPath[MAX_PATH]; @@ -874,7 +921,15 @@ inline BOOL DoesWindows10StartMenuExist() wchar_t szPath[MAX_PATH]; GetWindowsDirectoryW(szPath, MAX_PATH); wcscat_s(szPath, MAX_PATH, L"\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\StartUI.dll"); - return FileExistsW(szPath); + if (FileExistsW(szPath)) + return TRUE; + + GetWindowsDirectoryW(szPath, MAX_PATH); + wcscat_s(szPath, MAX_PATH, L"\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\StartUI_.dll"); + if (FileExistsW(szPath)) + return TRUE; + + return FALSE; } inline BOOL IsStockWindows10TaskbarAvailable() diff --git a/README.md b/README.md index 678a5a876..fae1e9cc0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This project aims to enhance the working environment on Windows. ## How to? -1. Download the latest version of the setup program [for x64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.exe) or [for ARM64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.arm64.exe). +1. Download the latest version of the setup program [for x64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.exe) or [for ARM64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup_arm64.exe). 2. Run the installer. It will automatically prompt for elevation, after which it will install the necessary files. 3. When done, you will be greeted with the familiar Windows 10 taskbar. To customize the options offered by the program, right click the taskbar and choose "Properties". @@ -20,7 +20,7 @@ That's it. It's that simple. ## Updating * The program features built-in updates: go to "Properties" - "Updates" to configure, check for and install the latest updates. Learn more [here](https://github.com/valinet/ExplorerPatcher/wiki/Configure-updates). -* Download the latest version's [setup file for x64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.exe) or [setup file for ARM64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.arm64.exe) and simply run it. +* Download the latest version's [setup file for x64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup.exe) or [setup file for ARM64](https://github.com/valinet/ExplorerPatcher/releases/latest/download/ep_setup_arm64.exe) and simply run it. ## Donate diff --git a/ep_setup/ep_setup.c b/ep_setup/ep_setup.c index e841d7eb9..cd1da498d 100644 --- a/ep_setup/ep_setup.c +++ b/ep_setup/ep_setup.c @@ -471,7 +471,7 @@ unzFile LoadZipFileFromResources(MemoryBuffer** outMem) rijndaelDecrypt(rk, nrounds, pRsrc + offset, pMem->base + offset); } #else - memcpy(mem->base, pRsrc, cbRsrc); + memcpy(pMem->base, pRsrc, cbRsrc); #endif zlib_filefunc64_def fileFunc = { 0 }; @@ -480,7 +480,30 @@ unzFile LoadZipFileFromResources(MemoryBuffer** outMem) return unzOpen2_64(NULL, &fileFunc); } -BOOL InstallResourceHelper(BOOL bInstall, HMODULE hModule, unzFile zipFile, const WCHAR* wszPath) +int g_cleanupFileCounter = 1; + +// %APPDATA%\ExplorerPatcher\cleanup\_.tmp +BOOL StageFileForCleanup(const WCHAR* wszProblematicFilePath) +{ + WCHAR wszPath[MAX_PATH]; + SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wszPath); + wcscat_s(wszPath, MAX_PATH, L"\\ExplorerPatcher\\cleanup"); + CreateDirectoryW(wszPath, NULL); + + wcscat_s(wszPath, MAX_PATH, L"\\"); + WCHAR wszPID[10]; + _itow_s(GetCurrentProcessId(), wszPID, ARRAYSIZE(wszPID), 10); + wcscat_s(wszPath, MAX_PATH, wszPID); + wcscat_s(wszPath, MAX_PATH, L"_"); + WCHAR wszCounter[10]; + _itow_s(g_cleanupFileCounter++, wszCounter, ARRAYSIZE(wszCounter), 10); + wcscat_s(wszPath, MAX_PATH, wszCounter); + wcscat_s(wszPath, MAX_PATH, L".tmp"); + + return MoveFileW(wszProblematicFilePath, wszPath); +} + +__declspec(noinline) BOOL InstallResourceHelper(BOOL bInstall, HMODULE hModule, unzFile zipFile, const WCHAR* wszPath) { WCHAR wszReplace[MAX_PATH]; wcscpy_s(wszReplace, MAX_PATH, wszPath); @@ -493,7 +516,7 @@ BOOL InstallResourceHelper(BOOL bInstall, HMODULE hModule, unzFile zipFile, cons BOOL bRet = !bPrevExists || DeleteFileW(wszReplace); if (bRet || (!bRet && GetLastError() == ERROR_FILE_NOT_FOUND)) { - if (bFileExists && !DeleteFileW(wszPath) && !MoveFileW(wszPath, wszReplace)) + if (bFileExists && !DeleteFileW(wszPath) && !StageFileForCleanup(wszPath)) { return FALSE; } @@ -590,45 +613,199 @@ __declspec(noinline) BOOL InstallResource(BOOL bInstall, HMODULE hInstance, unzF return bRet; } -BOOL DeleteResource(LPCWSTR pwszDirectory, LPCWSTR pwszFileName) +const WCHAR* GetSystemLanguages() { - WCHAR wszPath[MAX_PATH]; - wcscpy_s(wszPath, MAX_PATH, pwszDirectory); - wcscat_s(wszPath, MAX_PATH, L"\\"); - wcscat_s(wszPath, MAX_PATH, pwszFileName); - return InstallResourceHelper(FALSE, NULL, NULL, wszPath); + wchar_t* wszLanguagesBuffer = NULL; + ULONG ulNumLanguages = 0; + ULONG cchLanguagesBuffer = 0; + if (GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &ulNumLanguages, NULL, &cchLanguagesBuffer)) + { + wszLanguagesBuffer = (wchar_t*)malloc(cchLanguagesBuffer * sizeof(wchar_t)); + if (wszLanguagesBuffer) + { + if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &ulNumLanguages, wszLanguagesBuffer, &cchLanguagesBuffer)) + { + free(wszLanguagesBuffer); + wszLanguagesBuffer = NULL; + } + } + } + return wszLanguagesBuffer ? wszLanguagesBuffer : L"en-US"; } -BOOL ShouldDownloadOrDelete(BOOL bInstall, WCHAR* wszPath, LPCSTR chash) +BOOL SystemHasLanguageInstalled(const WCHAR* languages, const char* langCode, int cchLangCode) { - if (FileExistsW(wszPath)) + WCHAR szLangCode[100]; + MultiByteToWideChar(CP_UTF8, 0, langCode, cchLangCode, szLangCode, ARRAYSIZE(szLangCode)); + szLangCode[cchLangCode] = 0; + for (const WCHAR* wszLang = languages; *wszLang; wszLang += wcslen(wszLang) + 1) { - char hash[100]; - ZeroMemory(hash, sizeof(char) * 100); - ComputeFileHash(wszPath, hash, 100); - if (_stricmp(hash, chash) != 0) + if (!_wcsicmp(wszLang, szLangCode)) { - if (bInstall) + return TRUE; + } + } + return FALSE; +} + +typedef enum LanguageCodeTreatment +{ + LCT_None, + LCT_MUI, // module\en-US\module.dll.pri + LCT_PRI, // resource\pris\resource.en-US.pri +} LanguageCodeTreatment; + +__declspec(noinline) BOOL ExtractDirectory(unzFile zipFile, const char* dirNameInZip, LPCWSTR pwszDirectory, const WCHAR* languages, LanguageCodeTreatment langCodeTreatment) +{ + if (!zipFile) + { + return FALSE; + } + + if (unzGoToFirstFile(zipFile) != UNZ_OK) + { + return FALSE; + } + + BOOL bRet = TRUE; + size_t dirNameLen = dirNameInZip ? strlen(dirNameInZip) : 0; + + do + { + char szFileNameInZip[260]; + unz_file_info64 fileInfo = { 0 }; + if (unzGetCurrentFileInfo64(zipFile, &fileInfo, szFileNameInZip, ARRAYSIZE(szFileNameInZip), NULL, 0, NULL, 0) != UNZ_OK) + { + return FALSE; + } + szFileNameInZip[fileInfo.size_filename] = 0; + + if (fileInfo.uncompressed_size == 0 || (fileInfo.external_fa & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + continue; + } + + if (dirNameInZip && strncmp(szFileNameInZip, dirNameInZip, dirNameLen) != 0) + { + continue; + } + + // Examples: + // - "module/en-US/module.dll.mui" -> "en-US/module.dll.mui" + // - "resource/pris/resource.en-US.pri" -> "pris/resource.en-US.pri" + const char* filePathInDir = szFileNameInZip + dirNameLen; + const char* lastSlash = strrchr(filePathInDir, '/'); + const char* fileName = lastSlash ? filePathInDir + (lastSlash - filePathInDir) + 1 : filePathInDir; + const char* lastDot = strrchr(fileName, '.'); + const char* fileExt = lastDot ? fileName + (lastDot - fileName) + 1 : NULL; + if (langCodeTreatment == LCT_MUI) + { + if (fileExt && !_stricmp(fileExt, "mui")) + { + if (!SystemHasLanguageInstalled(languages, filePathInDir, strchr(filePathInDir, '/') - filePathInDir)) + { + continue; + } + } + } + else if (langCodeTreatment == LCT_PRI) + { + if (fileExt && !_stricmp(fileExt, "pri") && strchr(fileName, '-') != NULL) + { + // Check if we're a language pri + const char* secondLastDot = NULL; + for (const char* p = lastDot - 1; p >= fileName; p--) + { + if (*p == '.') + { + secondLastDot = p; + break; + } + } + if (secondLastDot != lastDot) + { + const char* langCode = secondLastDot + 1; + if (!SystemHasLanguageInstalled(languages, langCode, lastDot - langCode)) + { + continue; + } + } + } + } + + if (unzOpenCurrentFile(zipFile) != UNZ_OK) + { + return FALSE; + } + + WCHAR wszFileNameInZip[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, szFileNameInZip, -1, wszFileNameInZip, MAX_PATH); + for (size_t i = 0; i < MAX_PATH && wszFileNameInZip[i] != 0; i++) + { + if (wszFileNameInZip[i] == '/') { - return TRUE; + wszFileNameInZip[i] = '\\'; } } + + WCHAR wszPath[MAX_PATH]; + wcscpy_s(wszPath, MAX_PATH, pwszDirectory); + wcscat_s(wszPath, MAX_PATH, L"\\"); + WCHAR* pwszPathInDir = wszPath + wcslen(wszPath); + if (dirNameInZip) + { + wcscat_s(wszPath, MAX_PATH, wcschr(wszFileNameInZip, '\\') + 1); // Skip the directory name in the zip file + } else { - if (!bInstall) + wcscat_s(wszPath, MAX_PATH, wszFileNameInZip); + } + + for (WCHAR* p = pwszPathInDir; *p; p++) + { + if (*p == '\\') { - return InstallResourceHelper(FALSE, NULL, NULL, wszPath); // Delete + *p = 0; + CreateDirectoryW(wszPath, NULL); + *p = '\\'; } } - } - else + + bRet = InstallResourceHelper(TRUE, NULL, zipFile, wszPath); + + unzCloseCurrentFile(zipFile); + } while (bRet && unzGoToNextFile(zipFile) == UNZ_OK); + + return bRet; +} + +BOOL DeleteResource(LPCWSTR pwszDirectory, LPCWSTR pwszFileName) +{ + WCHAR wszPath[MAX_PATH]; + wcscpy_s(wszPath, MAX_PATH, pwszDirectory); + wcscat_s(wszPath, MAX_PATH, L"\\"); + wcscat_s(wszPath, MAX_PATH, pwszFileName); + return InstallResourceHelper(FALSE, NULL, NULL, wszPath); +} + +/*BOOL ShouldDownloadOrDelete(BOOL bInstall, WCHAR* wszPath, LPCSTR chash) +{ + if (FileExistsW(wszPath)) { if (bInstall) { - return TRUE; + char hash[100]; + ZeroMemory(hash, sizeof(char) * 100); + ComputeFileHash(wszPath, hash, 100); + bInstall = _stricmp(hash, chash) != 0; + } + else + { + InstallResourceHelper(FALSE, NULL, NULL, wszPath); // Delete } } - return FALSE; + + return bInstall; } BOOL DownloadResource(BOOL bInstall, LPCWSTR pwszURL, DWORD dwSize, LPCSTR chash, LPCWSTR pwszDirectory, LPCWSTR pwszFileName) @@ -643,7 +820,7 @@ BOOL DownloadResource(BOOL bInstall, LPCWSTR pwszURL, DWORD dwSize, LPCSTR chash bOk = DownloadFile(pwszURL, dwSize, wszPath); } return bOk; -} +}*/ void ProcessTaskbarDlls(BOOL* bInOutOk, BOOL bInstall, BOOL bExtractMode, HINSTANCE hInstance, unzFile zipFile, WCHAR wszPath[260]) { @@ -654,6 +831,61 @@ void ProcessTaskbarDlls(BOOL* bInOutOk, BOOL bInstall, BOOL bExtractMode, HINSTA if (*bInOutOk) *bInOutOk = InstallResource(bInstall && (bExtractMode || pwszTaskbarDllName && !wcscmp(pwszTaskbarDllName, L"ep_taskbar.5.dll")), hInstance, zipFile, "ep_taskbar.5.dll", wszPath, L"ep_taskbar.5.dll"); } +BOOL RemoveDirectoryRecursive(const WCHAR* wszDirectoryPath) +{ + WCHAR szDir[MAX_PATH]; + wcscpy_s(szDir, MAX_PATH, wszDirectoryPath); + wcscat_s(szDir, MAX_PATH, L"\\*"); + + WIN32_FIND_DATA findFileData; + HANDLE hFind = FindFirstFileW(szDir, &findFileData); + + if (hFind == INVALID_HANDLE_VALUE) + { + return TRUE; + } + + do + { + if (lstrcmpW(findFileData.cFileName, L".") != 0 && lstrcmpW(findFileData.cFileName, L"..") != 0) + { + WCHAR szFilePath[MAX_PATH]; + wcscpy_s(szFilePath, MAX_PATH, wszDirectoryPath); + wcscat_s(szFilePath, MAX_PATH, L"\\"); + wcscat_s(szFilePath, MAX_PATH, findFileData.cFileName); + + if ((findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + if (!RemoveDirectoryRecursive(szFilePath)) + { + FindClose(hFind); + return FALSE; + } + } + else + { + if (!DeleteFileW(szFilePath) && !StageFileForCleanup(szFilePath)) + { + FindClose(hFind); + return FALSE; + } + } + } + } + while (FindNextFileW(hFind, &findFileData)); + + DWORD dwError = GetLastError(); + FindClose(hFind); + + if (dwError != ERROR_NO_MORE_FILES) + { + return FALSE; + } + + return RemoveDirectoryW(wszDirectoryPath); +} + + int WINAPI wWinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, @@ -690,19 +922,10 @@ int WINAPI wWinMain( MemoryBuffer* pMem; unzFile zipFile = LoadZipFileFromResources(&pMem); bOk = zipFile != NULL; - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, PRODUCT_NAME ".IA-32.dll", wszPath, _T(PRODUCT_NAME) L".IA-32.dll"); -#if defined(_M_X64) - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, PRODUCT_NAME ".amd64.dll", wszPath, _T(PRODUCT_NAME) L".amd64.dll"); -#elif defined(_M_ARM64) - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, PRODUCT_NAME ".arm64.dll", wszPath, _T(PRODUCT_NAME) L".arm64.dll"); -#endif - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "ep_dwm.exe", wszPath, L"ep_dwm.exe"); - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "ep_weather_host.dll", wszPath, L"ep_weather_host.dll"); - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "ep_weather_host_stub.dll", wszPath, L"ep_weather_host_stub.dll"); - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "WebView2Loader.dll", wszPath, L"WebView2Loader.dll"); - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "wincorlib.dll", wszPath, L"wincorlib.dll"); - if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "ep_gui.dll", wszPath, L"ep_gui.dll"); - ProcessTaskbarDlls(&bOk, bInstall, TRUE, hInstance, zipFile, wszPath); + if (bOk) + { + bOk = ExtractDirectory(zipFile, NULL, wszPath, NULL, LCT_None); + } if (zipFile) unzClose(zipFile); if (pMem) @@ -1100,6 +1323,78 @@ int WINAPI wWinMain( if (bOk) bOk = InstallResource(bInstall, hInstance, zipFile, "WebView2Loader.dll", wszPath, L"WebView2Loader.dll"); } ProcessTaskbarDlls(&bOk, bInstall, FALSE, hInstance, zipFile, wszPath); + const WCHAR* possibleDirs[] = + { + L"ar-SA", L"bg-BG", L"ca-ES", L"cs-CZ", L"da-DK", L"de-DE", L"el-GR", L"en-GB", L"en-US", L"es-ES", + L"es-MX", L"et-EE", L"eu-ES", L"fi-FI", L"fr-CA", L"fr-FR", L"gl-ES", L"he-IL", L"hr-HR", L"hu-HU", + L"id-ID", L"it-IT", L"ja-JP", L"ko-KR", L"lt-LT", L"lv-LV", L"nb-NO", L"nl-NL", L"pl-PL", L"pt-BR", + L"pt-PT", L"ro-RO", L"ru-RU", L"sk-SK", L"sl-SI", L"sr-Latn-RS", L"sv-SE", L"th-TH", L"tr-TR", L"uk-UA", + L"vi-VN", L"zh-CN", L"zh-TW", L"pris", L"StartUI", + }; + for (size_t i = 0; bOk && i < ARRAYSIZE(possibleDirs); i++) + { + WCHAR wszDirectoryPath[MAX_PATH]; + wcscpy_s(wszDirectoryPath, MAX_PATH, wszPath); + wcscat_s(wszDirectoryPath, MAX_PATH, L"\\"); + wcscat_s(wszDirectoryPath, MAX_PATH, possibleDirs[i]); + if (FileExistsW(wszDirectoryPath)) + { + bOk = RemoveDirectoryRecursive(wszDirectoryPath); + } + } + DeleteResource(wszPath, L"Windows.UI.ShellCommon.pri"); + BOOL bNoStartUIInThisBuild = ((global_rovi.dwBuildNumber >= 22621 && global_rovi.dwBuildNumber <= 22635) && global_ubr >= 3930) || global_rovi.dwBuildNumber >= 25169; + BOOL bNoPniduiInThisBuild = global_rovi.dwBuildNumber >= 25236; + if (bInstall) + { + const WCHAR* languages = GetSystemLanguages(); + if (bNoPniduiInThisBuild) + { + if (bOk) bOk = ExtractDirectory(zipFile, "pnidui/", wszPath, languages, LCT_MUI); + } + if (bNoStartUIInThisBuild) + { + if (bOk) bOk = ExtractDirectory(zipFile, "Windows.UI.ShellCommon/", wszPath, languages, LCT_PRI); + } + } + + if (bOk) bOk = InstallResource(bInstall && bNoPniduiInThisBuild, hInstance, zipFile, "pnidui/pnidui.dll", wszPath, L"pnidui.dll"); + + if (bOk && bNoPniduiInThisBuild) + { + // Windows Registry Editor Version 5.00 + // + // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellServiceObjects\{C2796011-81BA-4148-8FCA-C6643245113F}] + // "AutoStart"="" + if (bInstall) + { + HKEY hKey; + RegCreateKeyExW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellServiceObjects\\{C2796011-81BA-4148-8FCA-C6643245113F}", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_READ | KEY_WRITE, + NULL, + &hKey, + NULL + ); + if (hKey == NULL || hKey == INVALID_HANDLE_VALUE) + { + hKey = NULL; + } + if (hKey) + { + RegSetValueExW(hKey, L"AutoStart", 0, REG_SZ, (const BYTE*)L"", 1 * sizeof(WCHAR)); + RegCloseKey(hKey); + } + } + else + { + RegDeleteKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellServiceObjects\\{C2796011-81BA-4148-8FCA-C6643245113F}"); + } + } // -------------------------------------------------------------------------------- @@ -1116,6 +1411,7 @@ int WINAPI wWinMain( // C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy // + dxgi.dll + // + StartUI_.dll (download, optional) // + wincorlib.dll // + wincorlib_orig.dll (symlink) // - AppResolverLegacy.dll @@ -1145,6 +1441,8 @@ int WINAPI wWinMain( bOk = CreateSymbolicLinkW(wszSymLinkPath, wszOrigPath, 0); } + if (bOk) bOk = InstallResource(bInstall && bNoStartUIInThisBuild, hInstance, zipFile, "StartUI/StartUI.dll", wszPath, L"StartUI_.dll"); + // Delete remnants from earlier versions if (bOk) bOk = DeleteResource(wszPath, L"AppResolverLegacy.dll"); if (bOk) bOk = DeleteResource(wszPath, L"StartTileDataLegacy.dll"); @@ -1330,28 +1628,34 @@ int WINAPI wWinMain( { if (!bInstall) { - WCHAR wszTempPath[MAX_PATH]; - GetTempPathW(MAX_PATH, wszTempPath); - wcscat_s(wszTempPath, MAX_PATH, _T(SETUP_UTILITY_NAME)); - if (MoveFileExW(wszOwnPath, wszTempPath, MOVEFILE_REPLACE_EXISTING)) - { - HKEY hKey = NULL; - RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, NULL); - if (hKey && hKey != INVALID_HANDLE_VALUE) - { - WCHAR wszCommand[MAX_PATH]; - wcscpy_s(wszCommand, MAX_PATH, L"cmd /c del /f /q \""); - wcscat_s(wszCommand, MAX_PATH, wszTempPath); - wcscat_s(wszCommand, MAX_PATH, L"\""); - RegSetValueExW(hKey, L"ExplorerPatcherCleanup", 0, REG_SZ, (BYTE*)wszCommand, (DWORD)((wcslen(wszCommand) + 1) * sizeof(WCHAR))); - RegCloseKey(hKey); - } - } - SHGetFolderPathW(NULL, SPECIAL_FOLDER, NULL, SHGFP_TYPE_CURRENT, wszPath); wcscat_s(wszPath, MAX_PATH, _T(APP_RELATIVE_PATH)); - RemoveDirectoryW(wszPath); + bOk = RemoveDirectoryRecursive(wszPath); + } + if (bOk && (!bInstall || g_cleanupFileCounter > 1)) + { + WCHAR wszDirToDelete[MAX_PATH]; + SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wszDirToDelete); + wcscat_s(wszDirToDelete, MAX_PATH, _T(APP_RELATIVE_PATH)); + if (bInstall) + { + wcscat_s(wszDirToDelete, MAX_PATH, L"\\cleanup"); + } + HKEY hKey = NULL; + RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hKey, NULL); + if (hKey && hKey != INVALID_HANDLE_VALUE) + { + WCHAR wszCommand[MAX_PATH]; + wcscpy_s(wszCommand, MAX_PATH, L"cmd /c rmdir /s /q \""); + wcscat_s(wszCommand, MAX_PATH, wszDirToDelete); + wcscat_s(wszCommand, MAX_PATH, L"\""); + RegSetValueExW(hKey, L"ExplorerPatcherCleanup", 0, REG_SZ, (BYTE*)wszCommand, (DWORD)((wcslen(wszCommand) + 1) * sizeof(WCHAR))); + RegCloseKey(hKey); + } + } + if (!bInstall) + { wchar_t mbText[256]; mbText[0] = 0; if (bWasShellExt) diff --git a/ep_setup/ep_setup.vcxproj b/ep_setup/ep_setup.vcxproj index 9091620b4..281b63ee4 100644 --- a/ep_setup/ep_setup.vcxproj +++ b/ep_setup/ep_setup.vcxproj @@ -33,7 +33,7 @@ epsetup 10.0 0000000 - true + false @@ -287,6 +287,7 @@ + @@ -376,7 +377,11 @@ - + + + + + diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/BitMDL2.ttf b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/BitMDL2.ttf new file mode 100644 index 000000000..1005db8cb Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/BitMDL2.ttf differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/SkypeUISymbol-Regular.ttf b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/SkypeUISymbol-Regular.ttf new file mode 100644 index 000000000..f6674035c Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/Fonts/SkypeUISymbol-Regular.ttf differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub150x150.png b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub150x150.png new file mode 100644 index 000000000..4a2508123 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub150x150.png differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub71x71.png b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub71x71.png new file mode 100644 index 000000000..543253377 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/officehub71x71.png differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote150x150.png b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote150x150.png new file mode 100644 index 000000000..655d4e814 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote150x150.png differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote71x71.png b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote71x71.png new file mode 100644 index 000000000..8f54981f8 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/StartUI/Assets/onenote71x71.png differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/Windows.UI.ShellCommon.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/Windows.UI.ShellCommon.pri new file mode 100644 index 000000000..cf08c4d69 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/Windows.UI.ShellCommon.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ar-SA.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ar-SA.pri new file mode 100644 index 000000000..aa93f6a2a Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ar-SA.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.bg-BG.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.bg-BG.pri new file mode 100644 index 000000000..28d6f5094 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.bg-BG.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ca-ES.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ca-ES.pri new file mode 100644 index 000000000..956b698fb Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ca-ES.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.cs-CZ.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.cs-CZ.pri new file mode 100644 index 000000000..20d637295 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.cs-CZ.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.da-DK.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.da-DK.pri new file mode 100644 index 000000000..bcc30f492 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.da-DK.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.de-DE.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.de-DE.pri new file mode 100644 index 000000000..836314dec Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.de-DE.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.el-GR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.el-GR.pri new file mode 100644 index 000000000..8c99d3866 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.el-GR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-GB.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-GB.pri new file mode 100644 index 000000000..0ab825bfe Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-GB.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-US.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-US.pri new file mode 100644 index 000000000..4f7336021 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.en-US.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-ES.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-ES.pri new file mode 100644 index 000000000..401d48d23 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-ES.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-MX.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-MX.pri new file mode 100644 index 000000000..97386bc25 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.es-MX.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.et-EE.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.et-EE.pri new file mode 100644 index 000000000..654e35981 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.et-EE.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.eu-ES.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.eu-ES.pri new file mode 100644 index 000000000..22faba2b4 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.eu-ES.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fi-FI.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fi-FI.pri new file mode 100644 index 000000000..36ed771c1 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fi-FI.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-CA.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-CA.pri new file mode 100644 index 000000000..a210c3a3a Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-CA.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-FR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-FR.pri new file mode 100644 index 000000000..02e60ff3e Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.fr-FR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.gl-ES.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.gl-ES.pri new file mode 100644 index 000000000..a636e7f06 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.gl-ES.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.he-IL.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.he-IL.pri new file mode 100644 index 000000000..bd85316fa Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.he-IL.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hr-HR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hr-HR.pri new file mode 100644 index 000000000..d1840cad4 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hr-HR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hu-HU.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hu-HU.pri new file mode 100644 index 000000000..f83ad92f8 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.hu-HU.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.id-ID.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.id-ID.pri new file mode 100644 index 000000000..c17a7099c Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.id-ID.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.it-IT.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.it-IT.pri new file mode 100644 index 000000000..0f89f4849 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.it-IT.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ja-JP.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ja-JP.pri new file mode 100644 index 000000000..ecd06a299 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ja-JP.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ko-KR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ko-KR.pri new file mode 100644 index 000000000..aec341d24 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ko-KR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lt-LT.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lt-LT.pri new file mode 100644 index 000000000..ff0993ecf Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lt-LT.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lv-LV.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lv-LV.pri new file mode 100644 index 000000000..6626ee8ff Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.lv-LV.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nb-NO.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nb-NO.pri new file mode 100644 index 000000000..1eec340a8 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nb-NO.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nl-NL.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nl-NL.pri new file mode 100644 index 000000000..9b8ec0696 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.nl-NL.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pl-PL.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pl-PL.pri new file mode 100644 index 000000000..bd657126a Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pl-PL.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-BR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-BR.pri new file mode 100644 index 000000000..6b4f0e2f8 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-BR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-PT.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-PT.pri new file mode 100644 index 000000000..14827ce24 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.pt-PT.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ro-RO.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ro-RO.pri new file mode 100644 index 000000000..530693636 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ro-RO.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ru-RU.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ru-RU.pri new file mode 100644 index 000000000..6f7ab70dd Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.ru-RU.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sk-SK.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sk-SK.pri new file mode 100644 index 000000000..da91667f4 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sk-SK.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sl-SI.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sl-SI.pri new file mode 100644 index 000000000..fb0eaf338 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sl-SI.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sr-Latn-RS.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sr-Latn-RS.pri new file mode 100644 index 000000000..6b4f7de13 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sr-Latn-RS.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sv-SE.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sv-SE.pri new file mode 100644 index 000000000..ffa5088d1 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.sv-SE.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.th-TH.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.th-TH.pri new file mode 100644 index 000000000..09f13a987 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.th-TH.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.tr-TR.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.tr-TR.pri new file mode 100644 index 000000000..b8d5109ea Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.tr-TR.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.uk-UA.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.uk-UA.pri new file mode 100644 index 000000000..a797391be Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.uk-UA.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.vi-VN.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.vi-VN.pri new file mode 100644 index 000000000..927da6dfe Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.vi-VN.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-CN.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-CN.pri new file mode 100644 index 000000000..345ac8ecb Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-CN.pri differ diff --git a/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-TW.pri b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-TW.pri new file mode 100644 index 000000000..8256c11b2 Binary files /dev/null and b/ep_setup/resources/files/Windows.UI.ShellCommon/pris/Windows.UI.ShellCommon.zh-TW.pri differ diff --git a/ep_setup/resources/files/pnidui/ar-SA/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ar-SA/pnidui.dll.mui new file mode 100644 index 000000000..1977ef370 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ar-SA/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/bg-BG/pnidui.dll.mui b/ep_setup/resources/files/pnidui/bg-BG/pnidui.dll.mui new file mode 100644 index 000000000..bd2dfa1d5 Binary files /dev/null and b/ep_setup/resources/files/pnidui/bg-BG/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/ca-ES/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ca-ES/pnidui.dll.mui new file mode 100644 index 000000000..02a72f7c0 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ca-ES/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/cs-CZ/pnidui.dll.mui b/ep_setup/resources/files/pnidui/cs-CZ/pnidui.dll.mui new file mode 100644 index 000000000..7cc20ffa1 Binary files /dev/null and b/ep_setup/resources/files/pnidui/cs-CZ/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/da-DK/pnidui.dll.mui b/ep_setup/resources/files/pnidui/da-DK/pnidui.dll.mui new file mode 100644 index 000000000..4449129f2 Binary files /dev/null and b/ep_setup/resources/files/pnidui/da-DK/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/de-DE/pnidui.dll.mui b/ep_setup/resources/files/pnidui/de-DE/pnidui.dll.mui new file mode 100644 index 000000000..7061e76bc Binary files /dev/null and b/ep_setup/resources/files/pnidui/de-DE/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/el-GR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/el-GR/pnidui.dll.mui new file mode 100644 index 000000000..bae762811 Binary files /dev/null and b/ep_setup/resources/files/pnidui/el-GR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/en-GB/pnidui.dll.mui b/ep_setup/resources/files/pnidui/en-GB/pnidui.dll.mui new file mode 100644 index 000000000..acc60b391 Binary files /dev/null and b/ep_setup/resources/files/pnidui/en-GB/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/en-US/pnidui.dll.mui b/ep_setup/resources/files/pnidui/en-US/pnidui.dll.mui new file mode 100644 index 000000000..5db6e17b8 Binary files /dev/null and b/ep_setup/resources/files/pnidui/en-US/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/es-ES/pnidui.dll.mui b/ep_setup/resources/files/pnidui/es-ES/pnidui.dll.mui new file mode 100644 index 000000000..0d006fb90 Binary files /dev/null and b/ep_setup/resources/files/pnidui/es-ES/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/es-MX/pnidui.dll.mui b/ep_setup/resources/files/pnidui/es-MX/pnidui.dll.mui new file mode 100644 index 000000000..73bf69438 Binary files /dev/null and b/ep_setup/resources/files/pnidui/es-MX/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/et-EE/pnidui.dll.mui b/ep_setup/resources/files/pnidui/et-EE/pnidui.dll.mui new file mode 100644 index 000000000..e9c6e808d Binary files /dev/null and b/ep_setup/resources/files/pnidui/et-EE/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/eu-ES/pnidui.dll.mui b/ep_setup/resources/files/pnidui/eu-ES/pnidui.dll.mui new file mode 100644 index 000000000..b439ae973 Binary files /dev/null and b/ep_setup/resources/files/pnidui/eu-ES/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/fi-FI/pnidui.dll.mui b/ep_setup/resources/files/pnidui/fi-FI/pnidui.dll.mui new file mode 100644 index 000000000..eb8c41c78 Binary files /dev/null and b/ep_setup/resources/files/pnidui/fi-FI/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/fr-CA/pnidui.dll.mui b/ep_setup/resources/files/pnidui/fr-CA/pnidui.dll.mui new file mode 100644 index 000000000..0022aafa5 Binary files /dev/null and b/ep_setup/resources/files/pnidui/fr-CA/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/fr-FR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/fr-FR/pnidui.dll.mui new file mode 100644 index 000000000..518f338f2 Binary files /dev/null and b/ep_setup/resources/files/pnidui/fr-FR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/gl-ES/pnidui.dll.mui b/ep_setup/resources/files/pnidui/gl-ES/pnidui.dll.mui new file mode 100644 index 000000000..f0073a77d Binary files /dev/null and b/ep_setup/resources/files/pnidui/gl-ES/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/he-IL/pnidui.dll.mui b/ep_setup/resources/files/pnidui/he-IL/pnidui.dll.mui new file mode 100644 index 000000000..d86d19c73 Binary files /dev/null and b/ep_setup/resources/files/pnidui/he-IL/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/hr-HR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/hr-HR/pnidui.dll.mui new file mode 100644 index 000000000..72ac342b7 Binary files /dev/null and b/ep_setup/resources/files/pnidui/hr-HR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/hu-HU/pnidui.dll.mui b/ep_setup/resources/files/pnidui/hu-HU/pnidui.dll.mui new file mode 100644 index 000000000..15a8d38d2 Binary files /dev/null and b/ep_setup/resources/files/pnidui/hu-HU/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/id-ID/pnidui.dll.mui b/ep_setup/resources/files/pnidui/id-ID/pnidui.dll.mui new file mode 100644 index 000000000..749ce88c4 Binary files /dev/null and b/ep_setup/resources/files/pnidui/id-ID/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/it-IT/pnidui.dll.mui b/ep_setup/resources/files/pnidui/it-IT/pnidui.dll.mui new file mode 100644 index 000000000..0823e78fb Binary files /dev/null and b/ep_setup/resources/files/pnidui/it-IT/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/ja-JP/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ja-JP/pnidui.dll.mui new file mode 100644 index 000000000..a72f6d645 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ja-JP/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/ko-KR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ko-KR/pnidui.dll.mui new file mode 100644 index 000000000..6d07e03f0 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ko-KR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/lt-LT/pnidui.dll.mui b/ep_setup/resources/files/pnidui/lt-LT/pnidui.dll.mui new file mode 100644 index 000000000..43bf84fa0 Binary files /dev/null and b/ep_setup/resources/files/pnidui/lt-LT/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/lv-LV/pnidui.dll.mui b/ep_setup/resources/files/pnidui/lv-LV/pnidui.dll.mui new file mode 100644 index 000000000..703314448 Binary files /dev/null and b/ep_setup/resources/files/pnidui/lv-LV/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/nb-NO/pnidui.dll.mui b/ep_setup/resources/files/pnidui/nb-NO/pnidui.dll.mui new file mode 100644 index 000000000..e8918875a Binary files /dev/null and b/ep_setup/resources/files/pnidui/nb-NO/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/nl-NL/pnidui.dll.mui b/ep_setup/resources/files/pnidui/nl-NL/pnidui.dll.mui new file mode 100644 index 000000000..9f42fa331 Binary files /dev/null and b/ep_setup/resources/files/pnidui/nl-NL/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/pl-PL/pnidui.dll.mui b/ep_setup/resources/files/pnidui/pl-PL/pnidui.dll.mui new file mode 100644 index 000000000..7b325b775 Binary files /dev/null and b/ep_setup/resources/files/pnidui/pl-PL/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/pt-BR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/pt-BR/pnidui.dll.mui new file mode 100644 index 000000000..bc80a2ca5 Binary files /dev/null and b/ep_setup/resources/files/pnidui/pt-BR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/pt-PT/pnidui.dll.mui b/ep_setup/resources/files/pnidui/pt-PT/pnidui.dll.mui new file mode 100644 index 000000000..bfb2feab4 Binary files /dev/null and b/ep_setup/resources/files/pnidui/pt-PT/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/ro-RO/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ro-RO/pnidui.dll.mui new file mode 100644 index 000000000..96bac6ed5 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ro-RO/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/ru-RU/pnidui.dll.mui b/ep_setup/resources/files/pnidui/ru-RU/pnidui.dll.mui new file mode 100644 index 000000000..e8477a9c8 Binary files /dev/null and b/ep_setup/resources/files/pnidui/ru-RU/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/sk-SK/pnidui.dll.mui b/ep_setup/resources/files/pnidui/sk-SK/pnidui.dll.mui new file mode 100644 index 000000000..1600cc40d Binary files /dev/null and b/ep_setup/resources/files/pnidui/sk-SK/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/sl-SI/pnidui.dll.mui b/ep_setup/resources/files/pnidui/sl-SI/pnidui.dll.mui new file mode 100644 index 000000000..044b62689 Binary files /dev/null and b/ep_setup/resources/files/pnidui/sl-SI/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/sr-Latn-RS/pnidui.dll.mui b/ep_setup/resources/files/pnidui/sr-Latn-RS/pnidui.dll.mui new file mode 100644 index 000000000..055f4656c Binary files /dev/null and b/ep_setup/resources/files/pnidui/sr-Latn-RS/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/sv-SE/pnidui.dll.mui b/ep_setup/resources/files/pnidui/sv-SE/pnidui.dll.mui new file mode 100644 index 000000000..50c961bc8 Binary files /dev/null and b/ep_setup/resources/files/pnidui/sv-SE/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/th-TH/pnidui.dll.mui b/ep_setup/resources/files/pnidui/th-TH/pnidui.dll.mui new file mode 100644 index 000000000..bf8c98093 Binary files /dev/null and b/ep_setup/resources/files/pnidui/th-TH/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/tr-TR/pnidui.dll.mui b/ep_setup/resources/files/pnidui/tr-TR/pnidui.dll.mui new file mode 100644 index 000000000..e53ffadf2 Binary files /dev/null and b/ep_setup/resources/files/pnidui/tr-TR/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/uk-UA/pnidui.dll.mui b/ep_setup/resources/files/pnidui/uk-UA/pnidui.dll.mui new file mode 100644 index 000000000..811f337ed Binary files /dev/null and b/ep_setup/resources/files/pnidui/uk-UA/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/vi-VN/pnidui.dll.mui b/ep_setup/resources/files/pnidui/vi-VN/pnidui.dll.mui new file mode 100644 index 000000000..deff483ba Binary files /dev/null and b/ep_setup/resources/files/pnidui/vi-VN/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/zh-CN/pnidui.dll.mui b/ep_setup/resources/files/pnidui/zh-CN/pnidui.dll.mui new file mode 100644 index 000000000..c5ca90c55 Binary files /dev/null and b/ep_setup/resources/files/pnidui/zh-CN/pnidui.dll.mui differ diff --git a/ep_setup/resources/files/pnidui/zh-TW/pnidui.dll.mui b/ep_setup/resources/files/pnidui/zh-TW/pnidui.dll.mui new file mode 100644 index 000000000..40e05b9e5 Binary files /dev/null and b/ep_setup/resources/files/pnidui/zh-TW/pnidui.dll.mui differ diff --git a/ep_startmenu/ep_sm_main.c b/ep_startmenu/ep_sm_main.c index 4bb523981..811dca543 100644 --- a/ep_startmenu/ep_sm_main.c +++ b/ep_startmenu/ep_sm_main.c @@ -1,6 +1,6 @@ #include #include -#include +// #include #include #include "../ExplorerPatcher/utility.h" #include "ep_sm_forwards.h" @@ -22,6 +22,33 @@ DEFINE_GUID(IID_StartUI_XamlMetaDataProvider, 0xF2777C41, 0xD2CC, 0x34B6, 0xA7, return TRUE; }*/ +BOOL GetStartUIName(WCHAR* out, int cch) +{ + if (out && cch) + out[0] = 0; + + WCHAR szPath[MAX_PATH]; + wcscpy_s(szPath, MAX_PATH, L"StartUI.dll"); + if (FileExistsW(szPath)) + { + if (out && cch) + wcscpy_s(out, cch, szPath); + return TRUE; + } + + wcscpy_s(szPath, MAX_PATH, L"StartUI_.dll"); + if (FileExistsW(szPath)) + { + if (out && cch) + wcscpy_s(out, cch, szPath); + return TRUE; + } + + return FALSE; +} + +WCHAR g_szStartUIName[MAX_PATH]; + BOOL GetStartShowClassicMode() { DWORD dwStartShowClassicMode = 0; @@ -30,7 +57,7 @@ BOOL GetStartShowClassicMode() if (dwStartShowClassicMode == 0) return FALSE; - if (!FileExistsW(L"StartUI.dll")) + if (!GetStartUIName(g_szStartUIName, ARRAYSIZE(g_szStartUIName))) return FALSE; return TRUE; @@ -55,9 +82,10 @@ void PatchXamlMetaDataProviderGuid() PIMAGE_NT_HEADERS64 ntHeader = (PIMAGE_NT_HEADERS64)((u_char*)dosHeader + dosHeader->e_lfanew); if (ntHeader->Signature == IMAGE_NT_SIGNATURE) { + PIMAGE_SECTION_HEADER firstSection = IMAGE_FIRST_SECTION(ntHeader); for (unsigned int i = 0; i < ntHeader->FileHeader.NumberOfSections; ++i) { - PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeader) + i; + PIMAGE_SECTION_HEADER section = firstSection + i; if (!strncmp(section->Name, ".rdata", 6)) { beginRData = (PBYTE)dosHeader + section->VirtualAddress; @@ -72,7 +100,7 @@ void PatchXamlMetaDataProviderGuid() return; } - GUID* pguidTarget = memmem(beginRData, sizeRData, &IID_StartDocked_XamlMetaDataProvider, sizeof(GUID)); + GUID* pguidTarget = memmem(beginRData, sizeRData, (void*)&IID_StartDocked_XamlMetaDataProvider, sizeof(GUID)); if (!pguidTarget) { return; @@ -122,14 +150,17 @@ wchar_t* GetCmdArguments(int* a1) return pGetCmdArguments(a1); } +extern HRESULT LoadOurShellCommonPri(); +extern HRESULT GetActivationFactoryByPCWSTR_InStartUI(PCWSTR activatableClassId, REFIID riid, void** ppv); + #pragma comment(linker, "/export:?GetActivationFactoryByPCWSTR@@YAJPEAXAEAVGuid@Platform@@PEAPEAX@Z=GetActivationFactoryByPCWSTR,@129") -HRESULT GetActivationFactoryByPCWSTR(PCWSTR activatableClassId, const GUID* iid, void** ppv) +HRESULT GetActivationFactoryByPCWSTR(PCWSTR activatableClassId, REFIID riid, void** ppv) { if (!hOrig) { hOrig = LoadLibraryW(L"wincorlib_orig.dll"); } - static HRESULT (*pGetActivationFactoryByPCWSTR)(PCWSTR, const GUID*, void**) = NULL; + static HRESULT (*pGetActivationFactoryByPCWSTR)(PCWSTR, REFIID, void**) = NULL; if (!pGetActivationFactoryByPCWSTR && hOrig) { pGetActivationFactoryByPCWSTR = GetProcAddress(hOrig, "?GetActivationFactoryByPCWSTR@@YAJPEAXAEAVGuid@Platform@@PEAPEAX@Z"); @@ -139,22 +170,28 @@ HRESULT GetActivationFactoryByPCWSTR(PCWSTR activatableClassId, const GUID* iid, return E_FAIL; } - if (!wcscmp(activatableClassId, L"StartDocked.App") && IsEqualGUID(iid, &IID_StartDocked_App)) + if (!wcscmp(activatableClassId, L"StartDocked.App") && IsEqualGUID(riid, &IID_StartDocked_App)) { if (GetStartShowClassicMode()) { - return pGetActivationFactoryByPCWSTR(L"StartUI.App", &IID_StartUI_App, ppv); + LoadOurShellCommonPri(); + return GetActivationFactoryByPCWSTR_InStartUI(L"StartUI.App", &IID_StartUI_App, ppv); } } else if (!wcscmp(activatableClassId, L"StartDocked.startdocked_XamlTypeInfo.XamlMetaDataProvider")) { if (GetStartShowClassicMode()) { - return pGetActivationFactoryByPCWSTR(L"StartUI.startui_XamlTypeInfo.XamlMetaDataProvider", iid, ppv); + return GetActivationFactoryByPCWSTR_InStartUI(L"StartUI.startui_XamlTypeInfo.XamlMetaDataProvider", riid, ppv); } } - return pGetActivationFactoryByPCWSTR(activatableClassId, iid, ppv); + if (wcsncmp(activatableClassId, L"StartUI.", 8) == 0) + { + return GetActivationFactoryByPCWSTR_InStartUI(activatableClassId, riid, ppv); + } + + return pGetActivationFactoryByPCWSTR(activatableClassId, riid, ppv); } BOOL WINAPI DllMain( diff --git a/ep_startmenu/ep_sm_main_cpp.cpp b/ep_startmenu/ep_sm_main_cpp.cpp new file mode 100644 index 000000000..0e1447d48 --- /dev/null +++ b/ep_startmenu/ep_sm_main_cpp.cpp @@ -0,0 +1,89 @@ +#include +#include +#include + +#include +#include + +namespace ABI::Windows::ApplicationModel::Resources::Core::Internal +{ + MIDL_INTERFACE("4a8eac58-b652-459d-8de1-239471e8b22b") + IResourceManagerStaticInternal : IInspectable + { + virtual HRESULT STDMETHODCALLTYPE GetResourceManagerForSystemProfile(IResourceManager** result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentResourceManagerForSystemProfile(IResourceManager** result) = 0; + virtual HRESULT STDMETHODCALLTYPE GetCurrentResourceManagerState(DWORD* result) = 0; + }; + + MIDL_INTERFACE("c408a1f1-3ede-41e9-9a38-c203678c2df7") + ISystemResourceManagerExtensions : IInspectable + { + virtual HRESULT STDMETHODCALLTYPE GetDefaultResourceContextForCurrentThread(IResourceContext**) = 0; + virtual HRESULT STDMETHODCALLTYPE GetMrtResourceManagerForResourceManager(IInspectable**) = 0; + }; + + MIDL_INTERFACE("8c25e859-1042-4da0-9232-bf2aa8ff3726") + ISystemResourceManagerExtensions2 : IInspectable + { + virtual HRESULT STDMETHODCALLTYPE LoadPriFileForSystemUse(const WCHAR* path) = 0; + }; +} + +using namespace Microsoft::WRL; + +extern "C" HRESULT LoadOurShellCommonPri() +{ + using namespace ABI::Windows::Foundation; + + ComPtr pInspectable; + HRESULT hr = Windows::Foundation::GetActivationFactory( + Wrappers::HStringReference(L"Windows.ApplicationModel.Resources.Core.ResourceManager").Get(), + pInspectable.GetAddressOf() + ); + if (FAILED(hr)) + return hr; + + ComPtr pResourceManagerStaticInternal; + hr = pInspectable.As(&pResourceManagerStaticInternal); + if (FAILED(hr)) + return hr; + + ComPtr pResourceManager; + hr = pResourceManagerStaticInternal->GetCurrentResourceManagerForSystemProfile(&pResourceManager); + if (FAILED(hr)) + return hr; + + ComPtr pSystemResourceManagerExtensions2; + pResourceManager.As(&pSystemResourceManagerExtensions2); + WCHAR wszPath[MAX_PATH] = {}; + wcscat_s(wszPath, MAX_PATH, L"C:\\Program Files\\ExplorerPatcher\\Windows.UI.ShellCommon.pri"); + hr = pSystemResourceManagerExtensions2->LoadPriFileForSystemUse(wszPath); + + return hr; +} + +extern "C" WCHAR g_szStartUIName[MAX_PATH]; + +extern "C" HRESULT GetActivationFactoryByPCWSTR_InStartUI(PCWSTR activatableClassId, REFIID riid, void** ppv) +{ + typedef HRESULT (WINAPI* DllGetActivationFactory_t)(HSTRING, IActivationFactory**); + static DllGetActivationFactory_t pfnGetActivationFactory; + if (!pfnGetActivationFactory) + { + HMODULE hModule = GetModuleHandleW(g_szStartUIName); + if (hModule) + { + pfnGetActivationFactory = (DllGetActivationFactory_t)GetProcAddress(hModule, "DllGetActivationFactory"); + } + } + + if (!pfnGetActivationFactory) + return E_FAIL; + + ComPtr activationFactory; + HRESULT hr = pfnGetActivationFactory(Wrappers::HStringReference(activatableClassId).Get(), &activationFactory); + if (FAILED(hr)) + return hr; + + return activationFactory.CopyTo(riid, ppv); +} diff --git a/ep_startmenu/ep_startmenu.vcxproj b/ep_startmenu/ep_startmenu.vcxproj index 21b40c586..7304dd3bd 100644 --- a/ep_startmenu/ep_startmenu.vcxproj +++ b/ep_startmenu/ep_startmenu.vcxproj @@ -133,6 +133,7 @@ true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreadedDebug $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -149,6 +150,7 @@ true WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreaded $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -165,6 +167,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreadedDebug $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -181,6 +184,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreaded $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -197,6 +201,7 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreadedDebug $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -213,6 +218,7 @@ true NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true + stdcpp20 MultiThreaded $(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories) @@ -228,6 +234,7 @@ + diff --git a/libs/libvalinet b/libs/libvalinet index 126a8d6d8..6a8b474fa 160000 --- a/libs/libvalinet +++ b/libs/libvalinet @@ -1 +1 @@ -Subproject commit 126a8d6d8f0d5dd49f873999a81db5a49d19aae9 +Subproject commit 6a8b474fa96bfd2a7db40dc37fcae9b80105028c diff --git a/version.h b/version.h index c578290e7..9e5638532 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define VER_MAJOR 22621 #define VER_MINOR 3880 #define VER_BUILD_HI 66 -#define VER_BUILD_LO 3 +#define VER_BUILD_LO 4 #define VER_FLAGS VS_FF_PRERELEASE