2 * Copyright 1998 Marcus Meissner
3 * Copyright 1998,1999 Lionel Ulmer
4 * Copyright 2000-2002 TransGaming Technologies Inc.
5 * Copyright 2007 Vitaliy Margolen
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "dinput_private.h"
31 #include "device_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(dinput
);
38 static inline struct dinput
*impl_from_IDirectInput7W( IDirectInput7W
*iface
)
40 return CONTAINING_RECORD( iface
, struct dinput
, IDirectInput7W_iface
);
43 static inline struct dinput
*impl_from_IDirectInput8W( IDirectInput8W
*iface
)
45 return CONTAINING_RECORD( iface
, struct dinput
, IDirectInput8W_iface
);
48 #if defined __i386__ && defined _MSC_VER
49 __declspec(naked
) BOOL
enum_callback_wrapper(void *callback
, const void *instance
, void *ref
)
62 #elif defined __i386__ && defined __GNUC__
63 extern BOOL
enum_callback_wrapper(void *callback
, const void *instance
, void *ref
);
64 __ASM_GLOBAL_FUNC( enum_callback_wrapper
,
66 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
67 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
69 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
74 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
75 __ASM_CFI(".cfi_same_value %ebp\n\t")
78 #define enum_callback_wrapper(callback, instance, ref) (callback)((instance), (ref))
81 static HRESULT WINAPI
dinput7_EnumDevices( IDirectInput7W
*iface
, DWORD type
, LPDIENUMDEVICESCALLBACKW callback
,
82 void *context
, DWORD flags
)
84 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
86 TRACE( "iface %p, type %#lx, callback %p, context %p, flags %#lx.\n", iface
, type
, callback
, context
, flags
);
88 if (!callback
) return DIERR_INVALIDPARAM
;
90 if (type
> DIDEVTYPE_JOYSTICK
) return DIERR_INVALIDPARAM
;
91 if (flags
& ~(DIEDFL_ATTACHEDONLY
| DIEDFL_FORCEFEEDBACK
| DIEDFL_INCLUDEALIASES
| DIEDFL_INCLUDEPHANTOMS
))
92 return DIERR_INVALIDPARAM
;
94 return IDirectInput8_EnumDevices( &impl
->IDirectInput8W_iface
, type
, callback
, context
, flags
);
97 void dinput_internal_addref( struct dinput
*impl
)
99 ULONG ref
= InterlockedIncrement( &impl
->internal_ref
);
100 TRACE( "impl %p, internal ref %lu.\n", impl
, ref
);
103 void dinput_internal_release( struct dinput
*impl
)
105 ULONG ref
= InterlockedDecrement( &impl
->internal_ref
);
106 TRACE( "impl %p, internal ref %lu.\n", impl
, ref
);
110 struct DevicePlayer
*device_player
, *device_player2
;
112 LIST_FOR_EACH_ENTRY_SAFE( device_player
, device_player2
, &impl
->device_players
, struct DevicePlayer
, entry
)
113 free( device_player
);
119 static ULONG WINAPI
dinput7_AddRef( IDirectInput7W
*iface
)
121 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
122 ULONG ref
= InterlockedIncrement( &impl
->ref
);
123 TRACE( "iface %p increasing refcount to %lu.\n", iface
, ref
);
127 static ULONG WINAPI
dinput7_Release( IDirectInput7W
*iface
)
129 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
130 ULONG ref
= InterlockedDecrement( &impl
->ref
);
132 TRACE( "iface %p decreasing refcount to %lu.\n", iface
, ref
);
136 input_thread_remove_user();
137 dinput_internal_release( impl
);
143 static HRESULT WINAPI
dinput7_QueryInterface( IDirectInput7W
*iface
, REFIID iid
, void **out
)
145 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
147 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
149 if (!iid
|| !out
) return E_POINTER
;
153 #if DIRECTINPUT_VERSION == 0x0700
154 if (IsEqualGUID( &IID_IDirectInputA
, iid
) ||
155 IsEqualGUID( &IID_IDirectInput2A
, iid
) ||
156 IsEqualGUID( &IID_IDirectInput7A
, iid
))
157 *out
= &impl
->IDirectInput7A_iface
;
158 else if (IsEqualGUID( &IID_IUnknown
, iid
) ||
159 IsEqualGUID( &IID_IDirectInputW
, iid
) ||
160 IsEqualGUID( &IID_IDirectInput2W
, iid
) ||
161 IsEqualGUID( &IID_IDirectInput7W
, iid
))
162 *out
= &impl
->IDirectInput7W_iface
;
164 if (IsEqualGUID( &IID_IDirectInput8A
, iid
))
165 *out
= &impl
->IDirectInput8A_iface
;
166 else if (IsEqualGUID( &IID_IUnknown
, iid
) ||
167 IsEqualGUID( &IID_IDirectInput8W
, iid
))
168 *out
= &impl
->IDirectInput8W_iface
;
171 if (IsEqualGUID( &IID_IDirectInputJoyConfig8
, iid
))
172 *out
= &impl
->IDirectInputJoyConfig8_iface
;
176 IUnknown_AddRef( (IUnknown
*)*out
);
180 WARN( "Unsupported interface: %s\n", debugstr_guid( iid
) );
181 return E_NOINTERFACE
;
184 enum directinput_versions
186 DIRECTINPUT_VERSION_300
= 0x0300,
187 DIRECTINPUT_VERSION_500
= 0x0500,
188 DIRECTINPUT_VERSION_50A
= 0x050A,
189 DIRECTINPUT_VERSION_5B2
= 0x05B2,
190 DIRECTINPUT_VERSION_602
= 0x0602,
191 DIRECTINPUT_VERSION_61A
= 0x061A,
192 DIRECTINPUT_VERSION_700
= 0x0700,
195 static HRESULT WINAPI
dinput7_Initialize( IDirectInput7W
*iface
, HINSTANCE hinst
, DWORD version
)
197 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
199 TRACE( "iface %p, hinst %p, version %#lx.\n", iface
, hinst
, version
);
202 return DIERR_INVALIDPARAM
;
203 else if (version
== 0)
204 return DIERR_NOTINITIALIZED
;
205 else if (version
> DIRECTINPUT_VERSION_700
)
206 return DIERR_OLDDIRECTINPUTVERSION
;
207 else if (version
!= DIRECTINPUT_VERSION_300
&& version
!= DIRECTINPUT_VERSION_500
&&
208 version
!= DIRECTINPUT_VERSION_50A
&& version
!= DIRECTINPUT_VERSION_5B2
&&
209 version
!= DIRECTINPUT_VERSION_602
&& version
!= DIRECTINPUT_VERSION_61A
&&
210 version
!= DIRECTINPUT_VERSION_700
&& version
!= DIRECTINPUT_VERSION
)
211 return DIERR_BETADIRECTINPUTVERSION
;
213 if (!impl
->dwVersion
)
215 impl
->dwVersion
= version
;
216 impl
->evsequence
= 1;
222 static HRESULT WINAPI
dinput7_GetDeviceStatus( IDirectInput7W
*iface
, const GUID
*guid
)
224 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
226 IDirectInputDeviceW
*device
;
228 TRACE( "iface %p, guid %s.\n", iface
, debugstr_guid( guid
) );
230 if (!guid
) return E_POINTER
;
231 if (!impl
->dwVersion
) return DIERR_NOTINITIALIZED
;
233 hr
= IDirectInput_CreateDevice( iface
, guid
, &device
, NULL
);
234 if (hr
!= DI_OK
) return DI_NOTATTACHED
;
236 IUnknown_Release( device
);
241 static HRESULT WINAPI
dinput7_RunControlPanel( IDirectInput7W
*iface
, HWND owner
, DWORD flags
)
243 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
244 WCHAR control_exe
[] = {L
"control.exe"};
245 STARTUPINFOW si
= {0};
246 PROCESS_INFORMATION pi
;
248 TRACE( "iface %p, owner %p, flags %#lx.\n", iface
, owner
, flags
);
250 if (owner
&& !IsWindow( owner
)) return E_HANDLE
;
251 if (flags
) return DIERR_INVALIDPARAM
;
252 if (!impl
->dwVersion
) return DIERR_NOTINITIALIZED
;
254 if (!CreateProcessW( NULL
, control_exe
, NULL
, NULL
, FALSE
, DETACHED_PROCESS
, NULL
, NULL
, &si
, &pi
))
255 return HRESULT_FROM_WIN32(GetLastError());
260 static HRESULT WINAPI
dinput7_FindDevice( IDirectInput7W
*iface
, const GUID
*guid
, const WCHAR
*name
, GUID
*instance_guid
)
262 FIXME( "iface %p, guid %s, name %s, instance_guid %s stub!\n", iface
, debugstr_guid( guid
),
263 debugstr_w(name
), debugstr_guid( instance_guid
) );
267 static HRESULT WINAPI
dinput7_CreateDeviceEx( IDirectInput7W
*iface
, const GUID
*guid
,
268 REFIID iid
, void **out
, IUnknown
*outer
)
270 struct dinput
*impl
= impl_from_IDirectInput7W( iface
);
271 IDirectInputDevice8W
*device
;
274 TRACE( "iface %p, guid %s, iid %s, out %p, outer %p.\n", iface
, debugstr_guid( guid
),
275 debugstr_guid( iid
), out
, outer
);
277 if (!out
) return E_POINTER
;
280 if (!guid
) return E_POINTER
;
281 if (!impl
->dwVersion
) return DIERR_NOTINITIALIZED
;
283 if (IsEqualGUID( &GUID_SysKeyboard
, guid
)) hr
= keyboard_create_device( impl
, guid
, &device
);
284 else if (IsEqualGUID( &GUID_SysMouse
, guid
)) hr
= mouse_create_device( impl
, guid
, &device
);
285 else hr
= hid_joystick_create_device( impl
, guid
, &device
);
287 if (FAILED(hr
)) return hr
;
289 hr
= IDirectInputDevice8_QueryInterface( device
, iid
, out
);
290 IDirectInputDevice8_Release( device
);
294 static HRESULT WINAPI
dinput7_CreateDevice( IDirectInput7W
*iface
, const GUID
*guid
,
295 IDirectInputDeviceW
**out
, IUnknown
*outer
)
297 return IDirectInput7_CreateDeviceEx( iface
, guid
, &IID_IDirectInputDeviceW
, (void **)out
, outer
);
300 static ULONG WINAPI
dinput8_AddRef( IDirectInput8W
*iface
)
302 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
303 return IDirectInput7_AddRef( &impl
->IDirectInput7W_iface
);
306 static HRESULT WINAPI
dinput8_QueryInterface( IDirectInput8W
*iface
, REFIID iid
, void **out
)
308 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
309 return IDirectInput7_QueryInterface( &impl
->IDirectInput7W_iface
, iid
, out
);
312 static ULONG WINAPI
dinput8_Release( IDirectInput8W
*iface
)
314 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
315 return IDirectInput7_Release( &impl
->IDirectInput7W_iface
);
318 static HRESULT WINAPI
dinput8_CreateDevice( IDirectInput8W
*iface
, const GUID
*guid
,
319 IDirectInputDevice8W
**out
, IUnknown
*outer
)
321 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
322 return IDirectInput7_CreateDeviceEx( &impl
->IDirectInput7W_iface
, guid
,
323 &IID_IDirectInputDevice8W
, (void **)out
, outer
);
326 static BOOL
try_enum_device( DWORD type
, LPDIENUMDEVICESCALLBACKW callback
,
327 DIDEVICEINSTANCEW
*instance
, void *context
, DWORD flags
)
329 if (type
&& (instance
->dwDevType
& 0xff) != type
) return DIENUM_CONTINUE
;
330 if ((flags
& DIEDFL_FORCEFEEDBACK
) && IsEqualGUID( &instance
->guidFFDriver
, &GUID_NULL
))
331 return DIENUM_CONTINUE
;
332 return enum_callback_wrapper( callback
, instance
, context
);
335 static HRESULT WINAPI
dinput8_EnumDevices( IDirectInput8W
*iface
, DWORD type
, LPDIENUMDEVICESCALLBACKW callback
, void *context
,
338 DIDEVICEINSTANCEW instance
= {.dwSize
= sizeof(DIDEVICEINSTANCEW
)};
339 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
340 DWORD device_class
= 0, device_type
= 0;
344 TRACE( "iface %p, type %#lx, callback %p, context %p, flags %#lx.\n", iface
, type
, callback
, context
, flags
);
346 if (!callback
) return DIERR_INVALIDPARAM
;
348 if ((type
> DI8DEVCLASS_GAMECTRL
&& type
< DI8DEVTYPE_DEVICE
) || type
> DI8DEVTYPE_SUPPLEMENTAL
)
349 return DIERR_INVALIDPARAM
;
350 if (flags
& ~(DIEDFL_ATTACHEDONLY
| DIEDFL_FORCEFEEDBACK
| DIEDFL_INCLUDEALIASES
|
351 DIEDFL_INCLUDEPHANTOMS
| DIEDFL_INCLUDEHIDDEN
))
352 return DIERR_INVALIDPARAM
;
354 if (!impl
->dwVersion
) return DIERR_NOTINITIALIZED
;
356 if (type
<= DI8DEVCLASS_GAMECTRL
) device_class
= type
;
357 else device_type
= type
;
359 if (device_class
== DI8DEVCLASS_ALL
|| device_class
== DI8DEVCLASS_POINTER
)
361 hr
= mouse_enum_device( type
, flags
, &instance
, impl
->dwVersion
);
362 if (hr
== DI_OK
&& try_enum_device( device_type
, callback
, &instance
, context
, flags
) == DIENUM_STOP
)
366 if (device_class
== DI8DEVCLASS_ALL
|| device_class
== DI8DEVCLASS_KEYBOARD
)
368 hr
= keyboard_enum_device( type
, flags
, &instance
, impl
->dwVersion
);
369 if (hr
== DI_OK
&& try_enum_device( device_type
, callback
, &instance
, context
, flags
) == DIENUM_STOP
)
373 if (device_class
== DI8DEVCLASS_ALL
|| device_class
== DI8DEVCLASS_GAMECTRL
)
377 hr
= hid_joystick_enum_device( type
, flags
, &instance
, impl
->dwVersion
, i
++ );
378 if (hr
== DI_OK
&& try_enum_device( device_type
, callback
, &instance
, context
, flags
) == DIENUM_STOP
)
380 } while (SUCCEEDED(hr
));
386 static HRESULT WINAPI
dinput8_GetDeviceStatus( IDirectInput8W
*iface
, const GUID
*guid
)
388 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
389 return IDirectInput7_GetDeviceStatus( &impl
->IDirectInput7W_iface
, guid
);
392 static HRESULT WINAPI
dinput8_RunControlPanel( IDirectInput8W
*iface
, HWND owner
, DWORD flags
)
394 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
395 return IDirectInput7_RunControlPanel( &impl
->IDirectInput7W_iface
, owner
, flags
);
398 static HRESULT WINAPI
dinput8_Initialize( IDirectInput8W
*iface
, HINSTANCE hinst
, DWORD version
)
400 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
402 TRACE( "iface %p, hinst %p, version %#lx.\n", iface
, hinst
, version
);
405 return DIERR_INVALIDPARAM
;
406 else if (version
== 0)
407 return DIERR_NOTINITIALIZED
;
408 else if (version
< DIRECTINPUT_VERSION
)
409 return DIERR_BETADIRECTINPUTVERSION
;
410 else if (version
> DIRECTINPUT_VERSION
)
411 return DIERR_OLDDIRECTINPUTVERSION
;
413 if (!impl
->dwVersion
)
415 impl
->dwVersion
= version
;
416 impl
->evsequence
= 1;
422 static HRESULT WINAPI
dinput8_FindDevice( IDirectInput8W
*iface
, const GUID
*guid
, const WCHAR
*name
, GUID
*instance_guid
)
424 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
425 return IDirectInput7_FindDevice( &impl
->IDirectInput7W_iface
, guid
, name
, instance_guid
);
428 struct enum_device_by_semantics_params
430 IDirectInput8W
*iface
;
431 const WCHAR
*username
;
434 IDirectInputDevice8W
*devices
[128];
438 static BOOL CALLBACK
enum_device_by_semantics( const DIDEVICEINSTANCEW
*instance
, void *context
)
440 struct enum_device_by_semantics_params
*params
= context
;
441 DIDEVCAPS caps
= {.dwSize
= sizeof(caps
)};
442 DIPROPSTRING prop_username
=
446 .dwSize
= sizeof(DIPROPSTRING
),
447 .dwHeaderSize
= sizeof(DIPROPHEADER
),
448 .dwHow
= DIPH_DEVICE
,
451 IDirectInputDevice8W
*device
;
452 BOOL ret
= DIENUM_CONTINUE
;
455 if (params
->device_count
>= ARRAY_SIZE(params
->devices
)) return DIENUM_STOP
;
457 if (FAILED(hr
= IDirectInput8_CreateDevice( params
->iface
, &instance
->guidInstance
, &device
, NULL
)))
459 WARN( "Failed to create device, hr %#lx\n", hr
);
460 return DIENUM_CONTINUE
;
463 if (FAILED(hr
= IDirectInputDevice8_GetCapabilities( device
, &caps
)))
464 WARN( "Failed to get device capabilities, hr %#lx\n", hr
);
465 if ((params
->flags
& DIEDBSFL_FORCEFEEDBACK
) && !caps
.dwFFDriverVersion
) goto done
;
467 if (FAILED(hr
= IDirectInputDevice8_GetProperty( device
, DIPROP_USERNAME
, &prop_username
.diph
)))
468 WARN( "Failed to get device capabilities, hr %#lx\n", hr
);
469 else if ((params
->flags
& DIEDBSFL_THISUSER
) && *params
->username
&& wcscmp( params
->username
, prop_username
.wsz
))
471 else if ((params
->flags
& DIEDBSFL_AVAILABLEDEVICES
) && *prop_username
.wsz
)
474 IDirectInputDevice_AddRef( device
);
475 params
->devices
[params
->device_count
++] = device
;
478 IDirectInputDevice8_Release( device
);
482 struct enum_device_object_semantics_params
484 DIDEVICEINSTANCEW instance
;
485 DIACTIONFORMATW
*format
;
489 static BOOL CALLBACK
enum_device_object_semantics( const DIDEVICEOBJECTINSTANCEW
*obj
, void *args
)
491 struct enum_device_object_semantics_params
*params
= args
;
492 DIACTIONFORMATW
*format
= params
->format
;
495 for (i
= 0; format
&& i
< format
->dwNumActions
; i
++)
497 DIOBJECTDATAFORMAT object_format
= {.dwType
= obj
->dwType
, .dwOfs
= obj
->dwOfs
};
498 BYTE dev_type
= params
->instance
.dwDevType
& 0xf;
499 DIACTIONW
*action
= format
->rgoAction
+ i
;
501 if (!device_object_matches_semantic( ¶ms
->instance
, &object_format
, action
->dwSemantic
, FALSE
)) continue;
502 if (!(action
->dwSemantic
& 0x4000)) params
->flags
|= DIEDBS_MAPPEDPRI1
;
503 else if (dev_type
!= DIDEVTYPE_KEYBOARD
&& dev_type
!= DIDEVTYPE_MOUSE
) params
->flags
|= DIEDBS_MAPPEDPRI2
;
506 return DIENUM_CONTINUE
;
509 static HRESULT WINAPI
dinput8_EnumDevicesBySemantics( IDirectInput8W
*iface
, const WCHAR
*username
, DIACTIONFORMATW
*action_format
,
510 LPDIENUMDEVICESBYSEMANTICSCBW callback
, void *context
, DWORD flags
)
512 struct enum_device_by_semantics_params params
= {.iface
= iface
, .username
= username
? username
: L
"", .flags
= flags
};
513 DWORD enum_flags
= DIEDFL_ATTACHEDONLY
| (flags
& DIEDFL_FORCEFEEDBACK
);
514 struct dinput
*impl
= impl_from_IDirectInput8W( iface
);
518 TRACE( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx\n",
519 iface
, debugstr_w(username
), action_format
, callback
, context
, flags
);
521 if (!action_format
) return DIERR_INVALIDPARAM
;
523 TRACE( "format guid %s, genre %#lx, name %s\n", debugstr_guid(&action_format
->guidActionMap
),
524 action_format
->dwGenre
, debugstr_w(action_format
->tszActionMap
) );
525 for (i
= 0; i
< action_format
->dwNumActions
; i
++)
527 DIACTIONW
*action
= action_format
->rgoAction
+ i
;
528 TRACE( " %u: app_data %#Ix, semantic %#lx, flags %#lx, instance %s, obj_id %#lx, how %#lx, name %s\n",
529 i
, action
->uAppData
, action
->dwSemantic
, action
->dwFlags
, debugstr_guid(&action
->guidInstance
),
530 action
->dwObjID
, action
->dwHow
, debugstr_w(action
->lptszActionName
) );
533 if (FAILED(hr
= IDirectInput8_EnumDevices( &impl
->IDirectInput8W_iface
, DI8DEVCLASS_ALL
,
534 enum_device_by_semantics
, ¶ms
, enum_flags
)))
536 WARN( "Failed to enumerate devices, hr %#lx\n", hr
);
540 while (params
.device_count
--)
542 struct enum_device_object_semantics_params object_params
= {.instance
= {.dwSize
= sizeof(DIDEVICEINSTANCEW
)}, .format
= action_format
};
543 IDirectInputDevice8W
*device
= params
.devices
[params
.device_count
];
544 BOOL ret
= DIENUM_STOP
;
546 if (FAILED(hr
= IDirectInputDevice8_GetDeviceInfo( device
, &object_params
.instance
)))
547 WARN( "Failed to get device %p info, hr %#lx\n", device
, hr
);
548 else if (FAILED(hr
= IDirectInputDevice8_EnumObjects( device
, enum_device_object_semantics
, &object_params
, DIDFT_ALL
)))
549 WARN( "Failed to enumerate device %p objects, hr %#lx\n", device
, hr
);
551 ret
= callback( &object_params
.instance
, device
, object_params
.flags
, params
.device_count
, context
);
553 IDirectInputDevice8_Release( device
);
554 if (ret
== DIENUM_STOP
) goto cleanup
;
560 while (params
.device_count
--) IDirectInputDevice8_Release( params
.devices
[params
.device_count
] );
564 static HRESULT WINAPI
dinput8_ConfigureDevices( IDirectInput8W
*iface
, LPDICONFIGUREDEVICESCALLBACK callback
,
565 DICONFIGUREDEVICESPARAMSW
*params
, DWORD flags
, void *context
)
567 FIXME( "iface %p, callback %p, params %p, flags %#lx, context %p stub!\n", iface
, callback
,
568 params
, flags
, context
);
570 /* Call helper function in config.c to do the real work */
571 return _configure_devices( iface
, callback
, params
, flags
, context
);
574 static inline struct dinput
*impl_from_IDirectInputJoyConfig8( IDirectInputJoyConfig8
*iface
)
576 return CONTAINING_RECORD( iface
, struct dinput
, IDirectInputJoyConfig8_iface
);
579 static HRESULT WINAPI
joy_config_QueryInterface( IDirectInputJoyConfig8
*iface
, REFIID iid
, void **out
)
581 struct dinput
*impl
= impl_from_IDirectInputJoyConfig8( iface
);
582 return IDirectInput7_QueryInterface( &impl
->IDirectInput7W_iface
, iid
, out
);
585 static ULONG WINAPI
joy_config_AddRef( IDirectInputJoyConfig8
*iface
)
587 struct dinput
*impl
= impl_from_IDirectInputJoyConfig8( iface
);
588 return IDirectInput7_AddRef( &impl
->IDirectInput7W_iface
);
591 static ULONG WINAPI
joy_config_Release( IDirectInputJoyConfig8
*iface
)
593 struct dinput
*impl
= impl_from_IDirectInputJoyConfig8( iface
);
594 return IDirectInput7_Release( &impl
->IDirectInput7W_iface
);
597 static HRESULT WINAPI
joy_config_Acquire( IDirectInputJoyConfig8
*iface
)
599 FIXME( "iface %p stub!\n", iface
);
603 static HRESULT WINAPI
joy_config_Unacquire( IDirectInputJoyConfig8
*iface
)
605 FIXME( "iface %p stub!\n", iface
);
609 static HRESULT WINAPI
joy_config_SetCooperativeLevel( IDirectInputJoyConfig8
*iface
, HWND hwnd
, DWORD flags
)
611 FIXME( "iface %p, hwnd %p, flags %#lx stub!\n", iface
, hwnd
, flags
);
615 static HRESULT WINAPI
joy_config_SendNotify( IDirectInputJoyConfig8
*iface
)
617 FIXME( "iface %p stub!\n", iface
);
621 static HRESULT WINAPI
joy_config_EnumTypes( IDirectInputJoyConfig8
*iface
, LPDIJOYTYPECALLBACK callback
, void *context
)
623 FIXME( "iface %p, callback %p, context %p stub!\n", iface
, callback
, context
);
627 static HRESULT WINAPI
joy_config_GetTypeInfo( IDirectInputJoyConfig8
*iface
, const WCHAR
*name
,
628 DIJOYTYPEINFO
*info
, DWORD flags
)
630 FIXME( "iface %p, name %s, info %p, flags %#lx stub!\n", iface
, debugstr_w(name
), info
, flags
);
634 static HRESULT WINAPI
joy_config_SetTypeInfo( IDirectInputJoyConfig8
*iface
, const WCHAR
*name
,
635 const DIJOYTYPEINFO
*info
, DWORD flags
, WCHAR
*new_name
)
637 FIXME( "iface %p, name %s, info %p, flags %#lx, new_name %s stub!\n", iface
, debugstr_w(name
),
638 info
, flags
, debugstr_w(new_name
) );
642 static HRESULT WINAPI
joy_config_DeleteType( IDirectInputJoyConfig8
*iface
, const WCHAR
*name
)
644 FIXME( "iface %p, name %s stub!\n", iface
, debugstr_w(name
) );
648 struct find_device_from_index_params
651 DIDEVICEINSTANCEW instance
;
654 static BOOL CALLBACK
find_device_from_index( const DIDEVICEINSTANCEW
*instance
, void *context
)
656 struct find_device_from_index_params
*params
= context
;
657 params
->instance
= *instance
;
658 if (!params
->index
--) return DIENUM_STOP
;
659 return DIENUM_CONTINUE
;
662 static HRESULT WINAPI
joy_config_GetConfig( IDirectInputJoyConfig8
*iface
, UINT id
, DIJOYCONFIG
*info
, DWORD flags
)
664 struct dinput
*impl
= impl_from_IDirectInputJoyConfig8( iface
);
665 struct find_device_from_index_params params
= {.index
= id
};
668 FIXME( "iface %p, id %u, info %p, flags %#lx stub!\n", iface
, id
, info
, flags
);
670 #define X(x) if (flags & x) FIXME("\tflags |= "#x"\n");
672 X(DIJC_REGHWCONFIGTYPE
)
677 hr
= IDirectInput8_EnumDevices( &impl
->IDirectInput8W_iface
, DI8DEVCLASS_GAMECTRL
,
678 find_device_from_index
, ¶ms
, 0 );
679 if (FAILED(hr
)) return hr
;
680 if (params
.index
!= ~0) return DIERR_NOMOREITEMS
;
681 if (flags
& DIJC_GUIDINSTANCE
) info
->guidInstance
= params
.instance
.guidInstance
;
685 static HRESULT WINAPI
joy_config_SetConfig( IDirectInputJoyConfig8
*iface
, UINT id
, const DIJOYCONFIG
*info
, DWORD flags
)
687 FIXME( "iface %p, id %u, info %p, flags %#lx stub!\n", iface
, id
, info
, flags
);
691 static HRESULT WINAPI
joy_config_DeleteConfig( IDirectInputJoyConfig8
*iface
, UINT id
)
693 FIXME( "iface %p, id %u stub!\n", iface
, id
);
697 static HRESULT WINAPI
joy_config_GetUserValues( IDirectInputJoyConfig8
*iface
, DIJOYUSERVALUES
*info
, DWORD flags
)
699 FIXME( "iface %p, info %p, flags %#lx stub!\n", iface
, info
, flags
);
703 static HRESULT WINAPI
joy_config_SetUserValues( IDirectInputJoyConfig8
*iface
, const DIJOYUSERVALUES
*info
, DWORD flags
)
705 FIXME( "iface %p, info %p, flags %#lx stub!\n", iface
, info
, flags
);
709 static HRESULT WINAPI
joy_config_AddNewHardware( IDirectInputJoyConfig8
*iface
, HWND hwnd
, const GUID
*guid
)
711 FIXME( "iface %p, hwnd %p, guid %s stub!\n", iface
, hwnd
, debugstr_guid( guid
) );
715 static HRESULT WINAPI
joy_config_OpenTypeKey( IDirectInputJoyConfig8
*iface
, const WCHAR
*name
, DWORD security
, HKEY
*key
)
717 FIXME( "iface %p, name %s, security %lu, key %p stub!\n", iface
, debugstr_w(name
), security
, key
);
721 static HRESULT WINAPI
joy_config_OpenAppStatusKey( IDirectInputJoyConfig8
*iface
, HKEY
*key
)
723 FIXME( "iface %p, key %p stub!\n", iface
, key
);
727 static const IDirectInput7WVtbl dinput7_vtbl
=
729 dinput7_QueryInterface
,
732 dinput7_CreateDevice
,
734 dinput7_GetDeviceStatus
,
735 dinput7_RunControlPanel
,
738 dinput7_CreateDeviceEx
,
741 static const IDirectInput8WVtbl dinput8_vtbl
=
743 dinput8_QueryInterface
,
746 dinput8_CreateDevice
,
748 dinput8_GetDeviceStatus
,
749 dinput8_RunControlPanel
,
752 dinput8_EnumDevicesBySemantics
,
753 dinput8_ConfigureDevices
,
756 static const IDirectInputJoyConfig8Vtbl joy_config_vtbl
=
758 joy_config_QueryInterface
,
762 joy_config_Unacquire
,
763 joy_config_SetCooperativeLevel
,
764 joy_config_SendNotify
,
765 joy_config_EnumTypes
,
766 joy_config_GetTypeInfo
,
767 joy_config_SetTypeInfo
,
768 joy_config_DeleteType
,
769 joy_config_GetConfig
,
770 joy_config_SetConfig
,
771 joy_config_DeleteConfig
,
772 joy_config_GetUserValues
,
773 joy_config_SetUserValues
,
774 joy_config_AddNewHardware
,
775 joy_config_OpenTypeKey
,
776 joy_config_OpenAppStatusKey
,
779 static HRESULT
dinput_create( IUnknown
**out
)
783 if (!(impl
= calloc( 1, sizeof(struct dinput
) ))) return E_OUTOFMEMORY
;
784 impl
->IDirectInput7A_iface
.lpVtbl
= &dinput7_a_vtbl
;
785 impl
->IDirectInput7W_iface
.lpVtbl
= &dinput7_vtbl
;
786 impl
->IDirectInput8A_iface
.lpVtbl
= &dinput8_a_vtbl
;
787 impl
->IDirectInput8W_iface
.lpVtbl
= &dinput8_vtbl
;
788 impl
->IDirectInputJoyConfig8_iface
.lpVtbl
= &joy_config_vtbl
;
789 impl
->internal_ref
= 1;
792 list_init( &impl
->device_players
);
794 #if DIRECTINPUT_VERSION == 0x0700
795 *out
= (IUnknown
*)&impl
->IDirectInput7W_iface
;
797 *out
= (IUnknown
*)&impl
->IDirectInput8W_iface
;
800 input_thread_add_user();
806 IClassFactory IClassFactory_iface
;
809 static inline struct class_factory
*impl_from_IClassFactory( IClassFactory
*iface
)
811 return CONTAINING_RECORD( iface
, struct class_factory
, IClassFactory_iface
);
814 static HRESULT WINAPI
class_factory_QueryInterface( IClassFactory
*iface
, REFIID iid
, void **out
)
816 struct class_factory
*impl
= impl_from_IClassFactory( iface
);
818 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
820 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
821 IsEqualGUID( iid
, &IID_IClassFactory
))
822 *out
= &impl
->IClassFactory_iface
;
826 WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
827 return E_NOINTERFACE
;
830 IUnknown_AddRef( (IUnknown
*)*out
);
834 static ULONG WINAPI
class_factory_AddRef( IClassFactory
*iface
)
839 static ULONG WINAPI
class_factory_Release( IClassFactory
*iface
)
844 static HRESULT WINAPI
class_factory_CreateInstance( IClassFactory
*iface
, IUnknown
*outer
, REFIID iid
, void **out
)
849 TRACE( "iface %p, outer %p, iid %s, out %p.\n", iface
, outer
, debugstr_guid( iid
), out
);
851 if (outer
) return CLASS_E_NOAGGREGATION
;
853 if (FAILED(hr
= dinput_create( &unknown
))) return hr
;
854 hr
= IUnknown_QueryInterface( unknown
, iid
, out
);
855 IUnknown_Release( unknown
);
860 static HRESULT WINAPI
class_factory_LockServer( IClassFactory
*iface
, BOOL lock
)
862 FIXME( "iface %p, lock %d stub!\n", iface
, lock
);
866 static const IClassFactoryVtbl class_factory_vtbl
=
868 class_factory_QueryInterface
,
869 class_factory_AddRef
,
870 class_factory_Release
,
871 class_factory_CreateInstance
,
872 class_factory_LockServer
,
875 static struct class_factory class_factory
= {{&class_factory_vtbl
}};
877 HRESULT WINAPI
DllGetClassObject( REFCLSID clsid
, REFIID iid
, void **out
)
879 TRACE( "clsid %s, iid %s, out %p.\n", debugstr_guid( clsid
), debugstr_guid( iid
), out
);
881 #if DIRECTINPUT_VERSION == 0x0700
882 if (IsEqualCLSID( &CLSID_DirectInput
, clsid
))
883 return IClassFactory_QueryInterface( &class_factory
.IClassFactory_iface
, iid
, out
);
885 if (IsEqualCLSID( &CLSID_DirectInput8
, clsid
))
886 return IClassFactory_QueryInterface( &class_factory
.IClassFactory_iface
, iid
, out
);
889 WARN( "%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid( clsid
) );
890 return CLASS_E_CLASSNOTAVAILABLE
;
893 #if DIRECTINPUT_VERSION == 0x0700
895 HRESULT WINAPI
DirectInputCreateEx( HINSTANCE hinst
, DWORD version
, REFIID iid
, void **out
, IUnknown
*outer
)
900 TRACE( "hinst %p, version %#lx, iid %s, out %p, outer %p.\n", hinst
, version
, debugstr_guid( iid
), out
, outer
);
902 if (!IsEqualGUID( &IID_IDirectInputA
, iid
) &&
903 !IsEqualGUID( &IID_IDirectInputW
, iid
) &&
904 !IsEqualGUID( &IID_IDirectInput2A
, iid
) &&
905 !IsEqualGUID( &IID_IDirectInput2W
, iid
) &&
906 !IsEqualGUID( &IID_IDirectInput7A
, iid
) &&
907 !IsEqualGUID( &IID_IDirectInput7W
, iid
))
908 return DIERR_NOINTERFACE
;
910 if (FAILED(hr
= dinput_create( &unknown
))) return hr
;
911 hr
= IUnknown_QueryInterface( unknown
, iid
, out
);
912 IUnknown_Release( unknown
);
913 if (FAILED(hr
)) return hr
;
915 if (outer
|| FAILED(hr
= IDirectInput7_Initialize( (IDirectInput7W
*)unknown
, hinst
, version
)))
917 IUnknown_Release( unknown
);
925 HRESULT WINAPI DECLSPEC_HOTPATCH
DirectInputCreateA( HINSTANCE hinst
, DWORD version
, IDirectInputA
**out
, IUnknown
*outer
)
927 return DirectInputCreateEx( hinst
, version
, &IID_IDirectInput7A
, (void **)out
, outer
);
930 HRESULT WINAPI DECLSPEC_HOTPATCH
DirectInputCreateW( HINSTANCE hinst
, DWORD version
, IDirectInputW
**out
, IUnknown
*outer
)
932 return DirectInputCreateEx( hinst
, version
, &IID_IDirectInput7W
, (void **)out
, outer
);
937 HRESULT WINAPI DECLSPEC_HOTPATCH
DirectInput8Create( HINSTANCE hinst
, DWORD version
, REFIID iid
, void **out
, IUnknown
*outer
)
942 TRACE( "hinst %p, version %#lx, iid %s, out %p, outer %p.\n", hinst
, version
, debugstr_guid( iid
), out
, outer
);
944 if (!out
) return E_POINTER
;
946 if (!IsEqualGUID( &IID_IDirectInput8A
, iid
) &&
947 !IsEqualGUID( &IID_IDirectInput8W
, iid
) &&
948 !IsEqualGUID( &IID_IUnknown
, iid
))
951 return DIERR_NOINTERFACE
;
954 if (FAILED(hr
= dinput_create( &unknown
))) return hr
;
955 hr
= IUnknown_QueryInterface( unknown
, iid
, out
);
956 IUnknown_Release( unknown
);
957 if (FAILED(hr
)) return hr
;
959 if (outer
|| FAILED(hr
= IDirectInput8_Initialize( (IDirectInput8W
*)unknown
, hinst
, version
)))
961 IUnknown_Release( unknown
);