Skip to content

Commit 284ee78

Browse files
Synchronize changes from 1.6 branch [ci skip]
56327f3 D3D fix-up #1
2 parents 4084deb + 56327f3 commit 284ee78

File tree

5 files changed

+143
-132
lines changed

5 files changed

+143
-132
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*****************************************************************************
2+
*
3+
* PROJECT: Multi Theft Auto v1.0
4+
* LICENSE: See LICENSE in the top level directory
5+
* FILE: core/DXHook/CProxyComHelpers.h
6+
* PURPOSE: Shared COM interface helper functions for proxy classes
7+
*
8+
* Multi Theft Auto is available from https://www.multitheftauto.com/
9+
*
10+
*****************************************************************************/
11+
12+
#pragma once
13+
14+
#include "ComPtrValidation.h"
15+
16+
template <typename T>
17+
void ReleaseInterface(T*& pointer, int errorCode, const char* context = nullptr)
18+
{
19+
if (!pointer)
20+
return;
21+
22+
T* heldPointer = pointer;
23+
24+
const bool valid = IsValidComInterfacePointer(pointer, ComPtrValidation::ValidationMode::ForceRefresh);
25+
26+
if (!valid)
27+
{
28+
SString label;
29+
label = context ? context : "ReleaseInterface";
30+
SString message;
31+
message.Format("%s: calling Release on potentially invalid COM pointer %p", label.c_str(), heldPointer);
32+
AddReportLog(errorCode, message, 5);
33+
ComPtrValidation::Invalidate(heldPointer);
34+
}
35+
36+
heldPointer->Release();
37+
pointer = nullptr;
38+
}
39+
40+
template <typename T>
41+
void ReleaseInterface(T*& pointer)
42+
{
43+
if (pointer)
44+
{
45+
pointer->Release();
46+
pointer = nullptr;
47+
}
48+
}
49+
50+
template <typename T>
51+
void ReplaceInterface(T*& destination, T* source, int releaseErrorCode, int replaceErrorCode, const char* context = nullptr)
52+
{
53+
if (destination == source)
54+
return;
55+
56+
ReleaseInterface(destination, releaseErrorCode, context);
57+
58+
if (source && !IsValidComInterfacePointer(source, ComPtrValidation::ValidationMode::ForceRefresh))
59+
{
60+
SString label;
61+
label = context ? context : "ReplaceInterface";
62+
SString message;
63+
message.Format("%s: refusing to assign invalid COM pointer %p", label.c_str(), source);
64+
AddReportLog(replaceErrorCode, message, 5);
65+
destination = nullptr;
66+
return;
67+
}
68+
69+
destination = source;
70+
if (destination)
71+
destination->AddRef();
72+
}
73+
74+
template <typename T>
75+
void ReplaceInterface(T*& destination, T* source)
76+
{
77+
if (destination == source)
78+
return;
79+
80+
if (destination)
81+
{
82+
destination->Release();
83+
destination = nullptr;
84+
}
85+
86+
destination = source;
87+
if (destination)
88+
destination->AddRef();
89+
}
90+
91+
template <typename T>
92+
void ReplaceInterface(T*& destination, T* source, const char* context)
93+
{
94+
constexpr int GENERIC_COM_ERROR = 8799;
95+
ReplaceInterface(destination, source, GENERIC_COM_ERROR, GENERIC_COM_ERROR, context);
96+
}

Client/core/DXHook/CProxyDirect3D9.cpp

Lines changed: 26 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,17 @@
1010
*****************************************************************************/
1111

1212
#include "StdInc.h"
13+
#include "CProxyComHelpers.h"
1314
#include "ComPtrValidation.h"
1415
#include <dwmapi.h>
16+
#include <mutex>
17+
#include <atomic>
1518
#include <resource.h>
1619

1720
extern HINSTANCE g_hModule;
1821

