From 97069dff270c6dd59911e955543db9852ccbf885 Mon Sep 17 00:00:00 2001 From: Soreepeong Date: Tue, 23 Jul 2024 17:48:11 +0900 Subject: [PATCH] Detect and warn reshade w/o addon support --- .../Interface/Internal/InterfaceManager.cs | 58 ++++++++++++++----- .../ReShadeAddonInterface.Exports.cs | 31 ++++++++++ 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/Dalamud/Interface/Internal/InterfaceManager.cs b/Dalamud/Interface/Internal/InterfaceManager.cs index 4941ea46c..cfbc23bc9 100644 --- a/Dalamud/Interface/Internal/InterfaceManager.cs +++ b/Dalamud/Interface/Internal/InterfaceManager.cs @@ -8,6 +8,8 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using CheapLoc; + using Dalamud.Configuration.Internal; using Dalamud.Game; using Dalamud.Game.ClientState.GamePad; @@ -15,6 +17,7 @@ using Dalamud.Game.ClientState.Keys; using Dalamud.Hooking; using Dalamud.Hooking.Internal; using Dalamud.Hooking.WndProcHook; +using Dalamud.Interface.ImGuiNotification; using Dalamud.Interface.ImGuiNotification.Internal; using Dalamud.Interface.Internal.ManagedAsserts; using Dalamud.Interface.Internal.ReShadeHandling; @@ -746,6 +749,9 @@ internal partial class InterfaceManager : IInternalDisposableService _ = this.dalamudAtlas.BuildFontsAsync(); SwapChainHelper.BusyWaitForGameDeviceSwapChain(); + var swapChainDesc = default(DXGI_SWAP_CHAIN_DESC); + if (SwapChainHelper.GameDeviceSwapChain->GetDesc(&swapChainDesc).SUCCEEDED) + this.gameWindowHandle = swapChainDesc.OutputWindow; try { @@ -765,6 +771,28 @@ internal partial class InterfaceManager : IInternalDisposableService 0, this.SetCursorDetour); + if (ReShadeAddonInterface.ReShadeHasSignature) + { + Log.Warning("Signed ReShade binary detected."); + Service + .GetAsync() + .ContinueWith( + nmt => nmt.Result.AddNotification( + new() + { + MinimizedText = Loc.Localize( + "ReShadeNoAddonSupportNotificationMinimizedText", + "Wrong ReShade installation"), + Content = Loc.Localize( + "ReShadeNoAddonSupportNotificationContent", + "Your installation of ReShade does not have full addon support, and may not work with Dalamud and/or the game.\n" + + "Download and install ReShade with full addon-support."), + Type = NotificationType.Warning, + InitialDuration = TimeSpan.MaxValue, + ShowIndeterminateIfNoExpiry = false, + })); + } + Log.Verbose("===== S W A P C H A I N ====="); if (this.dalamudConfiguration.ReShadeHandlingMode == ReShadeHandlingMode.UnwrapReShade) { @@ -772,23 +800,25 @@ internal partial class InterfaceManager : IInternalDisposableService Log.Verbose("Unwrapped ReShade."); } - ResizeBuffersDelegate resizeBuffersDelegate; - DxgiPresentDelegate? dxgiPresentDelegate; - if (this.dalamudConfiguration.ReShadeHandlingMode == ReShadeHandlingMode.ReShadeAddon && - ReShadeAddonInterface.TryRegisterAddon(out this.reShadeAddonInterface)) + ResizeBuffersDelegate? resizeBuffersDelegate = null; + DxgiPresentDelegate? dxgiPresentDelegate = null; + if (this.dalamudConfiguration.ReShadeHandlingMode == ReShadeHandlingMode.ReShadeAddon) { - resizeBuffersDelegate = this.AsReShadeAddonResizeBuffersDetour; - dxgiPresentDelegate = null; + if (ReShadeAddonInterface.TryRegisterAddon(out this.reShadeAddonInterface)) + { + resizeBuffersDelegate = this.AsReShadeAddonResizeBuffersDetour; - Log.Verbose( - "Registered as a ReShade({name}: 0x{addr:X}) addon.", - ReShadeAddonInterface.ReShadeModule!.FileName, - ReShadeAddonInterface.ReShadeModule!.BaseAddress); - this.reShadeAddonInterface.InitSwapChain += this.ReShadeAddonInterfaceOnInitSwapChain; - this.reShadeAddonInterface.DestroySwapChain += this.ReShadeAddonInterfaceOnDestroySwapChain; - this.reShadeAddonInterface.ReShadeOverlay += this.ReShadeAddonInterfaceOnReShadeOverlay; + Log.Verbose( + "Registered as a ReShade({name}: 0x{addr:X}) addon.", + ReShadeAddonInterface.ReShadeModule!.FileName, + ReShadeAddonInterface.ReShadeModule!.BaseAddress); + this.reShadeAddonInterface.InitSwapChain += this.ReShadeAddonInterfaceOnInitSwapChain; + this.reShadeAddonInterface.DestroySwapChain += this.ReShadeAddonInterfaceOnDestroySwapChain; + this.reShadeAddonInterface.ReShadeOverlay += this.ReShadeAddonInterfaceOnReShadeOverlay; + } } - else + + if (resizeBuffersDelegate is null) { resizeBuffersDelegate = this.AsHookResizeBuffersDetour; dxgiPresentDelegate = this.PresentDetour; diff --git a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs index 46d3cc1af..60bbc37cd 100644 --- a/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs +++ b/Dalamud/Interface/Internal/ReShadeHandling/ReShadeAddonInterface.Exports.cs @@ -30,8 +30,35 @@ internal sealed unsafe partial class ReShadeAddonInterface !GetProcAddressInto(m, nameof(e.ReShadeUnregisterEvent), &e.ReShadeUnregisterEvent)) continue; + fixed (void* pwszFile = m.FileName) + fixed (Guid* pguid = &WINTRUST_ACTION_GENERIC_VERIFY_V2) + { + var wtfi = new WINTRUST_FILE_INFO + { + cbStruct = (uint)sizeof(WINTRUST_FILE_INFO), + pcwszFilePath = (ushort*)pwszFile, + hFile = default, + pgKnownSubject = null, + }; + var wtd = new WINTRUST_DATA + { + cbStruct = (uint)sizeof(WINTRUST_DATA), + pPolicyCallbackData = null, + pSIPClientData = null, + dwUIChoice = WTD.WTD_UI_NONE, + fdwRevocationChecks = WTD.WTD_REVOKE_NONE, + dwUnionChoice = WTD.WTD_STATEACTION_VERIFY, + hWVTStateData = default, + pwszURLReference = null, + dwUIContext = 0, + pFile = &wtfi, + }; + ReShadeHasSignature = WinVerifyTrust(default, pguid, &wtd) != TRUST.TRUST_E_NOSIGNATURE; + } + ReShadeModule = m; Exports = e; + return; } @@ -49,6 +76,10 @@ internal sealed unsafe partial class ReShadeAddonInterface /// Gets the active ReShade module. public static ProcessModule? ReShadeModule { get; private set; } + /// Gets a value indicating whether the loaded ReShade has signatures. + /// ReShade without addon support is signed, but may not pass signature verification. + public static bool ReShadeHasSignature { get; private set; } + private struct ExportsStruct { public delegate* unmanaged ReShadeRegisterAddon;