diff --git a/ExplorerPatcher/ExplorerPatcher.vcxproj b/ExplorerPatcher/ExplorerPatcher.vcxproj
index 338c0f8..31dfc05 100644
--- a/ExplorerPatcher/ExplorerPatcher.vcxproj
+++ b/ExplorerPatcher/ExplorerPatcher.vcxproj
@@ -132,7 +132,7 @@
true
%(PreprocessorDefinitions)
true
- $(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)
+ inc;$(SolutionDir)libs\funchook\include;$(SolutionDir)libs\libvalinet;%(AdditionalIncludeDirectories)
stdcpp20
false
@@ -301,6 +301,12 @@
+
+
+
+
+
+
diff --git a/ExplorerPatcher/TwinUIPatches.cpp b/ExplorerPatcher/TwinUIPatches.cpp
index bc98692..dc51c1e 100644
--- a/ExplorerPatcher/TwinUIPatches.cpp
+++ b/ExplorerPatcher/TwinUIPatches.cpp
@@ -2,6 +2,7 @@
#include
#include
#include
+#include
#include
#include
@@ -14,12 +15,95 @@
#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* 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;
@@ -187,7 +271,7 @@ MIDL_INTERFACE("b8c1db5f-cbb3-48bc-afd9-ce6b880c79ed")
ILauncherTipContextMenu : IUnknown
{
virtual HRESULT STDMETHODCALLTYPE ShowLauncherTipContextMenu(POINT*) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetMenuItemsAsync(RECT, IUnknown**) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetMenuItemsAsync(RECT, IUnknown**) = 0; // New in 11 21H2, no GUID change
};
inline BOOL IsBiDiLocale(LCID locale)
@@ -338,17 +422,86 @@ BOOL IsCrashCounterEnabled();
#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)(void* _this, POINT* pt) = nullptr;
-static void(*CLauncherTipContextMenu_ExecuteCommandFunc)(void* _this, void* a2) = nullptr;
-static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)(void* _this, void* a2) = nullptr;
-static HRESULT(*CLauncherTipContextMenu_GetMenuItemsAsyncFunc)(void* _this, RECT rect, IUnknown** iunk) = nullptr;
-static DWORD g_rvaILauncherTipContextMenuVtbl;
+static HRESULT(*CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)(ILauncherTipContextMenu* _this, POINT* pptLocation) = nullptr;
+static void(*CLauncherTipContextMenu_ExecuteCommandFunc)(void* _this, ComPtr> spCommand) = nullptr;
+static void(*CLauncherTipContextMenu_ExecuteShutdownCommandFunc)(void* _this, ComPtr> 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 spLTCM;
+ HRESULT hr = MakeAndInitialize(&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;
+ hr = ((IUnknown*)*ppvObject)->QueryInterface(IID_PPV_ARGS(&pLTCM));
+ if (SUCCEEDED(hr))
+ {
+ 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;
@@ -402,13 +555,21 @@ extern "C" LRESULT CALLBACK CLauncherTipContextMenu_WndProc(HWND hWnd, UINT uMsg
return result;
}
-typedef struct
+struct ShowLauncherTipContextMenuParameters
{
- void* _this;
+ ILauncherTipContextMenu* _this;
POINT point;
- IUnknown* iunk;
- BOOL bShouldCenterWinXHorizontally;
-} ShowLauncherTipContextMenuParameters;
+ ComPtr spOperation;
+ bool bShouldCenterWinXHorizontally;
+
+ ShowLauncherTipContextMenuParameters(ILauncherTipContextMenu* _this, POINT point, IUnknown* pOperation, bool bShouldCenterWinXHorizontally)
+ : _this(_this)
+ , point(point)
+ , spOperation(pOperation)
+ , bShouldCenterWinXHorizontally(bShouldCenterWinXHorizontally)
+ {
+ }
+};
DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
{
@@ -432,6 +593,28 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
offset_in_class = 8;
}
+ char* pClassBase = (char*)params->_this - 0x58;
+
+ struct
+ {
+ // ComPtr _spScheduler;
+ // ComPtr _spWindowMessageService;
+ // ComPtr _spLauncher;
+ // ComPtr _spSystemMode;
+ // ComPtr _spMonitorManager;
+ CCoSimpleArray>> _rgCommands;
+ CCoSimpleArray>> _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*)(pClassBase + offset_in_class + 0xA8); // Begin at _rgCommands
+
static ATOM windowRegistrationAtom = 0;
if (windowRegistrationAtom == 0)
{
@@ -456,7 +639,7 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
0, 0, 0, 0,
nullptr, nullptr,
GetModuleHandle(nullptr),
- (char*)params->_this - 0x58,
+ pClassBase,
7 // ZBID_IMMERSIVE_EDGY
);
// DO NOT USE ShowWindow here; it breaks the window order
@@ -467,23 +650,98 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
// ShowWindow(hWinXWnd, SW_SHOW);
SetForegroundWindow(hWinXWnd);
- HMENU* phMenu = ((HMENU*)((char*)params->_this + 0xe8 + offset_in_class));
- while (!*phMenu)
+ while (!fields._fAreCommandsPopulated)
{
Sleep(1);
}
auto finalize = wil::scope_exit([&]() -> void
{
- params->iunk->Release();
SendMessageW(hWinXWnd, WM_CLOSE, 0, 0);
- free(params);
hIsWinXShown = nullptr;
+ delete params;
});
- if (!*phMenu)
+ if (!fields._rgCommands.GetSize())
{
return 0;
}
+ // Check if Windows Terminal is installed
+ bool fHasTerminal = false;
+ {
+ ComPtr spLocalAppDataItem;
+ HRESULT hr = SHGetKnownFolderItem(FOLDERID_LocalAppData, KF_FLAG_DEFAULT, nullptr, IID_PPV_ARGS(&spLocalAppDataItem));
+ if (SUCCEEDED(hr))
+ {
+ ComPtr 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>& 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>& 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)
@@ -518,32 +776,28 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
if (bPropertiesInWinX)
{
InsertMenuItemW(
- *phMenu,
- GetMenuItemCount(*phMenu) - 1,
+ hMenu.get(),
+ GetMenuItemCount(hMenu.get()) - 1,
TRUE,
&menuInfo
);
bCreatedMenu = TRUE;
}
- INT64* unknown_array = nullptr;
- if (bSkinMenus)
+ CSimplePointerArrayNewMem srgRenderingData;
+ if (bSkinMenus && ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)
{
- unknown_array = (INT64*)calloc(4, sizeof(INT64));
- if (ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc)
- {
- ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc(
- *phMenu,
- hWinXWnd,
- &(params->point),
- 0xc,
- unknown_array
- );
- }
+ ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc(
+ hMenu.get(),
+ hWinXWnd,
+ ¶ms->point,
+ ICMO_FORCEMOUSESTYLING | ICMO_USESYSTEMTHEME,
+ &srgRenderingData
+ );
}
BOOL res = TrackPopupMenu(
- *phMenu,
+ hMenu.get(),
TPM_RETURNCMD | TPM_RIGHTBUTTON | (params->bShouldCenterWinXHorizontally ? TPM_CENTERALIGN : 0),
params->point.x,
params->point.y,
@@ -552,25 +806,14 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
nullptr
);
- if (bSkinMenus)
+ if (bSkinMenus && ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)
{
- if (ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc)
- {
- ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc(
- *phMenu,
- hWinXWnd
- );
- }
- free(unknown_array);
+ ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc(hMenu.get(), hWinXWnd);
}
if (bCreatedMenu)
{
- RemoveMenu(
- *phMenu,
- 3999,
- MF_BYCOMMAND
- );
+ RemoveMenu(hMenu.get(), 3999, MF_BYCOMMAND);
}
if (res > 0)
@@ -579,26 +822,23 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
{
LaunchPropertiesGUI(hModule);
}
- else if (res < 4000)
+ else if (res >= 4000)
{
- INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xa8 + offset_in_class - 0x58)) + (INT64)res * 8 - 8);
- if (CLauncherTipContextMenu_ExecuteCommandFunc)
+ if (CLauncherTipContextMenu_ExecuteShutdownCommandFunc)
{
- CLauncherTipContextMenu_ExecuteCommandFunc(
- (char*)params->_this - 0x58,
- &info
- );
+ 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
{
- INT64 info = *(INT64*)((char*)(*(INT64*)((char*)params->_this + 0xc8 + offset_in_class - 0x58)) + ((INT64)res - 4000) * 8);
- if (CLauncherTipContextMenu_ExecuteShutdownCommandFunc)
+ if (CLauncherTipContextMenu_ExecuteCommandFunc)
{
- CLauncherTipContextMenu_ExecuteShutdownCommandFunc(
- (char*)params->_this - 0x58,
- &info
- );
+ CLauncherTipContextMenu_ExecuteCommandFunc(pClassBase, fields._rgCommands[res - 1]);
}
}
}
@@ -606,8 +846,10 @@ DWORD ShowLauncherTipContextMenu(LPVOID lpParams)
return 0;
}
-HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(void* _this, POINT* pt)
+HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(ILauncherTipContextMenu* _this, POINT* pt)
{
+ HRESULT hr = S_OK;
+
if (hWinXThread)
{
WaitForSingleObject(hWinXThread, INFINITE);
@@ -617,7 +859,7 @@ HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(void* _this, POIN
if (!hIsWinXShown)
{
- BOOL bShouldCenterWinXHorizontally = FALSE;
+ bool bShouldCenterWinXHorizontally = false;
POINT point;
if (pt)
{
@@ -637,37 +879,27 @@ HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(void* _this, POIN
HMONITOR hMonitor = MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO mi;
mi.cbSize = sizeof(MONITORINFO);
- GetMonitorInfo(hMonitor, &mi);
+ 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 = FindWindowEx(
- hWndUnder,
- nullptr,
- L"Start",
- nullptr
- );
+ hWndUnder = FindWindowExW(hWndUnder, nullptr, L"Start", nullptr);
}
RECT rcUnder;
GetWindowRect(hWndUnder, &rcUnder);
if (mi.rcMonitor.left != rcUnder.left)
{
- bShouldCenterWinXHorizontally = TRUE;
+ bShouldCenterWinXHorizontally = true;
point.x = rcUnder.left + (rcUnder.right - rcUnder.left) / 2;
point.y = rcUnder.top;
}
else
{
UINT dpiX, dpiY;
- HRESULT hr = GetDpiForMonitor(
- hMonitor,
- MDT_DEFAULT,
- &dpiX,
- &dpiY
- );
+ 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)
@@ -705,30 +937,23 @@ HRESULT CLauncherTipContextMenu_ShowLauncherTipContextMenuHook(void* _this, POIN
point = GetDefaultWinXPosition(FALSE, nullptr, nullptr, TRUE, FALSE);
}
- IUnknown* iunk = nullptr;
- if (CLauncherTipContextMenu_GetMenuItemsAsyncFunc)
+ RECT rc = {};
+ ComPtr spOperation;
+ hr = _this->GetMenuItemsAsync(rc, &spOperation);
+ if (SUCCEEDED(hr))
{
- RECT rc = { 0 };
- CLauncherTipContextMenu_GetMenuItemsAsyncFunc(_this, rc, &iunk);
- }
- if (iunk)
- {
- iunk->AddRef();
-
- ShowLauncherTipContextMenuParameters* params = (ShowLauncherTipContextMenuParameters*)malloc(sizeof(ShowLauncherTipContextMenuParameters));
- params->_this = _this;
- params->point = point;
- params->iunk = iunk;
- params->bShouldCenterWinXHorizontally = bShouldCenterWinXHorizontally;
+ ShowLauncherTipContextMenuParameters* params = new(std::nothrow) ShowLauncherTipContextMenuParameters(_this, point, spOperation.Get(), bShouldCenterWinXHorizontally);
hIsWinXShown = CreateThread(nullptr, 0, ShowLauncherTipContextMenu, params, 0, nullptr);
hWinXThread = hIsWinXShown;
}
}
- if (CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)
+
+ if (SUCCEEDED(hr) && CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc)
{
- return CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt);
+ hr = CLauncherTipContextMenu_ShowLauncherTipContextMenuFunc(_this, pt);
}
- return S_OK;
+
+ return hr;
}
extern "C" void ToggleLauncherTipContextMenu()
@@ -1654,19 +1879,19 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
{
// * Pattern for Germanium
// ```
- // 69 22 04 A9 ?? ?? 00 ?? 08 ?? ?? 91 60 A2 01 91 68 32 00 F9
+ // ?? 22 04 A9 ?? ?? 00 ?? 08 ?? ?? 91 ?? A2 01 91 ?? 32 00 F9
// ^^^^^^^^^^^+^^^^^^^^^^^
// ```
// Ref: CStartExperienceManager::CStartExperienceManager()
matchVtable = (PBYTE)FindPattern(
mi->lpBaseOfDll,
mi->SizeOfImage,
- "\x69\x22\x04\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x60\xA2\x01\x91\x68\x32\x00\xF9",
- "xxxx??x?x??xxxxxxxxx"
+ "\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 += 4;
+ matchVtable += 3;
matchVtable = (PBYTE)ARM64_DecodeADRL((UINT_PTR)matchVtable, *(DWORD*)matchVtable, *(DWORD*)(matchVtable + 4));
}
}
@@ -1695,15 +1920,15 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
}
#elif defined(_M_ARM64)
// ```
- // 22 08 80 52 61 82 01 91 60 ?? ?? 91 ?? ?? ?? ?? 1F 20 03 D5
+ // 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\x61\x82\x01\x91\x60\x00\x00\x91\x00\x00\x00\x00\x1F\x20\x03\xD5",
- "xxxxxxxxx??x????xxxx"
+ "\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)
{
@@ -1727,11 +1952,11 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
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"
- );
+ 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)
{
@@ -1740,7 +1965,7 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
}
#elif defined(_M_ARM64)
// ```
- // 08 07 80 52 7F ?? ?? 39 68 ?? ?? B9
+ // 08 07 80 52 ?? ?? ?? 39 ?? ?? ?? B9
// ^^^^^^^^^^^ AH1
// ```
// Ref: CStartExperienceManager::CStartExperienceManager()
@@ -1750,8 +1975,8 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
matchAnimationHelperFields = (PBYTE)FindPattern(
matchSingleViewShellExperienceFields + 20,
128,
- "\x08\x07\x80\x52\x7F\x00\x00\x39\x68\x00\x00\xB9",
- "xxxxx??xx??x"
+ "\x08\x07\x80\x52\x00\x00\x00\x39\x00\x00\x00\xB9",
+ "xxxx???x???x"
);
}
if (matchAnimationHelperFields)
@@ -2099,7 +2324,7 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
if (matchHideA)
{
matchHideA -= 3;
- printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX\n", matchHideA - (PBYTE)mi->lpBaseOfDll);
+ printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX (Pattern A)\n", matchHideA - (PBYTE)mi->lpBaseOfDll);
matchHideB = (PBYTE)FindPattern(
matchHideA + 12,
mi->SizeOfImage - (matchHideA + 12 - (PBYTE)mi->lpBaseOfDll),
@@ -2109,7 +2334,37 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
if (matchHideB)
{
matchHideB -= 3;
- printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX\n", matchHideB - (PBYTE)mi->lpBaseOfDll);
+ printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX (Pattern A)\n", matchHideB - (PBYTE)mi->lpBaseOfDll);
+ }
+ }
+ else
+ {
+ // ```
+ // ?? ?? ?? 34 ?? 00 80 52 ?? 4E 0B 39
+ // ^^^^^^^^^^^ Turn CBZ into B
+ // ```
+ // Perform on exactly two matches
+ matchHideA = (PBYTE)FindPattern(
+ mi->lpBaseOfDll,
+ mi->SizeOfImage,
+ "\x34\x00\x00\x80\x52\x00\x4E\x0B\x39",
+ "x?xxx?xxx"
+ );
+ if (matchHideA)
+ {
+ matchHideA -= 3;
+ printf("[SMA] matchHideA in CStartExperienceManager::Hide() = %llX (Pattern B)\n", matchHideA - (PBYTE)mi->lpBaseOfDll);
+ matchHideB = (PBYTE)FindPattern(
+ matchHideA + 12,
+ mi->SizeOfImage - (matchHideA + 12 - (PBYTE)mi->lpBaseOfDll),
+ "\x34\x00\x00\x80\x52\x00\x4E\x0B\x39",
+ "x?xxx?xxx"
+ );
+ if (matchHideB)
+ {
+ matchHideB -= 3;
+ printf("[SMA] matchHideB in CStartExperienceManager::Hide() = %llX (Pattern B)\n", matchHideB - (PBYTE)mi->lpBaseOfDll);
+ }
}
}
#endif
@@ -2889,64 +3144,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
printf("CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc() = %lX\n", pOffsets[0]);
}
}
- // if ((!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF) || (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF))
- {
- UINT_PTR* vtable = nullptr;
- UINT_PTR vtableRVA = 0;
-#if defined(_M_X64)
- // 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 41 18 48 8D 05 ?? ?? ?? ?? 48 89 41 20 48 8D 05 ?? ?? ?? ?? 48 89 41 58 48 8D 05 ?? ?? ?? ?? 48 89 41 60
- // ^^^^^^^^^^^
- PBYTE match = (PBYTE)FindPattern(
- pFile, dwSize,
- "\x48\x8D\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x89\x01\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x18\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x20\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x58\x48\x8D\x05\x00\x00\x00\x00\x48\x89\x41\x60",
- "xxx????xxxxxxxxx????xxxxxxx????xxxxxxx????xxxxxxx????xxxx"
- );
- if (match)
- {
- match += 35; // Point to 48
- vtable = (UINT_PTR*)(match + 7 + *(int*)(match + 3));
- vtableRVA = (PBYTE)vtable - pFile;
- }
-#elif defined(_M_ARM64)
- // * Pattern 1 (for 24H2):
- // 69 A2 01 A9 ?? ?? 00 ?? 09 ?? ?? 91 ?? ?? 00 ?? 08 ?? ?? 91 69 A2 05 A9 ?? ?? 00 ?? 08 ?? ?? 91 68 36 00 F9 ?? ?? 00 ?? 08 ?? ?? 91 68 3E 00 F9
- // ^^^^^^^^^^^+^^^^^^^^^^^
- PBYTE match = (PBYTE)FindPattern(
- pFile, dwSize,
- "\x69\xA2\x01\xA9\x00\x00\x00\x00\x09\x00\x00\x91\x00\x00\x00\x00\x08\x00\x00\x91\x69\xA2\x05\xA9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x36\x00\xF9\x00\x00\x00\x00\x08\x00\x00\x91\x68\x3E\x00\xF9",
- "xxxx??x?x??x??x?x??xxxxx??x?x??xxxxx??x?x??xxxxx"
- );
- // Patterns for 226xx are not implemented
- if (match)
- {
- match += 4; // Point to ADRP
- vtableRVA = ARM64_DecodeADRL(FileOffsetToRVA(pFile, match - pFile), *(DWORD*)match, *(DWORD*)(match + 4));
- vtable = (UINT_PTR*)((UINT_PTR)pFile + RVAToFileOffset(pFile, vtableRVA));
- }
-#endif
- if (vtable)
- {
- if (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF)
- {
- pOffsets[6] = (DWORD)(vtable[3] - 0x180000000);
- }
- if (!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF)
- {
- pOffsets[1] = (DWORD)(vtable[4] - 0x180000000);
- }
- g_rvaILauncherTipContextMenuVtbl = (DWORD)vtableRVA;
- printf("ILauncherTipContextMenuVtbl = %lX\n", g_rvaILauncherTipContextMenuVtbl);
- }
- if (pOffsets[6] && pOffsets[6] != 0xFFFFFFFF)
- {
- printf("CLauncherTipContextMenu::ShowLauncherTipContextMenu() = %lX\n", pOffsets[6]);
- }
- if (pOffsets[1] && pOffsets[1] != 0xFFFFFFFF)
- {
- printf("CLauncherTipContextMenu::GetMenuItemsAsync() = %lX\n", pOffsets[1]);
- }
- }
- if (!pOffsets[2] || pOffsets[2] == 0xFFFFFFFF)
+ if (!pOffsets[1] || pOffsets[1] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// Don't worry if this is too long, this works on 17763 and 25951
@@ -2958,7 +3156,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
);
if (match)
{
- pOffsets[2] = (DWORD)(match - pFile);
+ pOffsets[1] = (DWORD)(match - pFile);
}
#elif defined(_M_ARM64)
// 40 F9 43 03 1C 32 E4 03 15 AA ?? ?? FF 97
@@ -2972,15 +3170,15 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 10;
- pOffsets[2] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
+ pOffsets[1] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
- if (pOffsets[2] && pOffsets[2] != 0xFFFFFFFF)
+ if (pOffsets[1] && pOffsets[1] != 0xFFFFFFFF)
{
- printf("ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() = %lX\n", pOffsets[2]);
+ printf("ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu() = %lX\n", pOffsets[1]);
}
}
- if (!pOffsets[3] || pOffsets[3] == 0xFFFFFFFF)
+ 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
@@ -2991,7 +3189,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
);
if (match)
{
- pOffsets[3] = (DWORD)(match - pFile);
+ 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 F3 03 00 AA F4 03 01 AA ?? ?? ?? ?? FF ?? 03 A9
@@ -3004,15 +3202,15 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match -= 4;
- pOffsets[3] = (DWORD)FileOffsetToRVA(pFile, match - pFile);
+ pOffsets[2] = (DWORD)FileOffsetToRVA(pFile, match - pFile);
}
#endif
- if (pOffsets[3] && pOffsets[3] != 0xFFFFFFFF)
+ if (pOffsets[2] && pOffsets[2] != 0xFFFFFFFF)
{
- printf("ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu() = %lX\n", pOffsets[3]);
+ printf("ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu() = %lX\n", pOffsets[2]);
}
}
- if (!pOffsets[4] || pOffsets[4] == 0xFFFFFFFF)
+ if (!pOffsets[3] || pOffsets[3] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// 48 8B ? E8 ? ? ? ? 4C 8B ? 48 8B ? 48 8B CE E8 ? ? ? ? 90
@@ -3025,28 +3223,28 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 17;
- pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[3] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
#elif defined(_M_ARM64)
- // 82 62 00 91 ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5
+ // 82 62 00 91 ?? ?? 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5
// ^^^^^^^^^^^
PBYTE match = (PBYTE)FindPattern(
pFile, dwSize,
- "\x82\x62\x00\x91\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5",
- "xxxx?xxxxx?x????xxxx"
+ "\x82\x62\x00\x91\x00\x00\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5",
+ "xxxx??xxxx?x????xxxx"
);
if (match)
{
match += 12;
- pOffsets[4] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
+ pOffsets[3] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
- if (pOffsets[4] && pOffsets[4] != 0xFFFFFFFF)
+ if (pOffsets[3] && pOffsets[3] != 0xFFFFFFFF)
{
- printf("CLauncherTipContextMenu::_ExecuteShutdownCommand() = %lX\n", pOffsets[4]);
+ printf("CLauncherTipContextMenu::_ExecuteShutdownCommand() = %lX\n", pOffsets[3]);
}
}
- if (!pOffsets[5] || pOffsets[5] == 0xFFFFFFFF)
+ if (!pOffsets[4] || pOffsets[4] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// 48 8B ? E8 ? ? ? ? 48 8B D3 48 8B CF E8 ? ? ? ? 90 48 8D 56 ? 48 8B CE
@@ -3059,7 +3257,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 14;
- pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
else
{
@@ -3073,29 +3271,29 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 14;
- pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[4] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
}
#elif defined(_M_ARM64)
- // 08 09 40 F9 ?? 16 00 F9 ?? ?? ?? ?? ?? A2 00 91 E0 03 ?? AA ?? ?? ?? ?? 1F 20 03 D5
+ // 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\x16\x00\xF9\x00\x00\x00\x00\x00\xA2\x00\x91\xE0\x03\x00\xAA\x00\x00\x00\x00\x1F\x20\x03\xD5",
- "xxxx?xxx?????xxxxx?x????xxxx"
+ "\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[5] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
+ pOffsets[4] = (DWORD)FileOffsetToRVA(pFile, (PBYTE)ARM64_FollowBL((DWORD*)match) - pFile);
}
#endif
- if (pOffsets[5] && pOffsets[5] != 0xFFFFFFFF)
+ if (pOffsets[4] && pOffsets[4] != 0xFFFFFFFF)
{
- printf("CLauncherTipContextMenu::_ExecuteCommand() = %lX\n", pOffsets[5]);
+ printf("CLauncherTipContextMenu::_ExecuteCommand() = %lX\n", pOffsets[4]);
}
}
- if (!pOffsets[7] || pOffsets[7] == 0xFFFFFFFF)
+ if (!pOffsets[5] || pOffsets[5] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// Ref: CMultitaskingViewManager::_CreateMTVHost()
@@ -3110,7 +3308,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 16;
- pOffsets[7] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
else
{
@@ -3130,7 +3328,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
match += 26 + jnzSize;
if (match[0] == 0xE8)
{
- pOffsets[7] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[5] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
}
}
@@ -3144,15 +3342,15 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
);
if (match)
{
- pOffsets[7] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
+ pOffsets[5] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
}
#endif
- if (pOffsets[7] && pOffsets[7] != 0xFFFFFFFF)
+ if (pOffsets[5] && pOffsets[5] != 0xFFFFFFFF)
{
- printf("CMultitaskingViewManager::_CreateXamlMTVHost() = %lX\n", pOffsets[7]);
+ printf("CMultitaskingViewManager::_CreateXamlMTVHost() = %lX\n", pOffsets[5]);
}
}
- if (!pOffsets[8] || pOffsets[8] == 0xFFFFFFFF)
+ if (!pOffsets[6] || pOffsets[6] == 0xFFFFFFFF)
{
#if defined(_M_X64)
// Ref: CMultitaskingViewManager::_CreateMTVHost()
@@ -3167,7 +3365,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
if (match)
{
match += 16;
- pOffsets[8] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
+ pOffsets[6] = (DWORD)(match + 5 + *(int*)(match + 1) - pFile);
}
else
{
@@ -3184,7 +3382,7 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
DWORD jnzSize = 0;
if (FollowJnz(match + 26, &target, &jnzSize) && target[0] == 0xE8)
{
- pOffsets[8] = (DWORD)(target + 5 + *(int*)(target + 1) - pFile);
+ pOffsets[6] = (DWORD)(target + 5 + *(int*)(target + 1) - pFile);
}
}
}
@@ -3197,12 +3395,12 @@ void TryToFindTwinuiPCShellOffsets(DWORD* pOffsets)
);
if (match)
{
- pOffsets[8] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
+ pOffsets[6] = (DWORD)FileOffsetToRVA(pFile, match - 4 - pFile);
}
#endif
- if (pOffsets[8] && pOffsets[8] != 0xFFFFFFFF)
+ if (pOffsets[6] && pOffsets[6] != 0xFFFFFFFF)
{
- printf("CMultitaskingViewManager::_CreateDCompMTVHost() = %lX\n", pOffsets[8]);
+ printf("CMultitaskingViewManager::_CreateDCompMTVHost() = %lX\n", pOffsets[6]);
}
}
}
@@ -3229,51 +3427,56 @@ extern "C" void RunTwinUIPCShellPatches(symbols_addr* symbols_PTRS)
if (symbols_PTRS->twinui_pcshell_PTRS[1] && symbols_PTRS->twinui_pcshell_PTRS[1] != 0xFFFFFFFF)
{
- CLauncherTipContextMenu_GetMenuItemsAsyncFunc = (decltype(CLauncherTipContextMenu_GetMenuItemsAsyncFunc))
+ 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_ApplyOwnerDrawToMenuFunc = (decltype(ImmersiveContextMenuHelper_ApplyOwnerDrawToMenuFunc))
+ 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)
{
- ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc = (decltype(ImmersiveContextMenuHelper_RemoveOwnerDrawFromMenuFunc))
+ 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_ExecuteShutdownCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteShutdownCommandFunc))
- ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[4]);
- }
-
- if (symbols_PTRS->twinui_pcshell_PTRS[5] && symbols_PTRS->twinui_pcshell_PTRS[5] != 0xFFFFFFFF)
{
CLauncherTipContextMenu_ExecuteCommandFunc = (decltype(CLauncherTipContextMenu_ExecuteCommandFunc))
- ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[5]);
+ ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[4]);
}
int rv;
if (IsWindows11())
{
- if (g_rvaILauncherTipContextMenuVtbl)
+ if (bOldTaskbar)
{
- void** vtable = (void**)((PBYTE)hTwinuiPcshell + g_rvaILauncherTipContextMenuVtbl);
- REPLACE_VTABLE_ENTRY(vtable, 3, CLauncherTipContextMenu_ShowLauncherTipContextMenu);
+ 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[7] && symbols_PTRS->twinui_pcshell_PTRS[7] != 0xFFFFFFFF)
+ 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[8]);
+ ((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[7]);
+ ((uintptr_t)hTwinuiPcshell + symbols_PTRS->twinui_pcshell_PTRS[5]);
rv = funchook_prepare(
funchook,
(void**)&twinui_pcshell_CMultitaskingViewManager__CreateXamlMTVHostFunc,
diff --git a/ExplorerPatcher/inc/ContainerPolicies.h b/ExplorerPatcher/inc/ContainerPolicies.h
new file mode 100644
index 0000000..9a36a41
--- /dev/null
+++ b/ExplorerPatcher/inc/ContainerPolicies.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include
+
+#include
+
+template
+class CTContainer_PolicyUnOwned
+{
+public:
+ static void Destroy(T* p) {}
+};
+
+template
+class CTContainer_PolicyRelease
+{
+public:
+ static void Destroy(T* p)
+ {
+ if (p)
+ p->Release();
+ }
+};
+
+class CTContainer_PolicyNewMem
+{
+public:
+ template
+ static void Destroy(T* p)
+ {
+ delete p;
+ }
+};
+
+class CTContainer_PolicyCoTaskMem
+{
+public:
+ static void Destroy(void* p)
+ {
+ CoTaskMemFree(p);
+ }
+};
+
+class CTContainer_PolicyLocalMem
+{
+public:
+ static void Destroy(void* p)
+ {
+ DestroyMem(p);
+ }
+
+ static BOOL DestroyMem(void* p)
+ {
+ return !LocalFree(p);
+ }
+};
+
+template
+class CTPolicyCoTaskMem : CTContainer_PolicyCoTaskMem
+{
+public:
+ static void Destroy(void* p)
+ {
+ CTContainer_PolicyCoTaskMem::Destroy(p);
+ }
+
+ static HRESULT ReallocArray(T* pv, size_t cItems, T** ppv)
+ {
+ return CoReallocArray(pv, cItems, ppv);
+ }
+};
+
+template
+class CTPolicyLocalMem : CTContainer_PolicyLocalMem
+{
+public:
+ static void Destroy(void* p)
+ {
+ DestroyMem(p);
+ }
+
+ static HRESULT ReallocArray(T* pv, size_t cItems, T** ppv)
+ {
+ return LocalReallocArray(pv, cItems, ppv);
+ }
+};
diff --git a/ExplorerPatcher/inc/NativeString.h b/ExplorerPatcher/inc/NativeString.h
new file mode 100644
index 0000000..6296a32
--- /dev/null
+++ b/ExplorerPatcher/inc/NativeString.h
@@ -0,0 +1,906 @@
+#pragma once
+
+#include
+#include
+
+#include "ResultUtils.h"
+
+namespace Windows::Internal
+{
+ class ResourceString
+ {
+ public:
+ static bool FindAndSize(HINSTANCE hInstance, UINT uId, WORD wLanguage, const WCHAR** ppch, WORD* plen)
+ {
+ bool fRet = false;
+ *ppch = nullptr;
+ if (plen)
+ *plen = 0;
+ HRSRC hRes = FindResourceExW(hInstance, RT_STRING, MAKEINTRESOURCEW((uId >> 4) + 1), wLanguage);
+ if (hRes)
+ {
+ HGLOBAL hStringSeg = LoadResource(hInstance, hRes);
+ if (hStringSeg)
+ {
+ WCHAR* pch = (WCHAR*)LockResource(hStringSeg);
+ if (pch)
+ {
+ for (uId = (char)uId & 0xF; uId; --uId)
+ pch += *pch + 1;
+ *ppch = *pch ? pch + 1 : L"";
+ if (plen)
+ *plen = *pch;
+ fRet = true;
+ }
+ }
+ }
+ return fRet;
+ }
+ };
+
+ template
+ class CoTaskMemPolicy
+ {
+ public:
+ static ElementType* Alloc(size_t bytes)
+ {
+ return (ElementType*)CoTaskMemAlloc(bytes);
+ }
+
+ static ElementType* Realloc(ElementType* p, size_t bytes)
+ {
+ return (ElementType*)CoTaskMemRealloc(p, bytes);
+ }
+
+ static void Free(ElementType* p)
+ {
+ CoTaskMemFree(p);
+ }
+ };
+
+ template
+ class LocalMemPolicy
+ {
+ public:
+ static ElementType* Alloc(size_t bytes)
+ {
+ return (ElementType*)LocalAlloc(LMEM_FIXED, bytes);
+ }
+
+ static ElementType* Realloc(ElementType* p, size_t bytes)
+ {
+ return (ElementType*)LocalReAlloc(p, bytes, LMEM_MOVEABLE);
+ }
+
+ static void Free(ElementType* p)
+ {
+ LocalFree(p);
+ }
+ };
+
+ template
+ class NativeString
+ {
+ public:
+ NativeString() : _pszStringData(nullptr), _cchStringData(0), _cchStringDataCapacity(0)
+ {
+ }
+
+ NativeString(NativeString&& other) noexcept
+ : _pszStringData(other._pszStringData)
+ , _cchStringData(other._cchStringData)
+ , _cchStringDataCapacity(other._cchStringDataCapacity)
+ {
+ other._pszStringData = nullptr;
+ other._cchStringData = 0;
+ other._cchStringDataCapacity = 0;
+ }
+
+ private:
+ NativeString(const NativeString&) = delete;
+
+ public:
+ ~NativeString()
+ {
+ Free();
+ }
+
+ HRESULT Initialize(const WCHAR* psz, const size_t cch)
+ {
+ return _Initialize(psz, cch);
+ }
+
+ HRESULT Initialize(const WCHAR* psz)
+ {
+ return _Initialize(psz, s_cchUnknown);
+ }
+
+ HRESULT Initialize(const NativeString& other)
+ {
+ return _Initialize(other._pszStringData, other.GetCount());
+ }
+
+ HRESULT Initialize(HINSTANCE hInstance, UINT uId, WORD wLanguage)
+ {
+ HRESULT hr;
+ const WCHAR* rgch;
+ WORD cch;
+ if (ResourceString::FindAndSize(hInstance, uId, wLanguage, &rgch, &cch))
+ {
+ hr = _Initialize(rgch, cch);
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+ return hr;
+ }
+
+ HRESULT Initialize(HINSTANCE hInstance, UINT uId)
+ {
+ return Initialize(hInstance, uId, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
+ }
+
+ HRESULT Initialize(HKEY hKey, const WCHAR* pszValueName)
+ {
+ return _InitializeFromRegistry(hKey, pszValueName, true);
+ }
+
+ HRESULT Initialize(HKEY hKey, const WCHAR* pszSubKey, const WCHAR* pszValueName)
+ {
+ HKEY hkeySub;
+ HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hkeySub));
+ if (SUCCEEDED(hr))
+ {
+ hr = Initialize(hkeySub, pszValueName);
+ RegCloseKey(hkeySub);
+ }
+ return hr;
+ }
+
+ HRESULT InitializeNoExpand(HKEY hKey, const WCHAR* pszValueName)
+ {
+ return _InitializeFromRegistry(hKey, pszValueName, false);
+ }
+
+ HRESULT InitializeNoExpand(HKEY hKey, const WCHAR* pszSubKey, const WCHAR* pszValueName)
+ {
+ HKEY hkeySub;
+ HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hkeySub));
+ if (SUCCEEDED(hr))
+ {
+ hr = InitializeNoExpand(hkeySub, pszValueName);
+ RegCloseKey(hkeySub);
+ }
+ return hr;
+ }
+
+ HRESULT InitializeFormat(const WCHAR* pszFormat, va_list argList)
+ {
+ return _InitializeHelper(pszFormat, argList, [](const WCHAR* pszFormat, va_list argList, WCHAR* pszStringData, size_t cchStringData) -> HRESULT
+ {
+ _set_errno(0);
+ HRESULT hr = StringCchVPrintfW(pszStringData, cchStringData, pszFormat, argList);
+ if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
+ {
+ errno_t err;
+ _get_errno(&err);
+ if (err == EINVAL)
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+ return hr;
+ });
+ }
+
+ HRESULT InitializeFormat(const WCHAR* pszFormat, ...)
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ return InitializeFormat(pszFormat, args);
+ }
+
+ HRESULT InitializeResFormat(HINSTANCE hInstance, UINT uId, ...)
+ {
+ va_list argList;
+ va_start(argList, uId);
+ NativeString spszFormat;
+ HRESULT hr = spszFormat.Initialize(hInstance, uId);
+ if (SUCCEEDED(hr))
+ {
+ hr = InitializeFormat(spszFormat._pszStringData, argList);
+ }
+ return hr;
+ }
+
+ HRESULT InitializeResMessage(HINSTANCE hInstance, UINT uId, ...)
+ {
+ va_list argList;
+ va_start(argList, uId);
+ NativeString spszFormat;
+ HRESULT hr = spszFormat.Initialize(hInstance, uId);
+ if (SUCCEEDED(hr))
+ {
+ hr = _InitializeHelper(spszFormat._pszStringData, argList, [](const WCHAR* pszFormat, va_list argList, WCHAR* pszStringData, size_t cchStringData) -> HRESULT
+ {
+ va_list argListT = argList;
+ DWORD cchResult = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, pszStringData, (DWORD)cchStringData, &argListT);
+ return ResultFromWin32Bool(cchResult);
+ });
+ }
+ return hr;
+ }
+
+ void Free()
+ {
+ _Free();
+ }
+
+ void Attach(WCHAR* psz)
+ {
+ _Attach(psz);
+ }
+
+ void Attach(WCHAR* psz, const size_t cch)
+ {
+ _Attach(psz, cch);
+ }
+
+ WCHAR* Detach()
+ {
+ return _Detach();
+ }
+
+ HRESULT DetachInitializeIfEmpty(WCHAR** ppsz)
+ {
+ *ppsz = nullptr;
+ HRESULT hr = S_OK;
+
+ if (_pszStringData)
+ {
+ hr = Initialize(L"");
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *ppsz = Detach();
+ }
+
+ return hr;
+ }
+
+ WCHAR** FreeAndGetAddressOf()
+ {
+ return _FreeAndGetAddressOf();
+ }
+
+ HRESULT CopyTo(WCHAR** ppszDest) const
+ {
+ HRESULT hr;
+ *ppszDest = nullptr;
+ if (_pszStringData)
+ {
+ NativeString spszT;
+ hr = spszT.Initialize(*this);
+ if (SUCCEEDED(hr))
+ {
+ *ppszDest = spszT.Detach();
+ }
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+ return hr;
+ }
+
+ HRESULT CopyTo(WCHAR* pszDest, size_t cchDest) const
+ {
+ if (!_pszStringData)
+ {
+ if (cchDest)
+ *pszDest = 0;
+ return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+ return StringCchCopyW(pszDest, cchDest, _pszStringData);
+ }
+
+ const WCHAR* Get() const
+ {
+ return _Get();
+ }
+
+ const WCHAR* GetNonNull() const
+ {
+ return _pszStringData ? _pszStringData : L"";
+ }
+
+ size_t GetCount()
+ {
+ return _GetCount();
+ }
+
+ size_t GetCount() const
+ {
+ return _GetCount();
+ }
+
+ bool IsEmpty() const
+ {
+ return _IsEmpty();
+ }
+
+ bool HasLength() const
+ {
+ return !_IsEmpty();
+ }
+
+ int CompareOrdinal(const WCHAR* psz, const size_t cch) const
+ {
+ return CompareStringOrdinal(GetNonNull(), (int)GetCount(), psz ? psz : L"", psz ? (int)cch : 0, FALSE);
+ }
+
+ int CompareOrdinal(const WCHAR* psz) const
+ {
+ return CompareOrdinal(psz, s_cchUnknown);
+ }
+
+ int CompareOrdinal(const NativeString& other) const
+ {
+ return CompareOrdinal(other.GetNonNull(), other.GetCount());
+ }
+
+ int CompareOrdinalIgnoreCase(const WCHAR* psz, const size_t cch) const
+ {
+ return CompareStringOrdinal(GetNonNull(), (int)GetCount(), psz ? psz : L"", psz ? (int)cch : 0, TRUE);
+ }
+
+ int CompareOrdinalIgnoreCase(const WCHAR* psz) const
+ {
+ return CompareOrdinalIgnoreCase(psz, s_cchUnknown);
+ }
+
+ int CompareOrdinalIgnoreCase(const NativeString& other) const
+ {
+ return CompareOrdinalIgnoreCase(other.GetNonNull(), other.GetCount());
+ }
+
+ HRESULT Concat(const WCHAR* psz, const size_t cch)
+ {
+ return _Concat(psz, cch);
+ }
+
+ HRESULT Concat(WCHAR c)
+ {
+ return _Concat(c);
+ }
+
+ HRESULT Concat(const WCHAR* psz)
+ {
+ return _Concat(psz, psz ? wcslen(psz) : 0);
+ }
+
+ HRESULT Concat(const NativeString& other)
+ {
+ return _Concat(other.Get(), other.GetCount());
+ }
+
+ HRESULT Concat(HINSTANCE hInstance, UINT uId, WORD wLanguage)
+ {
+ HRESULT hr;
+ const WCHAR* rgch;
+ WORD cch;
+ if (ResourceString::FindAndSize(hInstance, uId, wLanguage, &rgch, &cch))
+ {
+ hr = _Concat(rgch, cch);
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
+ }
+ return hr;
+ }
+
+ HRESULT Concat(HINSTANCE hInstance, UINT uId)
+ {
+ return Concat(hInstance, uId, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
+ }
+
+ HRESULT ConcatFormat(const WCHAR* pszFormat, va_list argList)
+ {
+ if (IsEmpty())
+ {
+ return InitializeFormat(pszFormat, argList);
+ }
+ NativeString strT;
+ HRESULT hr = strT.InitializeFormat(pszFormat, argList);
+ if (SUCCEEDED(hr))
+ {
+ hr = Concat(strT);
+ }
+ return hr;
+ }
+
+ HRESULT ConcatFormat(const WCHAR* pszFormat, ...)
+ {
+ va_list argList;
+ va_start(argList, pszFormat);
+ return ConcatFormat(pszFormat, argList);
+ }
+
+ bool RemoveAt(size_t iElem, size_t cchElem)
+ {
+ return _RemoveAt(iElem, cchElem);
+ }
+
+ bool TrimStart(const WCHAR* pszTrim)
+ {
+ return _TrimStart(pszTrim);
+ }
+
+ bool TrimEnd(const WCHAR* pszTrim)
+ {
+ return _TrimEnd(pszTrim);
+ }
+
+ inline static const WCHAR* const s_pszTrimWhitespaceCharacterSet =
+ L"\u0020" // Space
+ L"\u0009" // Tab
+ L"\u3000" // Ideographic Space
+ L"\u17D2" // Khmer Sign Coeng
+ L"\u0F0B" // Tibetan Mark Intersyllabic Tsheg
+ L"\u1680" // Ogham Space Mark
+ L"\u180E" // Mongolian Vowel Separator
+ ;
+
+ bool TrimWhitespace()
+ {
+ bool fWasCharacterTrimmedEnd = _TrimEnd(s_pszTrimWhitespaceCharacterSet);
+ bool fWasCharacterTrimmedStart = _TrimStart(s_pszTrimWhitespaceCharacterSet);
+ return fWasCharacterTrimmedStart || fWasCharacterTrimmedEnd;
+ }
+
+ void ReplaceChars(const WCHAR wcFind, const WCHAR wcReplace)
+ {
+ _EnsureCount();
+ for (size_t i = 0; i < _cchStringData; i++)
+ {
+ if (_pszStringData[i] == wcFind)
+ _pszStringData[i] = wcReplace;
+ }
+ }
+
+ NativeString& operator=(NativeString&& other) noexcept
+ {
+ _Free();
+ _pszStringData = other._pszStringData;
+ _cchStringData = other._cchStringData;
+ _cchStringDataCapacity = other._cchStringDataCapacity;
+ other._pszStringData = nullptr;
+ other._cchStringData = 0;
+ other._cchStringDataCapacity = 0;
+ return *this;
+ }
+
+ private:
+ NativeString& operator=(const NativeString& other) = delete;
+
+ public:
+ WCHAR** operator&()
+ {
+ return FreeAndGetAddressOf();
+ }
+
+ /*WCHAR* operator*() const
+ {
+ return Get();
+ }*/
+
+ bool operator==(const WCHAR* pszOther) const
+ {
+ return pszOther ? CompareOrdinal(pszOther) == CSTR_EQUAL : !_pszStringData;
+ }
+
+ bool operator!=(const WCHAR* pszOther) const
+ {
+ return !operator==(pszOther);
+ }
+
+ HRESULT AppendMayTruncate(const WCHAR* psz, size_t cchMaxCapacity)
+ {
+ return _ConcatMayTruncate(psz, cchMaxCapacity);
+ }
+
+ HRESULT EnsureCapacity(size_t cchDesired)
+ {
+ return _EnsureCapacity(cchDesired);
+ }
+
+ private:
+ void _EnsureCount()
+ {
+ if (_cchStringData == s_cchUnknown)
+ {
+ _cchStringData = _pszStringData ? wcslen(_pszStringData) : 0;
+ }
+ }
+
+ HRESULT _EnsureCapacity(size_t cchDesired)
+ {
+ size_t cchCapacityCur;
+ HRESULT hr = SizeTAdd(cchDesired, 1, &cchCapacityCur);
+ if (SUCCEEDED(hr))
+ {
+ if (_cchStringDataCapacity == s_cchUnknown)
+ {
+ _EnsureCount();
+ _cchStringDataCapacity = _pszStringData ? _cchStringData + 1 : 0;
+ }
+ if (_cchStringDataCapacity == 0) // First allocation
+ {
+ size_t cbDesired;
+ hr = SizeTMult(cchCapacityCur, sizeof(WCHAR), &cbDesired);
+ if (SUCCEEDED(hr))
+ {
+ WCHAR* pvArrayT = Allocator::Alloc(cbDesired);
+ hr = pvArrayT ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ _cchStringDataCapacity = cchCapacityCur;
+ _pszStringData = pvArrayT;
+ pvArrayT[0] = 0;
+ }
+ }
+ }
+ else if (cchCapacityCur > _cchStringDataCapacity) // Growing
+ {
+ size_t celemNew;
+ hr = SizeTMult(_cchStringDataCapacity, 2, &celemNew); // Double the capacity
+ if (SUCCEEDED(hr))
+ {
+ if (celemNew - _cchStringDataCapacity > 2048)
+ celemNew = _cchStringDataCapacity + 2048; // Make sure it doesn't grow too much; TODO Check disassembly
+ if (cchCapacityCur <= celemNew)
+ cchCapacityCur = celemNew;
+ WCHAR* pvArrayT = Allocator::Realloc(_pszStringData, sizeof(WCHAR) * cchCapacityCur);
+ hr = pvArrayT ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ _cchStringDataCapacity = cchCapacityCur;
+ _pszStringData = pvArrayT;
+ }
+ }
+ }
+ }
+ return hr;
+ }
+
+ bool _IsEmpty() const
+ {
+ return !_pszStringData || !_pszStringData[0];
+ }
+
+ HRESULT _Initialize(const WCHAR* psz, size_t cch)
+ {
+ size_t cchDesired = cch;
+ size_t cchStringData;
+ HRESULT hr = S_OK;
+ if (psz)
+ {
+ if (cchDesired == s_cchUnknown)
+ {
+ cchDesired = wcslen(psz);
+ cchStringData = cchDesired;
+ }
+ else
+ {
+ cchStringData = _NativeString_Min(cchDesired, wcslen(psz)); // @MOD Prevent double evaluation
+ }
+ hr = _EnsureCapacity(cchDesired);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyNW(_pszStringData, cchDesired + 1, psz, cchStringData);
+ _cchStringData = cchStringData;
+ }
+ }
+ else
+ {
+ _Free();
+ }
+ return hr;
+ }
+
+ template
+ HRESULT _InitializeHelper(const WCHAR* pszFormat, va_list argList, const T& callback)
+ {
+ HRESULT hr;
+ size_t cchCapacityGuess = 32;
+ do
+ {
+ hr = _EnsureCapacity(cchCapacityGuess);
+ if (SUCCEEDED(hr))
+ {
+ hr = callback(pszFormat, argList, _pszStringData, _cchStringDataCapacity);
+ if (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
+ {
+ size_t cchCapacityT;
+ hr = SizeTAdd(_cchStringDataCapacity, 32, &cchCapacityT);
+ if (SUCCEEDED(hr))
+ {
+ cchCapacityGuess = cchCapacityT;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ while (SUCCEEDED(hr));
+ if (SUCCEEDED(hr))
+ {
+ _cchStringData = s_cchUnknown;
+ }
+ else
+ {
+ _Free();
+ }
+ return hr;
+ }
+
+ HRESULT _InitializeFromRegistry(HKEY hKey, const WCHAR* pszValueName, bool fExpand)
+ {
+ DWORD dwType;
+ DWORD cbT = 0;
+ LSTATUS lRes = RegQueryValueExW(hKey, pszValueName, nullptr, &dwType, nullptr, &cbT);
+ HRESULT hr = HRESULT_FROM_WIN32(lRes);
+ if (SUCCEEDED(hr) && ((dwType != REG_SZ && dwType != REG_EXPAND_SZ) || cbT == 0 || (cbT & 1) != 0))
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
+ }
+
+ WCHAR* pszT = nullptr;
+ if (SUCCEEDED(hr))
+ {
+ pszT = Allocator::Alloc(cbT);
+ hr = pszT ? S_OK : E_OUTOFMEMORY;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ lRes = RegQueryValueExW(hKey, pszValueName, nullptr, &dwType, (LPBYTE)pszT, &cbT);
+ hr = HRESULT_FROM_WIN32(lRes);
+ }
+
+ DWORD cchT = 0;
+ if (SUCCEEDED(hr))
+ {
+ cchT = (cbT / sizeof(WCHAR)) - 1;
+ if (dwType == REG_EXPAND_SZ && fExpand)
+ {
+ DWORD cchBuffer = ExpandEnvironmentStringsW(pszT, nullptr, 0);
+ if (cchBuffer != 0)
+ {
+ WCHAR* pszExpand = Allocator::Alloc(sizeof(WCHAR) * cchBuffer);
+ hr = pszExpand ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr))
+ {
+ DWORD cchResult = ExpandEnvironmentStringsW(pszT, pszExpand, cchBuffer);
+ hr = ResultFromWin32Count(cchResult, cchBuffer);
+ if (SUCCEEDED(hr))
+ {
+ Allocator::Free(pszT);
+ pszT = pszExpand;
+ cchT = cchResult - 1;
+ }
+ else
+ {
+ Allocator::Free(pszExpand);
+ }
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (!pszT[cchT])
+ {
+ _Attach(pszT, cchT + 1);
+ pszT = nullptr;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
+ }
+ }
+
+ Allocator::Free(pszT);
+ return hr;
+ }
+
+ size_t _GetCount()
+ {
+ _EnsureCount();
+ return _cchStringData;
+ }
+
+ size_t _GetCount() const
+ {
+ if (_cchStringData != s_cchUnknown)
+ return _cchStringData;
+ return _pszStringData ? wcslen(_pszStringData) : 0;
+ }
+
+ const WCHAR* _Get() const
+ {
+ return _pszStringData;
+ }
+
+ HRESULT _Concat(const WCHAR c)
+ {
+ WCHAR sz[2] = { c, 0 };
+ return _Concat(sz, 1);
+ }
+
+ HRESULT _Concat(const WCHAR* psz, const size_t cch)
+ {
+ HRESULT hr = S_OK;
+ if (psz)
+ {
+ _EnsureCount();
+ hr = _EnsureCapacity(cch + _cchStringData);
+ if (SUCCEEDED(hr))
+ {
+ StringCchCopyNW(&_pszStringData[_cchStringData], cch + 1, psz, cch);
+ _cchStringData += cch;
+ }
+ }
+ return hr;
+ }
+
+ HRESULT _ConcatMayTruncate(const WCHAR* psz, size_t cchMaxCapacity)
+ {
+ _EnsureCount();
+ HRESULT hr = S_OK;
+ if (cchMaxCapacity > _cchStringData)
+ {
+ size_t cchDesired = _NativeString_Min(cchMaxCapacity - _cchStringData, wcslen(psz)); // @MOD Prevent double evaluation
+ hr = _Concat(psz, cchDesired);
+ }
+ else if (cchMaxCapacity < _cchStringData)
+ {
+ _cchStringData = cchMaxCapacity;
+ _pszStringData[cchMaxCapacity] = 0;
+ }
+ return hr;
+ }
+
+ bool _RemoveAt(size_t iElem, size_t cchElem)
+ {
+ _EnsureCount();
+
+ bool fRet = false;
+
+ if (iElem < _cchStringData)
+ {
+ cchElem = _NativeString_Min(cchElem, _cchStringData - iElem); // @MOD Prevent double evaluation
+ if (cchElem)
+ {
+ memmove(&_pszStringData[iElem], &_pszStringData[iElem + cchElem], sizeof(WCHAR) * (_cchStringData - iElem - cchElem));
+ _cchStringData -= cchElem;
+ }
+ _pszStringData[_cchStringData] = 0;
+ fRet = true;
+ }
+
+ return fRet;
+ }
+
+ bool _TrimStart(const WCHAR* pszTrim)
+ {
+ _EnsureCount();
+
+ bool fNeedsTrimming = false;
+
+ size_t cch;
+ for (cch = 0; cch < _cchStringData; ++cch)
+ {
+ if (!wcschr(pszTrim, _pszStringData[cch]))
+ break;
+ }
+
+ if (cch)
+ {
+ fNeedsTrimming = true;
+ memmove(_pszStringData, &_pszStringData[cch], sizeof(WCHAR) * (_cchStringData - cch) + sizeof(WCHAR));
+ _cchStringData -= cch;
+ }
+
+ return fNeedsTrimming;
+ }
+
+ bool _TrimEnd(const WCHAR* pszTrim)
+ {
+ _EnsureCount();
+
+ size_t cch;
+ for (cch = _cchStringData; cch; --cch)
+ {
+ if (!wcschr(pszTrim, _pszStringData[cch - 1]))
+ break;
+ }
+
+ bool fNeedsTrimming = false;
+
+ if (cch != _cchStringData)
+ {
+ fNeedsTrimming = true;
+ _pszStringData[cch] = 0;
+ _cchStringData = cch;
+ }
+
+ return fNeedsTrimming;
+ }
+
+ void _Free()
+ {
+ if (_pszStringData)
+ {
+ Allocator::Free(_pszStringData);
+ _pszStringData = nullptr;
+ }
+ _cchStringData = 0;
+ _cchStringDataCapacity = 0;
+ }
+
+ void _Attach(WCHAR* psz)
+ {
+ return _Attach(psz, wcslen(psz) + 1);
+ }
+
+ void _Attach(WCHAR* psz, const size_t cch)
+ {
+ _Free();
+ if (psz && cch)
+ {
+ _pszStringData = psz;
+ _cchStringData = cch - 1;
+ _cchStringDataCapacity = cch;
+ psz[cch - 1] = 0;
+ }
+ }
+
+ WCHAR* _Detach()
+ {
+ WCHAR* pszStringData = _pszStringData;
+ _pszStringData = nullptr;
+ _cchStringData = 0;
+ _cchStringDataCapacity = 0;
+ return pszStringData;
+ }
+
+ WCHAR** _FreeAndGetAddressOf()
+ {
+ _Free();
+ _cchStringData = s_cchUnknown;
+ _cchStringDataCapacity = s_cchUnknown;
+ return &_pszStringData;
+ }
+
+ static const size_t s_cchUnknown = -1;
+
+ WCHAR* _pszStringData;
+ size_t _cchStringData;
+ size_t _cchStringDataCapacity;
+
+ template
+ static FORCEINLINE constexpr const T& (_NativeString_Min)(const T& a, const T& b)
+ {
+ return a < b ? a : b;
+ }
+ };
+}
+
+typedef Windows::Internal::NativeString> CoTaskMemNativeString;
diff --git a/ExplorerPatcher/inc/RefCountedObject.h b/ExplorerPatcher/inc/RefCountedObject.h
new file mode 100644
index 0000000..08670dd
--- /dev/null
+++ b/ExplorerPatcher/inc/RefCountedObject.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include
+
+template
+class CRefCountedObject : public IUnknown, public T
+{
+public:
+ template
+ CRefCountedObject(TArgs&& ...args)
+ : T(std::forward(args)...)
+ , _cRef(0)
+ {
+ }
+
+ virtual ~CRefCountedObject()
+ {
+ }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject) override
+ {
+ *ppvObject = nullptr;
+ return E_NOTIMPL;
+ }
+
+ STDMETHODIMP_(ULONG) AddRef() override
+ {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ STDMETHODIMP_(ULONG) Release() override
+ {
+ ULONG refCount = InterlockedDecrement(&_cRef);
+ if (refCount == 0)
+ delete this;
+ return refCount;
+ }
+
+ ULONG _cRef;
+};
+
+template
+Microsoft::WRL::ComPtr> CreateRefCountedObj(TArgs&& ...args)
+{
+ return new(std::nothrow) CRefCountedObject(std::forward(args)...);
+}
diff --git a/ExplorerPatcher/inc/ResultUtils.h b/ExplorerPatcher/inc/ResultUtils.h
new file mode 100644
index 0000000..c8ec6c4
--- /dev/null
+++ b/ExplorerPatcher/inc/ResultUtils.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+
+inline HRESULT ResultFromWin32(__in DWORD dwErr)
+{
+ return HRESULT_FROM_WIN32(dwErr);
+}
+
+inline HRESULT ResultFromLastError()
+{
+ return ResultFromWin32(GetLastError());
+}
+
+inline HRESULT ResultFromKnownLastError()
+{
+ HRESULT hr = ResultFromLastError();
+ return (SUCCEEDED(hr) ? E_FAIL : hr);
+}
+
+inline HRESULT ResultFromWin32Bool(BOOL b)
+{
+ return b ? S_OK : ResultFromKnownLastError();
+}
+
+inline HRESULT ResultFromWin32Count(UINT cchResult, UINT cchBuffer)
+{
+ return cchResult && cchResult <= cchBuffer ? S_OK : ResultFromWin32(ERROR_INSUFFICIENT_BUFFER);
+}
diff --git a/ExplorerPatcher/inc/SimpleArray.h b/ExplorerPatcher/inc/SimpleArray.h
new file mode 100644
index 0000000..e89abd3
--- /dev/null
+++ b/ExplorerPatcher/inc/SimpleArray.h
@@ -0,0 +1,583 @@
+#pragma once
+
+#include
+#include
+
+#include "ContainerPolicies.h"
+
+template
+class CSimpleArrayStandardCompareHelper
+{
+public:
+ int Compare(const T& t1, const T& t2) const
+ {
+ return t2 == t1 ? 0 : t2 < t1 ? 1 : -1;
+ }
+};
+
+class CSimpleArrayCaseInsensitiveOrdinalStringCompareHelper
+{
+public:
+ int Compare(const WCHAR* psz1, const WCHAR* psz2) const
+ {
+ return CompareStringOrdinal(psz1, -1, psz2, -1, TRUE) - CSTR_EQUAL;
+ }
+};
+
+template
+class CSimpleArrayStandardMergeHelper
+{
+};
+
+template <
+ typename T,
+ typename CompareHelper
+>
+class CTSimpleFixedArray
+{
+public:
+ T* _parray;
+ size_t _celem;
+
+ CTSimpleFixedArray()
+ : _parray(nullptr)
+ , _celem(0)
+ {
+ }
+
+ size_t GetSize() const { return _celem; }
+
+ T& operator[](size_t iElem) { return _parray[iElem]; }
+ const T& operator[](size_t iElem) const { return _parray[iElem]; }
+
+ HRESULT GetAt(size_t iElem, T& tOut) const
+ {
+ HRESULT hr = TYPE_E_OUTOFBOUNDS;
+ if (iElem < _celem)
+ {
+ tOut = _parray[iElem];
+ hr = S_OK;
+ }
+ return hr;
+ }
+
+ T* GetData() const { return _parray; }
+ T* begin() { return _parray; }
+ T* begin() const { return _parray; }
+ T* end() { return _parray + _celem; }
+ T* end() const { return _parray + _celem; }
+
+ HRESULT Find(const T& t, size_t* piElem, size_t iStartAt = 0) const
+ {
+ return FindEx(CompareHelper(), t, piElem, iStartAt);
+ }
+
+ template
+ HRESULT FindEx(const Comparer& tcompare, const T& t, size_t* piElem, size_t iStartAt = 0) const
+ {
+ *piElem = 0;
+ for (size_t i = iStartAt; i < _celem; ++i)
+ {
+ if (tcompare.Compare(_parray[i], t) == 0)
+ {
+ *piElem = i;
+ return S_OK;
+ }
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+ }
+
+ HRESULT BinarySearch(const T& t, size_t* piElem) const
+ {
+ return BinarySearchEx(CompareHelper(), t, piElem);
+ }
+
+ template
+ HRESULT BinarySearchEx(const Comparer& tcompare, const T& t, size_t* piElem) const
+ {
+ *piElem = 0;
+
+ HRESULT hr = TYPE_E_ELEMENTNOTFOUND;
+
+ if (_celem != 0)
+ {
+ hr = S_OK;
+
+ size_t iLow = 0;
+ size_t iHigh = _celem - 1;
+ while (true)
+ {
+ size_t iMid = (iLow + iHigh) / 2;
+
+ int compare = tcompare.Compare(_parray[iMid], t);
+ if (compare > 0)
+ {
+ if (iMid != 0)
+ {
+ iHigh = iMid - 1;
+ }
+ else
+ {
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ }
+ }
+ else if (compare < 0)
+ {
+ iLow = iMid + 1;
+ }
+ else
+ {
+ for (; iMid != 0; --iMid)
+ {
+ if (tcompare.Compare(_parray[iMid - 1], t) != 0)
+ break;
+ }
+ *piElem = iMid;
+ break;
+ }
+
+ if (iHigh < iLow)
+ hr = TYPE_E_ELEMENTNOTFOUND;
+
+ if (FAILED(hr))
+ {
+ *piElem = compare < 0 ? iLow : iMid;
+ break;
+ }
+ }
+ }
+
+ return hr;
+ }
+
+ template
+ void ForEach(const TCallback& callback) const // @MOD Pass callback by reference
+ {
+ for (size_t iElement = 0; iElement < _celem; ++iElement)
+ {
+ callback(iElement, _parray[iElement]);
+ }
+ }
+};
+
+template <
+ typename T,
+ size_t MaxSize,
+ typename Allocator,
+ typename CompareHelper,
+ typename MergeHelper = CSimpleArrayStandardMergeHelper
+>
+class CTSimpleArray : public CTSimpleFixedArray
+{
+public:
+ T* _parrayT;
+ size_t _celemCapacity;
+
+ CTSimpleArray()
+ : CTSimpleFixedArray()
+ , _parrayT(nullptr)
+ , _celemCapacity(0)
+ {
+ }
+
+ ~CTSimpleArray()
+ {
+ RemoveAll();
+ }
+
+ HRESULT Add(const T& t, size_t* piElemInsertedAt = nullptr)
+ {
+ return _Add(t, piElemInsertedAt);
+ }
+
+ HRESULT Add(T&& t, size_t* piElemInsertedAt = nullptr)
+ {
+ return _Add(std::move(t), piElemInsertedAt);
+ }
+
+ HRESULT InsertAt(const T& t, size_t iElem)
+ {
+ return _InsertAt(t, iElem);
+ }
+
+ HRESULT InsertAt(T&& t, size_t iElem)
+ {
+ return _InsertAt(std::move(t), iElem);
+ }
+
+ HRESULT SetAtIndex(size_t iElem, const T& t)
+ {
+ return _SetAtIndex(iElem, t);
+ }
+
+ HRESULT SetAtIndex(size_t iElem, T&& t)
+ {
+ return _SetAtIndex(iElem, std::move(t));
+ }
+
+ HRESULT Remove(const T& t, size_t* piElemRemovedAt = nullptr)
+ {
+ if (piElemRemovedAt)
+ *piElemRemovedAt = 0;
+
+ size_t iElem;
+ HRESULT hr = this->Find(t, &iElem);
+ if (SUCCEEDED(hr))
+ {
+ hr = RemoveAt(iElem);
+ if (SUCCEEDED(hr) && piElemRemovedAt)
+ {
+ *piElemRemovedAt = iElem;
+ }
+ }
+
+ return hr;
+ }
+
+ HRESULT RemoveAt(size_t iElem)
+ {
+ if (iElem >= this->_celem)
+ return TYPE_E_OUTOFBOUNDS;
+ if constexpr (!std::is_trivially_destructible_v)
+ this->_parray[iElem].~T();
+ if (iElem != this->_celem - 1)
+ memmove(std::addressof(this->_parray[iElem]), std::addressof(this->_parray[iElem + 1]), sizeof(T) * (this->_celem - iElem - 1));
+ --this->_celem;
+ return S_OK;
+ }
+
+ void RemoveAll()
+ {
+ if (this->_parray)
+ {
+ if constexpr (!std::is_trivially_destructible_v)
+ {
+ for (size_t i = 0; i < this->_celem; ++i)
+ this->_parray[i].~T();
+ }
+ Allocator::Destroy(this->_parray);
+ this->_parray = nullptr;
+ }
+ this->_celem = 0;
+ _celemCapacity = 0;
+ }
+
+ void TransferData(CTSimpleArray* other)
+ {
+ RemoveAll();
+ this->_parray = other->_parray;
+ this->_celem = other->_celem;
+ this->_parrayT = other->_parrayT;
+ this->_celemCapacity = other->_celemCapacity;
+ other->_parray = nullptr;
+ other->_celem = 0;
+ other->_parrayT = nullptr;
+ other->_celemCapacity = 0;
+ }
+
+ size_t GetCapacity() const
+ {
+ return _celemCapacity;
+ }
+
+ HRESULT Sort()
+ {
+ return SortEx(CompareHelper());
+ }
+
+ template
+ HRESULT SortEx(const Comparer& tcompare)
+ {
+ HRESULT hr = S_OK;
+
+ if (this->_celem > 1)
+ {
+ _parrayT = nullptr;
+ hr = Allocator::ReallocArray(nullptr, this->_celem / 2, &_parrayT);
+ if (SUCCEEDED(hr))
+ {
+ _MergeSort(tcompare, 0, this->_celem);
+ Allocator::Destroy(_parrayT);
+ _parrayT = nullptr;
+ }
+ }
+
+ return hr;
+ }
+
+ HRESULT _EnsureCapacity(size_t celemCapacityDesired, size_t celemMaxCapacity = 4096)
+ {
+ HRESULT hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ if (celemCapacityDesired > MaxSize)
+ return hr;
+
+ // If we have enough capacity, we're done
+ hr = S_OK;
+ size_t celemCapacityCur = _celemCapacity;
+ if (celemCapacityDesired <= celemCapacityCur)
+ return hr;
+
+ // Double the capacity
+ size_t celemCapacityT;
+ hr = SizeTMult(celemCapacityCur, 2, &celemCapacityT);
+ if (FAILED(hr))
+ return hr;
+
+ // Make sure we don't grow too much
+ celemCapacityT = celemCapacityT - celemCapacityCur > celemMaxCapacity ? celemCapacityCur + celemMaxCapacity : celemCapacityT;
+
+ // Cap at desired capacity and max capacity
+ celemCapacityT = celemCapacityDesired > celemCapacityT || celemCapacityT <= MaxSize ? max(celemCapacityDesired, celemCapacityT) : MaxSize;
+
+ // Realloc
+ T* pvArrayT;
+ hr = Allocator::ReallocArray(this->_parray, celemCapacityT, &pvArrayT);
+ if (FAILED(hr))
+ return hr;
+
+ _celemCapacity = celemCapacityT;
+ this->_parray = pvArrayT;
+
+ return hr;
+ }
+
+ HRESULT _MakeRoomAt(size_t iElem)
+ {
+ HRESULT hr = S_OK;
+
+ size_t cElemGrowTo = max(this->_celem, iElem) + 1;
+ if (cElemGrowTo > _celemCapacity)
+ {
+ hr = _EnsureCapacity(cElemGrowTo);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (iElem < this->_celem)
+ memmove(std::addressof(this->_parray[iElem + 1]), std::addressof(this->_parray[iElem]), sizeof(T) * (this->_celem - iElem));
+ this->_celem = cElemGrowTo;
+ }
+
+ return hr;
+ }
+
+ template
+ void _InternalSetAtIndex(size_t iElem, ArgType&& t)
+ {
+ T* newPos = std::addressof(this->_parray[iElem]);
+ if (newPos)
+ new(newPos) T(std::forward(t));
+ }
+
+ template
+ HRESULT _Add(ArgType&& t, size_t* piElemInsertedAt)
+ {
+ if (piElemInsertedAt)
+ *piElemInsertedAt = 0;
+
+ HRESULT hr = S_OK;
+
+ if (this->_celem == _celemCapacity)
+ {
+ hr = _EnsureCapacity(_celemCapacity + 1);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ _InternalSetAtIndex(this->_celem++, std::forward(t));
+ if (piElemInsertedAt)
+ *piElemInsertedAt = this->_celem - 1;
+ }
+
+ return hr;
+ }
+
+ template
+ HRESULT _InsertAt(ArgType&& t, size_t iElem)
+ {
+ HRESULT hr = _MakeRoomAt(iElem);
+
+ if (SUCCEEDED(hr))
+ {
+ _InternalSetAtIndex(iElem, std::forward(t));
+ }
+
+ return hr;
+ }
+
+ template
+ HRESULT _SetAtIndex(size_t iElem, ArgType&& t)
+ {
+ HRESULT hr = TYPE_E_OUTOFBOUNDS;
+
+ if (iElem < this->_celem)
+ {
+ _InternalSetAtIndex(iElem, std::forward(t));
+ hr = S_OK;
+ }
+
+ return hr;
+ }
+
+ template
+ void _MergeThem(const Comparer& tcompare, size_t iFirst, size_t cElems)
+ {
+ size_t cHalf = cElems / 2;
+ T* parraySrc = &this->_parray[iFirst];
+ memcpy(_parrayT, parraySrc, sizeof(T) * cHalf);
+
+ size_t iIn1 = 0;
+ size_t iIn2 = cHalf;
+ size_t iOut = 0;
+ bool fDone = false;
+ while (!fDone)
+ {
+ if (tcompare.Compare(_parrayT[iIn1], parraySrc[iIn2]) > 0)
+ {
+ memmove(&parraySrc[iOut], &parraySrc[iIn2], sizeof(T));
+ ++iOut;
+ if (++iIn2 == cElems)
+ {
+ memcpy(&parraySrc[iOut], &_parrayT[iIn1], sizeof(T) * (cElems - iOut));
+ fDone = true;
+ }
+ }
+ else
+ {
+ memmove(&parraySrc[iOut], &_parrayT[iIn1], sizeof(T));
+ ++iOut;
+ if (++iIn1 == cHalf)
+ {
+ fDone = true;
+ }
+ }
+ }
+ }
+
+ template
+ void _MergeSort(const Comparer& tcompare, size_t iFirst, size_t cElems)
+ {
+ if (cElems == 1)
+ return;
+
+ if (cElems == 2)
+ {
+ if (tcompare.Compare(this->_parray[iFirst], this->_parray[iFirst + 1]) > 0)
+ {
+ memmove(_parrayT, &this->_parray[iFirst], sizeof(T));
+ memmove(&this->_parray[iFirst], &this->_parray[iFirst + 1], sizeof(T));
+ memmove(&this->_parray[iFirst + 1], _parrayT, sizeof(T));
+ }
+ }
+ else
+ {
+ size_t cHalf = cElems >> 1;
+ _MergeSort(tcompare, iFirst, cHalf);
+ _MergeSort(tcompare, iFirst + cHalf, cElems - cHalf);
+ _MergeThem(tcompare, iFirst, cElems);
+ }
+ }
+};
+
+template <
+ typename T,
+ size_t MaxSize = UINT_MAX - 1,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CCoSimpleArray : public CTSimpleArray, CompareHelper>
+{
+public:
+ CCoSimpleArray()
+ {
+ }
+
+ CCoSimpleArray(CCoSimpleArray&& other) noexcept
+ {
+ this->TransferData(&other);
+ }
+
+ CCoSimpleArray& operator=(CCoSimpleArray&& other) noexcept
+ {
+ if (this != &other)
+ {
+ this->TransferData(&other);
+ }
+ return *this;
+ }
+};
+
+template <
+ typename T,
+ size_t MaxSize = UINT_MAX - 1,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CLocalSimpleArray : public CTSimpleArray, CompareHelper>
+{
+};
+
+template <
+ typename T,
+ typename ElementAllocator,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CSimplePointerArray : public CCoSimpleArray
+{
+public:
+ ~CSimplePointerArray()
+ {
+ RemoveAndReleaseAll();
+ }
+
+ HRESULT RemoveAndReleaseAt(size_t iElem)
+ {
+ T* pT;
+ HRESULT hr = this->GetAt(iElem, pT);
+ if (SUCCEEDED(hr))
+ {
+ hr = this->RemoveAt(iElem);
+ if (SUCCEEDED(hr))
+ {
+ ElementAllocator::Destroy(pT);
+ }
+ }
+ return hr;
+ }
+
+ void RemoveAndReleaseAll()
+ {
+ for (size_t i = 0; i < this->_celem; ++i)
+ {
+ ElementAllocator::Destroy(this->_parray[i]);
+ }
+ this->RemoveAll();
+ }
+};
+
+template <
+ typename T,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CSimplePointerArrayNewMem : public CSimplePointerArray
+{
+};
+
+template <
+ typename T,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CSimplePointerArrayCoTaskMem : public CSimplePointerArray, CompareHelper>
+{
+};
+
+template <
+ typename T,
+ typename CompareHelper = CSimpleArrayStandardCompareHelper
+>
+class CSimplePointerArrayLocalMem : public CSimplePointerArray, CompareHelper>
+{
+};
+
+template
+class CSimplePointerArrayRelease : public CSimplePointerArray>
+{
+};
diff --git a/ExplorerPatcher/inc/memsafe.h b/ExplorerPatcher/inc/memsafe.h
new file mode 100644
index 0000000..6896e00
--- /dev/null
+++ b/ExplorerPatcher/inc/memsafe.h
@@ -0,0 +1,720 @@
+// Downloaded from:
+// https://github.com/namealt/winsdk10/blob/d1acc505c51b11a6ceafb0f93c9dc584b8b4a9d3/Include/10.0.16299.0/um/memsafe.h
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+#if (_MSC_VER > 1000)
+#pragma once
+#endif
+
+#ifndef __memsafe_h__
+#define __memsafe_h__
+
+#ifdef __cplusplus
+
+//
+// Various heap allocation helpers, featuring
+// - Fully annotated
+// - HRESULT return values
+// - Integer overflow checks via intsafe.h
+// - Type safety via templates (no typecasting required)
+// - Zero initialization
+//
+// CoAllocBytes
+// CoReallocBytes
+// CoAllocObject
+// CoAllocArray
+// CoReallocArray
+//
+// CoAllocString
+// CoAllocStringLen
+// CoAllocStringDoubleNullTerminate
+// CoAllocStringOpt
+//
+// LocalAllocBytes
+// LocalReallocBytes
+// LocalAllocObject
+// LocalAllocArray
+// LocalReallocArray
+//
+// LocalAllocString
+// LocalAllocStringLen
+// LocalAllocStringDoubleNullTerminate
+// LocalAllocStringOpt
+//
+// HeapAllocBytes
+// HeapReallocBytes
+// HeapAllocObject
+// HeapAllocArray
+// HeapReallocArray
+//
+// HeapAllocString
+// HeapAllocStringLen
+// HeapAllocStringDoubleNullTerminate
+// HeapAllocStringOpt
+//
+// GlobalAllocBytes
+// GlobalReallocBytes
+// GlobalAllocObject
+// GlobalAllocArray
+// GlobalReallocArray
+//
+// GlobalAllocString
+// GlobalAllocStringLen
+// GlobalAllocStringDoubleNullTerminate
+// GlobalAllocStringOpt
+//
+
+#include
+#include
+
+// Flag for inhibiting zero-initialization
+#define NO_ZERO_INIT 0x00000000
+
+// Templates for isolating T* <--> void* conversions and integer arithmetic
+
+template
+ inline HRESULT _AllocBytes(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return TAllocPolicy::Alloc(hHeap, dwFlags, cb, (void**)ppv);
+}
+
+template
+inline HRESULT _ReallocBytes(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return TAllocPolicy::Realloc(hHeap, dwFlags, pv, cb, (void**)ppv);
+}
+
+template
+inline HRESULT _AllocArray(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ *ppv = NULL;
+ size_t cb;
+ HRESULT hr = SizeTMult(cItems, sizeof(T), &cb);
+ if (SUCCEEDED(hr))
+ {
+ hr = TAllocPolicy::Alloc(hHeap, dwFlags, cb, (void**)ppv);
+ }
+ return hr;
+}
+
+template
+inline HRESULT _ReallocArray(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ *ppv = NULL;
+ size_t cb;
+ HRESULT hr = SizeTMult(cItems, sizeof(T), &cb);
+ if (SUCCEEDED(hr))
+ {
+ hr = TAllocPolicy::Realloc(hHeap, dwFlags, pv, cb, (void**)ppv);
+ }
+ return hr;
+}
+
+// Templates for isolating string-specific functionality
+
+template
+inline HRESULT _AllocStringWorker(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_reads_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _In_ size_t cchExtra, _Outptr_result_buffer_(cch+cchExtra) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ *ppsz = NULL;
+ size_t cchTotal;
+ HRESULT hr = SizeTAdd(cch, cchExtra, &cchTotal);
+ if (SUCCEEDED(hr))
+ {
+ // Note that we do not require dwFlags to include the allocator-specific
+ // zero-initialization flag here.
+ hr = _AllocArray(hHeap, dwFlags, cchTotal, ppsz);
+ if (SUCCEEDED(hr))
+ {
+ // The source string may be shorter than cch, so zero-initialize
+ // the entire buffer using STRSAFE_FILL_BEHIND_NULL.
+ //
+ // Note that _AllocStringDoubleNullTerminate relies on
+ // zero-initialization to provide the 2nd NULL terminator.
+ StringCchCopyNExW(*ppsz, cchTotal, pszSource, cch, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL);
+ }
+ }
+ return hr;
+}
+
+template
+inline HRESULT _AllocString(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ // pszSource must be valid (non-NULL)
+ return _AllocStringWorker(hHeap, dwFlags, pszSource, wcslen(pszSource), 1, ppsz);
+}
+
+template
+inline HRESULT _AllocStringLen(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_reads_or_z_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ // pszSource is optional (may be NULL)
+ return _AllocStringWorker(hHeap, dwFlags, pszSource, cch, 1, ppsz);
+}
+
+// Takes a single-null terminated string and allocates a double-null terminated string.
+template
+inline HRESULT _AllocStringDoubleNullTerminate(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz)
+{
+ // pszSource must be valid (non-NULL)
+ return _AllocStringWorker(hHeap, dwFlags, pszSource, wcslen(pszSource), 2, ppsz);
+}
+
+template
+inline HRESULT _AllocStringOpt(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ // pszSource is optional (may be NULL)
+ if (pszSource != NULL)
+ {
+ return _AllocString(hHeap, dwFlags, pszSource, ppsz);
+ }
+ *ppsz = NULL;
+ return S_OK;
+}
+
+#ifndef NO_COALLOC_HELPERS
+
+#include
+
+// CoTaskMemAlloc does not zero-initialize by default. Define a flag to enable
+// zero-init behavior.
+#define CO_MEM_ZERO_INIT 0x00000001
+
+class CTCoAllocPolicy
+{
+private:
+#if (NTDDI_VERSION < NTDDI_WIN10_RS1) || defined(COM_SUPPORT_MALLOC_SPIES)
+ static size_t _CoTaskMemSize(_In_ _Post_writable_byte_size_(return) void *pv)
+ {
+ size_t cb = 0;
+ IMalloc *pMalloc;
+ if (SUCCEEDED(CoGetMalloc(1, &pMalloc))) // should never fail (static v-table)
+ {
+ // Returns (size_t)-1 if pv is NULL.
+ // Result is indeterminate if pv does not belong to CoTaskMemAlloc.
+ cb = pMalloc->GetSize(pv);
+ pMalloc->Release();
+ }
+ return cb;
+ }
+#endif
+
+public:
+ static HRESULT Alloc(_In_opt_ HANDLE /*hHeap*/, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ *ppv = CoTaskMemAlloc(cb);
+ if (*ppv)
+ {
+ if (dwFlags & CO_MEM_ZERO_INIT)
+ {
+#ifdef COM_SUPPORT_MALLOC_SPIES
+ // Zero-initialize the buffer
+ // The actual size might be larger than cb due to spies present.
+ // Initialize to the actual size in case of realloc later,
+ // or there might be an uninitialized gap in between.
+ size_t cbActual = _CoTaskMemSize(*ppv);
+ ZeroMemory(*ppv, cbActual);
+#else
+ ZeroMemory(*ppv, cb);
+#endif
+ }
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+ }
+
+ static HRESULT Realloc(_In_opt_ HANDLE /*hHeap*/, _In_ DWORD dwFlags, _In_opt_ void *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+#if (NTDDI_VERSION < NTDDI_WIN10_RS1)
+ size_t cbKeepIntact = 0;
+
+ if (pv && (dwFlags & CO_MEM_ZERO_INIT))
+ {
+ // Get the current size, so we know how much to zero-initialize
+ cbKeepIntact = _CoTaskMemSize(pv);
+ if (cb < cbKeepIntact)
+ {
+ // Shrinking the buffer, only keep the new size
+ cbKeepIntact = cb;
+ }
+ }
+#else
+ // As of Redstone CoTaskMemRealloc always zero-initializes
+ // the tail of the allocation.
+ size_t cbKeepIntact = cb;
+#endif
+
+ // If pv is NULL, CoTaskMemRealloc allocates a new block
+ *ppv = CoTaskMemRealloc(pv, cb);
+
+ if (*ppv)
+ {
+ if (dwFlags & CO_MEM_ZERO_INIT)
+ {
+ // Zero-initialize the trailing part of the buffer
+#ifdef COM_SUPPORT_MALLOC_SPIES
+ // The actual size might be larger than cb due to due to spies present.
+ size_t cbActual = _CoTaskMemSize(*ppv);
+#else
+ size_t cbActual = cb;
+#endif
+ if (cbActual > cbKeepIntact)
+ {
+ ZeroMemory(((BYTE*)*ppv) + cbKeepIntact, cbActual - cbKeepIntact);
+ }
+ }
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+ }
+};
+
+// CoTaskMemAlloc helpers
+
+template
+ inline HRESULT CoAllocBytes(_In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, cb, ppv);
+}
+
+template
+inline HRESULT CoReallocBytes(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocBytes(NULL, dwFlags, pv, cb, ppv);
+}
+
+template
+inline HRESULT CoAllocObject(_In_ DWORD dwFlags, _Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, sizeof(T), ppv);
+}
+
+template
+inline HRESULT CoAllocArray(_In_ DWORD dwFlags, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocArray(NULL, dwFlags, cItems, ppv);
+}
+
+template
+inline HRESULT CoReallocArray(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocArray(NULL, dwFlags, pv, cItems, ppv);
+}
+
+// Zero-initializing CoTaskMemAlloc helpers
+
+template
+ inline HRESULT CoAllocBytes(_In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return CoAllocBytes(CO_MEM_ZERO_INIT, cb, ppv);
+}
+
+template
+inline HRESULT CoReallocBytes(_In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return CoReallocBytes(CO_MEM_ZERO_INIT, pv, cb, ppv);
+}
+
+template
+inline HRESULT CoAllocObject(_Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return CoAllocObject(CO_MEM_ZERO_INIT, ppv);
+}
+
+template
+inline HRESULT CoAllocArray(_In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return CoAllocArray(CO_MEM_ZERO_INIT, cItems, ppv);
+}
+
+template
+inline HRESULT CoReallocArray(_In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return CoReallocArray(CO_MEM_ZERO_INIT, pv, cItems, ppv);
+}
+
+// CoTaskMemAlloc string helpers
+
+inline HRESULT CoAllocString(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ return _AllocString(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT CoAllocStringLen( _In_reads_or_z_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringLen(NULL, NO_ZERO_INIT, pszSource, cch, ppsz);
+}
+
+inline HRESULT CoAllocStringDoubleNullTerminate(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz)
+{
+ return _AllocStringDoubleNullTerminate(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT CoAllocStringOpt(_In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringOpt(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+#endif // NO_COALLOC_HELPERS
+
+#ifndef NO_LOCALALLOC_HELPERS
+
+class CTLocalAllocPolicy
+{
+public:
+ static HRESULT Alloc(_In_opt_ HANDLE /*hHeap*/, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ // ignore flags other than zero-init, assume fixed
+ *ppv = LocalAlloc(LMEM_FIXED | (dwFlags & LMEM_ZEROINIT), cb);
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+
+ static HRESULT Realloc(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ void *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ if (pv == NULL)
+ {
+ return Alloc(hHeap, dwFlags, cb, ppv);
+ }
+
+ // LMEM_MOVEABLE is correct when reallocating LMEM_FIXED buffers
+ *ppv = LocalReAlloc(pv, cb, LMEM_MOVEABLE | (dwFlags & LMEM_ZEROINIT));
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+};
+
+// LocalAlloc helpers
+
+template
+ inline HRESULT LocalAllocBytes(_In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, cb, ppv);
+}
+
+template
+inline HRESULT LocalReallocBytes(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocBytes(NULL, dwFlags, pv, cb, ppv);
+}
+
+template
+inline HRESULT LocalAllocObject(_In_ DWORD dwFlags, _Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, sizeof(T), ppv);
+}
+
+template
+inline HRESULT LocalAllocArray(_In_ DWORD dwFlags, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocArray(NULL, dwFlags, cItems, ppv);
+}
+
+template
+inline HRESULT LocalReallocArray(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocArray(NULL, dwFlags, pv, cItems, ppv);
+}
+
+// Zero-initializing LocalAlloc helpers
+
+template
+ inline HRESULT LocalAllocBytes(_In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return LocalAllocBytes(LMEM_ZEROINIT, cb, ppv);
+}
+
+template
+inline HRESULT LocalReallocBytes(_In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return LocalReallocBytes(LMEM_ZEROINIT, pv, cb, ppv);
+}
+
+template
+inline HRESULT LocalAllocObject(_Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return LocalAllocObject(LMEM_ZEROINIT, ppv);
+}
+
+template
+inline HRESULT LocalAllocArray(_In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return LocalAllocArray(LMEM_ZEROINIT, cItems, ppv);
+}
+
+template
+inline HRESULT LocalReallocArray(_In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return LocalReallocArray(LMEM_ZEROINIT, pv, cItems, ppv);
+}
+
+// LocalAlloc string helpers
+
+inline HRESULT LocalAllocString(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ return _AllocString(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT LocalAllocStringLen( _In_reads_or_z_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringLen(NULL, NO_ZERO_INIT, pszSource, cch, ppsz);
+}
+
+inline HRESULT LocalAllocStringDoubleNullTerminate(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz) //todo sal 00?
+{
+ return _AllocStringDoubleNullTerminate(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT LocalAllocStringOpt(_In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringOpt(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+#endif // NO_LOCALALLOC_HELPERS
+
+#ifndef NO_HEAPALLOC_HELPERS
+
+class CTHeapAllocPolicy
+{
+public:
+ static HRESULT Alloc(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ *ppv = HeapAlloc(hHeap, dwFlags, cb);
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+
+ static HRESULT Realloc(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ void *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ if (pv == NULL)
+ {
+ return Alloc(hHeap, dwFlags, cb, ppv);
+ }
+ *ppv = HeapReAlloc(hHeap, dwFlags, pv, cb);
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+};
+
+// HeapAlloc helpers
+
+template
+ inline HRESULT HeapAllocBytes(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(hHeap, dwFlags, cb, ppv);
+}
+
+template
+inline HRESULT HeapReallocBytes(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocBytes(hHeap, dwFlags, pv, cb, ppv);
+}
+
+template
+inline HRESULT HeapAllocObject(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(hHeap, dwFlags, sizeof(T), ppv);
+}
+
+template
+inline HRESULT HeapAllocArray(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocArray(hHeap, dwFlags, cItems, ppv);
+}
+
+template
+inline HRESULT HeapReallocArray(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocArray(hHeap, dwFlags, pv, cItems, ppv);
+}
+
+// Zero-initializing HeapAlloc helpers (process heap)
+
+template
+ inline HRESULT HeapAllocBytes(_In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return HeapAllocBytes(GetProcessHeap(), HEAP_ZERO_MEMORY, cb, ppv);
+}
+
+template
+inline HRESULT HeapReallocBytes(_In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return HeapReallocBytes(GetProcessHeap(), HEAP_ZERO_MEMORY, pv, cb, ppv);
+}
+
+template
+inline HRESULT HeapAllocObject(_Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return HeapAllocObject(GetProcessHeap(), HEAP_ZERO_MEMORY, ppv);
+}
+
+template
+inline HRESULT HeapAllocArray(_In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return HeapAllocArray(GetProcessHeap(), HEAP_ZERO_MEMORY, cItems, ppv);
+}
+
+template
+inline HRESULT HeapReallocArray(_In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return HeapReallocArray(GetProcessHeap(), HEAP_ZERO_MEMORY, pv, cItems, ppv);
+}
+
+// HeapAlloc string helpers
+
+inline HRESULT HeapAllocString(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ return _AllocString(hHeap, dwFlags, pszSource, ppsz);
+}
+
+inline HRESULT HeapAllocStringLen(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_reads_or_z_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringLen(hHeap, dwFlags, pszSource, cch, ppsz);
+}
+
+inline HRESULT HeapAllocStringDoubleNullTerminate(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz)
+{
+ return _AllocStringDoubleNullTerminate(hHeap, dwFlags, pszSource, ppsz);
+}
+
+inline HRESULT HeapAllocStringOpt(_In_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringOpt(hHeap, dwFlags, pszSource, ppsz);
+}
+
+// HeapAlloc string helpers (process heap)
+
+inline HRESULT HeapAllocString(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ return HeapAllocString(GetProcessHeap(), NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT HeapAllocStringLen(_In_reads_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return HeapAllocStringLen(GetProcessHeap(), NO_ZERO_INIT, pszSource, cch, ppsz);
+}
+
+inline HRESULT HeapAllocStringDoubleNullTerminate(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz)
+{
+ return HeapAllocStringDoubleNullTerminate(GetProcessHeap(), NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT HeapAllocStringOpt(_In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return HeapAllocStringOpt(GetProcessHeap(), NO_ZERO_INIT, pszSource, ppsz);
+}
+
+#endif // NO_HEAPALLOC_HELPERS
+
+#ifndef NO_GLOBALALLOC_HELPERS
+
+class CTGlobalAllocPolicy
+{
+public:
+ static HRESULT Alloc(_In_opt_ HANDLE /*hHeap*/, _In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ // ignore flags other than zero-init, assume fixed
+ *ppv = GlobalAlloc(GMEM_FIXED | (dwFlags & GMEM_ZEROINIT), cb);
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+
+ static HRESULT Realloc(_In_opt_ HANDLE hHeap, _In_ DWORD dwFlags, _In_opt_ void *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) void **ppv)
+ {
+ if (pv == NULL)
+ {
+ return Alloc(hHeap, dwFlags, cb, ppv);
+ }
+
+ // GMEM_MOVEABLE is correct when reallocating GMEM_FIXED buffers
+ *ppv = GlobalReAlloc(pv, cb, GMEM_MOVEABLE | (dwFlags & GMEM_ZEROINIT));
+ return (*ppv) ? S_OK : E_OUTOFMEMORY;
+ }
+};
+
+// GlobalAlloc helpers
+
+template
+ inline HRESULT GlobalAllocBytes(_In_ DWORD dwFlags, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, cb, ppv);
+}
+
+template
+inline HRESULT GlobalReallocBytes(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocBytes(NULL, dwFlags, pv, cb, ppv);
+}
+
+template
+inline HRESULT GlobalAllocObject(_In_ DWORD dwFlags, _Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocBytes(NULL, dwFlags, sizeof(T), ppv);
+}
+
+template
+inline HRESULT GlobalAllocArray(_In_ DWORD dwFlags, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _AllocArray(NULL, dwFlags, cItems, ppv);
+}
+
+template
+inline HRESULT GlobalReallocArray(_In_ DWORD dwFlags, _In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return _ReallocArray(NULL, dwFlags, pv, cItems, ppv);
+}
+
+// Zero-initializing GlobalAlloc helpers
+
+template
+ inline HRESULT GlobalAllocBytes(_In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return GlobalAllocBytes(GMEM_ZEROINIT, cb, ppv);
+}
+
+template
+inline HRESULT GlobalReallocBytes(_In_opt_ T *pv, _In_ size_t cb, _Outptr_result_bytebuffer_(cb) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return GlobalReallocBytes(GMEM_ZEROINIT, pv, cb, ppv);
+}
+
+template
+inline HRESULT GlobalAllocObject(_Outptr_result_buffer_(1) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return GlobalAllocObject(GMEM_ZEROINIT, ppv);
+}
+
+template
+inline HRESULT GlobalAllocArray(_In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return GlobalAllocArray(GMEM_ZEROINIT, cItems, ppv);
+}
+
+template
+inline HRESULT GlobalReallocArray(_In_opt_ T *pv, _In_ size_t cItems, _Outptr_result_buffer_(cItems) _On_failure_(_Post_satisfies_(*ppv == 0)) T **ppv)
+{
+ return GlobalReallocArray(GMEM_ZEROINIT, pv, cItems, ppv);
+}
+
+// GlobalAlloc string helpers
+
+inline HRESULT GlobalAllocString(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PWSTR *ppsz)
+{
+ return _AllocString(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT GlobalAllocStringLen( _In_reads_or_z_opt_(cch) PCNZWCH pszSource, _In_ size_t cch, _Outptr_result_buffer_(cch+1) _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringLen(NULL, NO_ZERO_INIT, pszSource, cch, ppsz);
+}
+
+inline HRESULT GlobalAllocStringDoubleNullTerminate(_In_ PCWSTR pszSource, _Outptr_result_nullonfailure_ PZZWSTR *ppsz)
+{
+ return _AllocStringDoubleNullTerminate(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+inline HRESULT GlobalAllocStringOpt(_In_opt_ PCWSTR pszSource, _Outptr_result_maybenull_ _On_failure_(_Post_satisfies_(*ppsz == 0)) PWSTR *ppsz)
+{
+ return _AllocStringOpt(NULL, NO_ZERO_INIT, pszSource, ppsz);
+}
+
+#endif // NO_GLOBALALLOC_HELPERS
+
+#endif // __cplusplus
+
+#endif // __memsafe_h__
+
diff --git a/ExplorerPatcher/symbols.c b/ExplorerPatcher/symbols.c
index 4484f2c..1914fce 100644
--- a/ExplorerPatcher/symbols.c
+++ b/ExplorerPatcher/symbols.c
@@ -1,3 +1,4 @@
+#include
#include "symbols.h"
const char* explorer_SN[EXPLORER_SB_CNT] = {
@@ -6,7 +7,7 @@ const char* explorer_SN[EXPLORER_SB_CNT] = {
EXPLORER_SB_2,
EXPLORER_SB_3,
EXPLORER_SB_4,
- EXPLORER_SB_5
+ EXPLORER_SB_5,
};
const char* explorer_SN_26244[1] = {
EXPLORER_SB_4,
@@ -19,18 +20,16 @@ const char* twinui_pcshell_SN[TWINUI_PCSHELL_SB_CNT] = {
TWINUI_PCSHELL_SB_4,
TWINUI_PCSHELL_SB_5,
TWINUI_PCSHELL_SB_6,
- TWINUI_PCSHELL_SB_7,
- TWINUI_PCSHELL_SB_8
};
const char* startdocked_SN[STARTDOCKED_SB_CNT] = {
STARTDOCKED_SB_0,
STARTDOCKED_SB_1,
STARTDOCKED_SB_2,
STARTDOCKED_SB_3,
- STARTDOCKED_SB_4
+ STARTDOCKED_SB_4,
};
const char* startui_SN[STARTUI_SB_CNT] = {
- STARTUI_SB_0
+ STARTUI_SB_0,
};
const wchar_t DownloadNotificationXML[] =
@@ -53,7 +52,7 @@ BOOL CheckVersion(HKEY hKey, DWORD dwVersion)
{
DWORD dwSize = sizeof(DWORD);
DWORD dwStoredVersion = 0;
- if (RegQueryValueExW(hKey, TEXT("Version"), 0, NULL, &dwStoredVersion, &dwSize) == ERROR_SUCCESS)
+ if (RegQueryValueExW(hKey, TEXT("Version"), 0, NULL, (LPBYTE)&dwStoredVersion, &dwSize) == ERROR_SUCCESS)
{
return dwStoredVersion == dwVersion;
}
@@ -62,10 +61,10 @@ BOOL CheckVersion(HKEY hKey, DWORD dwVersion)
void SaveVersion(HKEY hKey, DWORD dwVersion)
{
- RegSetValueExW(hKey, TEXT("Version"), 0, REG_DWORD, &dwVersion, sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT("Version"), 0, REG_DWORD, (const BYTE*)&dwVersion, sizeof(DWORD));
}
-static BOOL ProcessExplorerSymbols(const char* pszSettingsPath, DWORD* pOffsets)
+static BOOL ProcessExplorerSymbols(char* pszSettingsPath, DWORD* pOffsets)
{
HKEY hKey = NULL;
DWORD dwDisposition;
@@ -116,10 +115,10 @@ static BOOL ProcessExplorerSymbols(const char* pszSettingsPath, DWORD* pOffsets)
}
printf("[Symbols] Reading symbols...\n");
- if (VnGetSymbols(pszSettingsPath, pOffsets, explorer_SN, ARRAYSIZE(explorer_SN)) != 0)
+ if (VnGetSymbols(pszSettingsPath, pOffsets, (char**)explorer_SN, ARRAYSIZE(explorer_SN)) != 0)
{
DWORD offsets26244[ARRAYSIZE(explorer_SN_26244)];
- if (VnGetSymbols(pszSettingsPath, offsets26244, explorer_SN_26244, ARRAYSIZE(explorer_SN_26244)) == 0)
+ if (VnGetSymbols(pszSettingsPath, offsets26244, (char**)explorer_SN_26244, ARRAYSIZE(explorer_SN_26244)) == 0)
{
pOffsets[4] = offsets26244[0];
}
@@ -131,21 +130,21 @@ static BOOL ProcessExplorerSymbols(const char* pszSettingsPath, DWORD* pOffsets)
}
}
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_0), 0, REG_DWORD, &pOffsets[0], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_1), 0, REG_DWORD, &pOffsets[1], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_2), 0, REG_DWORD, &pOffsets[2], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_3), 0, REG_DWORD, &pOffsets[3], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_4), 0, REG_DWORD, &pOffsets[4], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(EXPLORER_SB_5), 0, REG_DWORD, &pOffsets[5], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_0), 0, REG_DWORD, (const BYTE*)&pOffsets[0], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_1), 0, REG_DWORD, (const BYTE*)&pOffsets[1], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_2), 0, REG_DWORD, (const BYTE*)&pOffsets[2], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_3), 0, REG_DWORD, (const BYTE*)&pOffsets[3], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_4), 0, REG_DWORD, (const BYTE*)&pOffsets[4], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(EXPLORER_SB_5), 0, REG_DWORD, (const BYTE*)&pOffsets[5], sizeof(DWORD));
- RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, strlen(szHash) + 1);
+ RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, (DWORD)(strlen(szHash) + 1));
SaveVersion(hKey, EXPLORER_SB_VERSION);
if (hKey) RegCloseKey(hKey);
return TRUE;
}
-static BOOL ProcessTwinuiPcshellSymbols(const char* pszSettingsPath, DWORD* pOffsets)
+static BOOL ProcessTwinuiPcshellSymbols(char* pszSettingsPath, DWORD* pOffsets)
{
HKEY hKey = NULL;
DWORD dwDisposition;
@@ -198,20 +197,11 @@ static BOOL ProcessTwinuiPcshellSymbols(const char* pszSettingsPath, DWORD* pOff
}
printf("[Symbols] Reading symbols...\n");
- if (!IsWindows11())
- {
- DWORD flOldProtect = 0;
- if (VirtualProtect(twinui_pcshell_SN, sizeof(twinui_pcshell_SN), PAGE_EXECUTE_READWRITE, &flOldProtect))
- {
- twinui_pcshell_SN[1] = twinui_pcshell_SN[0];
- VirtualProtect(twinui_pcshell_SN, sizeof(twinui_pcshell_SN), flOldProtect, &flOldProtect);
- }
- }
if (VnGetSymbols(
pszSettingsPath,
pOffsets,
- twinui_pcshell_SN,
- IsWindows11() ? TWINUI_PCSHELL_SB_CNT : 4
+ (char**)twinui_pcshell_SN,
+ IsWindows11() ? TWINUI_PCSHELL_SB_CNT : 3
))
{
printf("[Symbols] Failure in reading symbols for \"%s\".\n", twinui_pcshell_sb_dll);
@@ -223,24 +213,22 @@ static BOOL ProcessTwinuiPcshellSymbols(const char* pszSettingsPath, DWORD* pOff
{
pOffsets[1] = 0;
}
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_0), 0, REG_DWORD, &pOffsets[0], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_1), 0, REG_DWORD, &pOffsets[1], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_2), 0, REG_DWORD, &pOffsets[2], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_3), 0, REG_DWORD, &pOffsets[3], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_4), 0, REG_DWORD, &pOffsets[4], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_5), 0, REG_DWORD, &pOffsets[5], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_6), 0, REG_DWORD, &pOffsets[6], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_7), 0, REG_DWORD, &pOffsets[7], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_8), 0, REG_DWORD, &pOffsets[8], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_0), 0, REG_DWORD, (const BYTE*)&pOffsets[0], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_1), 0, REG_DWORD, (const BYTE*)&pOffsets[1], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_2), 0, REG_DWORD, (const BYTE*)&pOffsets[2], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_3), 0, REG_DWORD, (const BYTE*)&pOffsets[3], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_4), 0, REG_DWORD, (const BYTE*)&pOffsets[4], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_5), 0, REG_DWORD, (const BYTE*)&pOffsets[5], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_6), 0, REG_DWORD, (const BYTE*)&pOffsets[6], sizeof(DWORD));
- RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, strlen(szHash) + 1);
+ RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, (DWORD)(strlen(szHash) + 1));
SaveVersion(hKey, TWINUI_PCSHELL_SB_VERSION);
if (hKey) RegCloseKey(hKey);
return TRUE;
}
-static BOOL ProcessStartDockedSymbols(const char* pszSettingsPath, DWORD* pOffsets)
+static BOOL ProcessStartDockedSymbols(char* pszSettingsPath, DWORD* pOffsets)
{
HKEY hKey = NULL;
DWORD dwDisposition;
@@ -296,7 +284,7 @@ static BOOL ProcessStartDockedSymbols(const char* pszSettingsPath, DWORD* pOffse
if (VnGetSymbols(
pszSettingsPath,
pOffsets,
- startdocked_SN,
+ (char**)startdocked_SN,
STARTDOCKED_SB_CNT
))
{
@@ -305,20 +293,20 @@ static BOOL ProcessStartDockedSymbols(const char* pszSettingsPath, DWORD* pOffse
return FALSE;
}
- RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_0), 0, REG_DWORD, &pOffsets[0], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_1), 0, REG_DWORD, &pOffsets[1], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_2), 0, REG_DWORD, &pOffsets[2], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_3), 0, REG_DWORD, &pOffsets[3], sizeof(DWORD));
- RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_4), 0, REG_DWORD, &pOffsets[4], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_0), 0, REG_DWORD, (const BYTE*)&pOffsets[0], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_1), 0, REG_DWORD, (const BYTE*)&pOffsets[1], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_2), 0, REG_DWORD, (const BYTE*)&pOffsets[2], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_3), 0, REG_DWORD, (const BYTE*)&pOffsets[3], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTDOCKED_SB_4), 0, REG_DWORD, (const BYTE*)&pOffsets[4], sizeof(DWORD));
- RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, strlen(szHash) + 1);
+ RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, (DWORD)(strlen(szHash) + 1));
SaveVersion(hKey, STARTDOCKED_SB_VERSION);
if (hKey) RegCloseKey(hKey);
return TRUE;
}
-static BOOL ProcessStartUISymbols(const char* pszSettingsPath, DWORD* pOffsets)
+static BOOL ProcessStartUISymbols(char* pszSettingsPath, DWORD* pOffsets)
{
HKEY hKey = NULL;
DWORD dwDisposition;
@@ -384,7 +372,7 @@ static BOOL ProcessStartUISymbols(const char* pszSettingsPath, DWORD* pOffsets)
if (VnGetSymbols(
pszSettingsPath,
pOffsets,
- startui_SN,
+ (char**)startui_SN,
STARTUI_SB_CNT
))
{
@@ -393,9 +381,9 @@ static BOOL ProcessStartUISymbols(const char* pszSettingsPath, DWORD* pOffsets)
return FALSE;
}
- RegSetValueExW(hKey, TEXT(STARTUI_SB_0), 0, REG_DWORD, &pOffsets[0], sizeof(DWORD));
+ RegSetValueExW(hKey, TEXT(STARTUI_SB_0), 0, REG_DWORD, (const BYTE*)&pOffsets[0], sizeof(DWORD));
- RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, strlen(szHash) + 1);
+ RegSetValueExA(hKey, "Hash", 0, REG_SZ, szHash, (DWORD)(strlen(szHash) + 1));
SaveVersion(hKey, STARTUI_SB_VERSION);
if (hKey) RegCloseKey(hKey);
@@ -452,7 +440,7 @@ DWORD DownloadSymbols(DownloadSymbolsParams* params)
TEXT("SymbolsLastNotifiedOSBuild"),
0,
NULL,
- szLastNotifiedBuild,
+ (LPBYTE)szLastNotifiedBuild,
&dwSize
);
@@ -472,7 +460,7 @@ DWORD DownloadSymbols(DownloadSymbolsParams* params)
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
hr = String2IXMLDocument(
buffer,
- wcslen(buffer),
+ (DWORD)wcslen(buffer),
&inputXml,
#ifdef DEBUG
stdout
@@ -496,8 +484,8 @@ DWORD DownloadSymbols(DownloadSymbolsParams* params)
TEXT("SymbolsLastNotifiedOSBuild"),
0,
REG_SZ,
- szReportedVersion,
- wcslen(szReportedVersion) * sizeof(wchar_t)
+ (const BYTE*)szReportedVersion,
+ (DWORD)(wcslen(szReportedVersion) * sizeof(wchar_t))
);
}
@@ -600,7 +588,7 @@ DWORD DownloadSymbols(DownloadSymbolsParams* params)
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml2 = NULL;
HRESULT hr = String2IXMLDocument(
buffer,
- wcslen(buffer),
+ (DWORD)wcslen(buffer),
&inputXml2,
#ifdef DEBUG
stdout
@@ -676,12 +664,12 @@ LoadSymbolsResult LoadSymbols(symbols_addr* symbols_PTRS)
&& !_stricmp(szHash, szStoredHash) && CheckVersion(hKey, EXPLORER_SB_VERSION))
{
dwSize = sizeof(DWORD);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_0), 0, NULL, &symbols_PTRS->explorer_PTRS[0], &dwSize);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_1), 0, NULL, &symbols_PTRS->explorer_PTRS[1], &dwSize);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_2), 0, NULL, &symbols_PTRS->explorer_PTRS[2], &dwSize);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_3), 0, NULL, &symbols_PTRS->explorer_PTRS[3], &dwSize);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_4), 0, NULL, &symbols_PTRS->explorer_PTRS[4], &dwSize);
- RegQueryValueExW(hKey, TEXT(EXPLORER_SB_5), 0, NULL, &symbols_PTRS->explorer_PTRS[5], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_0), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[0], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_1), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[1], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_2), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[2], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_3), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[3], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_4), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[4], &dwSize);
+ RegQueryValueExW(hKey, TEXT(EXPLORER_SB_5), 0, NULL, (LPBYTE)&symbols_PTRS->explorer_PTRS[5], &dwSize);
bOffsetsValid = TRUE;
}
else
@@ -729,15 +717,13 @@ LoadSymbolsResult LoadSymbols(symbols_addr* symbols_PTRS)
&& !_stricmp(szHash, szStoredHash) && CheckVersion(hKey, TWINUI_PCSHELL_SB_VERSION))
{
dwSize = sizeof(DWORD);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_0), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[0], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_1), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[1], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_2), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[2], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_3), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[3], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_4), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[4], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_5), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[5], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_6), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[6], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_7), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[7], &dwSize);
- RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_8), 0, NULL, &symbols_PTRS->twinui_pcshell_PTRS[8], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_0), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[0], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_1), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[1], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_2), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[2], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_3), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[3], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_4), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[4], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_5), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[5], &dwSize);
+ RegQueryValueExW(hKey, TEXT(TWINUI_PCSHELL_SB_6), 0, NULL, (LPBYTE)&symbols_PTRS->twinui_pcshell_PTRS[6], &dwSize);
bOffsetsValid = TRUE;
}
else
@@ -784,11 +770,11 @@ LoadSymbolsResult LoadSymbols(symbols_addr* symbols_PTRS)
&& !_stricmp(szHash, szStoredHash) && CheckVersion(hKey, STARTDOCKED_SB_VERSION))
{
dwSize = sizeof(DWORD);
- RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_0), 0, NULL, &symbols_PTRS->startdocked_PTRS[0], &dwSize);
- RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_1), 0, NULL, &symbols_PTRS->startdocked_PTRS[1], &dwSize);
- RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_2), 0, NULL, &symbols_PTRS->startdocked_PTRS[2], &dwSize);
- RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_3), 0, NULL, &symbols_PTRS->startdocked_PTRS[3], &dwSize);
- RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_4), 0, NULL, &symbols_PTRS->startdocked_PTRS[4], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_0), 0, NULL, (LPBYTE)&symbols_PTRS->startdocked_PTRS[0], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_1), 0, NULL, (LPBYTE)&symbols_PTRS->startdocked_PTRS[1], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_2), 0, NULL, (LPBYTE)&symbols_PTRS->startdocked_PTRS[2], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_3), 0, NULL, (LPBYTE)&symbols_PTRS->startdocked_PTRS[3], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTDOCKED_SB_4), 0, NULL, (LPBYTE)&symbols_PTRS->startdocked_PTRS[4], &dwSize);
bOffsetsValid = TRUE;
}
else
@@ -838,7 +824,7 @@ LoadSymbolsResult LoadSymbols(symbols_addr* symbols_PTRS)
&& !_stricmp(szHash, szStoredHash) && CheckVersion(hKey, STARTUI_SB_VERSION))
{
dwSize = sizeof(DWORD);
- RegQueryValueExW(hKey, TEXT(STARTUI_SB_0), 0, NULL, &symbols_PTRS->startui_PTRS[0], &dwSize);
+ RegQueryValueExW(hKey, TEXT(STARTUI_SB_0), 0, NULL, (LPBYTE)&symbols_PTRS->startui_PTRS[0], &dwSize);
bOffsetsValid = TRUE;
}
else
diff --git a/ExplorerPatcher/symbols.h b/ExplorerPatcher/symbols.h
index 3b06c28..4fd4ad6 100644
--- a/ExplorerPatcher/symbols.h
+++ b/ExplorerPatcher/symbols.h
@@ -25,16 +25,14 @@
#define TWINUI_PCSHELL_SB_NAME "twinui.pcshell"
#define TWINUI_PCSHELL_SB_0 "CImmersiveContextMenuOwnerDrawHelper::s_ContextMenuWndProc"
-#define TWINUI_PCSHELL_SB_1 "CLauncherTipContextMenu::GetMenuItemsAsync"
-#define TWINUI_PCSHELL_SB_2 "ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu"
-#define TWINUI_PCSHELL_SB_3 "ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu"
-#define TWINUI_PCSHELL_SB_4 "CLauncherTipContextMenu::_ExecuteShutdownCommand"
-#define TWINUI_PCSHELL_SB_5 "CLauncherTipContextMenu::_ExecuteCommand"
-#define TWINUI_PCSHELL_SB_6 "CLauncherTipContextMenu::ShowLauncherTipContextMenu"
-#define TWINUI_PCSHELL_SB_7 "CMultitaskingViewManager::_CreateXamlMTVHost"
-#define TWINUI_PCSHELL_SB_8 "CMultitaskingViewManager::_CreateDCompMTVHost"
-#define TWINUI_PCSHELL_SB_CNT 9
-#define TWINUI_PCSHELL_SB_VERSION 1
+#define TWINUI_PCSHELL_SB_1 "ImmersiveContextMenuHelper::ApplyOwnerDrawToMenu"
+#define TWINUI_PCSHELL_SB_2 "ImmersiveContextMenuHelper::RemoveOwnerDrawFromMenu"
+#define TWINUI_PCSHELL_SB_3 "CLauncherTipContextMenu::_ExecuteShutdownCommand"
+#define TWINUI_PCSHELL_SB_4 "CLauncherTipContextMenu::_ExecuteCommand"
+#define TWINUI_PCSHELL_SB_5 "CMultitaskingViewManager::_CreateXamlMTVHost"
+#define TWINUI_PCSHELL_SB_6 "CMultitaskingViewManager::_CreateDCompMTVHost"
+#define TWINUI_PCSHELL_SB_CNT 7
+#define TWINUI_PCSHELL_SB_VERSION 2
#define STARTDOCKED_SB_NAME "StartDocked"
#define STARTDOCKED_SB_0 "StartDocked::LauncherFrame::ShowAllApps" // UNUSED