1922
namespace
2023
{
21-
template <typename T>
22-
void ReleaseInterface(T*& pointer, const char* context = nullptr)
23-
{
24-
if (!pointer)
25-
return;
26-
27-
T* heldPointer = pointer;
28-
29-
const bool valid = IsValidComInterfacePointer(pointer, ComPtrValidation::ValidationMode::ForceRefresh);
30-
31-
if (valid)
32-
{
33-
heldPointer->Release();
34-
}
35-
else
36-
{
37-
SString label;
38-
label = context ? context : "ReleaseInterface";
39-
SString message;
40-
message.Format("%s: skipping Release on invalid COM pointer %p", label.c_str(), heldPointer);
41-
AddReportLog(8752, message, 5);
42-
ComPtrValidation::Invalidate(heldPointer);
43-
}
44-
45-
pointer = nullptr;
46-
}
47-
48-
template <typename T>
49-
void ReplaceInterface(T*& destination, T* source, const char* context = nullptr)
50-
{
51-
if (destination == source)
52-
return;
53-
54-
if (source && !IsValidComInterfacePointer(source, ComPtrValidation::ValidationMode::ForceRefresh))
55-
{
56-
SString label;
57-
label = context ? context : "ReplaceInterface";
58-
SString message;
59-
message.Format("%s: rejected invalid COM pointer %p", label.c_str(), source);
60-
AddReportLog(8753, message, 5);
61-
return;
62-
}
63-
64-
ReleaseInterface(destination, context);
65-
destination = source;
66-
if (destination)
67-
destination->AddRef();
68-
}
6924

7025
IDirect3D9* GetFirstValidTrackedDirect3D(std::vector<IDirect3D9*>& trackedList)
7126
{
@@ -88,7 +43,9 @@ IDirect3D9* GetFirstValidTrackedDirect3D(std::vector<IDirect3D9*>& trackedList)
8843

8944
HRESULT HandleCreateDeviceResult(HRESULT hResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
9045
D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface);
46+
9147
std::vector<IDirect3D9*> ms_CreatedDirect3D9List;
48+
std::mutex ms_Direct3D9ListMutex;
9249
bool CreateDeviceSecondCallCheck(HRESULT& hOutResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
9350
D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface);
9451
void ApplyBorderlessColorCorrection(CProxyDirect3DDevice9* proxyDevice, const D3DPRESENT_PARAMETERS& presentationParameters);
@@ -108,15 +65,15 @@ CProxyDirect3D9::CProxyDirect3D9(IDirect3D9* pInterface)
10865
return;
10966
}
11067

111-
// Take ownership of the interface pointer
112-
// ReplaceInterface will AddRef(), giving us our own reference
113-
// Caller retains their reference
114-
ReplaceInterface(m_pDevice, pInterface, "CProxyDirect3D9 ctor");
68+
pInterface->AddRef();
69+
m_pDevice = pInterface;
11570

71+
// Track this Direct3D9 instance for StaticGetDirect3D() lookups
11672
if (m_pDevice)
11773
{
11874
if (IsValidComInterfacePointer(m_pDevice, ComPtrValidation::ValidationMode::ForceRefresh))
11975
{
76+
std::lock_guard<std::mutex> lock(ms_Direct3D9ListMutex);
12077
ms_CreatedDirect3D9List.push_back(m_pDevice);
12178
}
12279
else
@@ -131,8 +88,11 @@ CProxyDirect3D9::CProxyDirect3D9(IDirect3D9* pInterface)
13188
CProxyDirect3D9::~CProxyDirect3D9()
13289
{
13390
WriteDebugEvent(SString("CProxyDirect3D9::~CProxyDirect3D9 %08x", this));
134-
ListRemove(ms_CreatedDirect3D9List, m_pDevice);
135-
ReleaseInterface(m_pDevice, "CProxyDirect3D9 dtor");
91+
{
92+
std::lock_guard<std::mutex> lock(ms_Direct3D9ListMutex);
93+
ListRemove(ms_CreatedDirect3D9List, m_pDevice);
94+
}
95+
ReleaseInterface(m_pDevice, 8752);
13696
}
13797

13898
/*** IUnknown methods ***/
@@ -150,7 +110,7 @@ HRESULT CProxyDirect3D9::QueryInterface(REFIID riid, void** ppvObj)
150110

151111
ULONG CProxyDirect3D9::AddRef()
152112
{
153-
LONG lNewRefCount = InterlockedIncrement(&m_lRefCount);
113+
LONG lNewRefCount = m_lRefCount.fetch_add(1, std::memory_order_relaxed) + 1;
154114

155115
if (m_pDevice)
156116
m_pDevice->AddRef();
@@ -160,7 +120,7 @@ ULONG CProxyDirect3D9::AddRef()
160120

161121
ULONG CProxyDirect3D9::Release()
162122
{
163-
LONG lNewRefCount = InterlockedDecrement(&m_lRefCount);
123+
LONG lNewRefCount = m_lRefCount.fetch_sub(1, std::memory_order_acq_rel) - 1;
164124

165125
if (lNewRefCount < 0)
166126
{
@@ -276,6 +236,7 @@ HMONITOR CProxyDirect3D9::GetAdapterMonitor(UINT Adapter)
276236

277237
HMONITOR CProxyDirect3D9::StaticGetAdapterMonitor(UINT Adapter)
278238
{
239+
std::lock_guard<std::mutex> lock(ms_Direct3D9ListMutex);
279240
IDirect3D9* pDirect3D = GetFirstValidTrackedDirect3D(ms_CreatedDirect3D9List);
280241
if (!pDirect3D)
281242
return NULL;
@@ -285,6 +246,7 @@ HMONITOR CProxyDirect3D9::StaticGetAdapterMonitor(UINT Adapter)
285246

286247
IDirect3D9* CProxyDirect3D9::StaticGetDirect3D()
287248
{
249+
std::lock_guard<std::mutex> lock(ms_Direct3D9ListMutex);
288250
return GetFirstValidTrackedDirect3D(ms_CreatedDirect3D9List);
289251
}
290252

@@ -393,7 +355,7 @@ HRESULT CProxyDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND
393355
SString message;
394356
message.Format("CProxyDirect3D9::CreateDevice - rejected invalid IDirect3DDevice9 pointer %p", pCreatedDevice);
395357
AddReportLog(8755, message, 5);
396-
ReleaseInterface(pCreatedDevice, "CProxyDirect3D9::CreateDevice invalid return");
358+
ReleaseInterface(pCreatedDevice, 8755, "CProxyDirect3D9::CreateDevice invalid return");
397359
*ppReturnedDeviceInterface = nullptr;
398360
hResult = D3DERR_INVALIDDEVICE;
399361
}
@@ -607,7 +569,7 @@ HRESULT CreateDeviceInsist(uint uiMinTries, uint uiTimeout, IDirect3D9* pDirect3
607569
SString message;
608570
message.Format("CreateDeviceInsist: rejected invalid IDirect3DDevice9 pointer %p", pCreatedDevice);
609571
AddReportLog(8755, message, 5);
610-
ReleaseInterface(pCreatedDevice, "CreateDeviceInsist invalid return");
572+
ReleaseInterface(pCreatedDevice, 8755, "CreateDeviceInsist invalid return");
611573
*ppReturnedDeviceInterface = nullptr;
612574
hResult = D3DERR_INVALIDDEVICE;
613575
}
@@ -889,7 +851,7 @@ void AddCapsReport(UINT Adapter, IDirect3D9* pDirect3D, IDirect3DDevice9* pD3DDe
889851
}
890852
}
891853

892-
ReleaseInterface(pDirect3DOther, "AddCapsReport GetDirect3D");
854+
ReleaseInterface(pDirect3DOther, 8799, "AddCapsReport GetDirect3D");
893855

894856
// Get caps from D3D
895857
D3DCAPS9 D3DCaps9;
@@ -923,7 +885,7 @@ void AddCapsReport(UINT Adapter, IDirect3D9* pDirect3D, IDirect3DDevice9* pD3DDe
923885
VertexElements[0].Type = DeclTypesList[i].VertexType;
924886
IDirect3DVertexDeclaration9* pD3DVertexDecl = nullptr;
925887
hr = pD3DDevice9->CreateVertexDeclaration(VertexElements, &pD3DVertexDecl);
926-
ReleaseInterface(pD3DVertexDecl, "AddCapsReport CreateVertexDeclaration");
888+
ReleaseInterface(pD3DVertexDecl, 8799, "AddCapsReport CreateVertexDeclaration");
927889

928890
// Check against device caps
929891
bool bCapsSaysOk = (DeviceCaps9.DeclTypes & DeclTypesList[i].CapsType) ? true : false;
@@ -1073,7 +1035,7 @@ HRESULT HandleCreateDeviceResult(HRESULT hResult, IDirect3D9* pDirect3D, UINT Ad
10731035
SString message;
10741036
message.Format("HandleCreateDeviceResult: rejected invalid IDirect3DDevice9 pointer %p", pCreatedDevice);
10751037
AddReportLog(8755, message, 5);
1076-
ReleaseInterface(pCreatedDevice, "HandleCreateDeviceResult invalid return");
1038+
ReleaseInterface(pCreatedDevice, 8755, "HandleCreateDeviceResult invalid return");
10771039
*ppReturnedDeviceInterface = nullptr;
10781040
hResult = D3DERR_INVALIDDEVICE;
10791041
}
@@ -1205,7 +1167,7 @@ void CCore::OnPreCreateDevice(IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE De
12051167
WriteDebugEvent(ToString(Adapter, DeviceType, hFocusWindow, BehaviorFlags, *pPresentationParameters));
12061168
IDirect3DDevice9* pReturnedDeviceInterface = NULL;
12071169
HRESULT hResult = pDirect3D->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, &pReturnedDeviceInterface);
1208-
ReleaseInterface(pReturnedDeviceInterface, "CCore::OnPreCreateDevice temp release");
1170+
ReleaseInterface(pReturnedDeviceInterface, 8799, "CCore::OnPreCreateDevice temp release");
12091171
WriteDebugEvent(SString(" Unmodified result is: %08x", hResult));
12101172
}
12111173

@@ -1285,7 +1247,7 @@ HRESULT CCore::OnPostCreateDevice(HRESULT hResult, IDirect3D9* pDirect3D, UINT A
12851247

12861248
AddCapsReport(Adapter, pDirect3D, pDevice, false);
12871249

1288-
ReleaseInterface(pDevice, "CCore::OnPostCreateDevice temp release");
1250+
ReleaseInterface(pDevice, 8799, "CCore::OnPostCreateDevice temp release");
12891251
*ppReturnedDeviceInterface = pDevice;
12901252

12911253
//
@@ -1328,7 +1290,7 @@ HRESULT CCore::OnPostCreateDevice(HRESULT hResult, IDirect3D9* pDirect3D, UINT A
13281290
{
13291291
AddReportLog(8755,
13301292
SString("CCore::OnPostCreateDevice: rejected invalid IDirect3DDevice9 pointer %p", pCreatedDevice), 5);
1331-
ReleaseInterface(pCreatedDevice, "CCore::OnPostCreateDevice invalid return");
1293+
ReleaseInterface(pCreatedDevice, 8755, "CCore::OnPostCreateDevice invalid return");
13321294
*ppReturnedDeviceInterface = nullptr;
13331295
hResult = D3DERR_INVALIDDEVICE;
13341296
}

Client/core/DXHook/CProxyDirect3D9.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ class CProxyDirect3D9 : public IDirect3D9
4949

5050
private:
5151
IDirect3D9* m_pDevice;
52-
volatile LONG m_lRefCount;
52+
std::atomic<LONG> m_lRefCount;
5353
};

0 commit comments

Comments
 (0)