From 8cf54703761f02f3050073bed485cc91f7713720 Mon Sep 17 00:00:00 2001 From: Elisha Riedlinger Date: Sun, 17 Feb 2019 04:29:45 -0800 Subject: [PATCH] Fix crash when array is used in dod Fix GetDeviceData() and SendDeviceData() functions --- BuildNo.rc | 2 +- IDirectInputDeviceX.cpp | 66 +++++++++++++++++++++++++++++++++++------ IDirectInputDeviceX.h | 10 +++++++ 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/BuildNo.rc b/BuildNo.rc index ad84f08..185863a 100644 --- a/BuildNo.rc +++ b/BuildNo.rc @@ -1 +1 @@ -#define BUILD_NUMBER 15 +#define BUILD_NUMBER 16 diff --git a/IDirectInputDeviceX.cpp b/IDirectInputDeviceX.cpp index 355f452..6fcde54 100644 --- a/IDirectInputDeviceX.cpp +++ b/IDirectInputDeviceX.cpp @@ -104,20 +104,42 @@ HRESULT m_IDirectInputDeviceX::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJEC { Logging::LogDebug() << __FUNCTION__ << "(" << this << ")"; - if (!rgdod || !cbObjectData || cbObjectData > sizeof(DIDEVICEOBJECTDATA)) + if (*pdwInOut == (DWORD)-1) { return DIERR_INVALIDPARAM; } - DIDEVICEOBJECTDATA dod; + // Verify that only one thrad can use the varable at a time + while (dodThreadFlag) {} + dodThreadFlag = true; - HRESULT hr = ProxyInterface->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &dod, pdwInOut, dwFlags); + // Check the size of the array + if (rgdod && *pdwInOut && *pdwInOut != dodSize) + { + if (pdod) + { + delete pdod; + } + + dodSize = *pdwInOut; + pdod = new DIDEVICEOBJECTDATA[dodSize]; + + Logging::LogDebug() << __FUNCTION__ << " Created dod memory! " << dodSize; + } - if (SUCCEEDED(hr)) + HRESULT hr = ProxyInterface->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), (rgdod) ? pdod : nullptr, pdwInOut, dwFlags); + + // Copy array + if (SUCCEEDED(hr) && rgdod && cbObjectData) { - CopyMemory(rgdod, &dod, cbObjectData); + for (UINT x = 0; x < *pdwInOut; x++) + { + CopyMemory((void*)((DWORD)rgdod + (cbObjectData * x)), &pdod[x], cbObjectData); + } } + dodThreadFlag = false; + return hr; } @@ -257,16 +279,42 @@ HRESULT m_IDirectInputDeviceX::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJ { Logging::LogDebug() << __FUNCTION__ << "(" << this << ")"; - if (!rgdod || !cbObjectData || cbObjectData > sizeof(DIDEVICEOBJECTDATA)) + if (*pdwInOut == (DWORD)-1) { return DIERR_INVALIDPARAM; } - DIDEVICEOBJECTDATA dod = { NULL }; + // Verify that only one thrad can use the varable at a time + while (dodThreadFlag) {} + dodThreadFlag = true; + + // Check the size of the array + if (rgdod && *pdwInOut && *pdwInOut != dodSize) + { + if (pdod) + { + delete pdod; + } + + dodSize = *pdwInOut; + pdod = new DIDEVICEOBJECTDATA[dodSize]; + + Logging::LogDebug() << __FUNCTION__ << " Created dod memory! " << dodSize; + } + + // Copy array + if (rgdod && cbObjectData) + { + ZeroMemory(pdod, sizeof(DIDEVICEOBJECTDATA) * dodSize); + for (UINT x = 0; x < *pdwInOut; x++) + { + CopyMemory(&pdod[x], (void*)((DWORD)rgdod + (cbObjectData * x)), cbObjectData); + } + } - CopyMemory(&dod, rgdod, cbObjectData); + HRESULT hr = ProxyInterface->SendDeviceData(sizeof(DIDEVICEOBJECTDATA), pdod, pdwInOut, fl); - HRESULT hr = ProxyInterface->SendDeviceData(sizeof(DIDEVICEOBJECTDATA), &dod, pdwInOut, fl); + dodThreadFlag = false; return hr; } diff --git a/IDirectInputDeviceX.h b/IDirectInputDeviceX.h index af41b98..61fea6b 100644 --- a/IDirectInputDeviceX.h +++ b/IDirectInputDeviceX.h @@ -10,6 +10,11 @@ class m_IDirectInputDeviceX DWORD StringType; ULONG RefCount = 1; + // For DeviceData + bool dodThreadFlag = false; + DIDEVICEOBJECTDATA *pdod = nullptr; + DWORD dodSize = 0; + public: m_IDirectInputDeviceX(IDirectInputDevice8W *aOriginal, DWORD Version, REFIID riid, m_IDirectInputDevice7W *Interface) : ProxyInterface(aOriginal), DirectXVersion(Version), WrapperID(riid), WrapperInterface(Interface) { @@ -20,6 +25,11 @@ class m_IDirectInputDeviceX ~m_IDirectInputDeviceX() { Logging::LogDebug() << __FUNCTION__ << "(" << this << ")" << " deleting device!"; + + if (pdod) + { + delete pdod; + } } // Helper functions