From 8823e4bb3de0906d4658d0bde2be9c43a927db8d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 22 Mar 2022 20:36:49 +0100 Subject: [PATCH] [dxgi] Work around swapchain use-after-free bugs Affects Divinity: Original Sin Enhanced Edition. Requires Wine hack to delay memory deallocation to not crash during resolution changes. --- src/dxgi/dxgi_swapchain_dispatcher.h | 33 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/dxgi/dxgi_swapchain_dispatcher.h b/src/dxgi/dxgi_swapchain_dispatcher.h index fd48d837..4ef50d04 100644 --- a/src/dxgi/dxgi_swapchain_dispatcher.h +++ b/src/dxgi/dxgi_swapchain_dispatcher.h @@ -16,16 +16,28 @@ namespace dxvk { } ULONG STDMETHODCALLTYPE AddRef() { - return m_dispatch->AddRef(); + if (likely(m_dispatch != nullptr)) + return m_dispatch->AddRef(); + + return 0; } ULONG STDMETHODCALLTYPE Release() { - ULONG refCount = m_dispatch->Release(); + if (likely(m_dispatch != nullptr)) { + ULONG refCount = m_dispatch->Release(); - if (unlikely(!refCount)) - delete this; + if (unlikely(!refCount)) { + // Clear the underlying swap chain pointer. Helps in + // use-after-free situations encountered in Divinity + // Original Sin Enhanced Edition. + m_dispatch = nullptr; + delete this; + } - return refCount; + return refCount; + } + + return ~0u; } HRESULT STDMETHODCALLTYPE QueryInterface( @@ -114,7 +126,16 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE GetFullscreenState( BOOL* pFullscreen, IDXGIOutput** ppTarget) final { - return m_dispatch->GetFullscreenState(pFullscreen, ppTarget); + if (likely(m_dispatch != nullptr)) + return m_dispatch->GetFullscreenState(pFullscreen, ppTarget); + + if (pFullscreen) + *pFullscreen = FALSE; + + if (ppTarget) + *ppTarget = nullptr; + + return S_OK; } HRESULT STDMETHODCALLTYPE GetFullscreenDesc(