Skip to content

Commit

Permalink
Make interfaces reusable to handle game misuse
Browse files Browse the repository at this point in the history
  • Loading branch information
elishacloud committed Dec 2, 2024
1 parent a54e087 commit 9932160
Show file tree
Hide file tree
Showing 34 changed files with 1,340 additions and 125 deletions.
38 changes: 38 additions & 0 deletions AddressLookupTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,44 @@

constexpr UINT MaxIndex = 16;

template <typename T>
inline void SaveInterfaceAddress(T*& Interface, T*& InterfaceBackup)
{
if (Interface)
{
SetCriticalSection();
Interface->SetProxy(nullptr);
if (InterfaceBackup)
{
InterfaceBackup->DeleteMe();
InterfaceBackup = nullptr;
}
InterfaceBackup = Interface;
ReleaseCriticalSection();
}
}

template <typename T, typename S, typename X>
inline T* GetInterfaceAddress(T*& Interface, T*& InterfaceBackup, S* ProxyInterface, X* InterfaceX)
{
if (!Interface)
{
SetCriticalSection();
if (InterfaceBackup)
{
Interface = InterfaceBackup;
InterfaceBackup = nullptr;
Interface->SetProxy(InterfaceX);
}
else
{
Interface = new T(ProxyInterface, InterfaceX);
}
ReleaseCriticalSection();
}
return Interface;
}

