1 /* DirectInput
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 * Copyright 2000-2002 TransGaming Technologies Inc.
6 * Copyright 2007 Vitaliy Margolen
7 *
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23 /* Status:
24 *
25 * - Tomb Raider 2 Demo:
26 * Playable using keyboard only.
27 * - WingCommander Prophecy Demo:
28 * Doesn't get Input Focus.
29 *
30 * - Fallout : works great in X and DGA mode
31 */
32
33 #include "config.h"
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <string.h>
37
38 #define COBJMACROS
39 #define NONAMELESSUNION
40
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
43 #include "windef.h"
44 #include "winbase.h"
45 #include "winuser.h"
46 #include "winerror.h"
47 #include "dinput_private.h"
48 #include "device_private.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
51
52 static const IDirectInput7AVtbl ddi7avt;
53 static const IDirectInput7WVtbl ddi7wvt;
54 static const IDirectInput8AVtbl ddi8avt;
55 static const IDirectInput8WVtbl ddi8wvt;
56
57 static inline IDirectInputImpl *impl_from_IDirectInput7W( IDirectInput7W *iface )
58 {
59 return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl7w );
60 }
61
62 static inline IDirectInputImpl *impl_from_IDirectInput8A( IDirectInput8A *iface )
63 {
64 return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl8a );
65 }
66
67 static inline IDirectInputImpl *impl_from_IDirectInput8W( IDirectInput8W *iface )
68 {
69 return CONTAINING_RECORD( iface, IDirectInputImpl, lpVtbl8w );
70 }
71
72 static inline IDirectInput7W *IDirectInput7W_from_impl( IDirectInputImpl *iface )
73 {
74 return (IDirectInput7W *)(&iface->lpVtbl7w);
75 }
76
77 static const struct dinput_device *dinput_devices[] =
78 {
79 &mouse_device,
80 &keyboard_device,
81 &joystick_linuxinput_device,
82 &joystick_linux_device
83 };
84 #define NB_DINPUT_DEVICES (sizeof(dinput_devices)/sizeof(dinput_devices[0]))
85
86 static HINSTANCE DINPUT_instance = NULL;
87
88 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
89 {
90 switch(reason)
91 {
92 case DLL_PROCESS_ATTACH:
93 DisableThreadLibraryCalls(inst);
94 DINPUT_instance = inst;
95 break;
96 case DLL_PROCESS_DETACH:
97 break;
98 }
99 return TRUE;
100 }
101
102 static BOOL check_hook_thread(void);
103 static CRITICAL_SECTION dinput_hook_crit;
104 static struct list direct_input_list = LIST_INIT( direct_input_list );
105
106 /******************************************************************************
107 * DirectInputCreateEx (DINPUT.@)
108 */
109 HRESULT WINAPI DirectInputCreateEx(
110 HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
111 LPUNKNOWN punkOuter)
112 {
113 IDirectInputImpl* This;
114
115 TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter);
116
117 if (IsEqualGUID( &IID_IDirectInputA, riid ) ||
118 IsEqualGUID( &IID_IDirectInput2A, riid ) ||
119 IsEqualGUID( &IID_IDirectInput7A, riid ) ||
120 IsEqualGUID( &IID_IDirectInputW, riid ) ||
121 IsEqualGUID( &IID_IDirectInput2W, riid ) ||
122 IsEqualGUID( &IID_IDirectInput7W, riid ) ||
123 IsEqualGUID( &IID_IDirectInput8A, riid ) ||
124 IsEqualGUID( &IID_IDirectInput8W, riid ))
125 {
126 if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
127 return DIERR_OUTOFMEMORY;
128 }
129 else
130 return DIERR_OLDDIRECTINPUTVERSION;
131
132 This->lpVtbl = &ddi7avt;
133 This->lpVtbl7w = &ddi7wvt;
134 This->lpVtbl8a = &ddi8avt;
135 This->lpVtbl8w = &ddi8wvt;
136 This->ref = 0;
137 This->dwVersion = dwVersion;
138 This->evsequence = 1;
139
140 InitializeCriticalSection(&This->crit);
141 This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
142
143 list_init( &This->devices_list );
144
145 /* Add self to the list of the IDirectInputs */
146 EnterCriticalSection( &dinput_hook_crit );
147 list_add_head( &direct_input_list, &This->entry );
148 LeaveCriticalSection( &dinput_hook_crit );
149
150 if (!check_hook_thread())
151 {
152 IUnknown_Release( (LPDIRECTINPUT7A)This );
153 return DIERR_GENERIC;
154 }
155
156 IDirectInput_QueryInterface( (IDirectInput7A *)This, riid, ppDI );
157 return DI_OK;
158 }
159
160 /******************************************************************************
161 * DirectInputCreateA (DINPUT.@)
162 */
163 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
164 {
165 return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7A, (LPVOID *)ppDI, punkOuter);
166 }
167
168 /******************************************************************************
169 * DirectInputCreateW (DINPUT.@)
170 */
171 HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)
172 {
173 return DirectInputCreateEx(hinst, dwVersion, &IID_IDirectInput7W, (LPVOID *)ppDI, punkOuter);
174 }
175
176 static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) {
177 switch (dwDevType) {
178 case 0: return "All devices";
179 case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE";
180 case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD";
181 case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK";
182 case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE";
183 default: return "Unknown";
184 }
185 }
186
187 static void _dump_EnumDevices_dwFlags(DWORD dwFlags) {
188 if (TRACE_ON(dinput)) {
189 unsigned int i;
190 static const struct {
191 DWORD mask;
192 const char *name;
193 } flags[] = {
194 #define FE(x) { x, #x}
195 FE(DIEDFL_ALLDEVICES),
196 FE(DIEDFL_ATTACHEDONLY),
197 FE(DIEDFL_FORCEFEEDBACK),
198 FE(DIEDFL_INCLUDEALIASES),
199 FE(DIEDFL_INCLUDEPHANTOMS)
200 #undef FE
201 };
202 TRACE(" flags: ");
203 if (dwFlags == 0) {
204 TRACE("DIEDFL_ALLDEVICES");
205 return;
206 }
207 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
208 if (flags[i].mask & dwFlags)
209 TRACE("%s ",flags[i].name);
210 }
211 TRACE("\n");
212 }
213
214 void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat) {
215 int i;
216
217 FIXME("diaf.dwSize = %d\n", lpdiActionFormat->dwSize);
218 FIXME("diaf.dwActionSize = %d\n", lpdiActionFormat->dwActionSize);
219 FIXME("diaf.dwDataSize = %d\n", lpdiActionFormat->dwDataSize);
220 FIXME("diaf.dwNumActions = %d\n", lpdiActionFormat->dwNumActions);
221 FIXME("diaf.rgoAction = %p\n", lpdiActionFormat->rgoAction);
222 for (i=0;i<lpdiActionFormat->dwNumActions;i++) {
223 FIXME("diaf.rgoAction[%d]:\n", i);
224 FIXME("\tuAppData=%lx\n", lpdiActionFormat->rgoAction[i].uAppData);
225 FIXME("\tdwSemantics=%x\n", lpdiActionFormat->rgoAction[i].dwSemantics);
226 FIXME("\tdwFlags=%x\n", lpdiActionFormat->rgoAction[i].dwFlags);
227 FIXME("\tszActionName=%s\n", debugstr_a(lpdiActionFormat->rgoAction[i].u.lptszActionName));
228 FIXME("\tguidInstance=%s\n", debugstr_guid(&lpdiActionFormat->rgoAction[i].guidInstance));
229 FIXME("\tdwObjID=%x\n", lpdiActionFormat->rgoAction[i].dwObjID);
230 FIXME("\tdwHow=%x\n", lpdiActionFormat->rgoAction[i].dwHow);
231 }
232 FIXME("diaf.guidActionMap = %s\n", debugstr_guid(&lpdiActionFormat->guidActionMap));
233 FIXME("diaf.dwGenre = %d\n", lpdiActionFormat->dwGenre);
234 FIXME("diaf.dwBufferSize = %d\n", lpdiActionFormat->dwBufferSize);
235 FIXME("diaf.lAxisMin = %d\n", lpdiActionFormat->lAxisMin);
236 FIXME("diaf.lAxisMax = %d\n", lpdiActionFormat->lAxisMax);
237 FIXME("diaf.hInstString = %p\n", lpdiActionFormat->hInstString);
238 FIXME("diaf.ftTimeStamp ...\n");
239 FIXME("diaf.dwCRC = %x\n", lpdiActionFormat->dwCRC);
240 FIXME("diaf.tszActionMap = %s\n", debugstr_a(lpdiActionFormat->tszActionMap));
241 }
242
243 /******************************************************************************
244 * IDirectInputA_EnumDevices
245 */
246 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
247 LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
248 LPVOID pvRef, DWORD dwFlags)
249 {
250 IDirectInputImpl *This = (IDirectInputImpl *)iface;
251 DIDEVICEINSTANCEA devInstance;
252 int i, j, r;
253
254 TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n",
255 This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
256 lpCallback, pvRef, dwFlags);
257 _dump_EnumDevices_dwFlags(dwFlags);
258
259 for (i = 0; i < NB_DINPUT_DEVICES; i++) {
260 if (!dinput_devices[i]->enum_deviceA) continue;
261 for (j = 0, r = -1; r != 0; j++) {
262 devInstance.dwSize = sizeof(devInstance);
263 TRACE(" - checking device %d ('%s')\n", i, dinput_devices[i]->name);
264 if ((r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
265 if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
266 return 0;
267 }
268 }
269 }
270
271 return 0;
272 }
273 /******************************************************************************
274 * IDirectInputW_EnumDevices
275 */
276 static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
277 LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
278 LPVOID pvRef, DWORD dwFlags)
279 {
280 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
281 DIDEVICEINSTANCEW devInstance;
282 int i, j, r;
283
284 TRACE("(this=%p,0x%04x '%s',%p,%p,%04x)\n",
285 This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
286 lpCallback, pvRef, dwFlags);
287 _dump_EnumDevices_dwFlags(dwFlags);
288
289 for (i = 0; i < NB_DINPUT_DEVICES; i++) {
290 if (!dinput_devices[i]->enum_deviceW) continue;
291 for (j = 0, r = -1; r != 0; j++) {
292 devInstance.dwSize = sizeof(devInstance);
293 TRACE(" - checking device %d ('%s')\n", i, dinput_devices[i]->name);
294 if ((r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
295 if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
296 return 0;
297 }
298 }
299 }
300
301 return 0;
302 }
303
304 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
305 {
306 IDirectInputImpl *This = (IDirectInputImpl *)iface;
307 ULONG ref = InterlockedIncrement(&This->ref);
308
309 TRACE( "(%p) incrementing from %d\n", This, ref - 1);
310 return ref;
311 }
312
313 static ULONG WINAPI IDirectInputWImpl_AddRef(LPDIRECTINPUT7W iface)
314 {
315 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
316 return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
317 }
318
319 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
320 {
321 IDirectInputImpl *This = (IDirectInputImpl *)iface;
322 ULONG ref = InterlockedDecrement( &This->ref );
323
324 TRACE( "(%p) releasing from %d\n", This, ref + 1 );
325
326 if (ref) return ref;
327
328 /* Remove self from the list of the IDirectInputs */
329 EnterCriticalSection( &dinput_hook_crit );
330 list_remove( &This->entry );
331 LeaveCriticalSection( &dinput_hook_crit );
332
333 check_hook_thread();
334
335 This->crit.DebugInfo->Spare[0] = 0;
336 DeleteCriticalSection( &This->crit );
337 HeapFree( GetProcessHeap(), 0, This );
338
339 return 0;
340 }
341
342 static ULONG WINAPI IDirectInputWImpl_Release(LPDIRECTINPUT7W iface)
343 {
344 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
345 return IDirectInputAImpl_Release( (IDirectInput7A *)This );
346 }
347
348 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj)
349 {
350 IDirectInputImpl *This = (IDirectInputImpl *)iface;
351
352 TRACE( "(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj );
353
354 if (IsEqualGUID( &IID_IUnknown, riid ) ||
355 IsEqualGUID( &IID_IDirectInputA, riid ) ||
356 IsEqualGUID( &IID_IDirectInput2A, riid ) ||
357 IsEqualGUID( &IID_IDirectInput7A, riid ))
358 {
359 *ppobj = &This->lpVtbl;
360 IUnknown_AddRef( (IUnknown*)*ppobj );
361
362 return DI_OK;
363 }
364
365 if (IsEqualGUID( &IID_IDirectInputW, riid ) ||
366 IsEqualGUID( &IID_IDirectInput2W, riid ) ||
367 IsEqualGUID( &IID_IDirectInput7W, riid ))
368 {
369 *ppobj = &This->lpVtbl7w;
370 IUnknown_AddRef( (IUnknown*)*ppobj );
371
372 return DI_OK;
373 }
374
375 if (IsEqualGUID( &IID_IDirectInput8A, riid ))
376 {
377 *ppobj = &This->lpVtbl8a;
378 IUnknown_AddRef( (IUnknown*)*ppobj );
379
380 return DI_OK;
381 }
382
383 if (IsEqualGUID( &IID_IDirectInput8W, riid ))
384 {
385 *ppobj = &This->lpVtbl8w;
386 IUnknown_AddRef( (IUnknown*)*ppobj );
387
388 return DI_OK;
389 }
390
391 FIXME( "Unsupported interface !\n" );
392 return E_FAIL;
393 }
394
395 static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj)
396 {
397 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
398 return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
399 }
400
401 static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {
402 TRACE("(this=%p,%p,%x)\n",iface, hinst, x);
403
404 /* Initialize can return: DIERR_BETADIRECTINPUTVERSION, DIERR_OLDDIRECTINPUTVERSION and DI_OK.
405 * Since we already initialized the device, return DI_OK. In the past we returned DIERR_ALREADYINITIALIZED
406 * which broke applications like Tomb Raider Legend because it isn't a legal return value.
407 */
408 return DI_OK;
409 }
410
411 static HRESULT WINAPI IDirectInputWImpl_Initialize(LPDIRECTINPUT7W iface, HINSTANCE hinst, DWORD x)
412 {
413 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
414 return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
415 }
416
417 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface, REFGUID rguid)
418 {
419 IDirectInputImpl *This = (IDirectInputImpl *)iface;
420 HRESULT hr;
421 LPDIRECTINPUTDEVICEA device;
422
423 TRACE( "(%p)->(%s)\n", This, debugstr_guid(rguid) );
424
425 hr = IDirectInput_CreateDevice( iface, rguid, &device, NULL );
426 if (hr != DI_OK) return DI_NOTATTACHED;
427
428 IUnknown_Release( device );
429
430 return DI_OK;
431 }
432
433 static HRESULT WINAPI IDirectInputWImpl_GetDeviceStatus(LPDIRECTINPUT7W iface, REFGUID rguid)
434 {
435 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
436 return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
437 }
438
439 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
440 HWND hwndOwner,
441 DWORD dwFlags)
442 {
443 IDirectInputImpl *This = (IDirectInputImpl *)iface;
444
445 FIXME( "(%p)->(%p,%08x): stub\n", This, hwndOwner, dwFlags );
446
447 return DI_OK;
448 }
449
450 static HRESULT WINAPI IDirectInputWImpl_RunControlPanel(LPDIRECTINPUT7W iface, HWND hwndOwner, DWORD dwFlags)
451 {
452 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
453 return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
454 }
455
456 static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
457 LPCSTR pszName, LPGUID pguidInstance)
458 {
459 IDirectInputImpl *This = (IDirectInputImpl *)iface;
460
461 FIXME( "(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance );
462
463 return DI_OK;
464 }
465
466 static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
467 LPCWSTR pszName, LPGUID pguidInstance)
468 {
469 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
470
471 FIXME( "(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance );
472
473 return DI_OK;
474 }
475
476 static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
477 REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
478 {
479 IDirectInputImpl *This = (IDirectInputImpl *)iface;
480 HRESULT ret_value = DIERR_DEVICENOTREG;
481 int i;
482
483 TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
484
485 if (!rguid || !pvOut) return E_POINTER;
486
487 /* Loop on all the devices to see if anyone matches the given GUID */
488 for (i = 0; i < NB_DINPUT_DEVICES; i++) {
489 HRESULT ret;
490
491 if (!dinput_devices[i]->create_deviceA) continue;
492 if ((ret = dinput_devices[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
493 {
494 EnterCriticalSection( &This->crit );
495 list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
496 LeaveCriticalSection( &This->crit );
497 return DI_OK;
498 }
499
500 if (ret == DIERR_NOINTERFACE)
501 ret_value = DIERR_NOINTERFACE;
502 }
503
504 if (ret_value == DIERR_NOINTERFACE)
505 {
506 WARN("invalid device GUID %s\n", debugstr_guid(rguid));
507 }
508
509 return ret_value;
510 }
511
512 static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
513 REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
514 {
515 IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
516 HRESULT ret_value = DIERR_DEVICENOTREG;
517 int i;
518
519 TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
520
521 if (!rguid || !pvOut) return E_POINTER;
522
523 /* Loop on all the devices to see if anyone matches the given GUID */
524 for (i = 0; i < NB_DINPUT_DEVICES; i++) {
525 HRESULT ret;
526
527 if (!dinput_devices[i]->create_deviceW) continue;
528 if ((ret = dinput_devices[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
529 {
530 EnterCriticalSection( &This->crit );
531 list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
532 LeaveCriticalSection( &This->crit );
533 return DI_OK;
534 }
535
536 if (ret == DIERR_NOINTERFACE)
537 ret_value = DIERR_NOINTERFACE;
538 }
539
540 return ret_value;
541 }
542
543 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
544 LPDIRECTINPUTDEVICEA* pdev, LPUNKNOWN punk)
545 {
546 return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
547 }
548
549 static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
550 LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk)
551 {
552 return IDirectInput7WImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
553 }
554
555 /*******************************************************************************
556 * DirectInput8
557 */
558
559 static ULONG WINAPI IDirectInput8AImpl_AddRef(LPDIRECTINPUT8A iface)
560 {
561 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
562 return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
563 }
564
565 static ULONG WINAPI IDirectInput8WImpl_AddRef(LPDIRECTINPUT8W iface)
566 {
567 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
568 return IDirectInputAImpl_AddRef( (IDirectInput7A *)This );
569 }
570
571 static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj)
572 {
573 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
574 return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
575 }
576
577 static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj)
578 {
579 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
580 return IDirectInputAImpl_QueryInterface( (IDirectInput7A *)This, riid, ppobj );
581 }
582
583 static ULONG WINAPI IDirectInput8AImpl_Release(LPDIRECTINPUT8A iface)
584 {
585 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
586 return IDirectInputAImpl_Release( (IDirectInput7A *)This );
587 }
588
589 static ULONG WINAPI IDirectInput8WImpl_Release(LPDIRECTINPUT8W iface)
590 {
591 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
592 return IDirectInputAImpl_Release( (IDirectInput7A *)This );
593 }
594
595 static HRESULT WINAPI IDirectInput8AImpl_CreateDevice(LPDIRECTINPUT8A iface, REFGUID rguid,
596 LPDIRECTINPUTDEVICE8A* pdev, LPUNKNOWN punk)
597 {
598 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
599 return IDirectInput7AImpl_CreateDeviceEx( (IDirectInput7A *)This, rguid, NULL, (LPVOID*)pdev, punk );
600 }
601
602 static HRESULT WINAPI IDirectInput8WImpl_CreateDevice(LPDIRECTINPUT8W iface, REFGUID rguid,
603 LPDIRECTINPUTDEVICE8W* pdev, LPUNKNOWN punk)
604 {
605 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
606 return IDirectInput7WImpl_CreateDeviceEx( IDirectInput7W_from_impl( This ), rguid, NULL, (LPVOID*)pdev, punk );
607 }
608
609 static HRESULT WINAPI IDirectInput8AImpl_EnumDevices(LPDIRECTINPUT8A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
610 LPVOID pvRef, DWORD dwFlags)
611 {
612 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
613 return IDirectInputAImpl_EnumDevices( (IDirectInput7A *)This, dwDevType, lpCallback, pvRef, dwFlags );
614 }
615
616 static HRESULT WINAPI IDirectInput8WImpl_EnumDevices(LPDIRECTINPUT8W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
617 LPVOID pvRef, DWORD dwFlags)
618 {
619 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
620 return IDirectInputWImpl_EnumDevices( IDirectInput7W_from_impl( This ), dwDevType, lpCallback, pvRef, dwFlags );
621 }
622
623 static HRESULT WINAPI IDirectInput8AImpl_GetDeviceStatus(LPDIRECTINPUT8A iface, REFGUID rguid)
624 {
625 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
626 return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
627 }
628
629 static HRESULT WINAPI IDirectInput8WImpl_GetDeviceStatus(LPDIRECTINPUT8W iface, REFGUID rguid)
630 {
631 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
632 return IDirectInputAImpl_GetDeviceStatus( (IDirectInput7A *)This, rguid );
633 }
634
635 static HRESULT WINAPI IDirectInput8AImpl_RunControlPanel(LPDIRECTINPUT8A iface, HWND hwndOwner, DWORD dwFlags)
636 {
637 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
638 return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
639 }
640
641 static HRESULT WINAPI IDirectInput8WImpl_RunControlPanel(LPDIRECTINPUT8W iface, HWND hwndOwner, DWORD dwFlags)
642 {
643 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
644 return IDirectInputAImpl_RunControlPanel( (IDirectInput7A *)This, hwndOwner, dwFlags );
645 }
646
647 static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINSTANCE hinst, DWORD x)
648 {
649 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
650 return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
651 }
652
653 static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD x)
654 {
655 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
656 return IDirectInputAImpl_Initialize( (IDirectInput7A *)This, hinst, x );
657 }
658
659 static HRESULT WINAPI IDirectInput8AImpl_FindDevice(LPDIRECTINPUT8A iface, REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance)
660 {
661 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
662 return IDirectInput2AImpl_FindDevice( (IDirectInput7A *)This, rguid, pszName, pguidInstance );
663 }
664
665 static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance)
666 {
667 IDirectInput7W *This = IDirectInput7W_from_impl( impl_from_IDirectInput8W( iface ) );
668 return IDirectInput2WImpl_FindDevice( This, rguid, pszName, pguidInstance );
669 }
670
671 static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
672 LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
673 LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
674 LPVOID pvRef, DWORD dwFlags
675 )
676 {
677 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
678
679 FIXME("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, ptszUserName, lpdiActionFormat,
680 lpCallback, pvRef, dwFlags);
681 #define X(x) if (dwFlags & x) FIXME("\tdwFlags |= "#x"\n");
682 X(DIEDBSFL_ATTACHEDONLY)
683 X(DIEDBSFL_THISUSER)
684 X(DIEDBSFL_FORCEFEEDBACK)
685 X(DIEDBSFL_AVAILABLEDEVICES)
686 X(DIEDBSFL_MULTIMICEKEYBOARDS)
687 X(DIEDBSFL_NONGAMINGDEVICES)
688 #undef X
689
690 _dump_diactionformatA(lpdiActionFormat);
691
692 return DI_OK;
693 }
694
695 static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
696 LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,
697 LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,
698 LPVOID pvRef, DWORD dwFlags
699 )
700 {
701 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
702
703 FIXME("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,
704 lpCallback, pvRef, dwFlags);
705 return 0;
706 }
707
708 static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
709 LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
710 LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
711 )
712 {
713 IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
714
715 FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams,
716 dwFlags, pvRefData);
717 return 0;
718 }
719
720 static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
721 LPDIRECTINPUT8W iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
722 LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
723 )
724 {
725 IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
726
727 FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams,
728 dwFlags, pvRefData);
729 return 0;
730 }
731
732 static const IDirectInput7AVtbl ddi7avt = {
733 IDirectInputAImpl_QueryInterface,
734 IDirectInputAImpl_AddRef,
735 IDirectInputAImpl_Release,
736 IDirectInputAImpl_CreateDevice,
737 IDirectInputAImpl_EnumDevices,
738 IDirectInputAImpl_GetDeviceStatus,
739 IDirectInputAImpl_RunControlPanel,
740 IDirectInputAImpl_Initialize,
741 IDirectInput2AImpl_FindDevice,
742 IDirectInput7AImpl_CreateDeviceEx
743 };
744
745 static const IDirectInput7WVtbl ddi7wvt = {
746 IDirectInputWImpl_QueryInterface,
747 IDirectInputWImpl_AddRef,
748 IDirectInputWImpl_Release,
749 IDirectInputWImpl_CreateDevice,
750 IDirectInputWImpl_EnumDevices,
751 IDirectInputWImpl_GetDeviceStatus,
752 IDirectInputWImpl_RunControlPanel,
753 IDirectInputWImpl_Initialize,
754 IDirectInput2WImpl_FindDevice,
755 IDirectInput7WImpl_CreateDeviceEx
756 };
757
758 static const IDirectInput8AVtbl ddi8avt = {
759 IDirectInput8AImpl_QueryInterface,
760 IDirectInput8AImpl_AddRef,
761 IDirectInput8AImpl_Release,
762 IDirectInput8AImpl_CreateDevice,
763 IDirectInput8AImpl_EnumDevices,
764 IDirectInput8AImpl_GetDeviceStatus,
765 IDirectInput8AImpl_RunControlPanel,
766 IDirectInput8AImpl_Initialize,
767 IDirectInput8AImpl_FindDevice,
768 IDirectInput8AImpl_EnumDevicesBySemantics,
769 IDirectInput8AImpl_ConfigureDevices
770 }