├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── AddressLookupTable.h ├── BuildNo.rc ├── IDirectInputDeviceX.cpp ├── IDirectInputDeviceX.h ├── IDirectInputEffect.cpp ├── IDirectInputEffect.h ├── IDirectInputTypes.cpp ├── IDirectInputTypes.h ├── IDirectInputX.cpp ├── IDirectInputX.h ├── Include ├── VersionHelpers.h ├── winapifamily.h └── winsdk-10 │ └── hidusage.h ├── InterfaceQuery.cpp ├── License.txt ├── Logging ├── License.txt ├── Logging.cpp └── Logging.h ├── README.md ├── Versions ├── IDirectInput2A.cpp ├── IDirectInput2A.h ├── IDirectInput2W.cpp ├── IDirectInput2W.h ├── IDirectInput7A.cpp ├── IDirectInput7A.h ├── IDirectInput7W.cpp ├── IDirectInput7W.h ├── IDirectInputA.cpp ├── IDirectInputA.h ├── IDirectInputDevice2A.cpp ├── IDirectInputDevice2A.h ├── IDirectInputDevice2W.cpp ├── IDirectInputDevice2W.h ├── IDirectInputDevice7A.cpp ├── IDirectInputDevice7A.h ├── IDirectInputDevice7W.cpp ├── IDirectInputDevice7W.h ├── IDirectInputDeviceA.cpp ├── IDirectInputDeviceA.h ├── IDirectInputDeviceW.cpp ├── IDirectInputDeviceW.h ├── IDirectInputW.cpp ├── IDirectInputW.h └── License.txt ├── dinput.def ├── dinputto8.cpp ├── dinputto8.h ├── dinputto8.rc ├── dinputto8.sln ├── dinputto8.vcxproj ├── dinputto8.vcxproj.filters ├── ditypes.h └── resource.h /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: [ "master" ] 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | UseMultiToolTask: true 14 | 15 | jobs: 16 | build: 17 | runs-on: windows-latest 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | config: [Workflow] 22 | platform: [Win32] 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | with: 27 | submodules: true 28 | - uses: microsoft/setup-msbuild@v1 29 | - uses: Trass3r/setup-cpp@master 30 | - name: Build 31 | run: msbuild /m /p:Configuration=${{ matrix.config }} /p:Platform=${{ matrix.platform }} dinputto8.sln 32 | - uses: actions/upload-artifact@v4 33 | with: 34 | name: ${{ matrix.config }} binaries 35 | path: | 36 | bin/${{ matrix.config }}/* 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | [Bb]in/* 3 | [Oo]bj/* 4 | [Bb]uild/* 5 | [Dd]ebug/* 6 | [Rr]elease/* 7 | [Ss]tub/[Dd]ebug/* 8 | [Ss]tub/[Rr]elease/* 9 | 10 | # Compiled Object files 11 | *.slo 12 | *.lo 13 | *.o 14 | *.obj 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Other Visual Studio files 21 | .vs/* 22 | RC* 23 | ipch/* 24 | *.ipch 25 | *.user 26 | *.suo 27 | *.aps 28 | *.log 29 | *.tlog 30 | *.exp 31 | *.ncb 32 | *.res 33 | *.sdf 34 | *.opensdf 35 | *.lastbuildstate 36 | *.ipsh 37 | *.idb 38 | *.db 39 | .opendb 40 | *.opendb 41 | *.TMP 42 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "External/Logging"] 2 | path = External/Logging 3 | url = https://github.com/elishacloud/Logging 4 | -------------------------------------------------------------------------------- /AddressLookupTable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "dinputto8.h" 6 | 7 | constexpr UINT MaxIndex = 16; 8 | 9 | template 10 | inline void SaveInterfaceAddress(T*& Interface, T*& InterfaceBackup) 11 | { 12 | if (Interface) 13 | { 14 | SetCriticalSection(); 15 | Interface->SetProxy(nullptr); 16 | if (InterfaceBackup) 17 | { 18 | InterfaceBackup->DeleteMe(); 19 | InterfaceBackup = nullptr; 20 | } 21 | InterfaceBackup = Interface; 22 | ReleaseCriticalSection(); 23 | } 24 | } 25 | 26 | template 27 | inline T* GetInterfaceAddress(T*& Interface, T*& InterfaceBackup, S* ProxyInterface, X* InterfaceX) 28 | { 29 | if (!Interface) 30 | { 31 | SetCriticalSection(); 32 | if (InterfaceBackup) 33 | { 34 | Interface = InterfaceBackup; 35 | InterfaceBackup = nullptr; 36 | Interface->SetProxy(InterfaceX); 37 | } 38 | else 39 | { 40 | Interface = new T(ProxyInterface, InterfaceX); 41 | } 42 | ReleaseCriticalSection(); 43 | } 44 | return Interface; 45 | } 46 | 47 | template 48 | class AddressLookupTableDinput 49 | { 50 | private: 51 | bool ConstructorFlag = false; 52 | std::unordered_map g_map[MaxIndex]; 53 | 54 | template 55 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 0; }; 56 | template <> 57 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 1; }; 58 | template <> 59 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 2; 60 | using Type1A = m_IDirectInputA; 61 | using Type2A = m_IDirectInput2A; 62 | using Type7A = m_IDirectInput7A; 63 | using Type1W = m_IDirectInputW; 64 | using Type2W = m_IDirectInput2W; 65 | using Type7W = m_IDirectInput7W; 66 | }; 67 | template <> 68 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 3; }; 69 | template <> 70 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 4; }; 71 | template <> 72 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 5; }; 73 | template <> 74 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 6; }; 75 | template <> 76 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 7; }; 77 | template <> 78 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 8; 79 | using Type1A = m_IDirectInputDeviceA; 80 | using Type2A = m_IDirectInputDevice2A; 81 | using Type7A = m_IDirectInputDevice7A; 82 | using Type1W = m_IDirectInputDeviceW; 83 | using Type2W = m_IDirectInputDevice2W; 84 | using Type7W = m_IDirectInputDevice7W; 85 | }; 86 | template <> 87 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 9; }; 88 | template <> 89 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 10; }; 90 | template <> 91 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 11; }; 92 | template <> 93 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 12; }; 94 | template <> 95 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 13; }; 96 | template <> 97 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 14; }; 98 | template <> 99 | struct AddressCacheIndex { static constexpr UINT CacheIndex = 15; }; 100 | 101 | void DeleteAll() 102 | { 103 | for (const auto& x : { 13, 14, 15 }) 104 | { 105 | for (const auto& entry : g_map[x]) 106 | { 107 | entry.second->DeleteMe(); 108 | } 109 | } 110 | } 111 | 112 | template 113 | T *FindAddressVersion(void *Proxy, REFIID riid) 114 | { 115 | T *Interface = FindAddressAllInterfaces(Proxy); 116 | 117 | if (!Interface) 118 | { 119 | X *InterfaceX = new X((I*)Proxy, riid); 120 | 121 | Interface = (T*)InterfaceX->GetWrapperInterfaceX(GetGUIDVersion(riid)); 122 | } 123 | 124 | return Interface; 125 | } 126 | 127 | template 128 | T *FindAddressPrivate(void *Proxy) 129 | { 130 | T *Interface = FindAddressAllInterfaces(Proxy); 131 | 132 | if (!Interface) 133 | { 134 | Interface = new T(static_cast(Proxy)); 135 | } 136 | 137 | return Interface; 138 | } 139 | template <> 140 | m_IDirectInputA *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputA); } 141 | template <> 142 | m_IDirectInputW *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputW); } 143 | template <> 144 | m_IDirectInput2A *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInput2A); } 145 | template <> 146 | m_IDirectInput2W *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInput2W); } 147 | template <> 148 | m_IDirectInput7A *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInput7A); } 149 | template <> 150 | m_IDirectInput7W *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInput7W); } 151 | template <> 152 | m_IDirectInputDeviceA *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDeviceA); } 153 | template <> 154 | m_IDirectInputDeviceW *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDeviceW); } 155 | template <> 156 | m_IDirectInputDevice2A *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDevice2A); } 157 | template <> 158 | m_IDirectInputDevice2W *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDevice2W); } 159 | template <> 160 | m_IDirectInputDevice7A *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDevice7A); } 161 | template <> 162 | m_IDirectInputDevice7W *FindAddressPrivate(void *Proxy) { return FindAddressVersion(Proxy, IID_IDirectInputDevice7W); } 163 | 164 | template 165 | T *FindAddressAllInterfaces(void *Proxy) 166 | { 167 | constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; 168 | auto it = g_map[CacheIndex].find(Proxy); 169 | 170 | if (it != std::end(g_map[CacheIndex])) 171 | { 172 | Logging::LogDebug() << __FUNCTION__ << " Found device address!"; 173 | return static_cast(it->second); 174 | } 175 | 176 | return nullptr; 177 | } 178 | 179 | public: 180 | explicit AddressLookupTableDinput() {} 181 | ~AddressLookupTableDinput() 182 | { 183 | ConstructorFlag = true; 184 | void DeleteAll(); 185 | } 186 | 187 | template 188 | T *FindAddress(void *Proxy, DWORD Version, DWORD Type) 189 | { 190 | switch (Type) 191 | { 192 | case ANSI_CHARSET: 193 | { 194 | switch (Version) 195 | { 196 | case 1: 197 | return (T*)FindAddress::Type1A>(Proxy); 198 | case 2: 199 | return (T*)FindAddress::Type2A>(Proxy); 200 | case 7: 201 | return (T*)FindAddress::Type7A>(Proxy); 202 | default: 203 | return nullptr; 204 | } 205 | } 206 | case UNICODE_CHARSET: 207 | { 208 | switch (Version) 209 | { 210 | case 1: 211 | return (T*)FindAddress::Type1W>(Proxy); 212 | case 2: 213 | return (T*)FindAddress::Type2W>(Proxy); 214 | case 7: 215 | return (T*)FindAddress::Type7W>(Proxy); 216 | default: 217 | return nullptr; 218 | } 219 | } 220 | default: 221 | return nullptr; 222 | } 223 | } 224 | 225 | template 226 | T *FindAddress(void *Proxy) 227 | { 228 | if (!Proxy) 229 | { 230 | return nullptr; 231 | } 232 | 233 | return FindAddressPrivate(Proxy); 234 | } 235 | 236 | template 237 | void SaveAddress(T *Wrapper, void *Proxy) 238 | { 239 | constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; 240 | if (Wrapper && Proxy) 241 | { 242 | g_map[CacheIndex][Proxy] = Wrapper; 243 | } 244 | } 245 | 246 | template 247 | void DeleteAddress(T *Wrapper) 248 | { 249 | if (!Wrapper || ConstructorFlag) 250 | { 251 | return; 252 | } 253 | 254 | constexpr UINT CacheIndex = AddressCacheIndex::CacheIndex; 255 | auto it = std::find_if(g_map[CacheIndex].begin(), g_map[CacheIndex].end(), 256 | [=](auto& Map) -> bool { return Map.second == Wrapper; }); 257 | 258 | if (it != std::end(g_map[CacheIndex])) 259 | { 260 | it = g_map[CacheIndex].erase(it); 261 | } 262 | } 263 | }; 264 | 265 | class AddressLookupTableDinputObject 266 | { 267 | public: 268 | virtual ~AddressLookupTableDinputObject() { } 269 | 270 | void DeleteMe() 271 | { 272 | delete this; 273 | } 274 | }; 275 | -------------------------------------------------------------------------------- /BuildNo.rc: -------------------------------------------------------------------------------- 1 | #define BUILD_NUMBER 85 2 | -------------------------------------------------------------------------------- /IDirectInputDeviceX.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class m_IDirectInputDeviceX : public AddressLookupTableDinputObject 7 | { 8 | private: 9 | IDirectInputDevice8W *ProxyInterface; 10 | const IID WrapperID; 11 | DWORD StringType; 12 | 13 | // Requested DirectInput version - used to alter behaviour by requested version 14 | DWORD diVersion = 0; 15 | 16 | // Version Interfaces 17 | void *WrapperInterface = nullptr; 18 | void *WrapperInterface2 = nullptr; 19 | void *WrapperInterface7 = nullptr; 20 | 21 | // For SetCooperativeLevel 22 | bool IsMouse = false; 23 | 24 | // Format memory 25 | DWORD Offset = 0; 26 | 27 | // For data format fixups 28 | DWORD DevType7 = 0; 29 | 30 | // Critical section for shared memory 31 | CRITICAL_SECTION dics = {}; 32 | 33 | // For DeviceData 34 | std::vector pdod; 35 | 36 | // For EnumObjects 37 | struct ObjectOrderValue 38 | { 39 | DWORD dwOfs = 0; 40 | DWORD dwSortOrder = MAXDWORD; 41 | }; 42 | using EnumObjectDataMap = std::map; 43 | EnumObjectDataMap EnumObjectDataLUT; 44 | DWORD OffsetForMissingObjects = 0; // -1 after the data format is set 45 | 46 | void InitializeEnumObjectData(); 47 | void SetEnumObjectDataFromFormat(LPCDIDATAFORMAT lpdf); 48 | 49 | template 50 | inline void CopyDeviceData(T* DestDod, DIDEVICEOBJECTDATA* SrcDod, DWORD dwNumRecords) 51 | { 52 | for (UINT x = 0; x < dwNumRecords; x++) 53 | { 54 | *DestDod = *(T*)SrcDod; 55 | SrcDod = (DIDEVICEOBJECTDATA*)((DWORD)SrcDod + sizeof(DIDEVICEOBJECTDATA)); 56 | DestDod = (T*)((DWORD)DestDod + sizeof(T)); 57 | } 58 | } 59 | inline void CopyDeviceData(DIDEVICEOBJECTDATA* DestDod, DIDEVICEOBJECTDATA_DX3* SrcDod, DWORD dwNumRecords) 60 | { 61 | for (UINT x = 0; x < dwNumRecords; x++) 62 | { 63 | *(DIDEVICEOBJECTDATA_DX3*)DestDod = *SrcDod; 64 | DestDod->uAppData = NULL; 65 | SrcDod = (DIDEVICEOBJECTDATA_DX3*)((DWORD)SrcDod + sizeof(DIDEVICEOBJECTDATA_DX3)); 66 | DestDod = (DIDEVICEOBJECTDATA*)((DWORD)DestDod + sizeof(DIDEVICEOBJECTDATA)); 67 | } 68 | } 69 | 70 | // Wrapper interface functions 71 | inline REFIID GetWrapperType(DWORD DirectXVersion) 72 | { 73 | return (StringType == ANSI_CHARSET) ? 74 | ((DirectXVersion == 1) ? IID_IDirectInputDeviceA : 75 | (DirectXVersion == 2) ? IID_IDirectInputDevice2A : 76 | (DirectXVersion == 7) ? IID_IDirectInputDevice7A : IID_IUnknown) : 77 | ((DirectXVersion == 1) ? IID_IDirectInputDeviceW : 78 | (DirectXVersion == 2) ? IID_IDirectInputDevice2W : 79 | (DirectXVersion == 7) ? IID_IDirectInputDevice7W : IID_IUnknown); 80 | } 81 | inline bool CheckWrapperType(REFIID IID) 82 | { 83 | return (StringType == ANSI_CHARSET) ? 84 | ((IID == IID_IDirectInputDeviceA || 85 | IID == IID_IDirectInputDevice2A || 86 | IID == IID_IDirectInputDevice7A) ? true : false) : 87 | ((IID == IID_IDirectInputDeviceW || 88 | IID == IID_IDirectInputDevice2W || 89 | IID == IID_IDirectInputDevice7W) ? true : false); 90 | } 91 | template 92 | inline auto *GetProxyInterface() { return (T*)ProxyInterface; } 93 | 94 | template 95 | inline HRESULT EnumObjectsX(V lpCallback, LPVOID pvRef, DWORD dwFlags); 96 | 97 | template 98 | inline HRESULT GetObjectInfoX(V pdidoi, DWORD dwObj, DWORD dwHow); 99 | 100 | template 101 | inline HRESULT GetDeviceInfoX(V pdidi); 102 | 103 | template 104 | inline HRESULT EnumEffectsX(V lpCallback, LPVOID pvRef, DWORD dwEffType); 105 | 106 | template 107 | inline HRESULT GetEffectInfoX(V pdei, REFGUID rguid); 108 | 109 | template 110 | inline HRESULT EnumEffectsInFileX(V lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags); 111 | 112 | template 113 | inline HRESULT WriteEffectToFileX(V lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags); 114 | 115 | void ReleaseInterface(); 116 | 117 | public: 118 | m_IDirectInputDeviceX(IDirectInputDevice8W *aOriginal, REFIID riid) : ProxyInterface(aOriginal), WrapperID(riid), StringType(GetStringType(riid)) 119 | { 120 | LOG_LIMIT(3, "Creating interface " << __FUNCTION__ << "(" << this << ")" << " converting interface from v" << GetGUIDVersion(riid) << " to v8 using " << ((StringType == ANSI_CHARSET) ? "ANSI" : "UNICODE")); 121 | 122 | // Initialize Critical Section 123 | InitializeCriticalSection(&dics); 124 | 125 | InitializeEnumObjectData(); 126 | } 127 | ~m_IDirectInputDeviceX() 128 | { 129 | LOG_LIMIT(3, __FUNCTION__ << " (" << this << ")" << " deleting interface!"); 130 | 131 | // Delete Critical Section 132 | DeleteCriticalSection(&dics); 133 | 134 | ReleaseInterface(); 135 | } 136 | 137 | /*** IUnknown methods ***/ 138 | STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj, DWORD DirectXVersion); 139 | STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) { return QueryInterface(riid, ppvObj, GetGUIDVersion(riid)); } 140 | STDMETHOD_(ULONG, AddRef)(THIS); 141 | STDMETHOD_(ULONG, Release)(THIS); 142 | 143 | /*** IDirectInputDevice methods ***/ 144 | template 145 | HRESULT GetCapabilities(T lpDIDevCaps); 146 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 147 | { 148 | return EnumObjectsX(lpCallback, pvRef, dwFlags); 149 | } 150 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 151 | { 152 | return EnumObjectsX(lpCallback, pvRef, dwFlags); 153 | } 154 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 155 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 156 | STDMETHOD(Acquire)(THIS); 157 | STDMETHOD(Unacquire)(THIS); 158 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 159 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 160 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 161 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 162 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 163 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) 164 | { 165 | return GetObjectInfoX(pdidoi, dwObj, dwHow); 166 | } 167 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) 168 | { 169 | return GetObjectInfoX(pdidoi, dwObj, dwHow); 170 | } 171 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA pdidi) 172 | { 173 | return GetDeviceInfoX(pdidi); 174 | } 175 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW pdidi) 176 | { 177 | return GetDeviceInfoX(pdidi); 178 | } 179 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 180 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 181 | 182 | /*** IDirectInputDevice2 methods ***/ 183 | STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); 184 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) 185 | { 186 | return EnumEffectsX(lpCallback, pvRef, dwEffType); 187 | } 188 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) 189 | { 190 | return EnumEffectsX(lpCallback, pvRef, dwEffType); 191 | } 192 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA pdei, REFGUID rguid) 193 | { 194 | return GetEffectInfoX(pdei, rguid); 195 | } 196 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW pdei, REFGUID rguid) 197 | { 198 | return GetEffectInfoX(pdei, rguid); 199 | } 200 | STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); 201 | STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); 202 | STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); 203 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 204 | STDMETHOD(Poll)(THIS); 205 | STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); 206 | 207 | /*** IDirectInputDevice7 methods ***/ 208 | STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) 209 | { 210 | return EnumEffectsInFileX(lpszFileName, pec, pvRef, dwFlags); 211 | } 212 | STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) 213 | { 214 | return EnumEffectsInFileX(lpszFileName, pec, pvRef, dwFlags); 215 | } 216 | STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) 217 | { 218 | return WriteEffectToFileX(lpszFileName, dwEntries, rgDiFileEft, dwFlags); 219 | } 220 | STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) 221 | { 222 | return WriteEffectToFileX(lpszFileName, dwEntries, rgDiFileEft, dwFlags); 223 | } 224 | 225 | // Helper functions 226 | LPVOID GetWrapperInterfaceX(DWORD DXVersion); 227 | 228 | void SetVersion(DWORD dwVersion) { diVersion = dwVersion; } 229 | void SetAsMouse() { IsMouse = true; } 230 | }; 231 | -------------------------------------------------------------------------------- /IDirectInputEffect.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "dinputto8.h" 18 | 19 | // Cached wrapper interface 20 | namespace { 21 | m_IDirectInputEffect* WrapperInterfaceBackup = nullptr; 22 | } 23 | 24 | m_IDirectInputEffect* CreateEffectWrapper(IDirectInputEffect* aOriginal) 25 | { 26 | SetCriticalSection(); 27 | m_IDirectInputEffect* Interface = nullptr; 28 | if (WrapperInterfaceBackup) 29 | { 30 | Interface = WrapperInterfaceBackup; 31 | if (aOriginal) 32 | { 33 | WrapperInterfaceBackup = nullptr; 34 | Interface->SetProxy(aOriginal); 35 | } 36 | } 37 | else 38 | { 39 | Interface = new m_IDirectInputEffect(aOriginal); 40 | if (!aOriginal) 41 | { 42 | Interface->SetProxy(nullptr); 43 | WrapperInterfaceBackup = Interface; 44 | } 45 | } 46 | ReleaseCriticalSection(); 47 | return Interface; 48 | } 49 | 50 | HRESULT m_IDirectInputEffect::QueryInterface(REFIID riid, LPVOID * ppvObj) 51 | { 52 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 53 | 54 | if (!ProxyInterface) 55 | { 56 | if (ppvObj) 57 | { 58 | *ppvObj = nullptr; 59 | } 60 | return E_NOINTERFACE; 61 | } 62 | 63 | return ProxyQueryInterface(ProxyInterface, riid, ppvObj, WrapperID, WrapperInterface); 64 | } 65 | 66 | ULONG m_IDirectInputEffect::AddRef() 67 | { 68 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 69 | 70 | if (!ProxyInterface) 71 | { 72 | return 0; 73 | } 74 | 75 | return ProxyInterface->AddRef(); 76 | } 77 | 78 | ULONG m_IDirectInputEffect::Release() 79 | { 80 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 81 | 82 | if (!ProxyInterface) 83 | { 84 | return 0; 85 | } 86 | 87 | ULONG ref = ProxyInterface->Release(); 88 | 89 | if (ref == 0) 90 | { 91 | // Don't delete wrapper interface 92 | SaveInterfaceAddress((m_IDirectInputEffect*&)WrapperInterface, WrapperInterfaceBackup); 93 | } 94 | 95 | return ref; 96 | } 97 | 98 | HRESULT m_IDirectInputEffect::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 99 | { 100 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 101 | 102 | if (!ProxyInterface) 103 | { 104 | return DIERR_OBJECTNOTFOUND; 105 | } 106 | 107 | HRESULT hr = hresValidInstanceAndVersion(hinst, dwVersion); 108 | if (SUCCEEDED(hr)) 109 | { 110 | hr = ProxyInterface->Initialize(hinst, 0x0800, rguid); 111 | 112 | if (SUCCEEDED(hr)) 113 | { 114 | diVersion = dwVersion; 115 | } 116 | } 117 | 118 | return hr; 119 | } 120 | 121 | HRESULT m_IDirectInputEffect::GetEffectGuid(LPGUID pguid) 122 | { 123 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 124 | 125 | if (!ProxyInterface) 126 | { 127 | return DIERR_OBJECTNOTFOUND; 128 | } 129 | 130 | return ProxyInterface->GetEffectGuid(pguid); 131 | } 132 | 133 | HRESULT m_IDirectInputEffect::GetParameters(LPDIEFFECT lpeff, DWORD dwFlags) 134 | { 135 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 136 | 137 | if (!ProxyInterface) 138 | { 139 | return DIERR_OBJECTNOTFOUND; 140 | } 141 | 142 | if (!lpeff || !lpeff->dwSize) 143 | { 144 | return DIERR_INVALIDPARAM; 145 | } 146 | 147 | DIEFFECT eff = {}; 148 | eff.dwSize = sizeof(DIEFFECT); 149 | 150 | HRESULT hr = ProxyInterface->GetParameters(&eff, dwFlags); 151 | 152 | if (SUCCEEDED(hr)) 153 | { 154 | CopyMemory(lpeff, &eff, min(lpeff->dwSize, sizeof(DIEFFECT))); 155 | } 156 | 157 | return hr; 158 | } 159 | 160 | HRESULT m_IDirectInputEffect::SetParameters(LPCDIEFFECT lpeff, DWORD dwFlags) 161 | { 162 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ") Trying! " << Logging::hex(dwFlags); 163 | 164 | if (!ProxyInterface) 165 | { 166 | return DIERR_OBJECTNOTFOUND; 167 | } 168 | 169 | #ifdef _DEBUG 170 | GUID guid; 171 | GetEffectGuid(&guid); 172 | LogEffectFormat(lpeff, guid); 173 | #endif // DEBUG 174 | 175 | DIEFFECT eff = {}; 176 | if (lpeff && lpeff->dwSize == sizeof(DIEFFECT_DX5)) 177 | { 178 | *(DIEFFECT_DX5*)&eff = *(DIEFFECT_DX5*)lpeff; 179 | eff.dwSize = sizeof(DIEFFECT); 180 | lpeff = &eff; 181 | } 182 | 183 | HRESULT hr = ProxyInterface->SetParameters(lpeff, dwFlags); 184 | 185 | if (FAILED(hr)) 186 | { 187 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ") Failed! hr: " << (DIERR)hr; 188 | } 189 | 190 | return hr; 191 | } 192 | 193 | HRESULT m_IDirectInputEffect::Start(DWORD dwIterations, DWORD dwFlags) 194 | { 195 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ") Trying! " << dwIterations << " " << Logging::hex(dwFlags); 196 | 197 | if (!ProxyInterface) 198 | { 199 | return DIERR_OBJECTNOTFOUND; 200 | } 201 | 202 | HRESULT hr = ProxyInterface->Start(dwIterations, dwFlags); 203 | 204 | if (FAILED(hr)) 205 | { 206 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ") Failed! hr: " << (DIERR)hr; 207 | } 208 | 209 | return hr; 210 | } 211 | 212 | HRESULT m_IDirectInputEffect::Stop() 213 | { 214 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 215 | 216 | if (!ProxyInterface) 217 | { 218 | return DIERR_OBJECTNOTFOUND; 219 | } 220 | 221 | return ProxyInterface->Stop(); 222 | } 223 | 224 | HRESULT m_IDirectInputEffect::GetEffectStatus(LPDWORD pdwFlags) 225 | { 226 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 227 | 228 | if (!ProxyInterface) 229 | { 230 | return DIERR_OBJECTNOTFOUND; 231 | } 232 | 233 | return ProxyInterface->GetEffectStatus(pdwFlags); 234 | } 235 | 236 | HRESULT m_IDirectInputEffect::Download() 237 | { 238 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 239 | 240 | if (!ProxyInterface) 241 | { 242 | return DIERR_OBJECTNOTFOUND; 243 | } 244 | 245 | return ProxyInterface->Download(); 246 | } 247 | 248 | HRESULT m_IDirectInputEffect::Unload() 249 | { 250 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 251 | 252 | if (!ProxyInterface) 253 | { 254 | return DIERR_OBJECTNOTFOUND; 255 | } 256 | 257 | return ProxyInterface->Unload(); 258 | } 259 | 260 | HRESULT m_IDirectInputEffect::Escape(LPDIEFFESCAPE pesc) 261 | { 262 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 263 | 264 | if (!ProxyInterface) 265 | { 266 | return DIERR_OBJECTNOTFOUND; 267 | } 268 | 269 | return ProxyInterface->Escape(pesc); 270 | } 271 | -------------------------------------------------------------------------------- /IDirectInputEffect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | m_IDirectInputEffect* CreateEffectWrapper(IDirectInputEffect* aOriginal); 4 | 5 | class m_IDirectInputEffect : public IDirectInputEffect, public AddressLookupTableDinputObject 6 | { 7 | private: 8 | IDirectInputEffect *ProxyInterface; 9 | m_IDirectInputEffect *WrapperInterface; 10 | const IID WrapperID = IID_IDirectInputEffect; 11 | 12 | // Requested DirectInput version - used to alter behaviour by requested version 13 | DWORD diVersion = 0; 14 | 15 | public: 16 | m_IDirectInputEffect(IDirectInputEffect *aOriginal) : ProxyInterface(aOriginal), WrapperInterface(this) 17 | { 18 | LOG_LIMIT(3, "Creating interface " << __FUNCTION__ << " (" << this << ")"); 19 | 20 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 21 | } 22 | ~m_IDirectInputEffect() 23 | { 24 | LOG_LIMIT(3, __FUNCTION__ << " (" << this << ")" << " deleting interface!"); 25 | 26 | ProxyAddressLookupTable.DeleteAddress(this); 27 | } 28 | 29 | void SetProxy(IDirectInputEffect* NewProxyInterface) 30 | { 31 | ProxyInterface = NewProxyInterface; 32 | if (NewProxyInterface) 33 | { 34 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 35 | } 36 | else 37 | { 38 | ProxyAddressLookupTable.DeleteAddress(this); 39 | } 40 | } 41 | 42 | /*** IUnknown methods ***/ 43 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 44 | STDMETHOD_(ULONG, AddRef)(THIS); 45 | STDMETHOD_(ULONG, Release)(THIS); 46 | 47 | /*** IDirectInputEffect methods ***/ 48 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 49 | STDMETHOD(GetEffectGuid)(THIS_ LPGUID); 50 | STDMETHOD(GetParameters)(THIS_ LPDIEFFECT, DWORD); 51 | STDMETHOD(SetParameters)(THIS_ LPCDIEFFECT, DWORD); 52 | STDMETHOD(Start)(THIS_ DWORD, DWORD); 53 | STDMETHOD(Stop)(THIS); 54 | STDMETHOD(GetEffectStatus)(THIS_ LPDWORD); 55 | STDMETHOD(Download)(THIS); 56 | STDMETHOD(Unload)(THIS); 57 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 58 | 59 | // Helper functions 60 | void SetVersion(DWORD dwVersion) 61 | { 62 | diVersion = dwVersion; 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /IDirectInputTypes.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "dinputto8.h" 18 | #include 19 | 20 | namespace dinputto8 21 | { 22 | CRITICAL_SECTION dics; 23 | bool IsInitialized = false; 24 | } 25 | 26 | const DIDATAFORMAT c_dfDIKeyboard = { 27 | sizeof(DIDATAFORMAT), 28 | sizeof(DIOBJECTDATAFORMAT), 29 | DIDF_RELAXIS, 30 | MAX_KEYBAORD, 31 | sizeof(dfDIKeyboard) / sizeof(*dfDIKeyboard), 32 | (LPDIOBJECTDATAFORMAT)dfDIKeyboard 33 | }; 34 | 35 | const DIDATAFORMAT c_dfDIMouse = { 36 | sizeof(DIDATAFORMAT), 37 | sizeof(DIOBJECTDATAFORMAT), 38 | DIDF_RELAXIS, 39 | sizeof(DIMOUSESTATE), 40 | sizeof(dfDIMouse) / sizeof(*dfDIMouse), 41 | (LPDIOBJECTDATAFORMAT)dfDIMouse 42 | }; 43 | 44 | const DIDATAFORMAT c_dfDIMouse2 = { 45 | sizeof(DIDATAFORMAT), 46 | sizeof(DIOBJECTDATAFORMAT), 47 | DIDF_RELAXIS, 48 | sizeof(DIMOUSESTATE2), 49 | sizeof(dfDIMouse2) / sizeof(*dfDIMouse2), 50 | (LPDIOBJECTDATAFORMAT)dfDIMouse2 51 | }; 52 | 53 | const DIDATAFORMAT c_dfDIJoystick = { 54 | sizeof(DIDATAFORMAT), 55 | sizeof(DIOBJECTDATAFORMAT), 56 | DIDF_ABSAXIS, 57 | sizeof(DIJOYSTATE), 58 | sizeof(dfDIJoystick) / sizeof(*dfDIJoystick), 59 | (LPDIOBJECTDATAFORMAT)dfDIJoystick 60 | }; 61 | 62 | const DIDATAFORMAT c_dfDIJoystick2 = { 63 | sizeof(DIDATAFORMAT), 64 | sizeof(DIOBJECTDATAFORMAT), 65 | DIDF_ABSAXIS, 66 | sizeof(DIJOYSTATE2), 67 | sizeof(dfDIJoystick2) / sizeof(*dfDIJoystick2), 68 | (LPDIOBJECTDATAFORMAT)dfDIJoystick2 69 | }; 70 | 71 | DWORD ConvertDevTypeTo7(DWORD dwDevType, WORD wUsagePage, WORD wUsage, BOOL isHID, BOOL& IsGamepad) 72 | { 73 | IsGamepad = FALSE; 74 | switch (dwDevType) 75 | { 76 | case DIDEVTYPE_DEVICE: 77 | case DI8DEVTYPE_DEVICE: 78 | case DI8DEVTYPE_DEVICECTRL: 79 | default: 80 | if (isHID && wUsagePage == HID_USAGE_PAGE_GENERIC) 81 | { 82 | if (wUsage == HID_USAGE_GENERIC_MOUSE) 83 | { 84 | return DIDEVTYPE_MOUSE; 85 | } 86 | else if (wUsage == HID_USAGE_GENERIC_JOYSTICK) 87 | { 88 | return DIDEVTYPE_JOYSTICK; 89 | } 90 | else if (wUsage == HID_USAGE_GENERIC_GAMEPAD) 91 | { 92 | IsGamepad = TRUE; 93 | return DIDEVTYPE_JOYSTICK; 94 | } 95 | else if (wUsage == HID_USAGE_GENERIC_KEYBOARD) 96 | { 97 | return DIDEVTYPE_KEYBOARD; 98 | } 99 | } 100 | if (isHID && wUsagePage == HID_USAGE_PAGE_KEYBOARD) 101 | { 102 | return DIDEVTYPE_KEYBOARD; 103 | } 104 | return DIDEVTYPE_DEVICE; 105 | case DIDEVTYPE_MOUSE: 106 | case DI8DEVTYPE_MOUSE: 107 | return DIDEVTYPE_MOUSE; 108 | case DIDEVTYPE_KEYBOARD: 109 | case DI8DEVTYPE_KEYBOARD: 110 | return DIDEVTYPE_KEYBOARD; 111 | case DI8DEVTYPE_GAMEPAD: 112 | IsGamepad = TRUE; 113 | [[fallthrough]]; 114 | case DIDEVTYPE_JOYSTICK: 115 | case DI8DEVTYPE_JOYSTICK: 116 | case DI8DEVTYPE_DRIVING: 117 | case DI8DEVTYPE_FLIGHT: 118 | case DI8DEVTYPE_SUPPLEMENTAL: 119 | case DI8DEVTYPE_1STPERSON: 120 | case DI8DEVTYPE_SCREENPOINTER: 121 | case DI8DEVTYPE_REMOTE: 122 | return DIDEVTYPE_JOYSTICK; 123 | } 124 | } 125 | 126 | DWORD ConvertDevSubTypeTo7(DWORD dwDevType, DWORD dwDevType7, DWORD dwDevSubType, BOOL IsGamepad) 127 | { 128 | switch (dwDevType) 129 | { 130 | case DIDEVTYPE_DEVICE: 131 | case DI8DEVTYPE_DEVICE: 132 | case DI8DEVTYPE_DEVICECTRL: 133 | default: 134 | switch (dwDevType7) 135 | { 136 | case DIDEVTYPE_MOUSE: 137 | return DIDEVTYPEMOUSE_UNKNOWN; 138 | case DIDEVTYPE_KEYBOARD: 139 | return DIDEVTYPEKEYBOARD_UNKNOWN; 140 | case DIDEVTYPE_JOYSTICK: 141 | if (IsGamepad) 142 | return DIDEVTYPEJOYSTICK_GAMEPAD; 143 | else 144 | return DIDEVTYPEJOYSTICK_TRADITIONAL; 145 | } 146 | return 0; 147 | case DIDEVTYPE_MOUSE: 148 | case DI8DEVTYPE_MOUSE: 149 | switch (dwDevSubType) 150 | { 151 | case DI8DEVTYPEMOUSE_ABSOLUTE: 152 | return DIDEVTYPEMOUSE_TOUCHPAD; 153 | default: 154 | return dwDevSubType; 155 | } 156 | case DIDEVTYPE_KEYBOARD: 157 | case DI8DEVTYPE_KEYBOARD: 158 | return dwDevSubType; 159 | case DIDEVTYPE_JOYSTICK: 160 | case DI8DEVTYPE_JOYSTICK: 161 | return DIDEVTYPEJOYSTICK_TRADITIONAL; 162 | case DI8DEVTYPE_GAMEPAD: 163 | return DIDEVTYPEJOYSTICK_GAMEPAD; 164 | case DI8DEVTYPE_DRIVING: 165 | return DIDEVTYPEJOYSTICK_WHEEL; 166 | case DI8DEVTYPE_FLIGHT: 167 | return DIDEVTYPEJOYSTICK_FLIGHTSTICK; 168 | case DI8DEVTYPE_SUPPLEMENTAL: 169 | switch (dwDevSubType) 170 | { 171 | case DI8DEVTYPESUPPLEMENTAL_HEADTRACKER: 172 | return DIDEVTYPEJOYSTICK_HEADTRACKER; 173 | case DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS: 174 | return DIDEVTYPEJOYSTICK_RUDDER; 175 | default: 176 | return DIDEVTYPEJOYSTICK_UNKNOWN; 177 | } 178 | case DI8DEVTYPE_1STPERSON: 179 | case DI8DEVTYPE_SCREENPOINTER: 180 | case DI8DEVTYPE_REMOTE: 181 | return DIDEVTYPEJOYSTICK_UNKNOWN; 182 | } 183 | } 184 | 185 | void dinputto8::SetCriticalSection() 186 | { 187 | if (!IsInitialized) 188 | { 189 | InitializeCriticalSection(&dics); 190 | IsInitialized = true; 191 | } 192 | if (IsInitialized) 193 | { 194 | EnterCriticalSection(&dics); 195 | return; 196 | } 197 | } 198 | 199 | void dinputto8::ReleaseCriticalSection() 200 | { 201 | if (IsInitialized) 202 | { 203 | LeaveCriticalSection(&dics); 204 | return; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /IDirectInputTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | DWORD ConvertDevTypeTo7(DWORD dwDevType, WORD wUsagePage, WORD wUsage, BOOL isHID, BOOL& IsGamepad); 4 | DWORD ConvertDevSubTypeTo7(DWORD dwDevType, DWORD dwDevType7, DWORD dwDevSubType, BOOL IsGamepad); 5 | -------------------------------------------------------------------------------- /IDirectInputX.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "dinputto8.h" 18 | 19 | // Cached wrapper interface 20 | namespace { 21 | m_IDirectInputA* WrapperInterfaceBackupA = nullptr; 22 | m_IDirectInputW* WrapperInterfaceBackupW = nullptr; 23 | m_IDirectInput2A* WrapperInterfaceBackup2A = nullptr; 24 | m_IDirectInput2W* WrapperInterfaceBackup2W = nullptr; 25 | m_IDirectInput7A* WrapperInterfaceBackup7A = nullptr; 26 | m_IDirectInput7W* WrapperInterfaceBackup7W = nullptr; 27 | } 28 | 29 | HRESULT m_IDirectInputX::QueryInterface(REFIID riid, LPVOID FAR * ppvObj, DWORD DirectXVersion) 30 | { 31 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 32 | 33 | DWORD DxVersion = (CheckWrapperType(riid)) ? GetGUIDVersion(riid) : DirectXVersion; 34 | 35 | return ProxyQueryInterface(ProxyInterface, riid, ppvObj, GetWrapperType(DxVersion), GetWrapperInterfaceX(DxVersion)); 36 | } 37 | 38 | LPVOID m_IDirectInputX::GetWrapperInterfaceX(DWORD DirectXVersion) 39 | { 40 | switch (DirectXVersion) 41 | { 42 | case 0: 43 | if (WrapperInterface7) return WrapperInterface7; 44 | if (WrapperInterface2) return WrapperInterface2; 45 | if (WrapperInterface) return WrapperInterface; 46 | break; 47 | case 1: 48 | if (StringType == ANSI_CHARSET) 49 | { 50 | return GetInterfaceAddress((m_IDirectInputA*&)WrapperInterface, WrapperInterfaceBackupA, (LPDIRECTINPUTA)ProxyInterface, this); 51 | } 52 | else 53 | { 54 | return GetInterfaceAddress((m_IDirectInputW*&)WrapperInterface, WrapperInterfaceBackupW, (LPDIRECTINPUTW)ProxyInterface, this); 55 | } 56 | case 2: 57 | if (StringType == ANSI_CHARSET) 58 | { 59 | return GetInterfaceAddress((m_IDirectInput2A*&)WrapperInterface2, WrapperInterfaceBackup2A, (LPDIRECTINPUT2A)ProxyInterface, this); 60 | } 61 | else 62 | { 63 | return GetInterfaceAddress((m_IDirectInput2W*&)WrapperInterface2, WrapperInterfaceBackup2W, (LPDIRECTINPUT2W)ProxyInterface, this); 64 | } 65 | case 7: 66 | if (StringType == ANSI_CHARSET) 67 | { 68 | return GetInterfaceAddress((m_IDirectInput7A*&)WrapperInterface7, WrapperInterfaceBackup7A, (LPDIRECTINPUT7A)ProxyInterface, this); 69 | } 70 | else 71 | { 72 | return GetInterfaceAddress((m_IDirectInput7W*&)WrapperInterface7, WrapperInterfaceBackup7W, (LPDIRECTINPUT7W)ProxyInterface, this); 73 | } 74 | } 75 | LOG_LIMIT(100, __FUNCTION__ << " Error: wrapper interface version not found: " << DirectXVersion); 76 | return nullptr; 77 | } 78 | 79 | ULONG m_IDirectInputX::AddRef() 80 | { 81 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 82 | 83 | return ProxyInterface->AddRef(); 84 | } 85 | 86 | ULONG m_IDirectInputX::Release() 87 | { 88 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 89 | 90 | ULONG ref = ProxyInterface->Release(); 91 | 92 | if (ref == 0) 93 | { 94 | delete this; 95 | } 96 | 97 | return ref; 98 | } 99 | 100 | template HRESULT m_IDirectInputX::EnumDevicesX(DWORD, LPDIENUMDEVICESCALLBACKA, LPVOID, DWORD); 101 | template HRESULT m_IDirectInputX::EnumDevicesX(DWORD, LPDIENUMDEVICESCALLBACKW, LPVOID, DWORD); 102 | template 103 | HRESULT m_IDirectInputX::EnumDevicesX(DWORD dwDevType, V lpCallback, LPVOID pvRef, DWORD dwFlags) 104 | { 105 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 106 | 107 | if (!lpCallback) 108 | { 109 | return DIERR_INVALIDPARAM; 110 | } 111 | 112 | // Callback structure 113 | struct DeviceEnumerator 114 | { 115 | V lpCallback = nullptr; 116 | LPVOID pvRef = nullptr; 117 | DWORD diVersion = 0; 118 | 119 | static BOOL CALLBACK EnumDeviceCallback(const D *lpddi, LPVOID pvRef) 120 | { 121 | const DeviceEnumerator* self = static_cast(pvRef); 122 | DWORD devType = GET_DIDEVICE_TYPE(lpddi->dwDevType); 123 | DWORD devSubType = GET_DIDEVICE_SUBTYPE(lpddi->dwDevType); 124 | DWORD hidDevice = lpddi->dwDevType & DIDEVTYPE_HID; 125 | BOOL IsGamepad = FALSE; 126 | DWORD devType7 = ConvertDevTypeTo7(devType, lpddi->wUsagePage, lpddi->wUsage, hidDevice, IsGamepad); 127 | DWORD devSubType7 = ConvertDevSubTypeTo7(devType, devType7, devSubType, IsGamepad); 128 | 129 | // DirectInput 0x300 and earlier do not enumerate any game controllers 130 | if (devType7 == DIDEVTYPE_JOYSTICK && self->diVersion <= 0x300) 131 | { 132 | return DIENUM_CONTINUE; 133 | } 134 | 135 | D DI = {}; 136 | CopyMemory(&DI, lpddi, lpddi->dwSize); 137 | 138 | // Prevent DInput3 games from encountering a structure bigger than they might expect. 139 | DI.dwSize = self->diVersion >= 0x0500 ? sizeof(D) : sizeof(D_Old); 140 | 141 | DI.dwDevType = devType7 | (devSubType7 << 8) | hidDevice; 142 | 143 | // Filter unknown device types 144 | if (DI.dwDevType == 0x10001) 145 | { 146 | return DIENUM_CONTINUE; 147 | } 148 | 149 | return self->lpCallback(&DI, self->pvRef); 150 | } 151 | } CallbackContext; 152 | CallbackContext.pvRef = pvRef; 153 | CallbackContext.lpCallback = lpCallback; 154 | CallbackContext.diVersion = diVersion; 155 | 156 | // Reorder to send game devices first 157 | if (dwDevType == DI8DEVCLASS_ALL) 158 | { 159 | // Instead of directly calling the ProxyInterface here, we are adding some extra code to sort the devices. This is an exclusive fix 160 | // for a known bug in Rayman 2 that would prevent any gamepad from working. The fix has been extracted from this old VS 2010 project: 161 | // https://code.google.com/archive/p/noser-sandbox/source/default/source 162 | // There is only one download link with a zip file containing other projects too. You will find the extracted code in the 163 | // Rayman2InputFix_DirectInputA.cpp file from the Rayman2InputFix project. 164 | // Thanks to Nolan Check for the fix! 165 | 166 | // The bug: Rayman 2 expects EnumDevices to give results in a certain 167 | // order, where gamepads come before the keyboard. DirectInput makes 168 | // no guarantee about the order. 169 | // The fix: Call DirectInput's EnumDevices, then sort the results in 170 | // an order where gamepads come first, then give them to Rayman 2. 171 | 172 | // Get devices and sort them 173 | using DeviceInstanceList = std::list; 174 | 175 | DeviceInstanceList gameDevices; 176 | DeviceInstanceList allDevices; 177 | 178 | std::list> sortedDevices; 179 | { 180 | auto StoreCallback = [](const D *lpddi, LPVOID pvRef) -> BOOL 181 | { 182 | DeviceInstanceList* self = static_cast(pvRef); 183 | self->emplace_back(*lpddi); 184 | return DIENUM_CONTINUE; 185 | }; 186 | 187 | // DirectInput 0x300 and earlier do not enumerate any game controllers 188 | if (diVersion > 0x300) 189 | { 190 | HRESULT hr = GetProxyInterface()->EnumDevices(DI8DEVCLASS_GAMECTRL, StoreCallback, &gameDevices, dwFlags); 191 | if (FAILED(hr)) 192 | { 193 | return hr; 194 | } 195 | } 196 | 197 | HRESULT hr = GetProxyInterface()->EnumDevices(DI8DEVCLASS_ALL, StoreCallback, &allDevices, dwFlags); 198 | if (FAILED(hr)) 199 | { 200 | return hr; 201 | } 202 | 203 | // Add all devices in gameDevices 204 | for (const D& device : gameDevices) 205 | { 206 | sortedDevices.emplace_back(device); 207 | } 208 | 209 | // Then, add all devices in allDevices that aren't in gameDevices 210 | for (const D& device : allDevices) 211 | { 212 | if (std::find_if(gameDevices.begin(), gameDevices.end(), [&guidInstance = device.guidInstance](const D& e) 213 | { 214 | return e.guidInstance == guidInstance; 215 | }) == gameDevices.end()) 216 | { 217 | sortedDevices.emplace_back(device); 218 | } 219 | } 220 | } 221 | 222 | // Execute Callback 223 | for (const D& sortedDevice : sortedDevices) 224 | { 225 | Logging::LogDebug() << __FUNCTION__ << " Enumerating Product: " << sortedDevice.tszProductName << " Instance: " << sortedDevice.tszInstanceName; 226 | 227 | if (DeviceEnumerator::EnumDeviceCallback(&sortedDevice, &CallbackContext) == DIENUM_STOP) 228 | { 229 | break; 230 | } 231 | } 232 | 233 | return DI_OK; 234 | } 235 | 236 | return GetProxyInterface()->EnumDevices(dwDevType, DeviceEnumerator::EnumDeviceCallback, &CallbackContext, dwFlags); 237 | } 238 | 239 | HRESULT m_IDirectInputX::GetDeviceStatus(REFGUID rguidInstance) 240 | { 241 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 242 | 243 | return ProxyInterface->GetDeviceStatus(rguidInstance); 244 | } 245 | 246 | HRESULT m_IDirectInputX::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 247 | { 248 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 249 | 250 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 251 | } 252 | 253 | HRESULT m_IDirectInputX::Initialize(HINSTANCE hinst, DWORD dwVersion) 254 | { 255 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 256 | 257 | HRESULT hr = hresValidInstanceAndVersion(hinst, dwVersion); 258 | if (SUCCEEDED(hr)) 259 | { 260 | hr = ProxyInterface->Initialize(hinst, 0x0800); 261 | 262 | if (SUCCEEDED(hr)) 263 | { 264 | diVersion = dwVersion; 265 | } 266 | } 267 | 268 | return hr; 269 | } 270 | 271 | template HRESULT m_IDirectInputX::FindDeviceX(REFGUID, LPCSTR, LPGUID); 272 | template HRESULT m_IDirectInputX::FindDeviceX(REFGUID, LPCWSTR, LPGUID); 273 | template 274 | HRESULT m_IDirectInputX::FindDeviceX(REFGUID rguidClass, V ptszName, LPGUID pguidInstance) 275 | { 276 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ")"; 277 | 278 | return GetProxyInterface()->FindDevice(rguidClass, ptszName, pguidInstance); 279 | } 280 | 281 | template HRESULT m_IDirectInputX::CreateDeviceExX(REFGUID, REFIID, LPDIRECTINPUTDEVICE8A*, LPUNKNOWN); 282 | template HRESULT m_IDirectInputX::CreateDeviceExX(REFGUID, REFIID, LPDIRECTINPUTDEVICE8W*, LPUNKNOWN); 283 | template 284 | HRESULT m_IDirectInputX::CreateDeviceExX(REFGUID rguid, REFIID riid, V *ppvObj, LPUNKNOWN pUnkOuter) 285 | { 286 | Logging::LogDebug() << __FUNCTION__ << " (" << this << ") " << rguid; 287 | 288 | HRESULT hr = GetProxyInterface()->CreateDevice(rguid, ppvObj, pUnkOuter); 289 | 290 | if (SUCCEEDED(hr) && ppvObj) 291 | { 292 | m_IDirectInputDeviceX *DIDevice = new m_IDirectInputDeviceX((IDirectInputDevice8W*)*ppvObj, riid); 293 | DIDevice->SetVersion(diVersion); 294 | 295 | if (IsEqualIID(GUID_SysMouse, rguid) || IsEqualIID(GUID_SysMouseEm, rguid) || IsEqualIID(GUID_SysMouseEm2, rguid)) 296 | { 297 | DIDevice->SetAsMouse(); 298 | } 299 | 300 | *ppvObj = (V)DIDevice->GetWrapperInterfaceX(GetGUIDVersion(riid)); 301 | } 302 | 303 | return hr; 304 | } 305 | 306 | void m_IDirectInputX::ReleaseInterface() 307 | { 308 | // Don't delete wrapper interface 309 | if (StringType == ANSI_CHARSET) 310 | { 311 | SaveInterfaceAddress((m_IDirectInputA*&)WrapperInterface, WrapperInterfaceBackupA); 312 | SaveInterfaceAddress((m_IDirectInput2A*&)WrapperInterface2, WrapperInterfaceBackup2A); 313 | SaveInterfaceAddress((m_IDirectInput7A*&)WrapperInterface7, WrapperInterfaceBackup7A); 314 | } 315 | else 316 | { 317 | SaveInterfaceAddress((m_IDirectInputW*&)WrapperInterface, WrapperInterfaceBackupW); 318 | SaveInterfaceAddress((m_IDirectInput2W*&)WrapperInterface2, WrapperInterfaceBackup2W); 319 | SaveInterfaceAddress((m_IDirectInput7W*&)WrapperInterface7, WrapperInterfaceBackup7W); 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /IDirectInputX.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputX : public AddressLookupTableDinputObject 4 | { 5 | private: 6 | IDirectInput8W *ProxyInterface; 7 | const IID WrapperID; 8 | DWORD StringType; 9 | 10 | // Requested DirectInput version - used to alter behaviour by requested version 11 | DWORD diVersion = 0; 12 | 13 | // Version Interfaces 14 | void *WrapperInterface = nullptr; 15 | void *WrapperInterface2 = nullptr; 16 | void *WrapperInterface7 = nullptr; 17 | 18 | // Wrapper interface functions 19 | inline REFIID GetWrapperType(DWORD DirectXVersion) 20 | { 21 | return (StringType == ANSI_CHARSET) ? 22 | ((DirectXVersion == 1) ? IID_IDirectInputA : 23 | (DirectXVersion == 2) ? IID_IDirectInput2A : 24 | (DirectXVersion == 7) ? IID_IDirectInput7A : IID_IUnknown) : 25 | ((DirectXVersion == 1) ? IID_IDirectInputW : 26 | (DirectXVersion == 2) ? IID_IDirectInput2W : 27 | (DirectXVersion == 7) ? IID_IDirectInput7W : IID_IUnknown); 28 | } 29 | inline bool CheckWrapperType(REFIID IID) 30 | { 31 | return (StringType == ANSI_CHARSET) ? 32 | ((IID == IID_IDirectInputA || 33 | IID == IID_IDirectInput2A || 34 | IID == IID_IDirectInput7A) ? true : false) : 35 | ((IID == IID_IDirectInputW || 36 | IID == IID_IDirectInput2W || 37 | IID == IID_IDirectInput7W) ? true : false); 38 | } 39 | template 40 | inline auto *GetProxyInterface() { return (T*)ProxyInterface; } 41 | 42 | template 43 | inline HRESULT EnumDevicesX(DWORD, V, LPVOID, DWORD); 44 | 45 | template 46 | inline HRESULT FindDeviceX(REFGUID rguidClass, V ptszName, LPGUID pguidInstance); 47 | 48 | template 49 | inline HRESULT CreateDeviceExX(REFGUID rguid, REFIID riid, V *ppvObj, LPUNKNOWN pUnkOuter); 50 | 51 | void ReleaseInterface(); 52 | 53 | public: 54 | m_IDirectInputX(IDirectInput8W *aOriginal, REFIID riid) : ProxyInterface(aOriginal), WrapperID(riid), StringType(GetStringType(riid)) 55 | { 56 | LOG_LIMIT(3, "Creating interface " << __FUNCTION__ << "(" << this << ")" << " converting interface from v" << GetGUIDVersion(riid) << " to v8 using " << ((StringType == ANSI_CHARSET) ? "ANSI" : "UNICODE")); 57 | } 58 | ~m_IDirectInputX() 59 | { 60 | LOG_LIMIT(3, __FUNCTION__ << " (" << this << ")" << " deleting interface!"); 61 | 62 | ReleaseInterface(); 63 | } 64 | 65 | /*** IUnknown methods ***/ 66 | STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj, DWORD DirectXVersion); 67 | STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) { return QueryInterface(riid, ppvObj, GetGUIDVersion(riid)); } 68 | STDMETHOD_(ULONG, AddRef)(THIS); 69 | STDMETHOD_(ULONG, Release)(THIS); 70 | 71 | /*** IDirectInput methods ***/ 72 | STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 73 | { 74 | return EnumDevicesX(dwDevType, lpCallback, pvRef, dwFlags); 75 | } 76 | STDMETHOD(EnumDevices)(THIS_ DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 77 | { 78 | return EnumDevicesX(dwDevType, lpCallback, pvRef, dwFlags); 79 | } 80 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 81 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 82 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 83 | 84 | /*** IDirectInput2 methods ***/ 85 | STDMETHOD(FindDevice)(THIS_ REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance) 86 | { 87 | return FindDeviceX(rguidClass, ptszName, pguidInstance); 88 | } 89 | STDMETHOD(FindDevice)(THIS_ REFGUID rguidClass, LPCWSTR ptszName, LPGUID pguidInstance) 90 | { 91 | return FindDeviceX(rguidClass, ptszName, pguidInstance); 92 | } 93 | 94 | /*** IDirectInput7 methods ***/ 95 | STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICE8A *ppvObj, LPUNKNOWN pUnkOuter) 96 | { 97 | return CreateDeviceExX(rguid, riid, ppvObj, pUnkOuter); 98 | } 99 | STDMETHOD(CreateDeviceEx)(THIS_ REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICE8W *ppvObj, LPUNKNOWN pUnkOuter) 100 | { 101 | return CreateDeviceExX(rguid, riid, ppvObj, pUnkOuter); 102 | } 103 | 104 | // Helper functions 105 | LPVOID GetWrapperInterfaceX(DWORD DXVersion); 106 | 107 | void SetVersion(DWORD dwVersion) 108 | { 109 | diVersion = dwVersion; 110 | } 111 | }; 112 | -------------------------------------------------------------------------------- /Include/VersionHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // _WIN32_WINNT version constants 3 | // 4 | #define _WIN32_WINNT_VISTA 0x0600 5 | #define _WIN32_WINNT_WIN7 0x0601 6 | #define _WIN32_WINNT_WIN8 0x0602 7 | #define _WIN32_WINNT_WINBLUE 0x0603 8 | 9 | inline bool IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor); 10 | -------------------------------------------------------------------------------- /Include/winapifamily.h: -------------------------------------------------------------------------------- 1 | #define WINAPI_PARTITION_DESKTOP 0x00000001 2 | #define WINAPI_FAMILY_DESKTOP_APP WINAPI_PARTITION_DESKTOP 3 | 4 | // WINAPI_FAMILY is usually defined by the build system based on the target platform 5 | #ifndef WINAPI_FAMILY 6 | #define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP 7 | #endif 8 | 9 | #define WINAPI_FAMILY_PARTITION(Partition) ((WINAPI_FAMILY & Partition) == Partition) -------------------------------------------------------------------------------- /Include/winsdk-10/hidusage.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Module Name: 6 | 7 | HIDUSAGE.H 8 | 9 | Abstract: 10 | 11 | Public Definitions of HID USAGES. 12 | 13 | Environment: 14 | 15 | Kernel & user mode 16 | 17 | --*/ 18 | 19 | #ifndef __HIDUSAGE_H__ 20 | #define __HIDUSAGE_H__ 21 | #include 22 | 23 | #pragma region Desktop Family 24 | #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) 25 | 26 | 27 | // 28 | // Usage Pages 29 | // 30 | 31 | typedef USHORT USAGE, *PUSAGE; 32 | 33 | #define HID_USAGE_PAGE_UNDEFINED ((USAGE) 0x00) 34 | #define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01) 35 | #define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02) 36 | #define HID_USAGE_PAGE_VR ((USAGE) 0x03) 37 | #define HID_USAGE_PAGE_SPORT ((USAGE) 0x04) 38 | #define HID_USAGE_PAGE_GAME ((USAGE) 0x05) 39 | #define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07) 40 | #define HID_USAGE_PAGE_LED ((USAGE) 0x08) 41 | #define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09) 42 | #define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A) 43 | #define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B) 44 | #define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C) 45 | #define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D) 46 | #define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10) 47 | #define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14) 48 | #define HID_USAGE_PAGE_SENSOR ((USAGE) 0x20) 49 | #define HID_USAGE_PAGE_BARCODE_SCANNER ((USAGE) 0x8C) 50 | #define HID_USAGE_PAGE_WEIGHING_DEVICE ((USAGE) 0x8D) 51 | #define HID_USAGE_PAGE_MAGNETIC_STRIPE_READER ((USAGE) 0x8E) 52 | #define HID_USAGE_PAGE_CAMERA_CONTROL ((USAGE) 0x90) 53 | #define HID_USAGE_PAGE_MICROSOFT_BLUETOOTH_HANDSFREE ((USAGE) 0xFFF3) 54 | #define HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN ((USAGE) 0xFF00) 55 | #define HID_USAGE_PAGE_VENDOR_DEFINED_END ((USAGE) 0xFFFF) 56 | 57 | // 58 | // Generic Desktop Page (0x01) 59 | // 60 | #define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01) 61 | #define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02) 62 | #define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04) 63 | #define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05) 64 | #define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06) 65 | #define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07) 66 | #define HID_USAGE_GENERIC_PORTABLE_DEVICE_CONTROL ((USAGE) 0x0D) 67 | #define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80) 68 | 69 | #define HID_USAGE_GENERIC_X ((USAGE) 0x30) 70 | #define HID_USAGE_GENERIC_Y ((USAGE) 0x31) 71 | #define HID_USAGE_GENERIC_Z ((USAGE) 0x32) 72 | #define HID_USAGE_GENERIC_RX ((USAGE) 0x33) 73 | #define HID_USAGE_GENERIC_RY ((USAGE) 0x34) 74 | #define HID_USAGE_GENERIC_RZ ((USAGE) 0x35) 75 | #define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36) 76 | #define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37) 77 | #define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38) 78 | #define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39) 79 | #define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A) 80 | #define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B) 81 | #define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C) 82 | #define HID_USAGE_GENERIC_VX ((USAGE) 0x40) 83 | #define HID_USAGE_GENERIC_VY ((USAGE) 0x41) 84 | #define HID_USAGE_GENERIC_VZ ((USAGE) 0x42) 85 | #define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43) 86 | #define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44) 87 | #define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45) 88 | #define HID_USAGE_GENERIC_VNO ((USAGE) 0x46) 89 | #define HID_USAGE_GENERIC_RESOLUTION_MULTIPLIER ((USAGE) 0x48) 90 | #define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81) 91 | #define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82) 92 | #define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83) 93 | #define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84) 94 | #define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85) 95 | #define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86) 96 | #define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87) 97 | #define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88) 98 | #define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89) 99 | #define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A) 100 | #define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B) 101 | #define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C) 102 | #define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D) 103 | #define HID_USAGE_GENERIC_SYSTEM_DISPLAY_ROTATION_LOCK_BUTTON ((USAGE) 0xC9) 104 | #define HID_USAGE_GENERIC_SYSTEM_DISPLAY_ROTATION_LOCK_SLIDER_SWITCH ((USAGE) 0xCA) 105 | #define HID_USAGE_GENERIC_CONTROL_ENABLE ((USAGE) 0xCB) 106 | 107 | // 108 | // Simulation Controls Page (0x02) 109 | // 110 | #define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA) 111 | #define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB) 112 | 113 | 114 | // 115 | // Virtual Reality Controls Page (0x03) 116 | // 117 | 118 | 119 | // 120 | // Sport Controls Page (0x04) 121 | // 122 | 123 | 124 | // 125 | // Game Controls Page (0x05) 126 | // 127 | 128 | 129 | // 130 | // Keyboard/Keypad Page (0x07) 131 | // 132 | 133 | // Error "keys" 134 | #define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00) 135 | #define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01) 136 | #define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02) 137 | #define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03) 138 | 139 | // Letters 140 | #define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04) 141 | #define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D) 142 | 143 | // Numbers 144 | #define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E) 145 | #define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27) 146 | 147 | // Modifier Keys 148 | #define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0) 149 | #define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1) 150 | #define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2) 151 | #define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3) 152 | #define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4) 153 | #define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5) 154 | #define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6) 155 | #define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7) 156 | #define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47) 157 | #define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53) 158 | #define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39) 159 | 160 | // Function keys 161 | #define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A) 162 | #define HID_USAGE_KEYBOARD_F2 ((USAGE) 0x3B) 163 | #define HID_USAGE_KEYBOARD_F3 ((USAGE) 0x3C) 164 | #define HID_USAGE_KEYBOARD_F4 ((USAGE) 0x3D) 165 | #define HID_USAGE_KEYBOARD_F5 ((USAGE) 0x3E) 166 | #define HID_USAGE_KEYBOARD_F6 ((USAGE) 0x3F) 167 | #define HID_USAGE_KEYBOARD_F7 ((USAGE) 0x40) 168 | #define HID_USAGE_KEYBOARD_F8 ((USAGE) 0x41) 169 | #define HID_USAGE_KEYBOARD_F9 ((USAGE) 0x42) 170 | #define HID_USAGE_KEYBOARD_F10 ((USAGE) 0x43) 171 | #define HID_USAGE_KEYBOARD_F11 ((USAGE) 0x44) 172 | #define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45) 173 | #define HID_USAGE_KEYBOARD_F13 ((USAGE) 0x68) 174 | #define HID_USAGE_KEYBOARD_F14 ((USAGE) 0x69) 175 | #define HID_USAGE_KEYBOARD_F15 ((USAGE) 0x6A) 176 | #define HID_USAGE_KEYBOARD_F16 ((USAGE) 0x6B) 177 | #define HID_USAGE_KEYBOARD_F17 ((USAGE) 0x6C) 178 | #define HID_USAGE_KEYBOARD_F18 ((USAGE) 0x6D) 179 | #define HID_USAGE_KEYBOARD_F19 ((USAGE) 0x6E) 180 | #define HID_USAGE_KEYBOARD_F20 ((USAGE) 0x6F) 181 | #define HID_USAGE_KEYBOARD_F21 ((USAGE) 0x70) 182 | #define HID_USAGE_KEYBOARD_F22 ((USAGE) 0x71) 183 | #define HID_USAGE_KEYBOARD_F23 ((USAGE) 0x72) 184 | #define HID_USAGE_KEYBOARD_F24 ((USAGE) 0x73) 185 | 186 | #define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28) 187 | #define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29) 188 | #define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A) 189 | 190 | #define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46) 191 | #define HID_USAGE_KEYBOARD_DELETE_FORWARD ((USAGE) 0x4C) 192 | 193 | 194 | // 195 | // LED Page (0x08) 196 | // 197 | #define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01) 198 | #define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02) 199 | #define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03) 200 | #define HID_USAGE_LED_COMPOSE ((USAGE) 0x04) 201 | #define HID_USAGE_LED_KANA ((USAGE) 0x05) 202 | #define HID_USAGE_LED_POWER ((USAGE) 0x06) 203 | #define HID_USAGE_LED_SHIFT ((USAGE) 0x07) 204 | #define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08) 205 | #define HID_USAGE_LED_MUTE ((USAGE) 0x09) 206 | #define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A) 207 | #define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B) 208 | #define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C) 209 | #define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D) 210 | #define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E) 211 | #define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F) 212 | #define HID_USAGE_LED_REPEAT ((USAGE) 0x10) 213 | #define HID_USAGE_LED_STEREO ((USAGE) 0x11) 214 | #define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12) 215 | #define HID_USAGE_LED_SPINNING ((USAGE) 0x13) 216 | #define HID_USAGE_LED_CAV ((USAGE) 0x14) 217 | #define HID_USAGE_LED_CLV ((USAGE) 0x15) 218 | #define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16) 219 | #define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17) 220 | #define HID_USAGE_LED_RING ((USAGE) 0x18) 221 | #define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19) 222 | #define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A) 223 | #define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B) 224 | #define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C) 225 | #define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D) 226 | #define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E) 227 | #define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F) 228 | #define HID_USAGE_LED_HOLD ((USAGE) 0x20) 229 | #define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21) 230 | #define HID_USAGE_LED_COVERAGE ((USAGE) 0x22) 231 | #define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23) 232 | #define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24) 233 | #define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25) 234 | #define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26) 235 | #define HID_USAGE_LED_STAND_BY ((USAGE) 0x27) 236 | #define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28) 237 | #define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29) 238 | #define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A) 239 | #define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B) 240 | #define HID_USAGE_LED_BUSY ((USAGE) 0x2C) 241 | #define HID_USAGE_LED_READY ((USAGE) 0x2D) 242 | #define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E) 243 | #define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F) 244 | #define HID_USAGE_LED_REMOTE ((USAGE) 0x30) 245 | #define HID_USAGE_LED_FORWARD ((USAGE) 0x31) 246 | #define HID_USAGE_LED_REVERSE ((USAGE) 0x32) 247 | #define HID_USAGE_LED_STOP ((USAGE) 0x33) 248 | #define HID_USAGE_LED_REWIND ((USAGE) 0x34) 249 | #define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35) 250 | #define HID_USAGE_LED_PLAY ((USAGE) 0x36) 251 | #define HID_USAGE_LED_PAUSE ((USAGE) 0x37) 252 | #define HID_USAGE_LED_RECORD ((USAGE) 0x38) 253 | #define HID_USAGE_LED_ERROR ((USAGE) 0x39) 254 | #define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A) 255 | #define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B) 256 | #define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C) 257 | #define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D) 258 | #define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E) 259 | #define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F) 260 | #define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40) 261 | #define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41) 262 | #define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42) 263 | #define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43) 264 | #define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44) 265 | #define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45) 266 | #define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46) 267 | #define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47) 268 | #define HID_USAGE_LED_RED ((USAGE) 0x48) 269 | #define HID_USAGE_LED_GREEN ((USAGE) 0x49) 270 | #define HID_USAGE_LED_AMBER ((USAGE) 0x4A) 271 | #define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x4B) 272 | 273 | // 274 | // Button Page (0x09) 275 | // 276 | // There is no need to label these usages. 277 | // 278 | 279 | 280 | // 281 | // Ordinal Page (0x0A) 282 | // 283 | // There is no need to label these usages. 284 | // 285 | 286 | 287 | // 288 | // Telephony Device Page (0x0B) 289 | // 290 | #define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01) 291 | #define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02) 292 | #define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03) 293 | #define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04) 294 | #define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05) 295 | #define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06) 296 | #define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07) 297 | #define HID_USAGE_TELEPHONY_REDIAL ((USAGE) 0x24) 298 | #define HID_USAGE_TELEPHONY_TRANSFER ((USAGE) 0x25) 299 | #define HID_USAGE_TELEPHONY_DROP ((USAGE) 0x26) 300 | #define HID_USAGE_TELEPHONY_LINE ((USAGE) 0x2A) 301 | #define HID_USAGE_TELEPHONY_RING_ENABLE ((USAGE) 0x2D) 302 | #define HID_USAGE_TELEPHONY_SEND ((USAGE) 0x31) 303 | #define HID_USAGE_TELEPHONY_KEYPAD_0 ((USAGE) 0xB0) 304 | #define HID_USAGE_TELEPHONY_KEYPAD_D ((USAGE) 0xBF) 305 | #define HID_USAGE_TELEPHONY_HOST_AVAILABLE ((USAGE) 0xF1) 306 | 307 | 308 | // 309 | // Consumer Controls Page (0x0C) 310 | // 311 | #define HID_USAGE_CONSUMERCTRL ((USAGE) 0x01) 312 | 313 | // channel 314 | #define HID_USAGE_CONSUMER_CHANNEL_INCREMENT ((USAGE) 0x9C) 315 | #define HID_USAGE_CONSUMER_CHANNEL_DECREMENT ((USAGE) 0x9D) 316 | 317 | // transport control 318 | #define HID_USAGE_CONSUMER_PLAY ((USAGE) 0xB0) 319 | #define HID_USAGE_CONSUMER_PAUSE ((USAGE) 0xB1) 320 | #define HID_USAGE_CONSUMER_RECORD ((USAGE) 0xB2) 321 | #define HID_USAGE_CONSUMER_FAST_FORWARD ((USAGE) 0xB3) 322 | #define HID_USAGE_CONSUMER_REWIND ((USAGE) 0xB4) 323 | #define HID_USAGE_CONSUMER_SCAN_NEXT_TRACK ((USAGE) 0xB5) 324 | #define HID_USAGE_CONSUMER_SCAN_PREV_TRACK ((USAGE) 0xB6) 325 | #define HID_USAGE_CONSUMER_STOP ((USAGE) 0xB7) 326 | #define HID_USAGE_CONSUMER_PLAY_PAUSE ((USAGE) 0xCD) 327 | 328 | // audio 329 | #define HID_USAGE_CONSUMER_VOLUME ((USAGE) 0xE0) 330 | #define HID_USAGE_CONSUMER_BALANCE ((USAGE) 0xE1) 331 | #define HID_USAGE_CONSUMER_MUTE ((USAGE) 0xE2) 332 | #define HID_USAGE_CONSUMER_BASS ((USAGE) 0xE3) 333 | #define HID_USAGE_CONSUMER_TREBLE ((USAGE) 0xE4) 334 | #define HID_USAGE_CONSUMER_BASS_BOOST ((USAGE) 0xE5) 335 | #define HID_USAGE_CONSUMER_SURROUND_MODE ((USAGE) 0xE6) 336 | #define HID_USAGE_CONSUMER_LOUDNESS ((USAGE) 0xE7) 337 | #define HID_USAGE_CONSUMER_MPX ((USAGE) 0xE8) 338 | #define HID_USAGE_CONSUMER_VOLUME_INCREMENT ((USAGE) 0xE9) 339 | #define HID_USAGE_CONSUMER_VOLUME_DECREMENT ((USAGE) 0xEA) 340 | 341 | // supplementary audio 342 | #define HID_USAGE_CONSUMER_BASS_INCREMENT ((USAGE) 0x152) 343 | #define HID_USAGE_CONSUMER_BASS_DECREMENT ((USAGE) 0x153) 344 | #define HID_USAGE_CONSUMER_TREBLE_INCREMENT ((USAGE) 0x154) 345 | #define HID_USAGE_CONSUMER_TREBLE_DECREMENT ((USAGE) 0x155) 346 | 347 | // Application Launch 348 | #define HID_USAGE_CONSUMER_AL_CONFIGURATION ((USAGE) 0x183) 349 | #define HID_USAGE_CONSUMER_AL_EMAIL ((USAGE) 0x18A) 350 | #define HID_USAGE_CONSUMER_AL_CALCULATOR ((USAGE) 0x192) 351 | #define HID_USAGE_CONSUMER_AL_BROWSER ((USAGE) 0x194) 352 | 353 | // Application Control 354 | #define HID_USAGE_CONSUMER_AC_SEARCH ((USAGE) 0x221) 355 | #define HID_USAGE_CONSUMER_AC_GOTO ((USAGE) 0x222) 356 | #define HID_USAGE_CONSUMER_AC_HOME ((USAGE) 0x223) 357 | #define HID_USAGE_CONSUMER_AC_BACK ((USAGE) 0x224) 358 | #define HID_USAGE_CONSUMER_AC_FORWARD ((USAGE) 0x225) 359 | #define HID_USAGE_CONSUMER_AC_STOP ((USAGE) 0x226) 360 | #define HID_USAGE_CONSUMER_AC_REFRESH ((USAGE) 0x227) 361 | #define HID_USAGE_CONSUMER_AC_PREVIOUS ((USAGE) 0x228) 362 | #define HID_USAGE_CONSUMER_AC_NEXT ((USAGE) 0x229) 363 | #define HID_USAGE_CONSUMER_AC_BOOKMARKS ((USAGE) 0x22A) 364 | #define HID_USAGE_CONSUMER_AC_PAN ((USAGE) 0x238) 365 | 366 | // Keyboard Extended Attributes (defined on consumer page in HUTRR42) 367 | #define HID_USAGE_CONSUMER_EXTENDED_KEYBOARD_ATTRIBUTES_COLLECTION ((USAGE) 0x2C0) 368 | #define HID_USAGE_CONSUMER_KEYBOARD_FORM_FACTOR ((USAGE) 0x2C1) 369 | #define HID_USAGE_CONSUMER_KEYBOARD_KEY_TYPE ((USAGE) 0x2C2) 370 | #define HID_USAGE_CONSUMER_KEYBOARD_PHYSICAL_LAYOUT ((USAGE) 0x2C3) 371 | #define HID_USAGE_CONSUMER_VENDOR_SPECIFIC_KEYBOARD_PHYSICAL_LAYOUT ((USAGE) 0x2C4) 372 | #define HID_USAGE_CONSUMER_KEYBOARD_IETF_LANGUAGE_TAG_INDEX ((USAGE) 0x2C5) 373 | #define HID_USAGE_CONSUMER_IMPLEMENTED_KEYBOARD_INPUT_ASSIST_CONTROLS ((USAGE) 0x2C6) 374 | 375 | // 376 | // Digitizer Page (0x0D) 377 | // 378 | #define HID_USAGE_DIGITIZER_PEN ((USAGE)0x02) 379 | #define HID_USAGE_DIGITIZER_IN_RANGE ((USAGE)0x32) 380 | #define HID_USAGE_DIGITIZER_TIP_SWITCH ((USAGE)0x42) 381 | #define HID_USAGE_DIGITIZER_BARREL_SWITCH ((USAGE)0x44) 382 | 383 | 384 | // 385 | // Sensor Page (0x20) 386 | // 387 | 388 | 389 | // 390 | // Camera Control Page (0x90) 391 | // 392 | #define HID_USAGE_CAMERA_AUTO_FOCUS ((USAGE) 0x20) 393 | #define HID_USAGE_CAMERA_SHUTTER ((USAGE) 0x21) 394 | 395 | // 396 | // Microsoft Bluetooth Handsfree Page (0xFFF3) 397 | // 398 | #define HID_USAGE_MS_BTH_HF_DIALNUMBER ((USAGE) 0x21) 399 | #define HID_USAGE_MS_BTH_HF_DIALMEMORY ((USAGE) 0x22) 400 | 401 | 402 | #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ 403 | #pragma endregion 404 | 405 | #endif 406 | -------------------------------------------------------------------------------- /InterfaceQuery.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "dinputto8.h" 18 | 19 | DWORD dinputto8::GetStringType(REFIID riid) 20 | { 21 | return (riid == IID_IDirectInputA || riid == IID_IDirectInput2A || riid == IID_IDirectInput7A || 22 | riid == IID_IDirectInputDeviceA || riid == IID_IDirectInputDevice2A || riid == IID_IDirectInputDevice7A) ? ANSI_CHARSET : 23 | (riid == IID_IDirectInputW || riid == IID_IDirectInput2W || riid == IID_IDirectInput7W || 24 | riid == IID_IDirectInputDeviceW || riid == IID_IDirectInputDevice2W || riid == IID_IDirectInputDevice7W) ? UNICODE_CHARSET : DIERR_UNSUPPORTED; 25 | } 26 | 27 | DWORD dinputto8::GetGUIDVersion(REFIID riid) 28 | { 29 | return (riid == IID_IDirectInputA || riid == IID_IDirectInputW || riid == IID_IDirectInputDeviceA || riid == IID_IDirectInputDeviceW) ? 1 : 30 | (riid == IID_IDirectInput2A || riid == IID_IDirectInput2W || riid == IID_IDirectInputDevice2A || riid == IID_IDirectInputDevice2W) ? 2 : 31 | (riid == IID_IDirectInput7A || riid == IID_IDirectInput7W || riid == IID_IDirectInputDevice7A || riid == IID_IDirectInputDevice7W) ? 7 : 0; 32 | } 33 | 34 | REFIID dinputto8::ReplaceIIDUnknown(REFIID riid, REFIID guid) 35 | { 36 | return (riid == IID_IUnknown) ? guid : riid; 37 | } 38 | 39 | REFCLSID dinputto8::ConvertREFCLSID(REFCLSID rclsid) 40 | { 41 | return (rclsid == CLSID_DirectInput) ? CLSID_DirectInput8 : 42 | (rclsid == CLSID_DirectInputDevice) ? CLSID_DirectInputDevice8 : rclsid; 43 | } 44 | 45 | REFIID dinputto8::ConvertREFIID(REFIID riid) 46 | { 47 | return (riid == IID_IDirectInputA || riid == IID_IDirectInput2A || riid == IID_IDirectInput7A) ? IID_IDirectInput8A : 48 | (riid == IID_IDirectInputW || riid == IID_IDirectInput2W || riid == IID_IDirectInput7W) ? IID_IDirectInput8W : 49 | (riid == IID_IDirectInputDeviceA || riid == IID_IDirectInputDevice2A || riid == IID_IDirectInputDevice7A) ? IID_IDirectInputDevice8A : 50 | (riid == IID_IDirectInputDeviceW || riid == IID_IDirectInputDevice2W || riid == IID_IDirectInputDevice7W) ? IID_IDirectInputDevice8W : riid; 51 | } 52 | 53 | HRESULT dinputto8::ProxyQueryInterface(LPVOID ProxyInterface, REFIID riid, LPVOID * ppvObj, REFIID WrapperID, LPVOID WrapperInterface) 54 | { 55 | Logging::LogDebug() << __FUNCTION__ << " Query for " << riid << " from " << WrapperID; 56 | 57 | if (!ppvObj) 58 | { 59 | return E_POINTER; 60 | } 61 | 62 | if ((riid == WrapperID || riid == IID_IUnknown) && ppvObj) 63 | { 64 | ((IUnknown*)WrapperInterface)->AddRef(); 65 | 66 | *ppvObj = WrapperInterface; 67 | 68 | return S_OK; 69 | } 70 | 71 | HRESULT hr = ((IUnknown*)ProxyInterface)->QueryInterface(ConvertREFIID(riid), ppvObj); 72 | 73 | Logging::LogDebug() << __FUNCTION__ << " QueryInterface --> '" << riid << "' QueryInterface result: " << (DIERR)hr; 74 | 75 | if (SUCCEEDED(hr)) 76 | { 77 | genericQueryInterface(riid, ppvObj); 78 | } 79 | 80 | return hr; 81 | } 82 | 83 | void WINAPI dinputto8::genericQueryInterface(REFIID riid, LPVOID * ppvObj) 84 | { 85 | if (!ppvObj || !*ppvObj) 86 | { 87 | return; 88 | } 89 | 90 | #define QUERYINTERFACE(x) \ 91 | if (riid == IID_ ## x) \ 92 | { \ 93 | Logging::LogDebug() << "Getting device for: m_" ## #x; \ 94 | *ppvObj = ProxyAddressLookupTable.FindAddress(*ppvObj); \ 95 | } 96 | 97 | QUERYINTERFACE(IDirectInputA); 98 | QUERYINTERFACE(IDirectInputW); 99 | QUERYINTERFACE(IDirectInput2A); 100 | QUERYINTERFACE(IDirectInput2W); 101 | QUERYINTERFACE(IDirectInput7A); 102 | QUERYINTERFACE(IDirectInput7W); 103 | QUERYINTERFACE(IDirectInputDeviceA); 104 | QUERYINTERFACE(IDirectInputDeviceW); 105 | QUERYINTERFACE(IDirectInputDevice2A); 106 | QUERYINTERFACE(IDirectInputDevice2W); 107 | QUERYINTERFACE(IDirectInputDevice7A); 108 | QUERYINTERFACE(IDirectInputDevice7W); 109 | QUERYINTERFACE(IDirectInputEffect); 110 | } 111 | 112 | HRESULT dinputto8::hresValidInstanceAndVersion(HINSTANCE& hinst, DWORD dwVersion) 113 | { 114 | bool bValidInstance; 115 | if (hinst != nullptr) 116 | { 117 | wchar_t path[4]; 118 | bValidInstance = GetModuleFileNameW(hinst, path, std::size(path) - 1) != 0; 119 | } 120 | else 121 | { 122 | // DInput version 0x300 permits no instance... 123 | bValidInstance = dwVersion == 0x300; 124 | } 125 | 126 | if (!bValidInstance) 127 | { 128 | return DIERR_INVALIDPARAM; 129 | } 130 | 131 | // ...but DInput8 does not, so if the instance is empty, give it one or else it'll fail. 132 | if (hinst == nullptr && dwVersion == 0x300) 133 | { 134 | hinst = ::GetModuleHandle(nullptr); 135 | } 136 | 137 | if (dwVersion == 0x300 || dwVersion == 0x500 || dwVersion == 0x50A || dwVersion == 0x5B2 || dwVersion == 0x602 || dwVersion == 0x61A || dwVersion == 0x700) 138 | { 139 | return DI_OK; 140 | } 141 | 142 | if (dwVersion == 0) 143 | { 144 | return DIERR_NOTINITIALIZED; 145 | } 146 | return dwVersion < 0x700 ? DIERR_BETADIRECTINPUTVERSION : DIERR_OLDDIRECTINPUTVERSION; 147 | } 148 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ -------------------------------------------------------------------------------- /Logging/License.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ -------------------------------------------------------------------------------- /Logging/Logging.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | #include "Logging.h" 19 | 20 | void LogDataFormat(const DIDATAFORMAT &df) 21 | { 22 | Logging::Log() << "DIDATAFORMAT " << df; 23 | 24 | for (DWORD x = 0; x < df.dwNumObjs; x++) 25 | { 26 | Logging::Log() << "DIOBJECTDATAFORMAT " << x << " " << df.rgodf[x]; 27 | } 28 | } 29 | 30 | void LogDataFormat(LPCDIDATAFORMAT lpdf) 31 | { 32 | if (lpdf) 33 | { 34 | LogDataFormat(*lpdf); 35 | } 36 | } 37 | 38 | void LogEffectFormat(const DIEFFECT &eff, REFGUID rguid) 39 | { 40 | Logging::Log() << "DIEFFECT " << eff; 41 | 42 | if (eff.cAxes && eff.rgdwAxes) 43 | { 44 | DWORD *pAxes = eff.rgdwAxes; 45 | 46 | for (int x = 0; x < (int)eff.cAxes; x++) 47 | { 48 | Logging::Log() << "DIEFFECT rgdwAxes " << x << ": " << pAxes[x]; 49 | } 50 | } 51 | 52 | if (eff.cAxes && eff.rglDirection) 53 | { 54 | LONG *pDirection = (LONG*)eff.rglDirection; 55 | 56 | for (int x = 0; x < (int)eff.cAxes; x++) 57 | { 58 | Logging::Log() << "DIEFFECT rglDirection " << x << ": " << pDirection[x]; 59 | } 60 | } 61 | 62 | if (eff.cbTypeSpecificParams && eff.lpvTypeSpecificParams) 63 | { 64 | // DIEFT_CONSTANTFORCE 65 | if (rguid == GUID_ConstantForce && eff.cbTypeSpecificParams == sizeof(DICONSTANTFORCE)) 66 | { 67 | DICONSTANTFORCE *lSpecificParams = (DICONSTANTFORCE*)eff.lpvTypeSpecificParams; 68 | 69 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams { lMagnitude: " << lSpecificParams->lMagnitude << " }"; 70 | } 71 | // DIEFT_RAMPFORCE 72 | else if (rguid == GUID_RampForce && eff.cbTypeSpecificParams == sizeof(DIRAMPFORCE)) 73 | { 74 | DIRAMPFORCE *lSpecificParams = (DIRAMPFORCE*)eff.lpvTypeSpecificParams; 75 | 76 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams {" << 77 | " lStart: " << lSpecificParams->lStart << 78 | " lEnd: " << lSpecificParams->lEnd << 79 | " }"; 80 | } 81 | // DIEFT_PERIODIC 82 | else if ((rguid == GUID_Square || rguid == GUID_Sine || rguid == GUID_Triangle || rguid == GUID_SawtoothUp || rguid == GUID_SawtoothDown) && eff.cbTypeSpecificParams == sizeof(DIPERIODIC)) 83 | { 84 | DIPERIODIC *lSpecificParams = (DIPERIODIC*)eff.lpvTypeSpecificParams; 85 | 86 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams {" << 87 | " dwMagnitude: " << lSpecificParams->dwMagnitude << 88 | " lOffset: " << lSpecificParams->lOffset << 89 | " dwPhase: " << lSpecificParams->dwPhase << 90 | " dwPeriod: " << lSpecificParams->dwPeriod << 91 | " }"; 92 | } 93 | // DIEFT_CONDITION 94 | else if ((rguid == GUID_Spring || rguid == GUID_Damper || rguid == GUID_Inertia || rguid == GUID_Friction) && eff.cbTypeSpecificParams == sizeof(DICONDITION)) 95 | { 96 | DICONDITION *lSpecificParams = (DICONDITION *)eff.lpvTypeSpecificParams; 97 | 98 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams {" << 99 | " lOffset: " << lSpecificParams->lOffset << 100 | " lPositiveCoefficient: " << lSpecificParams->lPositiveCoefficient << 101 | " lNegativeCoefficient: " << lSpecificParams->lNegativeCoefficient << 102 | " dwPositiveSaturation: " << lSpecificParams->dwPositiveSaturation << 103 | " dwNegativeSaturation: " << lSpecificParams->dwNegativeSaturation << 104 | " lDeadBand: " << lSpecificParams->lDeadBand << 105 | " }"; 106 | } 107 | // DIEFT_CUSTOMFORCE 108 | else if (rguid == GUID_CustomForce && eff.cbTypeSpecificParams == sizeof(DICUSTOMFORCE)) 109 | { 110 | DICUSTOMFORCE *lSpecificParams = (DICUSTOMFORCE*)eff.lpvTypeSpecificParams; 111 | 112 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams {" << 113 | " cChannels: " << lSpecificParams->cChannels << 114 | " dwSamplePeriod: " << lSpecificParams->dwSamplePeriod << 115 | " cSamples: " << lSpecificParams->cSamples << 116 | " rglForceData: " << lSpecificParams->rglForceData << 117 | " }"; 118 | 119 | if (lSpecificParams->rglForceData) 120 | { 121 | for (int x = 0; x < (int)lSpecificParams->cSamples; x++) 122 | { 123 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams rglForceData " << x << ": " << lSpecificParams->rglForceData[x]; 124 | } 125 | } 126 | } 127 | // Unknown device 128 | else 129 | { 130 | if (eff.lpvTypeSpecificParams) 131 | { 132 | DWORD *lSpecificParams = (DWORD*)eff.lpvTypeSpecificParams; 133 | 134 | for (int x = 0; x < (int)(eff.cbTypeSpecificParams / 4); x++) 135 | { 136 | Logging::Log() << "DIEFFECT lpvTypeSpecificParams " << x << ": " << lSpecificParams[x]; 137 | } 138 | } 139 | } 140 | } 141 | } 142 | 143 | void LogEffectFormat(LPCDIEFFECT lpeff, REFGUID rguid) 144 | { 145 | if (lpeff) 146 | { 147 | LogEffectFormat(*lpeff, rguid); 148 | } 149 | } 150 | 151 | std::ostream& operator<<(std::ostream& os, DIEFFECT deff) 152 | { 153 | return Logging::LogStruct(os) << 154 | " dwSize:" << deff.dwSize << 155 | " dwFlags:" << Logging::hex(deff.dwFlags) << 156 | " dwDuration:" << deff.dwDuration << 157 | " dwSamplePeriod:" << deff.dwSamplePeriod << 158 | " dwGain:" << deff.dwGain << 159 | " dwTriggerButton:" << deff.dwTriggerButton << 160 | " dwTriggerRepeatInterval:" << deff.dwTriggerRepeatInterval << 161 | " cAxes:" << deff.cAxes << 162 | " rgdwAxes:" << deff.rgdwAxes << 163 | " rglDirection:" << deff.rglDirection << 164 | " lpEnvelope:" << deff.lpEnvelope << 165 | " cbTypeSpecificParams:" << deff.cbTypeSpecificParams << 166 | " lpvTypeSpecificParams:" << deff.lpvTypeSpecificParams << 167 | ((deff.dwSize == sizeof(DIEFFECT)) ? " dwStartDelay:" : " ") << ((deff.dwSize == sizeof(DIEFFECT)) ? deff.dwStartDelay : 0) << " "; 168 | } 169 | 170 | std::ostream& operator<<(std::ostream& os, LPCDIEFFECT lpdeff) 171 | { 172 | if (!lpdeff) 173 | { 174 | return os << (void*)lpdeff; 175 | } 176 | 177 | return os << *lpdeff; 178 | } 179 | 180 | std::ostream& operator<<(std::ostream& os, DIENVELOPE de) 181 | { 182 | return Logging::LogStruct(os) << 183 | " dwSize:" << de.dwSize << 184 | " dwAttackLevel:" << de.dwAttackLevel << 185 | " dwAttackTime:" << de.dwAttackTime << 186 | " dwFadeLevel:" << de.dwFadeLevel << 187 | " dwFadeTime:" << de.dwFadeTime << " "; 188 | } 189 | 190 | std::ostream& operator<<(std::ostream& os, LPDIENVELOPE lpde) 191 | { 192 | if (!lpde) 193 | { 194 | return os << (void*)lpde; 195 | } 196 | 197 | return os << *lpde; 198 | } 199 | 200 | std::ostream& operator<<(std::ostream& os, DIDATAFORMAT df) 201 | { 202 | return Logging::LogStruct(os) << 203 | " ObjSize:" << df.dwObjSize << 204 | " Flags:" << Logging::hex(df.dwFlags) << 205 | " DataSize:" << df.dwDataSize << 206 | " NumObj:" << df.dwNumObjs << 207 | " Addr:" << Logging::hex((void*)df.rgodf) << " "; 208 | } 209 | 210 | std::ostream& operator<<(std::ostream& os, LPCDIDATAFORMAT lpdf) 211 | { 212 | if (!lpdf) 213 | { 214 | return os << (void*)lpdf; 215 | } 216 | 217 | return os << *lpdf; 218 | } 219 | 220 | std::ostream& operator<<(std::ostream& os, DIOBJECTDATAFORMAT odf) 221 | { 222 | return Logging::LogStruct(os) << 223 | " GUID:" << odf.pguid << 224 | " Offset:" << odf.dwOfs << 225 | " Type:" << Logging::hex(odf.dwType) << 226 | " Flags:" << Logging::hex(odf.dwFlags) << " "; 227 | } 228 | 229 | std::ostream& operator<<(std::ostream& os, LPCDIOBJECTDATAFORMAT rgodf) 230 | { 231 | if (!rgodf) 232 | { 233 | return os << (void*)rgodf; 234 | } 235 | 236 | return os << *rgodf; 237 | } 238 | 239 | #ifndef DISABLE_COMMON_LOGGING 240 | std::ostream& operator<<(std::ostream& os, REFIID riid) 241 | { 242 | #define CHECK_REFIID(riidPrefix, riidName) \ 243 | if (riid == riidPrefix ## _ ## riidName) \ 244 | { \ 245 | return os << #riidPrefix << "_" << #riidName; \ 246 | } 247 | 248 | CHECK_REFIID(IID, IUnknown); 249 | CHECK_REFIID(IID, IClassFactory); 250 | // dinput 251 | CHECK_REFIID(CLSID, DirectInput); 252 | CHECK_REFIID(CLSID, DirectInputDevice); 253 | CHECK_REFIID(CLSID, DirectInput8); 254 | CHECK_REFIID(CLSID, DirectInputDevice8); 255 | CHECK_REFIID(IID, IDirectInputA); 256 | CHECK_REFIID(IID, IDirectInputW); 257 | CHECK_REFIID(IID, IDirectInput2A); 258 | CHECK_REFIID(IID, IDirectInput2W); 259 | CHECK_REFIID(IID, IDirectInput7A); 260 | CHECK_REFIID(IID, IDirectInput7W); 261 | CHECK_REFIID(IID, IDirectInput8A); 262 | CHECK_REFIID(IID, IDirectInput8W); 263 | CHECK_REFIID(IID, IDirectInputDeviceA); 264 | CHECK_REFIID(IID, IDirectInputDeviceW); 265 | CHECK_REFIID(IID, IDirectInputDevice2A); 266 | CHECK_REFIID(IID, IDirectInputDevice2W); 267 | CHECK_REFIID(IID, IDirectInputDevice7A); 268 | CHECK_REFIID(IID, IDirectInputDevice7W); 269 | CHECK_REFIID(IID, IDirectInputDevice8A); 270 | CHECK_REFIID(IID, IDirectInputDevice8W); 271 | CHECK_REFIID(IID, IDirectInputEffect); 272 | // Predefined object types 273 | CHECK_REFIID(GUID, XAxis); 274 | CHECK_REFIID(GUID, YAxis); 275 | CHECK_REFIID(GUID, ZAxis); 276 | CHECK_REFIID(GUID, RxAxis); 277 | CHECK_REFIID(GUID, RyAxis); 278 | CHECK_REFIID(GUID, RzAxis); 279 | CHECK_REFIID(GUID, Slider); 280 | CHECK_REFIID(GUID, Button); 281 | CHECK_REFIID(GUID, Key); 282 | CHECK_REFIID(GUID, POV); 283 | CHECK_REFIID(GUID, Unknown); 284 | // Predefined product GUIDs 285 | CHECK_REFIID(GUID, SysMouse); 286 | CHECK_REFIID(GUID, SysKeyboard); 287 | CHECK_REFIID(GUID, Joystick); 288 | CHECK_REFIID(GUID, SysMouseEm); 289 | CHECK_REFIID(GUID, SysMouseEm2); 290 | CHECK_REFIID(GUID, SysKeyboardEm); 291 | CHECK_REFIID(GUID, SysKeyboardEm2); 292 | // Predefined force feedback effects 293 | CHECK_REFIID(GUID, ConstantForce); 294 | CHECK_REFIID(GUID, RampForce); 295 | CHECK_REFIID(GUID, Square); 296 | CHECK_REFIID(GUID, Sine); 297 | CHECK_REFIID(GUID, Triangle); 298 | CHECK_REFIID(GUID, SawtoothUp); 299 | CHECK_REFIID(GUID, SawtoothDown); 300 | CHECK_REFIID(GUID, Spring); 301 | CHECK_REFIID(GUID, Damper); 302 | CHECK_REFIID(GUID, Inertia); 303 | CHECK_REFIID(GUID, Friction); 304 | CHECK_REFIID(GUID, CustomForce); 305 | 306 | return Logging::LogStruct(os) 307 | << Logging::hex(riid.Data1) 308 | << Logging::hex(riid.Data2) 309 | << Logging::hex(riid.Data3) 310 | << Logging::hex((UINT)riid.Data4[0]) 311 | << Logging::hex((UINT)riid.Data4[1]) 312 | << Logging::hex((UINT)riid.Data4[2]) 313 | << Logging::hex((UINT)riid.Data4[3]) 314 | << Logging::hex((UINT)riid.Data4[4]) 315 | << Logging::hex((UINT)riid.Data4[5]) 316 | << Logging::hex((UINT)riid.Data4[6]) 317 | << Logging::hex((UINT)riid.Data4[7]); 318 | } 319 | 320 | std::ostream& operator<<(std::ostream& os, const DIERR& ErrCode) 321 | { 322 | #define VISIT_DIERR_CODES(visit) \ 323 | visit(DI_OK) \ 324 | visit(DI_POLLEDDEVICE) \ 325 | visit(DI_DOWNLOADSKIPPED) \ 326 | visit(DI_EFFECTRESTARTED) \ 327 | visit(DI_TRUNCATED) \ 328 | visit(DI_SETTINGSNOTSAVED) \ 329 | visit(DI_TRUNCATEDANDRESTARTED) \ 330 | visit(DI_WRITEPROTECT) \ 331 | visit(DIERR_OLDDIRECTINPUTVERSION) \ 332 | visit(DIERR_BETADIRECTINPUTVERSION) \ 333 | visit(DIERR_BADDRIVERVER) \ 334 | visit(DIERR_DEVICENOTREG) \ 335 | visit(DIERR_NOTFOUND) \ 336 | visit(DIERR_OBJECTNOTFOUND) \ 337 | visit(DIERR_INVALIDPARAM) \ 338 | visit(DIERR_NOINTERFACE) \ 339 | visit(DIERR_GENERIC) \ 340 | visit(DIERR_OUTOFMEMORY) \ 341 | visit(DIERR_UNSUPPORTED) \ 342 | visit(DIERR_NOTINITIALIZED) \ 343 | visit(DIERR_ALREADYINITIALIZED) \ 344 | visit(DIERR_NOAGGREGATION) \ 345 | visit(DIERR_OTHERAPPHASPRIO) \ 346 | visit(DIERR_INPUTLOST) \ 347 | visit(DIERR_ACQUIRED) \ 348 | visit(DIERR_NOTACQUIRED) \ 349 | visit(DIERR_READONLY) \ 350 | visit(DIERR_HANDLEEXISTS) \ 351 | visit(DIERR_INSUFFICIENTPRIVS) \ 352 | visit(DIERR_DEVICEFULL) \ 353 | visit(DIERR_MOREDATA) \ 354 | visit(DIERR_NOTDOWNLOADED) \ 355 | visit(DIERR_HASEFFECTS) \ 356 | visit(DIERR_NOTEXCLUSIVEACQUIRED) \ 357 | visit(DIERR_INCOMPLETEEFFECT) \ 358 | visit(DIERR_NOTBUFFERED) \ 359 | visit(DIERR_EFFECTPLAYING) \ 360 | visit(DIERR_UNPLUGGED) \ 361 | visit(DIERR_REPORTFULL) \ 362 | visit(DIERR_MAPFILEFAIL) \ 363 | visit(E_PENDING) \ 364 | visit(E_NOINTERFACE) \ 365 | visit(E_POINTER) \ 366 | visit(E_HANDLE) 367 | 368 | #define VISIT_DIERR_RETURN(x) \ 369 | if (ErrCode == x) \ 370 | { \ 371 | return os << #x; \ 372 | } 373 | 374 | if (ErrCode == S_FALSE) 375 | { 376 | return os << "'DI_NOTATTACHED' or 'DI_BUFFEROVERFLOW' or 'DI_PROPNOEFFECT' or 'DI_NOEFFECT'"; 377 | } 378 | 379 | VISIT_DIERR_CODES(VISIT_DIERR_RETURN); 380 | 381 | return os << Logging::hex((DWORD)ErrCode); 382 | } 383 | #endif // !DISABLE_COMMON_LOGGING 384 | -------------------------------------------------------------------------------- /Logging/Logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN 4 | #include 5 | #include 6 | 7 | #ifndef DINPUTTO8NOLOG 8 | #include "External\Logging\Logging.h" 9 | #endif 10 | 11 | #ifndef DIERR_SET 12 | #define DIERR_SET 13 | #pragma warning (disable: 26812) 14 | typedef enum _DIERR { } DIERR; 15 | #endif 16 | 17 | #ifdef DINPUTTO8NOLOG 18 | 19 | #define LOG_ONCE(msg) 20 | #define LOG_LIMIT(num, msg) 21 | 22 | namespace Logging 23 | { 24 | extern bool EnableLogging; 25 | 26 | template void Open(T) {} 27 | template struct Hex { explicit Hex(Num) {} }; 28 | template Hex hex(Num val) { return Hex(val); } 29 | template std::ostream& operator<<(std::ostream& os, Hex) { return os; } 30 | 31 | class Log 32 | { 33 | public: 34 | Log::Log(bool LogEvent = true) { UNREFERENCED_PARAMETER(LogEvent); } 35 | Log::~Log() {} 36 | 37 | template 38 | Log& operator<<(const T&) { return *this; } 39 | }; 40 | 41 | class LogStruct 42 | { 43 | public: 44 | LogStruct(std::ostream& os) : m_os(os) {} 45 | ~LogStruct() {} 46 | template LogStruct& operator<<(const T&) { return *this; } 47 | 48 | operator std::ostream&() { return m_os; } 49 | 50 | private: 51 | std::ostream& m_os; 52 | }; 53 | 54 | typedef Log LogDebug; 55 | 56 | void LogFormat(char *, ...); 57 | void LogFormat(wchar_t *, ...); 58 | void LogProcessNameAndPID(); 59 | void LogOSVersion(); 60 | void LogComputerManufacturer(); 61 | void LogVideoCard(); 62 | void LogGameType(); 63 | } 64 | 65 | extern std::ofstream LOG; 66 | 67 | #endif 68 | 69 | void LogDataFormat(const DIDATAFORMAT &df); 70 | void LogDataFormat(LPCDIDATAFORMAT lpdf); 71 | void LogEffectFormat(const DIEFFECT &eff, REFGUID rguid); 72 | void LogEffectFormat(LPCDIEFFECT lpeff, REFGUID rguid); 73 | std::ostream& operator<<(std::ostream& os, DIEFFECT df); 74 | std::ostream& operator<<(std::ostream& os, LPCDIEFFECT lpdf); 75 | std::ostream& operator<<(std::ostream& os, DIENVELOPE df); 76 | std::ostream& operator<<(std::ostream& os, LPDIENVELOPE lpdf); 77 | std::ostream& operator<<(std::ostream& os, DIDATAFORMAT df); 78 | std::ostream& operator<<(std::ostream& os, LPCDIDATAFORMAT lpdf); 79 | std::ostream& operator<<(std::ostream& os, DIOBJECTDATAFORMAT odf); 80 | std::ostream& operator<<(std::ostream& os, LPCDIOBJECTDATAFORMAT rgodf); 81 | std::ostream& operator<<(std::ostream& os, const DIERR& ErrCode); 82 | std::ostream& operator<<(std::ostream& os, REFIID riid); 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dinputto8 2 | 3 | dinputto8 is a dll module that is designed to improve compatibility in games using DirectInput 1-7 (dinput.dll) by converting all API calls to their equivalent DirectInput 8 (dinput8.dll) ones. This allows older games to be able to use newer tools and wrappers written for DirectInput 8. 4 | 5 | ### Installation 6 | 7 | To install just download the latest binary release from the repository's [Release](https://github.com/elishacloud/dinputto8/releases) page and unzip the `dinput.dll` file into the folder of a DirectInput 1-7 program or game. 8 | 9 | _Note: Do not attempt to overwrite any .dll in a Windows system directory as it is currently not supported and will not work._ 10 | 11 | ### Uninstallation 12 | 13 | Delete the `dinput.dll` files from the game's directory. You can also delete the associated log file, if there is one. 14 | 15 | ### Supported Games 16 | 17 | * 1NSANE 18 | * 8th Wonder of the World 19 | * Arcanum 20 | * Atlantis 3: The New World 21 | * B-17: Flying Fortress 22 | * Beyond Atlantis 23 | * Call To Power 2 24 | * Castle Adventure 25 | * Chris Sawyer's Locomotion 26 | * Colin McRae Rally 2.0 27 | * Commandos 2 28 | * Commandos 3 29 | * Conquest: Frontier Wars 30 | * Dark Reign 31 | * Digger XP 32 | * DOSBox 33 | * Dungeon Keeper 2 34 | * Enclave 35 | * FA-18E: Super Hornet 36 | * Gangsters: Organized Crime 37 | * Geneforge Saga 1-4 38 | * Hogs of War 39 | * Interstate 76 40 | * Interstate 82 41 | * Jazz Jackrabbit 2 42 | * Knight Rider 43 | * Knight Rider 2 44 | * Legacy of Kain: Soul Reaver 45 | * Lionheart: Legacy of the Crusader 46 | * MegaRace 3 47 | * Michelin Rally Masters: Race of Champions 48 | * Might and Magic IX 49 | * Moto Racer 50 | * Moto Racer 2 51 | * Myst III: Exile 52 | * NOX 53 | * Populous: The Beginning 54 | * Rayman 2: The Great Escape 55 | * Raymond 2 56 | * Requiem: Avenging Angel 57 | * Settlers 3 58 | * Shogo 59 | * Simon the Sorcerer 3D 60 | * Slave Zero 61 | * Star Wars Episode I: Racer 62 | * Swedish Touring Car Championship 63 | * Swedish Touring Car Championship 2 64 | * Uprising 2: Lead and Destroy 65 | * Uprising: Join or Die 66 | * V8 Challenge 67 | * Vampire: The Masquerade Redemption 68 | * Warrior Kings 69 | * Warrior Kings: Battles 70 | * X-COM: Interceptor 71 | 72 | ### Configuration 73 | 74 | There are no configuration options for dinputto8. 75 | 76 | ### License 77 | Copyright (C) 2025 Elisha Riedlinger 78 | 79 | This software is provided 'as-is', without any express or implied warranty. In no event will the author(s) be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 80 | 81 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 82 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 83 | 3. This notice may not be removed or altered from any source distribution. 84 | 85 | ### Credits 86 | dinputto8 uses code from some other projects. Below is a list of locations that source code was taken from: 87 | 88 | - [Aqrit's ddwrapper](http://bitpatch.com/ddwrapper.html): Includes code to read the ini config file. 89 | - [DDrawCompat](https://github.com/narzoul/DDrawCompat/): Includes code to for logging. 90 | - [noser-sandbox](https://code.google.com/archive/p/noser-sandbox/source/default/source) Includes code in EnumDevices() used to order the device list. You will find the extracted code in the Rayman2InputFix_DirectInputA.cpp file from the Rayman2InputFix project. 91 | 92 | ### Development 93 | dinputto8 is written in C++ using Microsoft Visual Studio Community 2017. 94 | 95 | Thanks for stopping by! 96 | -------------------------------------------------------------------------------- /Versions/IDirectInput2A.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInput2A::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInput2A::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInput2A::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInput2A::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDevice2A, (LPDIRECTINPUTDEVICE8A *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInput2A::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInput2A::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInput2A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInput2A::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | 99 | HRESULT m_IDirectInput2A::FindDevice(REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance) 100 | { 101 | if (!ProxyInterface) 102 | { 103 | return DIERR_OBJECTNOTFOUND; 104 | } 105 | return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); 106 | } 107 | -------------------------------------------------------------------------------- /Versions/IDirectInput2A.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInput2A : public IDirectInput2A, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInput2A; 8 | const DWORD DirectXVersion = 2; 9 | 10 | public: 11 | m_IDirectInput2A(IDirectInput2A *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInput2A() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputA methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | /*** IDirectInput2A methods ***/ 45 | STDMETHOD(FindDevice)(THIS_ REFGUID, LPCSTR, LPGUID); 46 | }; 47 | -------------------------------------------------------------------------------- /Versions/IDirectInput2W.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInput2W::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInput2W::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInput2W::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInput2W::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDevice2W, (LPDIRECTINPUTDEVICE8W *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInput2W::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInput2W::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInput2W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInput2W::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | 99 | HRESULT m_IDirectInput2W::FindDevice(REFGUID rguidClass, LPCWSTR ptszName, LPGUID pguidInstance) 100 | { 101 | if (!ProxyInterface) 102 | { 103 | return DIERR_OBJECTNOTFOUND; 104 | } 105 | return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); 106 | } 107 | -------------------------------------------------------------------------------- /Versions/IDirectInput2W.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInput2W : public IDirectInput2W, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInput2W; 8 | const DWORD DirectXVersion = 2; 9 | 10 | public: 11 | m_IDirectInput2W(IDirectInput2W *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInput2W() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputW methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEW *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | /*** IDirectInput2W methods ***/ 45 | STDMETHOD(FindDevice)(THIS_ REFGUID, LPCWSTR, LPGUID); 46 | }; 47 | -------------------------------------------------------------------------------- /Versions/IDirectInput7A.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInput7A::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInput7A::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInput7A::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInput7A::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDevice7A, (LPDIRECTINPUTDEVICE8A *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInput7A::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInput7A::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInput7A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInput7A::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | 99 | HRESULT m_IDirectInput7A::FindDevice(REFGUID rguidClass, LPCSTR ptszName, LPGUID pguidInstance) 100 | { 101 | if (!ProxyInterface) 102 | { 103 | return DIERR_OBJECTNOTFOUND; 104 | } 105 | return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); 106 | } 107 | 108 | HRESULT m_IDirectInput7A::CreateDeviceEx(REFGUID rguid, REFIID riid, LPVOID * ppvObj, LPUNKNOWN pUnkOuter) 109 | { 110 | if (!ProxyInterface) 111 | { 112 | if (ppvObj) 113 | { 114 | *ppvObj = nullptr; 115 | } 116 | return DIERR_OBJECTNOTFOUND; 117 | } 118 | return ProxyInterface->CreateDeviceEx(rguid, riid, (LPDIRECTINPUTDEVICE8A *)ppvObj, pUnkOuter); 119 | } 120 | -------------------------------------------------------------------------------- /Versions/IDirectInput7A.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInput7A : public IDirectInput7A, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInput7A; 8 | const DWORD DirectXVersion = 7; 9 | 10 | public: 11 | m_IDirectInput7A(IDirectInput7A *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInput7A() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputA methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | /*** IDirectInput2A methods ***/ 45 | STDMETHOD(FindDevice)(THIS_ REFGUID, LPCSTR, LPGUID); 46 | /*** IDirectInput7A methods ***/ 47 | STDMETHOD(CreateDeviceEx)(THIS_ REFGUID, REFIID, LPVOID *, LPUNKNOWN); 48 | }; 49 | -------------------------------------------------------------------------------- /Versions/IDirectInput7W.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInput7W::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInput7W::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInput7W::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInput7W::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDevice7W, (LPDIRECTINPUTDEVICE8W *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInput7W::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInput7W::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInput7W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInput7W::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | 99 | HRESULT m_IDirectInput7W::FindDevice(REFGUID rguidClass, LPCWSTR ptszName, LPGUID pguidInstance) 100 | { 101 | if (!ProxyInterface) 102 | { 103 | return DIERR_OBJECTNOTFOUND; 104 | } 105 | return ProxyInterface->FindDevice(rguidClass, ptszName, pguidInstance); 106 | } 107 | 108 | HRESULT m_IDirectInput7W::CreateDeviceEx(REFGUID rguid, REFIID riid, LPVOID * ppvObj, LPUNKNOWN pUnkOuter) 109 | { 110 | if (!ProxyInterface) 111 | { 112 | if (ppvObj) 113 | { 114 | *ppvObj = nullptr; 115 | } 116 | return DIERR_OBJECTNOTFOUND; 117 | } 118 | return ProxyInterface->CreateDeviceEx(rguid, riid, (LPDIRECTINPUTDEVICE8W *)ppvObj, pUnkOuter); 119 | } 120 | -------------------------------------------------------------------------------- /Versions/IDirectInput7W.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInput7W : public IDirectInput7W, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInput7W; 8 | const DWORD DirectXVersion = 7; 9 | 10 | public: 11 | m_IDirectInput7W(IDirectInput7W *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInput7W() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputW methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEW *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | /*** IDirectInput2W methods ***/ 45 | STDMETHOD(FindDevice)(THIS_ REFGUID, LPCWSTR, LPGUID); 46 | /*** IDirectInput7W methods ***/ 47 | STDMETHOD(CreateDeviceEx)(THIS_ REFGUID, REFIID, LPVOID *, LPUNKNOWN); 48 | }; 49 | -------------------------------------------------------------------------------- /Versions/IDirectInputA.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputA::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputA::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputA::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputA::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEA *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDeviceA, (LPDIRECTINPUTDEVICE8A *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInputA::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInputA::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInputA::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInputA::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | -------------------------------------------------------------------------------- /Versions/IDirectInputA.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputA : public IDirectInputA, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputA; 8 | const DWORD DirectXVersion = 1; 9 | 10 | public: 11 | m_IDirectInputA(IDirectInputA *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputA() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInput methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEA *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | }; 45 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice2A.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDevice2A::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDevice2A::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDevice2A::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDevice2A::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDevice2A::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDevice2A::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDevice2A::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDevice2A::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDevice2A::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDevice2A::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDevice2A::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDevice2A::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDevice2A::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDevice2A::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDevice2A::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDevice2A::GetDeviceInfo(LPDIDEVICEINSTANCEA pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDevice2A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDevice2A::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | 185 | HRESULT m_IDirectInputDevice2A::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) 186 | { 187 | if (!ProxyInterface) 188 | { 189 | if (ppdeff) 190 | { 191 | *ppdeff = nullptr; 192 | } 193 | return DIERR_OBJECTNOTFOUND; 194 | } 195 | return ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); 196 | } 197 | 198 | HRESULT m_IDirectInputDevice2A::EnumEffects(LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) 199 | { 200 | if (!ProxyInterface) 201 | { 202 | return DIERR_OBJECTNOTFOUND; 203 | } 204 | return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); 205 | } 206 | 207 | HRESULT m_IDirectInputDevice2A::GetEffectInfo(LPDIEFFECTINFOA pdei, REFGUID rguid) 208 | { 209 | if (!ProxyInterface) 210 | { 211 | return DIERR_OBJECTNOTFOUND; 212 | } 213 | return ProxyInterface->GetEffectInfo(pdei, rguid); 214 | } 215 | 216 | HRESULT m_IDirectInputDevice2A::GetForceFeedbackState(LPDWORD pdwOut) 217 | { 218 | if (!ProxyInterface) 219 | { 220 | return DIERR_OBJECTNOTFOUND; 221 | } 222 | return ProxyInterface->GetForceFeedbackState(pdwOut); 223 | } 224 | 225 | HRESULT m_IDirectInputDevice2A::SendForceFeedbackCommand(DWORD dwFlags) 226 | { 227 | if (!ProxyInterface) 228 | { 229 | return DIERR_OBJECTNOTFOUND; 230 | } 231 | return ProxyInterface->SendForceFeedbackCommand(dwFlags); 232 | } 233 | 234 | HRESULT m_IDirectInputDevice2A::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) 235 | { 236 | if (!ProxyInterface) 237 | { 238 | return DIERR_OBJECTNOTFOUND; 239 | } 240 | return ProxyInterface->EnumCreatedEffectObjects(lpCallback, pvRef, fl); 241 | } 242 | 243 | HRESULT m_IDirectInputDevice2A::Escape(LPDIEFFESCAPE pesc) 244 | { 245 | if (!ProxyInterface) 246 | { 247 | return DIERR_OBJECTNOTFOUND; 248 | } 249 | return ProxyInterface->Escape(pesc); 250 | } 251 | 252 | HRESULT m_IDirectInputDevice2A::Poll() 253 | { 254 | if (!ProxyInterface) 255 | { 256 | return DIERR_OBJECTNOTFOUND; 257 | } 258 | return ProxyInterface->Poll(); 259 | } 260 | 261 | HRESULT m_IDirectInputDevice2A::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) 262 | { 263 | if (!ProxyInterface) 264 | { 265 | return DIERR_OBJECTNOTFOUND; 266 | } 267 | return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); 268 | } 269 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice2A.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDevice2A : public IDirectInputDevice2A, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDevice2A; 8 | const DWORD DirectXVersion = 2; 9 | 10 | public: 11 | m_IDirectInputDevice2A(IDirectInputDevice2A *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDevice2A() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDeviceA methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | /*** IDirectInputDevice2A methods ***/ 55 | STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); 56 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA, LPVOID, DWORD); 57 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA, REFGUID); 58 | STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); 59 | STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); 60 | STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); 61 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 62 | STDMETHOD(Poll)(THIS); 63 | STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); 64 | }; 65 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice2W.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDevice2W::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDevice2W::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDevice2W::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDevice2W::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDevice2W::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDevice2W::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDevice2W::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDevice2W::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDevice2W::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDevice2W::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDevice2W::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDevice2W::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDevice2W::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDevice2W::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDevice2W::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDevice2W::GetDeviceInfo(LPDIDEVICEINSTANCEW pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDevice2W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDevice2W::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | 185 | HRESULT m_IDirectInputDevice2W::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) 186 | { 187 | if (!ProxyInterface) 188 | { 189 | if (ppdeff) 190 | { 191 | *ppdeff = nullptr; 192 | } 193 | return DIERR_OBJECTNOTFOUND; 194 | } 195 | return ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); 196 | } 197 | 198 | HRESULT m_IDirectInputDevice2W::EnumEffects(LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) 199 | { 200 | if (!ProxyInterface) 201 | { 202 | return DIERR_OBJECTNOTFOUND; 203 | } 204 | return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); 205 | } 206 | 207 | HRESULT m_IDirectInputDevice2W::GetEffectInfo(LPDIEFFECTINFOW pdei, REFGUID rguid) 208 | { 209 | if (!ProxyInterface) 210 | { 211 | return DIERR_OBJECTNOTFOUND; 212 | } 213 | return ProxyInterface->GetEffectInfo(pdei, rguid); 214 | } 215 | 216 | HRESULT m_IDirectInputDevice2W::GetForceFeedbackState(LPDWORD pdwOut) 217 | { 218 | if (!ProxyInterface) 219 | { 220 | return DIERR_OBJECTNOTFOUND; 221 | } 222 | return ProxyInterface->GetForceFeedbackState(pdwOut); 223 | } 224 | 225 | HRESULT m_IDirectInputDevice2W::SendForceFeedbackCommand(DWORD dwFlags) 226 | { 227 | if (!ProxyInterface) 228 | { 229 | return DIERR_OBJECTNOTFOUND; 230 | } 231 | return ProxyInterface->SendForceFeedbackCommand(dwFlags); 232 | } 233 | 234 | HRESULT m_IDirectInputDevice2W::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) 235 | { 236 | if (!ProxyInterface) 237 | { 238 | return DIERR_OBJECTNOTFOUND; 239 | } 240 | return ProxyInterface->EnumCreatedEffectObjects(lpCallback, pvRef, fl); 241 | } 242 | 243 | HRESULT m_IDirectInputDevice2W::Escape(LPDIEFFESCAPE pesc) 244 | { 245 | if (!ProxyInterface) 246 | { 247 | return DIERR_OBJECTNOTFOUND; 248 | } 249 | return ProxyInterface->Escape(pesc); 250 | } 251 | 252 | HRESULT m_IDirectInputDevice2W::Poll() 253 | { 254 | if (!ProxyInterface) 255 | { 256 | return DIERR_OBJECTNOTFOUND; 257 | } 258 | return ProxyInterface->Poll(); 259 | } 260 | 261 | HRESULT m_IDirectInputDevice2W::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) 262 | { 263 | if (!ProxyInterface) 264 | { 265 | return DIERR_OBJECTNOTFOUND; 266 | } 267 | return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); 268 | } 269 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice2W.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDevice2W : public IDirectInputDevice2W, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDevice2W; 8 | const DWORD DirectXVersion = 2; 9 | 10 | public: 11 | m_IDirectInputDevice2W(IDirectInputDevice2W *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDevice2W() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDeviceW methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | /*** IDirectInputDevice2W methods ***/ 55 | STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); 56 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW, LPVOID, DWORD); 57 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW, REFGUID); 58 | STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); 59 | STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); 60 | STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); 61 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 62 | STDMETHOD(Poll)(THIS); 63 | STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); 64 | }; 65 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice7A.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDevice7A::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDevice7A::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDevice7A::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDevice7A::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDevice7A::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDevice7A::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDevice7A::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDevice7A::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDevice7A::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDevice7A::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDevice7A::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDevice7A::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDevice7A::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDevice7A::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDevice7A::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDevice7A::GetDeviceInfo(LPDIDEVICEINSTANCEA pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDevice7A::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDevice7A::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | 185 | HRESULT m_IDirectInputDevice7A::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) 186 | { 187 | if (!ProxyInterface) 188 | { 189 | if (ppdeff) 190 | { 191 | *ppdeff = nullptr; 192 | } 193 | return DIERR_OBJECTNOTFOUND; 194 | } 195 | return ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); 196 | } 197 | 198 | HRESULT m_IDirectInputDevice7A::EnumEffects(LPDIENUMEFFECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwEffType) 199 | { 200 | if (!ProxyInterface) 201 | { 202 | return DIERR_OBJECTNOTFOUND; 203 | } 204 | return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); 205 | } 206 | 207 | HRESULT m_IDirectInputDevice7A::GetEffectInfo(LPDIEFFECTINFOA pdei, REFGUID rguid) 208 | { 209 | if (!ProxyInterface) 210 | { 211 | return DIERR_OBJECTNOTFOUND; 212 | } 213 | return ProxyInterface->GetEffectInfo(pdei, rguid); 214 | } 215 | 216 | HRESULT m_IDirectInputDevice7A::GetForceFeedbackState(LPDWORD pdwOut) 217 | { 218 | if (!ProxyInterface) 219 | { 220 | return DIERR_OBJECTNOTFOUND; 221 | } 222 | return ProxyInterface->GetForceFeedbackState(pdwOut); 223 | } 224 | 225 | HRESULT m_IDirectInputDevice7A::SendForceFeedbackCommand(DWORD dwFlags) 226 | { 227 | if (!ProxyInterface) 228 | { 229 | return DIERR_OBJECTNOTFOUND; 230 | } 231 | return ProxyInterface->SendForceFeedbackCommand(dwFlags); 232 | } 233 | 234 | HRESULT m_IDirectInputDevice7A::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) 235 | { 236 | if (!ProxyInterface) 237 | { 238 | return DIERR_OBJECTNOTFOUND; 239 | } 240 | return ProxyInterface->EnumCreatedEffectObjects(lpCallback, pvRef, fl); 241 | } 242 | 243 | HRESULT m_IDirectInputDevice7A::Escape(LPDIEFFESCAPE pesc) 244 | { 245 | if (!ProxyInterface) 246 | { 247 | return DIERR_OBJECTNOTFOUND; 248 | } 249 | return ProxyInterface->Escape(pesc); 250 | } 251 | 252 | HRESULT m_IDirectInputDevice7A::Poll() 253 | { 254 | if (!ProxyInterface) 255 | { 256 | return DIERR_OBJECTNOTFOUND; 257 | } 258 | return ProxyInterface->Poll(); 259 | } 260 | 261 | HRESULT m_IDirectInputDevice7A::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) 262 | { 263 | if (!ProxyInterface) 264 | { 265 | return DIERR_OBJECTNOTFOUND; 266 | } 267 | return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); 268 | } 269 | 270 | HRESULT m_IDirectInputDevice7A::EnumEffectsInFile(LPCSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) 271 | { 272 | if (!ProxyInterface) 273 | { 274 | return DIERR_OBJECTNOTFOUND; 275 | } 276 | return ProxyInterface->EnumEffectsInFile(lpszFileName, pec, pvRef, dwFlags); 277 | } 278 | 279 | HRESULT m_IDirectInputDevice7A::WriteEffectToFile(LPCSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) 280 | { 281 | if (!ProxyInterface) 282 | { 283 | return DIERR_OBJECTNOTFOUND; 284 | } 285 | return ProxyInterface->WriteEffectToFile(lpszFileName, dwEntries, rgDiFileEft, dwFlags); 286 | } 287 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice7A.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDevice7A : public IDirectInputDevice7A, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDevice7A; 8 | const DWORD DirectXVersion = 7; 9 | 10 | public: 11 | m_IDirectInputDevice7A(IDirectInputDevice7A *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDevice7A() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDeviceA methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | /*** IDirectInputDevice2A methods ***/ 55 | STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); 56 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA, LPVOID, DWORD); 57 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA, REFGUID); 58 | STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); 59 | STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); 60 | STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); 61 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 62 | STDMETHOD(Poll)(THIS); 63 | STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); 64 | /*** IDirectInputDevice7A methods ***/ 65 | STDMETHOD(EnumEffectsInFile)(THIS_ LPCSTR, LPDIENUMEFFECTSINFILECALLBACK, LPVOID, DWORD); 66 | STDMETHOD(WriteEffectToFile)(THIS_ LPCSTR, DWORD, LPDIFILEEFFECT, DWORD); 67 | }; 68 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice7W.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDevice7W::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDevice7W::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDevice7W::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDevice7W::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDevice7W::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDevice7W::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDevice7W::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDevice7W::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDevice7W::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDevice7W::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDevice7W::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDevice7W::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDevice7W::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDevice7W::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDevice7W::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDevice7W::GetDeviceInfo(LPDIDEVICEINSTANCEW pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDevice7W::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDevice7W::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | 185 | HRESULT m_IDirectInputDevice7W::CreateEffect(REFGUID rguid, LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT * ppdeff, LPUNKNOWN punkOuter) 186 | { 187 | if (!ProxyInterface) 188 | { 189 | if (ppdeff) 190 | { 191 | *ppdeff = nullptr; 192 | } 193 | return DIERR_OBJECTNOTFOUND; 194 | } 195 | return ProxyInterface->CreateEffect(rguid, lpeff, ppdeff, punkOuter); 196 | } 197 | 198 | HRESULT m_IDirectInputDevice7W::EnumEffects(LPDIENUMEFFECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwEffType) 199 | { 200 | if (!ProxyInterface) 201 | { 202 | return DIERR_OBJECTNOTFOUND; 203 | } 204 | return ProxyInterface->EnumEffects(lpCallback, pvRef, dwEffType); 205 | } 206 | 207 | HRESULT m_IDirectInputDevice7W::GetEffectInfo(LPDIEFFECTINFOW pdei, REFGUID rguid) 208 | { 209 | if (!ProxyInterface) 210 | { 211 | return DIERR_OBJECTNOTFOUND; 212 | } 213 | return ProxyInterface->GetEffectInfo(pdei, rguid); 214 | } 215 | 216 | HRESULT m_IDirectInputDevice7W::GetForceFeedbackState(LPDWORD pdwOut) 217 | { 218 | if (!ProxyInterface) 219 | { 220 | return DIERR_OBJECTNOTFOUND; 221 | } 222 | return ProxyInterface->GetForceFeedbackState(pdwOut); 223 | } 224 | 225 | HRESULT m_IDirectInputDevice7W::SendForceFeedbackCommand(DWORD dwFlags) 226 | { 227 | if (!ProxyInterface) 228 | { 229 | return DIERR_OBJECTNOTFOUND; 230 | } 231 | return ProxyInterface->SendForceFeedbackCommand(dwFlags); 232 | } 233 | 234 | HRESULT m_IDirectInputDevice7W::EnumCreatedEffectObjects(LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD fl) 235 | { 236 | if (!ProxyInterface) 237 | { 238 | return DIERR_OBJECTNOTFOUND; 239 | } 240 | return ProxyInterface->EnumCreatedEffectObjects(lpCallback, pvRef, fl); 241 | } 242 | 243 | HRESULT m_IDirectInputDevice7W::Escape(LPDIEFFESCAPE pesc) 244 | { 245 | if (!ProxyInterface) 246 | { 247 | return DIERR_OBJECTNOTFOUND; 248 | } 249 | return ProxyInterface->Escape(pesc); 250 | } 251 | 252 | HRESULT m_IDirectInputDevice7W::Poll() 253 | { 254 | if (!ProxyInterface) 255 | { 256 | return DIERR_OBJECTNOTFOUND; 257 | } 258 | return ProxyInterface->Poll(); 259 | } 260 | 261 | HRESULT m_IDirectInputDevice7W::SendDeviceData(DWORD cbObjectData, LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD fl) 262 | { 263 | if (!ProxyInterface) 264 | { 265 | return DIERR_OBJECTNOTFOUND; 266 | } 267 | return ProxyInterface->SendDeviceData(cbObjectData, rgdod, pdwInOut, fl); 268 | } 269 | 270 | HRESULT m_IDirectInputDevice7W::EnumEffectsInFile(LPCWSTR lpszFileName, LPDIENUMEFFECTSINFILECALLBACK pec, LPVOID pvRef, DWORD dwFlags) 271 | { 272 | if (!ProxyInterface) 273 | { 274 | return DIERR_OBJECTNOTFOUND; 275 | } 276 | return ProxyInterface->EnumEffectsInFile(lpszFileName, pec, pvRef, dwFlags); 277 | } 278 | 279 | HRESULT m_IDirectInputDevice7W::WriteEffectToFile(LPCWSTR lpszFileName, DWORD dwEntries, LPDIFILEEFFECT rgDiFileEft, DWORD dwFlags) 280 | { 281 | if (!ProxyInterface) 282 | { 283 | return DIERR_OBJECTNOTFOUND; 284 | } 285 | return ProxyInterface->WriteEffectToFile(lpszFileName, dwEntries, rgDiFileEft, dwFlags); 286 | } 287 | -------------------------------------------------------------------------------- /Versions/IDirectInputDevice7W.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDevice7W : public IDirectInputDevice7W, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDevice7W; 8 | const DWORD DirectXVersion = 7; 9 | 10 | public: 11 | m_IDirectInputDevice7W(IDirectInputDevice7W *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDevice7W() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDeviceW methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | /*** IDirectInputDevice2W methods ***/ 55 | STDMETHOD(CreateEffect)(THIS_ REFGUID, LPCDIEFFECT, LPDIRECTINPUTEFFECT *, LPUNKNOWN); 56 | STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW, LPVOID, DWORD); 57 | STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW, REFGUID); 58 | STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD); 59 | STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD); 60 | STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK, LPVOID, DWORD); 61 | STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE); 62 | STDMETHOD(Poll)(THIS); 63 | STDMETHOD(SendDeviceData)(THIS_ DWORD, LPCDIDEVICEOBJECTDATA, LPDWORD, DWORD); 64 | /*** IDirectInputDevice7W methods ***/ 65 | STDMETHOD(EnumEffectsInFile)(THIS_ LPCWSTR, LPDIENUMEFFECTSINFILECALLBACK, LPVOID, DWORD); 66 | STDMETHOD(WriteEffectToFile)(THIS_ LPCWSTR, DWORD, LPDIFILEEFFECT, DWORD); 67 | }; 68 | -------------------------------------------------------------------------------- /Versions/IDirectInputDeviceA.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDeviceA::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDeviceA::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDeviceA::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDeviceA::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDeviceA::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDeviceA::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDeviceA::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDeviceA::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDeviceA::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDeviceA::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDeviceA::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDeviceA::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDeviceA::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDeviceA::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDeviceA::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDeviceA::GetDeviceInfo(LPDIDEVICEINSTANCEA pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDeviceA::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDeviceA::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | -------------------------------------------------------------------------------- /Versions/IDirectInputDeviceA.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDeviceA : public IDirectInputDeviceA, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDeviceA; 8 | const DWORD DirectXVersion = 1; 9 | 10 | public: 11 | m_IDirectInputDeviceA(IDirectInputDeviceA *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDeviceA() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDevice methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | }; 55 | -------------------------------------------------------------------------------- /Versions/IDirectInputDeviceW.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputDeviceW::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputDeviceW::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputDeviceW::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputDeviceW::GetCapabilities(LPDIDEVCAPS lpDIDevCaps) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | return DIERR_OBJECTNOTFOUND; 55 | } 56 | return ProxyInterface->GetCapabilities(lpDIDevCaps); 57 | } 58 | 59 | HRESULT m_IDirectInputDeviceW::EnumObjects(LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 60 | { 61 | if (!ProxyInterface) 62 | { 63 | return DIERR_OBJECTNOTFOUND; 64 | } 65 | return ProxyInterface->EnumObjects(lpCallback, pvRef, dwFlags); 66 | } 67 | 68 | HRESULT m_IDirectInputDeviceW::GetProperty(REFGUID rguidProp, LPDIPROPHEADER pdiph) 69 | { 70 | if (!ProxyInterface) 71 | { 72 | return DIERR_OBJECTNOTFOUND; 73 | } 74 | return ProxyInterface->GetProperty(rguidProp, pdiph); 75 | } 76 | 77 | HRESULT m_IDirectInputDeviceW::SetProperty(REFGUID rguidProp, LPCDIPROPHEADER pdiph) 78 | { 79 | if (!ProxyInterface) 80 | { 81 | return DIERR_OBJECTNOTFOUND; 82 | } 83 | return ProxyInterface->SetProperty(rguidProp, pdiph); 84 | } 85 | 86 | HRESULT m_IDirectInputDeviceW::Acquire() 87 | { 88 | if (!ProxyInterface) 89 | { 90 | return DIERR_OBJECTNOTFOUND; 91 | } 92 | return ProxyInterface->Acquire(); 93 | } 94 | 95 | HRESULT m_IDirectInputDeviceW::Unacquire() 96 | { 97 | if (!ProxyInterface) 98 | { 99 | return DIERR_OBJECTNOTFOUND; 100 | } 101 | return ProxyInterface->Unacquire(); 102 | } 103 | 104 | HRESULT m_IDirectInputDeviceW::GetDeviceState(DWORD cbData, LPVOID lpvData) 105 | { 106 | if (!ProxyInterface) 107 | { 108 | return DIERR_OBJECTNOTFOUND; 109 | } 110 | return ProxyInterface->GetDeviceState(cbData, lpvData); 111 | } 112 | 113 | HRESULT m_IDirectInputDeviceW::GetDeviceData(DWORD cbObjectData, LPDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) 114 | { 115 | if (!ProxyInterface) 116 | { 117 | return DIERR_OBJECTNOTFOUND; 118 | } 119 | return ProxyInterface->GetDeviceData(cbObjectData, rgdod, pdwInOut, dwFlags); 120 | } 121 | 122 | HRESULT m_IDirectInputDeviceW::SetDataFormat(LPCDIDATAFORMAT lpdf) 123 | { 124 | if (!ProxyInterface) 125 | { 126 | return DIERR_OBJECTNOTFOUND; 127 | } 128 | return ProxyInterface->SetDataFormat(lpdf); 129 | } 130 | 131 | HRESULT m_IDirectInputDeviceW::SetEventNotification(HANDLE hEvent) 132 | { 133 | if (!ProxyInterface) 134 | { 135 | return DIERR_OBJECTNOTFOUND; 136 | } 137 | return ProxyInterface->SetEventNotification(hEvent); 138 | } 139 | 140 | HRESULT m_IDirectInputDeviceW::SetCooperativeLevel(HWND hwnd, DWORD dwFlags) 141 | { 142 | if (!ProxyInterface) 143 | { 144 | return DIERR_OBJECTNOTFOUND; 145 | } 146 | return ProxyInterface->SetCooperativeLevel(hwnd, dwFlags); 147 | } 148 | 149 | HRESULT m_IDirectInputDeviceW::GetObjectInfo(LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) 150 | { 151 | if (!ProxyInterface) 152 | { 153 | return DIERR_OBJECTNOTFOUND; 154 | } 155 | return ProxyInterface->GetObjectInfo(pdidoi, dwObj, dwHow); 156 | } 157 | 158 | HRESULT m_IDirectInputDeviceW::GetDeviceInfo(LPDIDEVICEINSTANCEW pdidi) 159 | { 160 | if (!ProxyInterface) 161 | { 162 | return DIERR_OBJECTNOTFOUND; 163 | } 164 | return ProxyInterface->GetDeviceInfo(pdidi); 165 | } 166 | 167 | HRESULT m_IDirectInputDeviceW::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 168 | { 169 | if (!ProxyInterface) 170 | { 171 | return DIERR_OBJECTNOTFOUND; 172 | } 173 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 174 | } 175 | 176 | HRESULT m_IDirectInputDeviceW::Initialize(HINSTANCE hinst, DWORD dwVersion, REFGUID rguid) 177 | { 178 | if (!ProxyInterface) 179 | { 180 | return DIERR_OBJECTNOTFOUND; 181 | } 182 | return ProxyInterface->Initialize(hinst, dwVersion, rguid); 183 | } 184 | -------------------------------------------------------------------------------- /Versions/IDirectInputDeviceW.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputDeviceW : public IDirectInputDeviceW, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputDeviceX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputDeviceW; 8 | const DWORD DirectXVersion = 1; 9 | 10 | public: 11 | m_IDirectInputDeviceW(IDirectInputDeviceW *, m_IDirectInputDeviceX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputDeviceW() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputDeviceX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInputDevice methods ***/ 39 | STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS); 40 | STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetProperty)(THIS_ REFGUID, LPDIPROPHEADER); 42 | STDMETHOD(SetProperty)(THIS_ REFGUID, LPCDIPROPHEADER); 43 | STDMETHOD(Acquire)(THIS); 44 | STDMETHOD(Unacquire)(THIS); 45 | STDMETHOD(GetDeviceState)(THIS_ DWORD, LPVOID); 46 | STDMETHOD(GetDeviceData)(THIS_ DWORD, LPDIDEVICEOBJECTDATA, LPDWORD, DWORD); 47 | STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT); 48 | STDMETHOD(SetEventNotification)(THIS_ HANDLE); 49 | STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD); 50 | STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW, DWORD, DWORD); 51 | STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW); 52 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 53 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD, REFGUID); 54 | }; 55 | -------------------------------------------------------------------------------- /Versions/IDirectInputW.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "..\dinputto8.h" 18 | 19 | HRESULT m_IDirectInputW::QueryInterface(REFIID riid, LPVOID FAR * ppvObj) 20 | { 21 | if (!ProxyInterface) 22 | { 23 | if (ppvObj) 24 | { 25 | *ppvObj = nullptr; 26 | } 27 | return E_NOINTERFACE; 28 | } 29 | return ProxyInterface->QueryInterface(ReplaceIIDUnknown(riid, WrapperID), ppvObj, DirectXVersion); 30 | } 31 | 32 | ULONG m_IDirectInputW::AddRef() 33 | { 34 | if (!ProxyInterface) 35 | { 36 | return 0; 37 | } 38 | return ProxyInterface->AddRef(); 39 | } 40 | 41 | ULONG m_IDirectInputW::Release() 42 | { 43 | if (!ProxyInterface) 44 | { 45 | return 0; 46 | } 47 | return ProxyInterface->Release(); 48 | } 49 | 50 | HRESULT m_IDirectInputW::CreateDevice(REFGUID rguid, LPDIRECTINPUTDEVICEW *lplpDirectInputDevice, LPUNKNOWN pUnkOuter) 51 | { 52 | if (!ProxyInterface) 53 | { 54 | if (lplpDirectInputDevice) 55 | { 56 | *lplpDirectInputDevice = nullptr; 57 | } 58 | return DIERR_OBJECTNOTFOUND; 59 | } 60 | return ProxyInterface->CreateDeviceEx(rguid, IID_IDirectInputDeviceW, (LPDIRECTINPUTDEVICE8W *)lplpDirectInputDevice, pUnkOuter); 61 | } 62 | 63 | HRESULT m_IDirectInputW::EnumDevices(DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback, LPVOID pvRef, DWORD dwFlags) 64 | { 65 | if (!ProxyInterface) 66 | { 67 | return DIERR_OBJECTNOTFOUND; 68 | } 69 | return ProxyInterface->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags); 70 | } 71 | 72 | HRESULT m_IDirectInputW::GetDeviceStatus(REFGUID rguidInstance) 73 | { 74 | if (!ProxyInterface) 75 | { 76 | return DIERR_OBJECTNOTFOUND; 77 | } 78 | return ProxyInterface->GetDeviceStatus(rguidInstance); 79 | } 80 | 81 | HRESULT m_IDirectInputW::RunControlPanel(HWND hwndOwner, DWORD dwFlags) 82 | { 83 | if (!ProxyInterface) 84 | { 85 | return DIERR_OBJECTNOTFOUND; 86 | } 87 | return ProxyInterface->RunControlPanel(hwndOwner, dwFlags); 88 | } 89 | 90 | HRESULT m_IDirectInputW::Initialize(HINSTANCE hinst, DWORD dwVersion) 91 | { 92 | if (!ProxyInterface) 93 | { 94 | return DIERR_OBJECTNOTFOUND; 95 | } 96 | return ProxyInterface->Initialize(hinst, dwVersion); 97 | } 98 | -------------------------------------------------------------------------------- /Versions/IDirectInputW.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class m_IDirectInputW : public IDirectInputW, public AddressLookupTableDinputObject 4 | { 5 | private: 6 | m_IDirectInputX *ProxyInterface; 7 | const IID WrapperID = IID_IDirectInputW; 8 | const DWORD DirectXVersion = 1; 9 | 10 | public: 11 | m_IDirectInputW(IDirectInputW *, m_IDirectInputX *Interface) : ProxyInterface(Interface) 12 | { 13 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 14 | } 15 | ~m_IDirectInputW() 16 | { 17 | ProxyAddressLookupTable.DeleteAddress(this); 18 | } 19 | 20 | void SetProxy(m_IDirectInputX* NewProxyInterface) 21 | { 22 | ProxyInterface = NewProxyInterface; 23 | if (NewProxyInterface) 24 | { 25 | ProxyAddressLookupTable.SaveAddress(this, ProxyInterface); 26 | } 27 | else 28 | { 29 | ProxyAddressLookupTable.DeleteAddress(this); 30 | } 31 | } 32 | 33 | /*** IUnknown methods ***/ 34 | STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR * ppvObj); 35 | STDMETHOD_(ULONG, AddRef)(THIS); 36 | STDMETHOD_(ULONG, Release)(THIS); 37 | 38 | /*** IDirectInput methods ***/ 39 | STDMETHOD(CreateDevice)(THIS_ REFGUID, LPDIRECTINPUTDEVICEW *, LPUNKNOWN); 40 | STDMETHOD(EnumDevices)(THIS_ DWORD, LPDIENUMDEVICESCALLBACKW, LPVOID, DWORD); 41 | STDMETHOD(GetDeviceStatus)(THIS_ REFGUID); 42 | STDMETHOD(RunControlPanel)(THIS_ HWND, DWORD); 43 | STDMETHOD(Initialize)(THIS_ HINSTANCE, DWORD); 44 | }; 45 | -------------------------------------------------------------------------------- /Versions/License.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ -------------------------------------------------------------------------------- /dinput.def: -------------------------------------------------------------------------------- 1 | LIBRARY dinput 2 | EXPORTS 3 | 4 | DirectInputCreateA @1 5 | DirectInputCreateEx @2 6 | DirectInputCreateW @3 7 | DllCanUnloadNow PRIVATE 8 | DllGetClassObject PRIVATE 9 | DllRegisterServer PRIVATE 10 | DllUnregisterServer PRIVATE 11 | -------------------------------------------------------------------------------- /dinputto8.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2025 Elisha Riedlinger 3 | * 4 | * This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | * authors be held liable for any damages arising from the use of this software. 6 | * Permission is granted to anyone to use this software for any purpose, including commercial 7 | * applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | * 9 | * 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | * original software. If you use this software in a product, an acknowledgment in the product 11 | * documentation would be appreciated but is not required. 12 | * 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 13 | * being the original software. 14 | * 3. This notice may not be removed or altered from any source distribution. 15 | */ 16 | 17 | #include "resource.h" 18 | #include "dinputto8.h" 19 | 20 | std::ofstream LOG; 21 | 22 | bool InitFlag = false; 23 | 24 | AddressLookupTableDinput ProxyAddressLookupTable = AddressLookupTableDinput(); 25 | 26 | DirectInput8CreateProc m_pDirectInput8Create = nullptr; 27 | DllCanUnloadNowProc m_pDllCanUnloadNow = nullptr; 28 | DllGetClassObjectProc m_pDllGetClassObject = nullptr; 29 | DllRegisterServerProc m_pDllRegisterServer = nullptr; 30 | DllUnregisterServerProc m_pDllUnregisterServer = nullptr; 31 | 32 | HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID * lplpDD, LPUNKNOWN punkOuter); 33 | 34 | void InitDinput8() 35 | { 36 | // Check if already initialized 37 | if (InitFlag) 38 | { 39 | return; 40 | } 41 | InitFlag = true; 42 | 43 | // Init logs 44 | #ifdef NOLOGGING 45 | Logging::EnableLogging = false; 46 | #else 47 | Logging::Open("dinput.log"); 48 | Logging::Log() << "Starting dinputto8 v" << APP_VERSION; 49 | Logging::LogComputerManufacturer(); 50 | Logging::LogOSVersion(); 51 | Logging::LogProcessNameAndPID(); 52 | Logging::LogGameType(); 53 | #endif 54 | 55 | // Load dll 56 | HMODULE dinput8dll = LoadLibraryA("dinput8.dll"); 57 | 58 | // Get function addresses 59 | m_pDirectInput8Create = (DirectInput8CreateProc)GetProcAddress(dinput8dll, "DirectInput8Create"); 60 | m_pDllCanUnloadNow = (DllCanUnloadNowProc)GetProcAddress(dinput8dll, "DllCanUnloadNow"); 61 | m_pDllGetClassObject = (DllGetClassObjectProc)GetProcAddress(dinput8dll, "DllGetClassObject"); 62 | m_pDllRegisterServer = (DllRegisterServerProc)GetProcAddress(dinput8dll, "DllRegisterServer"); 63 | m_pDllUnregisterServer = (DllUnregisterServerProc)GetProcAddress(dinput8dll, "DllUnregisterServer"); 64 | } 65 | 66 | HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* lplpDirectInput, LPUNKNOWN punkOuter) 67 | { 68 | InitDinput8(); 69 | 70 | LOG_LIMIT(1, __FUNCTION__); 71 | 72 | return DirectInputCreateEx(hinst, dwVersion, IID_IDirectInputA, (LPVOID*)lplpDirectInput, punkOuter); 73 | } 74 | 75 | HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW* lplpDirectInput, LPUNKNOWN punkOuter) 76 | { 77 | InitDinput8(); 78 | 79 | LOG_LIMIT(1, __FUNCTION__); 80 | 81 | return DirectInputCreateEx(hinst, dwVersion, IID_IDirectInputW, (LPVOID*)lplpDirectInput, punkOuter); 82 | } 83 | 84 | HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID * lplpDD, LPUNKNOWN punkOuter) 85 | { 86 | InitDinput8(); 87 | 88 | LOG_LIMIT(1, __FUNCTION__); 89 | 90 | if (!m_pDirectInput8Create) 91 | { 92 | return DIERR_GENERIC; 93 | } 94 | 95 | LOG_LIMIT(3, "Redirecting 'DirectInputCreate' " << riid << " version " << Logging::hex(dwVersion) << " to --> 'DirectInput8Create'"); 96 | 97 | HRESULT hr = hresValidInstanceAndVersion(hinst, dwVersion); 98 | if (SUCCEEDED(hr)) 99 | { 100 | hr = m_pDirectInput8Create(hinst, 0x0800, ConvertREFIID(riid), lplpDD, punkOuter); 101 | 102 | if (SUCCEEDED(hr) && lplpDD) 103 | { 104 | m_IDirectInputX *Interface = new m_IDirectInputX((IDirectInput8W*)*lplpDD, riid); 105 | Interface->SetVersion(dwVersion); 106 | 107 | *lplpDD = Interface->GetWrapperInterfaceX(GetGUIDVersion(riid)); 108 | } 109 | } 110 | 111 | return hr; 112 | } 113 | 114 | HRESULT WINAPI DllCanUnloadNow() 115 | { 116 | InitDinput8(); 117 | 118 | LOG_LIMIT(1, __FUNCTION__); 119 | 120 | if (!m_pDllCanUnloadNow) 121 | { 122 | return DIERR_GENERIC; 123 | } 124 | 125 | return m_pDllCanUnloadNow(); 126 | } 127 | 128 | HRESULT WINAPI DllGetClassObject(IN REFCLSID rclsid, IN REFIID riid, OUT LPVOID FAR* ppv) 129 | { 130 | InitDinput8(); 131 | 132 | LOG_LIMIT(1, __FUNCTION__); 133 | 134 | if (!m_pDllGetClassObject) 135 | { 136 | return DIERR_GENERIC; 137 | } 138 | 139 | HRESULT hr = m_pDllGetClassObject(ConvertREFCLSID(rclsid), ConvertREFIID(riid), ppv); 140 | 141 | if (SUCCEEDED(hr) && ppv) 142 | { 143 | genericQueryInterface(riid, ppv); 144 | } 145 | 146 | return hr; 147 | } 148 | 149 | HRESULT WINAPI DllRegisterServer() 150 | { 151 | InitDinput8(); 152 | 153 | LOG_LIMIT(1, __FUNCTION__); 154 | 155 | if (!m_pDllRegisterServer) 156 | { 157 | return DIERR_GENERIC; 158 | } 159 | 160 | return m_pDllRegisterServer(); 161 | } 162 | 163 | HRESULT WINAPI DllUnregisterServer() 164 | { 165 | InitDinput8(); 166 | 167 | LOG_LIMIT(1, __FUNCTION__); 168 | 169 | if (!m_pDllUnregisterServer) 170 | { 171 | return DIERR_GENERIC; 172 | } 173 | 174 | return m_pDllUnregisterServer(); 175 | } 176 | -------------------------------------------------------------------------------- /dinputto8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define INITGUID 4 | 5 | #define DIRECTINPUT_VERSION 0x0800 6 | #define UNICODE_CHARSET DEFAULT_CHARSET 7 | #include 8 | #include "ditypes.h" 9 | 10 | class m_IDirectInputA; 11 | class m_IDirectInputW; 12 | class m_IDirectInput2A; 13 | class m_IDirectInput2W; 14 | class m_IDirectInput7A; 15 | class m_IDirectInput7W; 16 | class m_IDirectInputDeviceA; 17 | class m_IDirectInputDeviceW; 18 | class m_IDirectInputDevice2A; 19 | class m_IDirectInputDevice2W; 20 | class m_IDirectInputDevice7A; 21 | class m_IDirectInputDevice7W; 22 | class m_IDirectInputEffect; 23 | class m_IDirectInputX; 24 | class m_IDirectInputDeviceX; 25 | 26 | #include 27 | #include "AddressLookupTable.h" 28 | #include "Logging\Logging.h" 29 | 30 | typedef HRESULT(WINAPI *DirectInput8CreateProc)(HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN); 31 | typedef HRESULT(WINAPI *DllCanUnloadNowProc)(); 32 | typedef HRESULT(WINAPI *DllGetClassObjectProc)(REFCLSID, REFIID, LPVOID *); 33 | typedef HRESULT(WINAPI *DllRegisterServerProc)(); 34 | typedef HRESULT(WINAPI *DllUnregisterServerProc)(); 35 | 36 | namespace dinputto8 37 | { 38 | void SetCriticalSection(); 39 | void ReleaseCriticalSection(); 40 | 41 | DWORD GetStringType(REFIID riid); 42 | DWORD GetGUIDVersion(REFIID riid); 43 | REFIID ReplaceIIDUnknown(REFIID riid, REFIID guid); 44 | REFCLSID ConvertREFCLSID(REFCLSID rclsid); 45 | REFIID ConvertREFIID(REFIID riid); 46 | HRESULT ProxyQueryInterface(LPVOID ProxyInterface, REFIID riid, LPVOID * ppvObj, REFIID WrapperID, LPVOID WrapperInterface); 47 | void WINAPI genericQueryInterface(REFIID riid, LPVOID * ppvObj); 48 | HRESULT hresValidInstanceAndVersion(HINSTANCE& hinst, DWORD dwVersion); 49 | } 50 | 51 | extern AddressLookupTableDinput ProxyAddressLookupTable; 52 | 53 | using namespace dinputto8; 54 | 55 | #include "Versions\IDirectInputA.h" 56 | #include "Versions\IDirectInputW.h" 57 | #include "Versions\IDirectInput2A.h" 58 | #include "Versions\IDirectInput2W.h" 59 | #include "Versions\IDirectInput7A.h" 60 | #include "Versions\IDirectInput7W.h" 61 | #include "Versions\IDirectInputDeviceA.h" 62 | #include "Versions\IDirectInputDeviceW.h" 63 | #include "Versions\IDirectInputDevice2A.h" 64 | #include "Versions\IDirectInputDevice2W.h" 65 | #include "Versions\IDirectInputDevice7A.h" 66 | #include "Versions\IDirectInputDevice7W.h" 67 | #include "IDirectInputEffect.h" 68 | #include "IDirectInputTypes.h" 69 | #include "IDirectInputX.h" 70 | #include "IDirectInputDeviceX.h" 71 | -------------------------------------------------------------------------------- /dinputto8.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include 4 | #include "resource.h" 5 | 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Version 9 | // 10 | 11 | VS_VERSION_INFO VERSIONINFO 12 | FILEVERSION VERSION_NUMBER 13 | PRODUCTVERSION VERSION_NUMBER 14 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 15 | FILEFLAGS 0 16 | FILEOS VOS_NT_WINDOWS32 17 | FILETYPE VFT_DLL 18 | FILESUBTYPE VFT2_UNKNOWN 19 | { 20 | BLOCK "StringFileInfo" 21 | { 22 | BLOCK "04090000" 23 | { 24 | VALUE "CompanyName", APP_COMPANYNAME 25 | VALUE "FileDescription", APP_DESCRPTION 26 | VALUE "FileVersion", APP_VERSION 27 | VALUE "InternalName", APP_INTERNALNAME 28 | VALUE "LegalCopyright", APP_COPYRIGHT 29 | VALUE "OriginalFilename", APP_ORIGINALVERSION 30 | VALUE "ProductName", APP_NAME 31 | VALUE "ProductVersion", APP_VERSION 32 | } 33 | } 34 | 35 | BLOCK "VarFileInfo" 36 | { 37 | VALUE "Translation", 0x409, 0 38 | } 39 | } 40 | 41 | ///////////////////////////////////////////////////////////////////////////// 42 | -------------------------------------------------------------------------------- /dinputto8.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.7.34221.43 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dinputto8", "dinputto8.vcxproj", "{0C32F7D5-4261-4E29-BBCB-93364B10A7BC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | Workflow|Win32 = Workflow|Win32 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Debug|Win32.ActiveCfg = Debug|Win32 16 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Debug|Win32.Build.0 = Debug|Win32 17 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Release|Win32.ActiveCfg = Release|Win32 18 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Release|Win32.Build.0 = Release|Win32 19 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Workflow|Win32.ActiveCfg = Workflow|Win32 20 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC}.Workflow|Win32.Build.0 = Workflow|Win32 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | GlobalSection(ExtensibilityGlobals) = postSolution 26 | SolutionGuid = {A61F34C2-0646-4629-9EC6-72808DDC361D} 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /dinputto8.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Workflow 14 | Win32 15 | 16 | 17 | 18 | {0C32F7D5-4261-4E29-BBCB-93364B10A7BC} 19 | Win32Proj 20 | dinput 21 | 22 | 23 | 24 | DynamicLibrary 25 | true 26 | Unicode 27 | v141_xp 28 | false 29 | 30 | 31 | DynamicLibrary 32 | false 33 | Unicode 34 | v141_xp 35 | false 36 | 37 | 38 | DynamicLibrary 39 | false 40 | Unicode 41 | v143 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | dinput 57 | $(SolutionDir)bin\$(Configuration)\ 58 | $(SolutionDir)bin\Intermediate\$(Configuration)\ 59 | 60 | 61 | dinput 62 | $(SolutionDir)bin\$(Configuration)\ 63 | $(SolutionDir)bin\Intermediate\$(Configuration)\ 64 | 65 | 66 | dinput 67 | $(SolutionDir)bin\$(Configuration)\ 68 | $(SolutionDir)bin\Intermediate\$(Configuration)\ 69 | 70 | 71 | 72 | 73 | 74 | Level4 75 | $(SolutionDir)bin\Intermediate\$(Configuration)\Object\%(RelativeDir) 76 | $(ProjectDir);Include;Include\winsdk-10 77 | MultiThreadedDebug 78 | ProgramDatabase 79 | _WINDLL;%(PreprocessorDefinitions) 80 | stdcpp17 81 | 82 | 83 | Windows 84 | dinput.def 85 | Psapi.lib;Shlwapi.lib;%(AdditionalDependencies) 86 | 87 | 88 | 89 | 90 | Level4 91 | 92 | 93 | $(SolutionDir)bin\Intermediate\$(Configuration)\Object\%(RelativeDir) 94 | MultiThreaded 95 | _WINDLL;_WIN32_WINNT=0x0501;DINPUTTO8NOLOG;%(PreprocessorDefinitions) 96 | $(ProjectDir);Include;Include\winsdk-10 97 | Speed 98 | stdcpp17 99 | 100 | 101 | Windows 102 | dinput.def 103 | true 104 | Psapi.lib;Shlwapi.lib;%(AdditionalDependencies) 105 | 106 | 107 | cmd /c "@echo off && cd /D ""$(ProjectDir)"" && if not exist BuildNo.rc echo #define BUILD_NUMBER 0 >BuildNo.rc" 108 | cmd /c "@echo off && cd /D ""$(ProjectDir)"" && FOR /F "tokens=3" %%i IN (BuildNo.rc) DO set /a var=%%i+1 >Build.txt" 109 | cmd /c "@echo off && cd /D ""$(ProjectDir)"" && FOR /F %%i IN (Build.txt) DO echo #define BUILD_NUMBER %%i >BuildNo.rc" 110 | cmd /c "@echo off && cd /D ""$(ProjectDir)"" && del Build.txt" 111 | cmd /c "@echo off && cd /D ""$(ProjectDir)"" && type BuildNo.rc" 112 | 113 | 114 | 115 | 116 | Level4 117 | 118 | 119 | $(SolutionDir)bin\Intermediate\$(Configuration)\Object\%(RelativeDir) 120 | MultiThreaded 121 | _WINDLL;_WIN32_WINNT=0x0501;DINPUTTO8NOLOG;%(PreprocessorDefinitions) 122 | $(ProjectDir);Include;Include\winsdk-10 123 | Speed 124 | stdcpp17 125 | 126 | 127 | Windows 128 | dinput.def 129 | true 130 | Psapi.lib;Shlwapi.lib;%(AdditionalDependencies) 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /dinputto8.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Versions 7 | 8 | 9 | Versions 10 | 11 | 12 | Versions 13 | 14 | 15 | Versions 16 | 17 | 18 | Versions 19 | 20 | 21 | Versions 22 | 23 | 24 | Versions 25 | 26 | 27 | Versions 28 | 29 | 30 | Versions 31 | 32 | 33 | Versions 34 | 35 | 36 | Versions 37 | 38 | 39 | Versions 40 | 41 | 42 | 43 | 44 | External\Logging 45 | 46 | 47 | 48 | 49 | Logging 50 | 51 | 52 | 53 | 54 | 55 | 56 | Versions 57 | 58 | 59 | Versions 60 | 61 | 62 | Versions 63 | 64 | 65 | Versions 66 | 67 | 68 | Versions 69 | 70 | 71 | Versions 72 | 73 | 74 | Versions 75 | 76 | 77 | Versions 78 | 79 | 80 | Versions 81 | 82 | 83 | Versions 84 | 85 | 86 | Versions 87 | 88 | 89 | Versions 90 | 91 | 92 | 93 | 94 | External\Logging 95 | 96 | 97 | 98 | 99 | 100 | Logging 101 | 102 | 103 | 104 | 105 | Include 106 | 107 | 108 | Include 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | {dab371b0-0104-4561-873e-4b46d6c55732} 117 | 118 | 119 | {936e3373-bf15-47fa-9a48-f4d6b81bd647} 120 | 121 | 122 | {8c10d327-5b6a-46b9-bbca-a46b90092d64} 123 | 124 | 125 | {f892643b-ec23-4837-8688-9750b30498f7} 126 | 127 | 128 | {52ed0387-73ab-49d1-9885-a27bcea3d8c6} 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by dinputto8.rc 4 | 5 | #include "BuildNo.rc" 6 | 7 | // Main resource file details 8 | #define APP_NAME "DirectInput1-7 to 8 Converter" 9 | #define APP_MAJOR 1 10 | #define APP_MINOR 0 11 | #define APP_BUILDNUMBER BUILD_NUMBER 12 | #define APP_REVISION 0 13 | #define APP_COMPANYNAME "Sadrate Presents" 14 | #define APP_DESCRPTION "Converts DirectInput 1-7 (dinput.dll) to DirectInput 8 (dinput8.dll) for older games." 15 | #define APP_COPYRIGHT "Copyright (C) 2025 Elisha Riedlinger" 16 | #define APP_ORIGINALVERSION "dinput.dll" 17 | #define APP_INTERNALNAME "dinputto8" 18 | 19 | // Get APP_VERSION 20 | #define _TO_STRING_(x) #x 21 | #define _TO_STRING(x) _TO_STRING_(x) 22 | #define APP_VERSION _TO_STRING(APP_MAJOR) "." _TO_STRING(APP_MINOR) "." _TO_STRING(APP_BUILDNUMBER) "." _TO_STRING(APP_REVISION) 23 | #define VERSION_NUMBER APP_MAJOR, APP_MINOR, APP_BUILDNUMBER, APP_REVISION 24 | 25 | // Next default values for new objects 26 | // 27 | #ifdef APSTUDIO_INVOKED 28 | #ifndef APSTUDIO_READONLY_SYMBOLS 29 | #define _APS_NEXT_RESOURCE_VALUE 101 30 | #define _APS_NEXT_COMMAND_VALUE 40001 31 | #define _APS_NEXT_CONTROL_VALUE 1001 32 | #define _APS_NEXT_SYMED_VALUE 101 33 | #endif 34 | #endif 35 | --------------------------------------------------------------------------------