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