template <typename D>
class AddressLookupTableDinput
{
Expand Down
2 changes: 1 addition & 1 deletion BuildNo.rc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define BUILD_NUMBER 79
#define BUILD_NUMBER 80
65 changes: 58 additions & 7 deletions IDirectInputDeviceX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@

#include "dinputto8.h"

// Cached wrapper interface
m_IDirectInputDeviceA* DirectInputDeviceWrapperBackupA = nullptr;
m_IDirectInputDeviceW* DirectInputDeviceWrapperBackupW = nullptr;
m_IDirectInputDevice2A* DirectInputDeviceWrapperBackup2A = nullptr;
m_IDirectInputDevice2W* DirectInputDeviceWrapperBackup2W = nullptr;
m_IDirectInputDevice7A* DirectInputDeviceWrapperBackup7A = nullptr;
m_IDirectInputDevice7W* DirectInputDeviceWrapperBackup7W = nullptr;

HWND GetMainWindow()
{
struct ENUMEDATA
Expand Down Expand Up @@ -255,15 +263,41 @@ LPVOID m_IDirectInputDeviceX::GetWrapperInterfaceX(DWORD DirectXVersion)
{
switch (DirectXVersion)
{
case 0:
if (WrapperInterface7) return WrapperInterface7;
if (WrapperInterface2) return WrapperInterface2;
if (WrapperInterface) return WrapperInterface;
break;
case 1:
return WrapperInterface;
if (StringType == ANSI_CHARSET)
{
return GetInterfaceAddress((m_IDirectInputDeviceA*&)WrapperInterface, DirectInputDeviceWrapperBackupA, (LPDIRECTINPUTDEVICEA)ProxyInterface, this);
}
else
{
return GetInterfaceAddress((m_IDirectInputDeviceW*&)WrapperInterface, DirectInputDeviceWrapperBackupW, (LPDIRECTINPUTDEVICEW)ProxyInterface, this);
}
case 2:
return WrapperInterface2;
if (StringType == ANSI_CHARSET)
{
return GetInterfaceAddress((m_IDirectInputDevice2A*&)WrapperInterface2, DirectInputDeviceWrapperBackup2A, (LPDIRECTINPUTDEVICE2A)ProxyInterface, this);
}
else
{
return GetInterfaceAddress((m_IDirectInputDevice2W*&)WrapperInterface2, DirectInputDeviceWrapperBackup2W, (LPDIRECTINPUTDEVICE2W)ProxyInterface, this);
}
case 7:
return WrapperInterface7;
default:
return nullptr;
if (StringType == ANSI_CHARSET)
{
return GetInterfaceAddress((m_IDirectInputDevice7A*&)WrapperInterface7, DirectInputDeviceWrapperBackup7A, (LPDIRECTINPUTDEVICE7A)ProxyInterface, this);
}
else
{
return GetInterfaceAddress((m_IDirectInputDevice7W*&)WrapperInterface7, DirectInputDeviceWrapperBackup7W, (LPDIRECTINPUTDEVICE7W)ProxyInterface, this);
}
}
LOG_LIMIT(100, __FUNCTION__ << " Error: wrapper interface version not found: " << DirectXVersion);
return nullptr;
}

ULONG m_IDirectInputDeviceX::AddRef()
Expand Down Expand Up @@ -747,7 +781,7 @@ HRESULT m_IDirectInputDeviceX::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LP

if (SUCCEEDED(hr))
{
m_IDirectInputEffect* pEffect = new m_IDirectInputEffect((IDirectInputEffect*)*ppdeff);
m_IDirectInputEffect* pEffect = CreateEffectWrapper((IDirectInputEffect*)*ppdeff);
pEffect->SetVersion(diVersion);

*ppdeff = pEffect;
Expand All @@ -756,7 +790,7 @@ HRESULT m_IDirectInputDeviceX::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LP
{
Logging::LogDebug() << __FUNCTION__ << " (" << this << ") Failed! hr: " << (DIERR)hr;

m_IDirectInputEffect* pEffect = new m_IDirectInputEffect(nullptr);
m_IDirectInputEffect* pEffect = CreateEffectWrapper(nullptr);
effects.push_back(pEffect);

// Return an effect class even on failure becasue some games don't check for failure
Expand Down Expand Up @@ -902,3 +936,20 @@ HRESULT m_IDirectInputDeviceX::WriteEffectToFileX(V lpszFileName, DWORD dwEntrie

return GetProxyInterface<T>()->WriteEffectToFile(lpszFileName, dwEntries, rgDiFileEft, dwFlags);
}

void m_IDirectInputDeviceX::ReleaseDirectInput()
{
// Don't delete wrapper interface
if (StringType == ANSI_CHARSET)
{
SaveInterfaceAddress((m_IDirectInputDeviceA*&)WrapperInterface, DirectInputDeviceWrapperBackupA);
SaveInterfaceAddress((m_IDirectInputDevice2A*&)WrapperInterface2, DirectInputDeviceWrapperBackup2A);
SaveInterfaceAddress((m_IDirectInputDevice7A*&)WrapperInterface7, DirectInputDeviceWrapperBackup7A);
}
else
{
SaveInterfaceAddress((m_IDirectInputDeviceW*&)WrapperInterface, DirectInputDeviceWrapperBackupW);
SaveInterfaceAddress((m_IDirectInputDevice2W*&)WrapperInterface2, DirectInputDeviceWrapperBackup2W);
SaveInterfaceAddress((m_IDirectInputDevice7W*&)WrapperInterface7, DirectInputDeviceWrapperBackup7W);
}
}
36 changes: 7 additions & 29 deletions IDirectInputDeviceX.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ class m_IDirectInputDeviceX : public AddressLookupTableDinputObject
DWORD diVersion = 0;

// Version Interfaces
void *WrapperInterface;
void *WrapperInterface2;
void *WrapperInterface7;
void *WrapperInterface = nullptr;
void *WrapperInterface2 = nullptr;
void *WrapperInterface7 = nullptr;

// Vector to store instances of m_IDirectInputEffect
std::vector<m_IDirectInputEffect*> effects;
Expand Down Expand Up @@ -115,24 +115,13 @@ class m_IDirectInputDeviceX : public AddressLookupTableDinputObject
template <class T, class V>
inline HRESULT WriteEffectToFileX(V lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags);

void ReleaseDirectInput();

public:
m_IDirectInputDeviceX(IDirectInputDevice8W *aOriginal, REFIID riid) : ProxyInterface(aOriginal), WrapperID(riid), StringType(GetStringType(riid))
{
LOG_LIMIT(3, "Creating interface " << __FUNCTION__ << "(" << this << ")" << " converting interface from v" << GetGUIDVersion(riid) << " to v8 using " << ((StringType == ANSI_CHARSET) ? "ANSI" : "UNICODE"));

if (StringType == ANSI_CHARSET)
{
WrapperInterface = new m_IDirectInputDeviceA((LPDIRECTINPUTDEVICEA)ProxyInterface, this);
WrapperInterface2 = new m_IDirectInputDevice2A((LPDIRECTINPUTDEVICE2A)ProxyInterface, this);
WrapperInterface7 = new m_IDirectInputDevice7A((LPDIRECTINPUTDEVICE7A)ProxyInterface, this);
}
else
{
WrapperInterface = new m_IDirectInputDeviceW((LPDIRECTINPUTDEVICEW)ProxyInterface, this);
WrapperInterface2 = new m_IDirectInputDevice2W((LPDIRECTINPUTDEVICE2W)ProxyInterface, this);
WrapperInterface7 = new m_IDirectInputDevice7W((LPDIRECTINPUTDEVICE7W)ProxyInterface, this);
}

// Initialize Critical Section
InitializeCriticalSection(&dics);

Expand All @@ -142,26 +131,15 @@ class m_IDirectInputDeviceX : public AddressLookupTableDinputObject
{
LOG_LIMIT(3, __FUNCTION__ << " (" << this << ")" << " deleting interface!");

if (StringType == ANSI_CHARSET)
{
((m_IDirectInputA*)WrapperInterface)->DeleteMe();
((m_IDirectInput2A*)WrapperInterface2)->DeleteMe();
((m_IDirectInput7A*)WrapperInterface7)->DeleteMe();
}
else
{
((m_IDirectInputW*)WrapperInterface)->DeleteMe();
((m_IDirectInput2W*)WrapperInterface2)->DeleteMe();
((m_IDirectInput7W*)WrapperInterface7)->DeleteMe();
}

for (auto& entry : effects)
{
entry->DeleteMe();
}

// Delete Critical Section
DeleteCriticalSection(&dics);

ReleaseDirectInput();
}

/*** IUnknown methods ***/
Expand Down
61 changes: 43 additions & 18 deletions IDirectInputEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@

#include "dinputto8.h"

// Cached wrapper interface
m_IDirectInputEffect* DirectInputEffectWrapperBackup = nullptr;

m_IDirectInputEffect* CreateEffectWrapper(IDirectInputEffect* aOriginal)
{
SetCriticalSection();
m_IDirectInputEffect* Interface = nullptr;
if (DirectInputEffectWrapperBackup)
{
Interface = DirectInputEffectWrapperBackup;
if (aOriginal)
{
DirectInputEffectWrapperBackup = nullptr;
Interface->SetProxy(aOriginal);
}
}
else
{
Interface = new m_IDirectInputEffect(aOriginal);
if (!aOriginal)
{
Interface->SetProxy(nullptr);
DirectInputEffectWrapperBackup = Interface;
}
}
ReleaseCriticalSection();
return Interface;
}

HRESULT m_IDirectInputEffect::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
Logging::LogDebug() << __FUNCTION__ << " (" << this << ")";
Expand Down Expand Up @@ -48,7 +77,7 @@ ULONG m_IDirectInputEffect::AddRef()

if (!ProxyInterface)
{
return InterlockedIncrement(&Ref);
return 0;
}

return ProxyInterface->AddRef();
Expand All @@ -60,19 +89,15 @@ ULONG m_IDirectInputEffect::Release()

if (!ProxyInterface)
{
if (InterlockedCompareExchange(&Ref, 0, 0) == 0)
{
return 0;
}

return InterlockedDecrement(&Ref);
return 0;
}

ULONG ref = ProxyInterface->Release();

if (ref == 0)
{
delete this;
// Don't delete wrapper interface
SaveInterfaceAddress((m_IDirectInputEffect*&)WrapperInterface, DirectInputEffectWrapperBackup);
}

return ref;
Expand All @@ -84,7 +109,7 @@ HRESULT m_IDirectInputEffect::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGU

if (!ProxyInterface)
{
return DIERR_INCOMPLETEEFFECT;
return DIERR_OBJECTNOTFOUND;
}

HRESULT hr = hresValidInstanceAndVersion(hinst, dwVersion);
Expand All @@ -107,7 +132,7 @@ HRESULT m_IDirectInputEffect::GetEffectGuid(LPGUID pguid)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->GetEffectGuid(pguid);
Expand All @@ -119,7 +144,7 @@ HRESULT m_IDirectInputEffect::GetParameters(LPDIEFFECT lpeff, DWORD dwFlags)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

if (!lpeff || !lpeff->dwSize)
Expand All @@ -146,7 +171,7 @@ HRESULT m_IDirectInputEffect::SetParameters(LPCDIEFFECT lpeff, DWORD dwFlags)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

#ifdef _DEBUG
Expand Down Expand Up @@ -179,7 +204,7 @@ HRESULT m_IDirectInputEffect::Start(DWORD dwIterations, DWORD dwFlags)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

HRESULT hr = ProxyInterface->Start(dwIterations, dwFlags);
Expand All @@ -198,7 +223,7 @@ HRESULT m_IDirectInputEffect::Stop()

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->Stop();
Expand All @@ -210,7 +235,7 @@ HRESULT m_IDirectInputEffect::GetEffectStatus(LPDWORD pdwFlags)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->GetEffectStatus(pdwFlags);
Expand All @@ -222,7 +247,7 @@ HRESULT m_IDirectInputEffect::Download()

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->Download();
Expand All @@ -234,7 +259,7 @@ HRESULT m_IDirectInputEffect::Unload()

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->Unload();
Expand All @@ -246,7 +271,7 @@ HRESULT m_IDirectInputEffect::Escape(LPDIEFFESCAPE pesc)

if (!ProxyInterface)
{
return DIERR_NOTINITIALIZED;
return DIERR_OBJECTNOTFOUND;
}

return ProxyInterface->Escape(pesc);
Expand Down
Loading

0 comments on commit 9932160

Please sign in to comment.