This project aims to enhance the working environment on Windows
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

3646 lines
135 KiB

#include <Windows.h>
#include <Shlwapi.h>
#include <ShellScalingApi.h>
#include <initguid.h>
#include <knownfolders.h>
#include <wrl/client.h>
#include <wil/resource.h>
#include <wil/result_macros.h>
#include <valinet/utility/memmem.h>
#include <wrl/wrappers/corewrappers.h>
#include "ArchiveMenu.h"
#include "utility.h"
#include "hooking.h"
#include "symbols.h"
#include "NativeString.h"
#include "RefCountedObject.h"
#include "SimpleArray.h"
// #define USE_REIMPLEMENTED_CLauncherTipContextMenu
using namespace Microsoft::WRL;
#pragma region "Types and utilities"
enum ContextMenuPaddingType
{
CMPT_NONE = 0x0,
CMPT_TOP_PADDING = 0x1,
CMPT_BOTTOM_PADDING = 0x2,
CMPT_TOUCH_INPUT = 0x4,
};
DEFINE_ENUM_FLAG_OPERATORS(ContextMenuPaddingType);
namespace DPIToPPIHelpers
{
enum class ScaleType
{
DPI,
PPI
};
enum class ScaleModifier
{
None,
CorrectBadDPI
};
}
struct ContextMenuRenderingData
{
CoTaskMemNativeString spszText;
DWORD uMenuFlags;
SHSTOCKICONID siid = SIID_MAX_ICONS;
HBITMAP hbmpItem;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
ContextMenuPaddingType cmpt;
DPIToPPIHelpers::ScaleType scaletype;
UINT xDpi;
bool fUseDarkTheme;
bool fUseSystemPadding;
BOOL fForceAccelerators;
CSimplePointerArrayNewMem<ContextMenuRenderingData>* prgParentArray;
#ifdef _DEBUG
private:
void* operator new(size_t stAllocateBlock) = delete;
public:
void* operator new(size_t stAllocateBlock, const std::nothrow_t&)
{
return HeapAlloc(GetProcessHeap(), 0, stAllocateBlock);
}
void operator delete(void* pvMem)
{
operator delete(pvMem, std::nothrow);
}
void operator delete(void* pvMem, const std::nothrow_t&)
{
if (pvMem)
{
HeapFree(GetProcessHeap(), 0, pvMem);
}
}
#endif
};
enum ImmersiveContextMenuOptions
{
ICMO_NONE = 0x0,
ICMO_USEPPI = 0x1,
ICMO_OVERRIDECOMPATCHECK = 0x2,
ICMO_FORCEMOUSESTYLING = 0x4,
ICMO_USESYSTEMTHEME = 0x8,
ICMO_ICMBRUSHAPPLIED = 0x10,
};
DEFINE_ENUM_FLAG_OPERATORS(ImmersiveContextMenuOptions);
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; // New in 11 21H2, no GUID change
};
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<ABI::Windows::Foundation::Collections::IPropertySet> _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<SingleViewShellExperiencePersonality> 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);
}
}
// Before using this, please make sure that the vtable is in the real module not a stub.
#define REPLACE_VTABLE_ENTRY(vtable, index, name) \
{ \
auto ppfn = (decltype(&name##Func))&vtable[index]; \
if (*ppfn != name##Hook) \
{ \
name##Func = *ppfn; \
DWORD dwOldProtectLocal; \
if (VirtualProtect(ppfn, sizeof(void*), PAGE_EXECUTE_READWRITE, &dwOldProtectLocal)) \
{ \
*ppfn = name##Hook; \
VirtualProtect(ppfn, sizeof(void*), dwOldProtectLocal, &dwOldProtectLocal); \
} \
} \
}
#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
class DECLSPEC_UUID("51d1268c-d0a5-47cc-a514-547f346f45e8")
CLauncherTipContextMenu;
enum LTCMITEMFLAGS
{
LTCMIF_DEFAULT = 0x0,
LTCMIF_RUNAS = 0x1,
LTCMIF_SWITCHTODESKTOP = 0x2,
LTCMIF_INVOKEARGS = 0x4,
LTCMIF_SHOWDESKTOPCOMMAND = 0x8,
LTCMIF_MOBILITYCENTER = 0x10,
LTCMIF_SEARCHCOMMAND = 0x20,
LTCMIF_PRIMARY_CMD = 0x40,
LTCMIF_SECONDARY_CMD = 0x80,
LTCMIF_POWERSHELLCOMMAND = 0x100,
LTCMIF_SUPPRESSONCLOUD = 0x200,
LTCMIF_ACTIVITIESCOMMAND = 0x400,
LTCMIF_TERMINALCOMMAND = 0x800, // Cobalt
};
struct LauncherTipMenuCommand
{
LauncherTipMenuCommand();
bool fSeparator;
CoTaskMemNativeString spszCommandName;
CoTaskMemNativeString spszCommandPath;
CoTaskMemNativeString spszCommandTargetArguments;
CoTaskMemNativeString spszVerb;
DWORD ltcmif;
};
struct LauncherTipShutdownMenuCommand
{
DWORD choice;
CoTaskMemNativeString spszCommandName;
};
static HRESULT(*winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc)(void* _this, UINT uMsg, WPARAM wParam, LPARAM lParam) = nullptr;
static HRESULT(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)(ILauncherTipContextMenu* _this, POINT* pptLocation) = nullptr;
static void(*CLauncherTipContextMenu_ExecuteCommandFunc)(void* _this, ComPtr<CRefCountedObject<LauncherTipMenuCommand>> spCommand) = nullptr;
static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)(void* _this, ComPtr<CRefCountedObject<LauncherTipShutdownMenuCommand>> spCommand, const RECT* prcDockTo) = nullptr;
HWND hWinXWnd;
HANDLE hIsWinXShown;
HANDLE hWinXThread;
HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(ILauncherTipContextMenu* _this, POINT* pt);
HRESULT (STDMETHODCALLTYPE *CLauncherTipContextMenu_CreateInstance_IClassFactory_Func)(
IClassFactory* This, IUnknown* pUnkOuter, REFIID riid, void** ppvObject);
HRESULT STDMETHODCALLTYPE CLauncherTipContextMenu_CreateInstance_IClassFactory_Hook(
IClassFactory* This, IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
{
#if defined(USE_REIMPLEMENTED_CLauncherTipContextMenu)
*ppvObject = nullptr;
ComPtr<CLauncherTipContextMenu> spLTCM;
HRESULT hr = MakeAndInitialize<CLauncherTipContextMenu>(&spLTCM);
if (SUCCEEDED(hr))
{
hr = spLTCM.CopyTo(riid, ppvObject);
}
return hr;
#else
HRESULT hr = CLauncherTipContextMenu_CreateInstance_IClassFactory_Func(This, pUnkOuter, riid, ppvObject);
if (SUCCEEDED(hr))
{
ILauncherTipContextMenu* pLTCM = nullptr;
if (SUCCEEDED(((IUnknown*)*ppvObject)->QueryInterface(IID_PPV_ARGS(&pLTCM)))) // Don't influence hr: if this fails, black screen
{
void** vtable = *(void***)pLTCM;
REPLACE_VTABLE_ENTRY(vtable, 3, CLauncherTipContextMenu_ShowLauncherTipContextMenu);
pLTCM->Release();
}
}
return hr;
#endif
}
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;
}
struct ShowLauncherTipContextMenuParameters
{
ILauncherTipContextMenu* _this;
POINT point;
ComPtr<IUnknown> spOperation;
bool bShouldCenterWinXHorizontally;
ShowLauncherTipContextMenuParameters(ILauncherTipContextMenu* _this, POINT point, IUnknown* pOperation, bool bShouldCenterWinXHorizontally)
: _this(_this)
, point(point)
, spOperation(pOperation)
, bShouldCenterWinXHorizontally(bShouldCenterWinXHorizontally)
{
}
};
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;
}
char* pClassBase = (char*)params->_this - 0x58;
struct
{
// ComPtr<IShellTaskScheduler> _spScheduler;
// ComPtr<IImmersiveWindowMessageService> _spWindowMessageService;
// ComPtr<IImmersiveLauncher> _spLauncher;
// ComPtr<IImmersiveSystemMode> _spSystemMode;
// ComPtr<IImmersiveMonitorManager> _spMonitorManager;
CCoSimpleArray<ComPtr<CRefCountedObject<LauncherTipMenuCommand>>> _rgCommands;
CCoSimpleArray<ComPtr<CRefCountedObject<LauncherTipShutdownMenuCommand>>> _rgShutdownCommands;
RTL_CRITICAL_SECTION _csEnumeration;
RTL_CRITICAL_SECTION _csContextMenuDisplay;
bool _fAreCommandsPopulated;
bool _fCommandPopulationInProgress;
bool _fTasksCancelled;
HMENU _hMenu;
HMENU _hMenuShutdown;
bool _fIsRTL;
bool _fReplacePrimaryCommandsWithSecondary;
}& fields = *(std::remove_reference_t<decltype(fields)>*)(pClassBase + offset_in_class + 0xA8); // Begin at _rgCommands
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),
pClassBase,
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 (!fields._fAreCommandsPopulated)
{
Sleep(1);
}
auto finalize = wil::scope_exit([&]() -> void
{
SendMessageW(hWinXWnd, WM_CLOSE, 0, 0);
hIsWinXShown = nullptr;
delete params;
});
if (!fields._rgCommands.GetSize())
{
return 0;
}
// Check if Windows Terminal is installed
bool fHasTerminal = false;
{
ComPtr<IShellItem> spLocalAppDataItem;
HRESULT hr = SHGetKnownFolderItem(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, IID_PPV_ARGS(&spLocalAppDataItem));
if (SUCCEEDED(hr))
{
ComPtr<IShellItem> spTerminalFolderItem;
if (SUCCEEDED(SHCreateItemFromRelativeName(spLocalAppDataItem.Get(), L"Microsoft\\WindowsApps\\wt.exe", nullptr, IID_PPV_ARGS(&spTerminalFolderItem))))
{
fHasTerminal = true;
}
}
}
// Do not use the _hMenu built by CLauncherTipContextMenu, it contains *both* PowerShell and Terminal entries.
// When Windows Terminal gets installed/uninstalled, the menu entries should be shown/hidden accordingly without
// restarting Explorer. Win32 does not support hiding menu entries. If we DeleteMenuW the Terminal entries in the
// provided menu due to Terminal not being installed, it will not reappear after Terminal is reinstalled.
//
// We build the menu ourselves to avoid those issues.
//
// Implementation based on:
// - CLauncherTipContextMenu::_EnumerateAndBuildMenu()
// - CLauncherTipContextMenu::_EnumerateAndBuildShutdownMenu()
wil::unique_hmenu hMenu(CreatePopupMenu());
wil::unique_hmenu hMenuShutdown;
HRESULT hr = ResultFromWin32Bool(hMenu.is_valid());
if (SUCCEEDED(hr))
{
size_t iPlusOne = fields._rgCommands.GetSize();
if (iPlusOne)
{
for (; iPlusOne; --iPlusOne)
{
size_t iContextMenuCommand = iPlusOne - 1;
ComPtr<CRefCountedObject<LauncherTipMenuCommand>>& spCommand = fields._rgCommands[iContextMenuCommand];
if ((spCommand->ltcmif & LTCMIF_POWERSHELLCOMMAND) != 0 && fHasTerminal
|| (spCommand->ltcmif & LTCMIF_TERMINALCOMMAND) != 0 && !fHasTerminal)
{
// Skip if this is PowerShell and Windows Terminal is installed
// or if this is Windows Terminal and Windows Terminal is not installed
continue;
}
AppendMenuW(hMenu.get(), spCommand->fSeparator ? MF_SEPARATOR : 0, iContextMenuCommand + 1, spCommand->spszCommandName.Get());
if (iContextMenuCommand == 1)
{
hMenuShutdown.reset(CreatePopupMenu());
hr = ResultFromWin32Bool(hMenuShutdown != nullptr);
if (SUCCEEDED(hr))
{
CoTaskMemNativeString spShutdownName;
hr = spShutdownName.Initialize(GetModuleHandleW(L"twinui.pcshell.dll"), 10930); // Sh&ut down or sign out
if (SUCCEEDED(hr))
{
AppendMenuW(hMenu.get(), MF_POPUP, (DWORD)(UINT_PTR)hMenuShutdown.get(), spShutdownName.Get());
}
UINT_PTR uIDNewItem = 4000;
for (size_t i = 0; i < fields._rgShutdownCommands.GetSize(); ++i)
{
ComPtr<CRefCountedObject<LauncherTipShutdownMenuCommand>>& spShutdownCommand = fields._rgShutdownCommands[i];
AppendMenuW(hMenuShutdown.get(), MF_STRING, uIDNewItem++, spShutdownCommand->spszCommandName.Get());
}
}
}
}
/*if (ShouldPowershellReplaceCmd())
{
LauncherTipContextMenuTelemetry::LauncherTipContextMenuDefaultConsole(!_fReplacePrimaryCommandsWithSecondary);
}*/
}
}
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(
hMenu.get(),
GetMenuItemCount(hMenu.get()) - 1,
TRUE,
&menuInfo
);
bCreatedMenu = TRUE;
}
CSimplePointerArrayNewMem<ContextMenuRenderingData> srgRenderingData;
if (bSkinMenus && ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)
{
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc(
hMenu.get(),
hWinXWnd,
&params->point,
ICMO_FORCEMOUSESTYLING | ICMO_USESYSTEMTHEME,
&srgRenderingData
);
}
BOOL res = TrackPopupMenu(
hMenu.get(),
TPM_RETURNCMD | TPM_RIGHTBUTTON | (params->bShouldCenterWinXHorizontally ? TPM_CENTERALIGN : 0),
params->point.x,
params->point.y,
0,
hWinXWnd,
nullptr
);
if (bSkinMenus && ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)
{
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc(hMenu.get(), hWinXWnd);
}
if (bCreatedMenu)
{
RemoveMenu(hMenu.get(), 3999, MF_BYCOMMAND);
}
if (res > 0)
{
if (bCreatedMenu && res == 3999)
{
LaunchPropertiesGUI(hModule);
}
else if (res >= 4000)
{
if (CLauncherTipContextMenu_ExecuteShutdownCommandFunc)
{
RECT rcAnchor;
rcAnchor.left = params->point.x;
rcAnchor.top = params->point.y - 1;
rcAnchor.right = rcAnchor.left + 1;
rcAnchor.bottom = rcAnchor.top + 1;
CLauncherTipContextMenu_ExecuteShutdownCommandFunc(pClassBase, fields._rgShutdownCommands[res - 4000], &rcAnchor);
}
}
else
{
if (CLauncherTipContextMenu_ExecuteCommandFunc)
{
CLauncherTipContextMenu_ExecuteCommandFunc(pClassBase, fields._rgCommands[res - 1]);
}
}
}
return 0;
}
HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(ILauncherTipContextMenu* _this, POINT* pt)
{
HRESULT hr = S_OK;
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);
GetMonitorInfoW(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 = FindWindowExW(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;
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);
}
RECT rc = {};
ComPtr<IUnknown> spOperation;
hr = _this->GetMenuItemsAsync(rc, &spOperation);
if (SUCCEEDED(hr))
{
ShowLauncherTipContextMenuParameters* params = new(std::nothrow) ShowLauncherTipContextMenuParameters(_this, point, spOperation.Get(), bShouldCenterWinXHorizontally);
hIsWinXShown = CreateThread(nullptr, 0, ShowLauncherTipContextMenu, params, 0, nullptr);
hWinXThread = hIsWinXShown;
}
}
if (SUCCEEDED(hr) && CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)
{
hr = CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt);
}
return hr;
}
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<IServiceProvider> pImmersiveShell;
if (SUCCEEDED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImmersiveShell))))
{
ComPtr<IImmersiveMonitorManager> pMonitorService;
if (SUCCEEDED(pImmersiveShell->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&pMonitorService))))
{
ComPtr<ILauncherTipContextMenu> 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;
}
HRESULT winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageHook(void* _this, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (!bClockFlyoutOnWinC)
{
if (winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc)
{
return winrt_Windows_Internal_Shell_implementation_MeetAndChatManager_OnMessageFunc(_this, uMsg, wParam, lParam);
}
return S_OK;
}
if (uMsg == 0x2C2 && wParam == 107)
{
InvokeClockFlyout();
}
return S_OK;
}
#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 <assignmentSize> 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<IServiceProvider> pImmersiveShell;
if (SUCCEEDED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pImmersiveShell))))
{
ComPtr<IImmersiveMonitorManager> pMonitorService;
if (SUCCEEDED(pImmersiveShell->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&pMonitorService))))
{
ComPtr<IEdgeUiManager> 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<IServiceProvider> spImmersiveShellServiceProvider;
RETURN_IF_FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&spImmersiveShellServiceProvider)));
ComPtr<IImmersiveLauncher> spImmersiveLauncher;
RETURN_IF_FAILED(spImmersiveShellServiceProvider->QueryService(SID_ImmersiveLauncher, IID_PPV_ARGS(&spImmersiveLauncher)));
ComPtr<IImmersiveMonitor> 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<IEdgeUiManager> 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)
// * Pattern for Nickel
// ```
// 69 A2 03 A9 ?? ?? 00 ?? 08 ?? ?? 91 ?? ?? 00 ?? 29 ?? ?? 91 68 32 00 F9
// ^^^^^^^^^^^+^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::CStartExperienceManager()
PBYTE matchVtable = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x69\xA2\x03\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x00\x00\x00\x00\x29\x00\x00\x91\x68\x32\x00\xF9",
"xxxx??x?x??x??x?x??xxxxx"
);
if (matchVtable)
{
matchVtable += 4;
matchVtable = (PBYTE)ARM64_DecodeADRL((UINT_PTR)matchVtable, *(DWORD*)matchVtable, *(DWORD*)(matchVtable + 4));
}
else
{
// * Pattern for Germanium
// ```
// ?? 22 04 A9 ?? ?? 00 ?? 08 ?? ?? 91 ?? A2 01 91 ?? 32 00 F9
// ^^^^^^^^^^^+^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::CStartExperienceManager()
matchVtable = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x22\x04\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x00\xA2\x01\x91\x00\x32\x00\xF9",
"xxx??x?x??x?xxx?xxx"
);
if (matchVtable)
{
matchVtable += 3;
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 ?? 82 01 91 ?? ?? ?? 91 ?? ?? ?? ?? 1F 20 03 D5
// ^^^SVSEEH^^ ^^^^^^^^^^^ SVSE
// ```
// Ref: CStartExperienceManager::CStartExperienceManager()
PBYTE matchSingleViewShellExperienceFields = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x22\x08\x80\x52\x00\x82\x01\x91\x00\x00\x00\x91\x00\x00\x00\x00\x1F\x20\x03\xD5",
"xxxx?xxx???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 ?? ?? ?? 39 ?? ?? ?? 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\x00\x00\x00\x39\x00\x00\x00\xB9",
"xxxx???x???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)
// `(CStartExperienceManager *)((char *)this - 40)` after field access
// ```
// 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);
}
else
{
// `(CStartExperienceManager *)((char *)this - 40)` before field access
// ```
// 48 83 C1 ?? 80 B9 ?? ?? ?? ?? 00 75 ?? 41 B0 01
// ^^^^^^^^^^^ bTransitioningToCortana
// ```
// Ref: CStartExperienceManager::DimStart()
matchTransitioningToCortanaField = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x48\x83\xC1\x00\x80\xB9\x00\x00\x00\x00\x00\x75\x00\x41\xB0\x01",
"xxx?xx????xx?xxx"
);
if (matchTransitioningToCortanaField)
{
g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana = *(int*)(matchTransitioningToCortanaField + 6);
}
}
#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 226xx, CSingleViewShellExperience* first arg *not* passed (E1 03 14 AA)
// ```
// A9 E4 ?? ?? ?? E3 ?? ?? 91 E2 ?? ?? 91 E0 03 13 AA ?? ?? ?? ?? ?? 03 00 2A
// ^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::PositionMenu()
PBYTE matchGetMonitorInformation = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\xA9\xE4\x00\x00\x00\xE3\x00\x00\x91\xE2\x00\x00\x91\xE0\x03\x13\xAA\x00\x00\x00\x00\x00\x03\x00\x2A",
"xx???x??xx??xxxxx?????xxx"
);
if (matchGetMonitorInformation)
{
matchGetMonitorInformation += 17;
matchGetMonitorInformation = (PBYTE)ARM64_FollowBL((DWORD*)matchGetMonitorInformation);
}
if (!matchGetMonitorInformation)
{
// * Pattern for 226xx, CSingleViewShellExperience* first arg passed (E1 03 14 AA)
// ```
// A9 E4 ?? ?? ?? E3 ?? ?? 91 E2 ?? ?? 91 E1 03 14 AA E0 03 13 AA ?? ?? ?? ?? ?? 03 00 2A
// ^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::PositionMenu()
matchGetMonitorInformation = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\xA9\xE4\x00\x00\x00\xE3\x00\x00\x91\xE2\x00\x00\x91\xE1\x03\x14\xAA\xE0\x03\x13\xAA\x00\x00\x00\x00\x00\x03\x00\x2A",
"xx???x??xx??xxxxxxxxx?????xxx"
);
if (matchGetMonitorInformation)
{
matchGetMonitorInformation += 21;
matchGetMonitorInformation = (PBYTE)ARM64_FollowBL((DWORD*)matchGetMonitorInformation);
}
}
if (!matchGetMonitorInformation)
{
// * Pattern for 26100.1, 265, 470, 560, 670, 712, 751, 863, 1000, 1150
// ```
// E2 82 00 91 E1 03 13 AA E0 03 14 AA ?? ?? ?? ??
// ^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::PositionMenu()
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);
}
}
if (!matchGetMonitorInformation)
{
// * Pattern for 26100.961, 1252, 1301, 1330, 1340, 1350, 1591, ...
// ```
// FF 02 00 39 E2 82 00 91 E0 03 13 AA ?? ?? ?? ??
// ^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::PositionMenu()
matchGetMonitorInformation = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\xFF\x02\x00\x39\xE2\x82\x00\x91\xE0\x03\x13\xAA",
"xxxxxxxxxxx"
);
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:
// ```
// 04 00 80 D2 03 00 80 D2 60 C2 05 91 ?? ?? ?? ?? E3 03 00 2A
// ^^^^^^^^^^^
// ```
// Ref: CJumpViewExperienceManager::OnViewUncloaking()
PBYTE matchAnimationBegin = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x04\x00\x80\xD2\x03\x00\x80\xD2\x60\xC2\x05\x91\x00\x00\x00\x00\xE3\x03\x00\x2A",
"xxxxxxxxxxxx????xxxx"
);
if (matchAnimationBegin)
{
matchAnimationBegin += 12;
matchAnimationBegin = (PBYTE)ARM64_FollowBL((DWORD*)matchAnimationBegin);
}
else
{
// * Pattern 2, used when a4, a5, and a6 are optimized out (e.g. 26020, 26058):
// ```
// ?? 02 0B 32 ?? ?? ?? 91 ?? ?? ?? 91 ?? ?? ?? ?? E3 03 00 2A
// ^^^^^^^^^^^
// ```
// Ref: CJumpViewExperienceManager::OnViewUncloaking()
matchAnimationBegin = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x02\x0B\x32\00\x00\x00\x91\x00\x00\x00\x91\x00\x00\x00\x00\xE3\x03\x00\x2A",
"xxx???x???x????xxxx"
);
if (matchAnimationBegin)
{
matchAnimationBegin += 11;
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)
// ```
// E1 03 ?? 2A ?? ?? 04 91 ?? ?? ?? ?? ?? 03 00 2A
// ```
// Check two instructions before, and NOP these:
// ```
// MOV W??, #3
// STRB W??, [X??,#0x???]
// ```
// Perform on exactly two matches
PBYTE matchHideA = nullptr;
PBYTE matchHideB = nullptr;
auto findTheIfBody = [](PBYTE pAnchor) -> PBYTE
{
// 27881.1000+ has CBNZ before us, follow it if it is.
// Otherwise, just check the two instructions before.
PBYTE pMaybeFollowed = (PBYTE)ARM64_FollowCBNZW((DWORD*)(pAnchor - 4));
PBYTE pIfBlockBegin = pMaybeFollowed ? pMaybeFollowed : pAnchor - 8;
DWORD insnMovzw = *(DWORD*)pIfBlockBegin;
if (!ARM64_IsMOVZW(insnMovzw))
return nullptr;
DWORD movzwImm16 = ARM64_ReadBitsSignExtend(insnMovzw, 20, 5);
if (movzwImm16 != 3)
return nullptr;
DWORD insnStrbimm = *(DWORD*)(pIfBlockBegin + 4);
if (!ARM64_IsSTRBIMM(insnStrbimm))
return nullptr;
return pIfBlockBegin;
};
PBYTE matchHideAAfter = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\xE1\x03\x00\x2A\x00\x00\x04\x91\x00\x00\x00\x00\x00\x03\x00\x2A",
"xx?x??xx?????xxx"
);
if (matchHideAAfter)
{
matchHideA = findTheIfBody(matchHideAAfter);
}
if (matchHideA)
{
printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll);
PBYTE matchHideBAfter = (PBYTE)FindPattern(
matchHideAAfter + 16,
1024,
"\xE1\x03\x00\x2A\x00\x00\x04\x91\x00\x00\x00\x00\x00\x03\x00\x2A",
"xx?x??xx?????xxx"
);
if (matchHideBAfter)
{
matchHideB = findTheIfBody(matchHideBAfter);
}
if (matchHideB)
{
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;
}
void** vtable = (void**)matchVtable;
REPLACE_VTABLE_ENTRY(vtable, 4, CStartExperienceManager_OnViewUncloaking);
REPLACE_VTABLE_ENTRY(vtable, 5, CStartExperienceManager_OnViewUncloaked);
REPLACE_VTABLE_ENTRY(vtable, 6, CStartExperienceManager_OnViewCloaking);
REPLACE_VTABLE_ENTRY(vtable, 10, CStartExperienceManager_OnViewHidden);
if (dwStartShowClassicMode)
{
DWORD dwOldProtect = 0;
#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, 8, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
*(DWORD*)(matchHideA + 0) = 0xD503201F; // NOP
*(DWORD*)(matchHideA + 4) = 0xD503201F; // NOP
VirtualProtect(matchHideA, 8, dwOldProtect, &dwOldProtect);
dwOldProtect = 0;
if (VirtualProtect(matchHideB, 8, PAGE_EXECUTE_READWRITE, &dwOldProtect))
{
*(DWORD*)(matchHideB + 0) = 0xD503201F; // NOP
*(DWORD*)(matchHideB + 4) = 0xD503201F; // NOP
VirtualProtect(matchHideB, 8, 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,
};
}
static struct
{
int jumpViewExperienceManager_rcWorkArea;
} g_JVPositioningPatchOffsets;
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<IServiceProvider> spImmersiveShellServiceProvider;
RETURN_IF_FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&spImmersiveShellServiceProvider)));
ComPtr<IImmersiveMonitorManager> spImmersiveMonitorManager;
RETURN_IF_FAILED(spImmersiveShellServiceProvider->QueryService(SID_IImmersiveMonitorService, IID_PPV_ARGS(&spImmersiveMonitorManager))); // 886
ComPtr<IEdgeUiManager> 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<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> 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 + g_JVPositioningPatchOffsets.jumpViewExperienceManager_rcWorkArea)) = 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)
// ?? ?? 41 B9 89 0B 80 52 A8 01 00 34 1F 05 00 71 20 01 00 54 1F 09 00 71 A0 00 00 54 1F 0D 00 71 01 01 00 54 69 0B 80 52
// ^^^^^^^^^^^ Important instr. to distinguish from MeetNowExperienceManager::OnViewUncloaking() in GE > !!!!!!!!!!!
// Ref: CJumpViewExperienceManager::OnViewCloaking()
PBYTE matchOffsetTrayStuckPlace = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x41\xB9\x89\x0B\x80\x52\xA8\x01\x00\x34\x1F\x05\x00\x71\x20\x01\x00\x54\x1F\x09\x00\x71\xA0\x00\x00\x54\x1F\x0D\x00\x71\x01\x01\x00\x54\x69\x0B\x80\x52",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
);
#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 ?? ?? ?? ??
// -- ^^^^^^^^^^^
// Ref: CJumpViewExperienceManager::OnViewUncloaking()
// Note: The ref function belongs to SingleViewShellExperienceEventHandler so `this` is +0x40.
// As long as the above sanity check passes, hardcoding it should be fine.
if (matchOffsetTrayStuckPlace)
{
matchOffsetRcWorkArea = (PBYTE)FindPattern(
matchOffsetTrayStuckPlace + 13,
256,
"\x48\x8B\x53\x70\x48\x8D\x83",
"xxxxxxx"
);
if (matchOffsetRcWorkArea)
{
g_JVPositioningPatchOffsets.jumpViewExperienceManager_rcWorkArea = 0x40 + *(int*)(matchOffsetRcWorkArea + 7);
}
}
#elif defined(_M_ARM64)
if (matchOffsetTrayStuckPlace)
{
// Without Feature_TaskbarJumplistOnHover (48980211)
// 01 38 40 F9 07 00 07 91
// ----------- ^^^^^^^^^^^
// If this matches then the offset of m_rcWorkArea is +0x200
// Ref: CJumpViewExperienceManager::OnViewCloaking()
matchOffsetRcWorkArea = (PBYTE)FindPattern(
matchOffsetTrayStuckPlace + 38,
128,
"\x01\x38\x40\xF9\x07\x00\x07\x91",
"xxxxxxxx"
);
if (matchOffsetRcWorkArea)
{
g_JVPositioningPatchOffsets.jumpViewExperienceManager_rcWorkArea = 0x200;
}
if (!matchOffsetRcWorkArea)
{
// With Feature_TaskbarJumplistOnHover (48980211)
// 22 01 03 32 67 32 07 91
// ^^^^^^^^^^^
// If this matches then the offset of m_rcWorkArea is +0x20C
// Ref: CJumpViewExperienceManager::OnViewCloaking()
matchOffsetRcWorkArea = (PBYTE)FindPattern(
matchOffsetTrayStuckPlace + 38,
128,
"\x22\x01\x03\x32\x67\x32\x07\x91",
"xxxxxxxx"
);
if (matchOffsetRcWorkArea)
{
g_JVPositioningPatchOffsets.jumpViewExperienceManager_rcWorkArea = 0x20C;
}
}
}
#endif
if (matchOffsetRcWorkArea)
{
printf("[JVP] matchOffsetRcWorkArea = %llX\n", matchOffsetRcWorkArea - (PBYTE)mi->lpBaseOfDll);
}
// CJumpViewExperienceManager::EnsureWindowPosition()
#if defined(_M_X64)
// Base Nickel and Germanium
// 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);
}
if (!matchEnsureWindowPosition)
{
// Nickel with Feature_TaskbarJumplistOnHover (48980211)
// - 22621.3930, 3936, 4000, 4010, 4076, 4082, 4110, 4145, ...
// 4C 8D 76 C0 48 8B D3 49 8B CE E8 ?? ?? ?? ?? 8B
// ^^^^^^^^^^^
// Ref: CJumpViewExperienceManager::OnViewPropertiesChanging()
matchEnsureWindowPosition = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x4C\x8D\x76\xC0\x48\x8B\xD3\x49\x8B\xCE\xE8\x00\x00\x00\x00\x8B",
"xxxxxxxxxxx????x"
);
if (matchEnsureWindowPosition)
{
matchEnsureWindowPosition += 10;
matchEnsureWindowPosition += 5 + *(int*)(matchEnsureWindowPosition + 1);
}
}
if (!matchEnsureWindowPosition)
{
// Germanium with Feature_TaskbarJumplistOnHover (48980211)
// - 26100.1350, 1591, ...
// 48 8B D7 49 8D 4E C0 E8 ?? ?? ?? ?? 8B
// ^^^^^^^^^^^
// Ref: CJumpViewExperienceManager::OnViewPropertiesChanging()
matchEnsureWindowPosition = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\x48\x8B\xD7\x49\x8D\x4E\xC0\xE8\x00\x00\x00\x00\x8B",
"xxxxxxxx????x"
);
if (matchEnsureWindowPosition)
{
matchEnsureWindowPosition += 7;
matchEnsureWindowPosition += 5 + *(int*)(matchEnsureWindowPosition + 1);
}
}
#elif defined(_M_ARM64)
// E1 03 ?? AA ?? 02 01 D1 ?? ?? ?? ?? ?? 03 00 2A
// !! ^^^^^^^^^^^
// Do not change this to a wildcard, this byte is important
// Ref: CJumpViewExperienceManager::OnViewPropertiesChanging()
PBYTE matchEnsureWindowPosition = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
"\xE1\x03\x00\xAA\x00\x02\x01\xD1\x00\x00\x00\x00\x00\x03\x00\x2A",
"xx?x?xxx?????xxx"
);
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)
// ?? ?? 00 71 ?? ?? 00 54 ?? ?? 40 F9 E3 03 ?? AA E2 03 ?? AA E1 03 ?? 2A ?? ?? ?? ??
// ^^^^^^^^^^^
// Ref: CMultitaskingViewFrame::v_WndProc()
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
"\x00\x71\x00\x00\x00\x54\x00\x00\x40\xF9\xE3\x03\x00\xAA\xE2\x03\x00\xAA\xE1\x03\x00\x2A",
"xx??xx??xxxx?xxx?xxx?x"
);
if (match)
{
match += 22;
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)
{
#if defined(_M_X64)
// Don't worry if this is too long, this works on 17763 ~ 27943
// 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 ? ? ? ? ? 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\x00\x00\x00\x00\x00\x41\x8B\xC1",
"xxxxxxxxxxxxxxxxx????xxx????xxx????xxxxxx????xx?????xxx"
);
if (match)
{
pOffsets[1] = (DWORD)(match - pFile);
}
#elif defined(_M_ARM64)
// 40 F9 43 03 1C 32 E4 03 ?? AA ?? ?? FF 97
// ^^^^^^^^^^^
// Ref: ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu()
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
"\x40\xF9\x43\x03\x1C\x32\xE4\x03\x00\xAA\x00\x00\xFF\x97",
"xxxxxxxx?x??xx"
);
if (match)
{
match += 10;
pOffsets[1] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
if (pOffsets[1] && pOffsets[1] != 0xFFFFFFFF)
{
printf("ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() = %lX\n", pOffsets[1]);
}
}
if (!pOffsets[2] || pOffsets[2] == 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[2] = (DWORD)(match - pFile);
}
#elif defined(_M_ARM64)
// 7F 23 03 D5 F3 53 BF A9 FD 7B BB A9 FD 03 00 91 ?? 03 00 AA ?? 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\x00\x03\x00\xAA\x00\x03\x01\xAA\x00\x00\x00\x00\xFF\x00\x03\xA9",
"xxxxxxxxxxxx?xxx?xxx????x?xx"
);
if (match)
{
match -= 4;
pOffsets[2] = (DWORD)FileOffsetToRVA(pFile, match - pFile);
}
#endif
if (pOffsets[2] && pOffsets[2] != 0xFFFFFFFF)
{
printf("ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu() = %lX\n", pOffsets[2]);
}
}
if (!pOffsets[3] || pOffsets[3] == 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[3] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
else
{
// 48 8B ? E8 ? ? ? ? 4C 8D 47 ? 48 8B ? 48 8B CE E8 ? ? ? ? 90
// ^^^^^^^
match = (PBYTE)FindPattern(
pFile, dwSize,
"\x48\x8B\xCB\xE8\x00\x00\x00\x00\x4C\x8D\x47\x00\x48\x8B\x00\x48\x8B\xCE\xE8\x00\x00\x00\x00\x90",
"xx?x????xxx?xx?xxxx????x"
);
if (match)
{
match += 18;
pOffsets[3] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
}
#elif defined(_M_ARM64)
// ?? 0A 40 F9 ?? 02 40 F9 ?? ?? 00 F9 ?? ?? ?? ?? ?? 62 00 91 ?? ?? 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5
// ^^^^^^^^^^^
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
"\x0A\x40\xF9\x00\x02\x40\xF9\x00\x00\x00\xF9\x00\x00\x00\x00\x00\x62\x00\x91\x00\x00\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5",
"xxx?xxx??xx?????xxx??xxxx?x????xxxx"
);
if (match)
{
match += 27;
pOffsets[3] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
if (pOffsets[3] && pOffsets[3] != 0xFFFFFFFF)
{
printf("CLauncherTipContextMenu::_ExecuteShutdownCommand() = %lX\n", pOffsets[3]);
}
}
if (!pOffsets[4] || pOffsets[4] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// Cobalt:
// 48 89 46 ? 48 8B CB E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90
// ^^^^^^^
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
"\x48\x89\x46\x00\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90",
"xxx?xxxx????xxxxxxx????x"
);
if (match)
{
match += 18;
pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
else
{
// Nickel+:
// 48 89 03 48 8B CB E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90
// ^^^^^^^
match = (PBYTE)FindPattern(
pFile, dwSize,
"\x48\x89\x03\x48\x8B\xCB\xE8\x00\x00\x00\x00\x48\x8B\xD3\x48\x8B\xCF\xE8\x00\x00\x00\x00\x90",
"xxxxxxx????xxxxxxx????x"
);
if (match)
{
match += 17;
pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
}
#elif defined(_M_ARM64)
// 08 09 40 F9 ?? ?? 00 F9 ?? ?? ?? ?? ?? ?? 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5
// ^^^^^^^^^^^
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
"\x08\x09\x40\xF9\x00\x00\x00\xF9\x00\x00\x00\x00\x00\x00\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5",
"xxxx??xx??????xxxx?x????xxxx"
);
if (match)
{
match += 20;
pOffsets[4] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
if (pOffsets[4] && pOffsets[4] != 0xFFFFFFFF)
{
printf("CLauncherTipContextMenu::_ExecuteCommand() = %lX\n", pOffsets[4]);
}
}
if (!pOffsets[5] || pOffsets[5] == 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[5] = (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 <jnz>
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[5] = (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 ?? 03 04 AA B0 ?? 00 F9 ?? 03 00 AA ?? 02 00 F9 ?? 2E 40 F9 ?? 03 03 AA ?? 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\x00\x03\x04\xAA\xB0\x00\x00\xF9\x00\x03\x00\xAA\x00\x02\x00\xF9\x00\x2E\x40\xF9\x00\x03\x03\xAA\x00\x23\x02\xA9\x00\x00\x00\xB5",
"xxxxxxxxxx?xxxxxxxxx?xxxx?xx?xxx?xxx?xxx?xxx?xxx??xx"
);
if (match)
{
pOffsets[5] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
}
#endif
if (pOffsets[5] && pOffsets[5] != 0xFFFFFFFF)
{
printf("CMultitaskingViewManager::_CreateXamlMTVHost() = %lX\n", pOffsets[5]);
}
}
if (!pOffsets[6] || pOffsets[6] == 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[6] = (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 <jnz>
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[6] = (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 ?? 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\x00\x03\x04\xAA",
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxx?xxxxxx?xxx"
);
if (match)
{
pOffsets[6] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
}
#endif
if (pOffsets[6] && pOffsets[6] != 0xFFFFFFFF)
{
printf("CMultitaskingViewManager::_CreateDCompMTVHost() = %lX\n", pOffsets[6]);
}
}
}
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)
{
ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc = (decltype(ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[1]);
}
if (symbols_PTRS->twinui_pcshell_PTRS[2] && symbols_PTRS->twinui_pcshell_PTRS[2] != 0xFFFFFFFF)
{
ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (decltype(ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[2]);
}
if (symbols_PTRS->twinui_pcshell_PTRS[3] && symbols_PTRS->twinui_pcshell_PTRS[3] != 0xFFFFFFFF)
{
CLauncherTipContextMenu_ExecuteShutdownCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteShutdownCommandFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[3]);
}
if (symbols_PTRS->twinui_pcshell_PTRS[4] && symbols_PTRS->twinui_pcshell_PTRS[4] != 0xFFFFFFFF)
{
CLauncherTipContextMenu_ExecuteCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteCommandFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[4]);
}
int rv;
if (IsWindows11())
{
if (bOldTaskbar)
{
typedef HRESULT (WINAPI *DllGetClassObject_t)(REFCLSID rclsid, REFIID riid, LPVOID* ppv);
DllGetClassObject_t pfnDllGetClassObject = (DllGetClassObject_t)GetProcAddress(hTwinuiPcshell, "DllGetClassObject");
if (pfnDllGetClassObject)
{
IClassFactory* pFactory;
HRESULT hr = pfnDllGetClassObject(__uuidof(CLauncherTipContextMenu), IID_PPV_ARGS(&pFactory));
if (SUCCEEDED(hr))
{
void** vtable = *(void***)pFactory;
REPLACE_VTABLE_ENTRY(vtable, 3, CLauncherTipContextMenu_CreateInstance_IClassFactory_);
pFactory->Release();
}
}
}
rv = -1;
if (symbols_PTRS->twinui_pcshell_PTRS[5] && symbols_PTRS->twinui_pcshell_PTRS[5] != 0xFFFFFFFF)
{
twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc = (decltype(twinui_pcshell_CMultitaskingViewManager__CreateDCompMTVHostFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[6]);
twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc = (decltype(twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc))
((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[5]);
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");
}