Fix SetProperty error returned.
[wine] / dlls / dinput / dinput_main.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  * Copyright 2000-2002 TransGaming Technologies Inc.
6  *
7  *
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.
12  *
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.
17  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 /* Status:
23  *
24  * - Tomb Raider 2 Demo:
25  *   Playable using keyboard only.
26  * - WingCommander Prophecy Demo:
27  *   Doesn't get Input Focus.
28  *
29  * - Fallout : works great in X and DGA mode
30  */
31
32 #include "config.h"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <string.h>
36
37 #define COBJMACROS
38
39 #include "wine/debug.h"
40 #include "wine/unicode.h"
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winuser.h"
44 #include "winerror.h"
45 #include "dinput_private.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
48
49 static IDirectInput7AVtbl ddi7avt;
50 static IDirectInput7WVtbl ddi7wvt;
51 static IDirectInput8AVtbl ddi8avt;
52 static IDirectInput8WVtbl ddi8wvt;
53
54 static const struct dinput_device *dinput_devices[] =
55 {
56     &mouse_device,
57     &keyboard_device,
58     &joystick_linuxinput_device,
59     &joystick_linux_device
60 };
61 #define NB_DINPUT_DEVICES (sizeof(dinput_devices)/sizeof(dinput_devices[0]))
62
63 HINSTANCE DINPUT_instance = NULL;
64
65 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv)
66 {
67     switch(reason)
68     {
69       case DLL_PROCESS_ATTACH:
70         DisableThreadLibraryCalls(inst);
71         DINPUT_instance = inst;
72         break;
73       case DLL_PROCESS_DETACH:
74         break;
75     }
76     return TRUE;
77 }
78
79
80 /******************************************************************************
81  *      DirectInputCreateEx (DINPUT.@)
82  */
83 HRESULT WINAPI DirectInputCreateEx(
84         HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
85         LPUNKNOWN punkOuter) 
86 {
87         IDirectInputImpl* This;
88
89         TRACE("(0x%08lx,%04lx,%s,%p,%p)\n", (DWORD)hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter);
90
91         if (IsEqualGUID(&IID_IDirectInputA,riid) ||
92             IsEqualGUID(&IID_IDirectInput2A,riid) ||
93             IsEqualGUID(&IID_IDirectInput7A,riid)) {
94           This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
95           This->lpVtbl = &ddi7avt;
96           This->ref = 1;
97           This->version = 1;
98           This->dwVersion = dwVersion; 
99           *ppDI = This;
100
101           return DI_OK;
102         }
103
104         if (IsEqualGUID(&IID_IDirectInputW,riid) ||
105             IsEqualGUID(&IID_IDirectInput2W,riid) ||
106             IsEqualGUID(&IID_IDirectInput7W,riid)) {
107           This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
108           This->lpVtbl = &ddi7wvt;
109           This->ref = 1;
110           This->version = 1;
111           This->dwVersion = dwVersion; 
112           *ppDI = This;
113
114           return DI_OK;
115         }
116
117         if (IsEqualGUID(&IID_IDirectInput8A,riid)) {
118           This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
119           This->lpVtbl = &ddi8avt;
120           This->ref = 1;
121           This->version = 8;
122           This->dwVersion = dwVersion; 
123           *ppDI = This;
124
125           return DI_OK;
126         }
127
128         if (IsEqualGUID(&IID_IDirectInput8W,riid)) {
129           This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
130           This->lpVtbl = &ddi8wvt;
131           This->ref = 1;
132           This->version = 8;
133           This->dwVersion = dwVersion; 
134           *ppDI = This;
135
136           return DI_OK;
137         }
138
139         return DIERR_OLDDIRECTINPUTVERSION;
140 }
141
142 /******************************************************************************
143  *      DirectInputCreateA (DINPUT.@)
144  */
145 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
146 {
147         IDirectInputImpl* This;
148         TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);
149         This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
150         This->lpVtbl = &ddi7avt;
151         This->ref = 1;
152         This->dwVersion = dwVersion; 
153         if (dwVersion >= 0x0800) {
154             This->version = 8;
155         } else {
156             /* We do not differientiate between version 1, 2 and 7 */
157             This->version = 1;
158         }
159         *ppDI = (IDirectInputA*)This;
160         return 0;
161
162 }
163
164 /******************************************************************************
165  *      DirectInputCreateW (DINPUT.@)
166  */
167 HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter)
168 {
169         IDirectInputImpl* This;
170         TRACE("(0x%08lx,%04lx,%p,%p)\n", (DWORD)hinst,dwVersion,ppDI,punkOuter);
171         This = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputImpl));
172         This->lpVtbl = &ddi7wvt;
173         This->ref = 1;
174         This->dwVersion = dwVersion; 
175         if (dwVersion >= 0x0800) {
176             This->version = 8;
177         } else {
178             /* We do not differientiate between version 1, 2 and 7 */
179             This->version = 1;
180         }
181         *ppDI = (IDirectInputW*)This;
182         return 0;
183 }
184
185 static const char *_dump_DIDEVTYPE_value(DWORD dwDevType) {
186     switch (dwDevType) {
187         case 0: return "All devices";
188         case DIDEVTYPE_MOUSE: return "DIDEVTYPE_MOUSE";
189         case DIDEVTYPE_KEYBOARD: return "DIDEVTYPE_KEYBOARD";
190         case DIDEVTYPE_JOYSTICK: return "DIDEVTYPE_JOYSTICK";
191         case DIDEVTYPE_DEVICE: return "DIDEVTYPE_DEVICE";
192         default: return "Unkown";
193     }
194 }
195
196 static void _dump_EnumDevices_dwFlags(DWORD dwFlags) {
197     if (TRACE_ON(dinput)) {
198         unsigned int   i;
199         static const struct {
200             DWORD       mask;
201             const char  *name;
202         } flags[] = {
203 #define FE(x) { x, #x}
204             FE(DIEDFL_ALLDEVICES),
205             FE(DIEDFL_ATTACHEDONLY),
206             FE(DIEDFL_FORCEFEEDBACK),
207             FE(DIEDFL_INCLUDEALIASES),
208             FE(DIEDFL_INCLUDEPHANTOMS)
209 #undef FE
210         };
211         if (dwFlags == 0) {
212             DPRINTF("DIEDFL_ALLDEVICES");
213             return;
214         }
215         for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
216             if (flags[i].mask & dwFlags)
217                 DPRINTF("%s ",flags[i].name);
218     }
219 }
220
221 /******************************************************************************
222  *      IDirectInputA_EnumDevices
223  */
224 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
225         LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
226         LPVOID pvRef, DWORD dwFlags)
227 {
228     IDirectInputImpl *This = (IDirectInputImpl *)iface;
229     DIDEVICEINSTANCEA devInstance;
230     int i, j, r;
231     
232     TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",
233           This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
234           lpCallback, pvRef, dwFlags);
235     TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");
236
237     /* joysticks are not supported in version 0x0300 */
238     if ((dwDevType == DIDEVTYPE_JOYSTICK) && (This->dwVersion <= 0x0300))
239         return E_INVALIDARG;
240
241     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
242         if (!dinput_devices[i]->enum_deviceA) continue;
243         for (j = 0, r = -1; r != 0; j++) {
244             devInstance.dwSize = sizeof(devInstance);
245             TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);
246             if ((r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->version, j))) {
247                 if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
248                     return 0;
249             }
250         }
251     }
252     
253     return 0;
254 }
255 /******************************************************************************
256  *      IDirectInputW_EnumDevices
257  */
258 static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
259         LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
260         LPVOID pvRef, DWORD dwFlags) 
261 {
262     IDirectInputImpl *This = (IDirectInputImpl *)iface;
263     DIDEVICEINSTANCEW devInstance;
264     int i, j, r;
265     
266     TRACE("(this=%p,0x%04lx '%s',%p,%p,%04lx)\n",
267           This, dwDevType, _dump_DIDEVTYPE_value(dwDevType),
268           lpCallback, pvRef, dwFlags);
269     TRACE(" flags: "); _dump_EnumDevices_dwFlags(dwFlags); TRACE("\n");
270
271     /* joysticks are not supported in version 0x0300 */
272     if ((dwDevType == DIDEVTYPE_JOYSTICK) && (This->dwVersion <= 0x0300))
273         return E_INVALIDARG;
274
275     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
276         if (!dinput_devices[i]->enum_deviceW) continue;
277         for (j = 0, r = -1; r != 0; j++) {
278             devInstance.dwSize = sizeof(devInstance);
279             TRACE("  - checking device %d ('%s')\n", i, dinput_devices[i]->name);
280             if ((r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->version, j))) {
281                 if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
282                     return 0;
283             }
284         }
285     }
286     
287     return 0;
288 }
289
290 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
291 {
292         IDirectInputImpl *This = (IDirectInputImpl *)iface;
293         return InterlockedIncrement((&This->ref));
294 }
295
296 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
297 {
298         IDirectInputImpl *This = (IDirectInputImpl *)iface;
299         ULONG ref;
300         ref = InterlockedDecrement(&(This->ref));
301         if (ref == 0)
302                 HeapFree(GetProcessHeap(),0,This);
303         return ref;
304 }
305
306 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj) {
307         IDirectInputImpl *This = (IDirectInputImpl *)iface;
308
309         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
310         if (IsEqualGUID(&IID_IUnknown,riid) ||
311             IsEqualGUID(&IID_IDirectInputA,riid) ||
312             IsEqualGUID(&IID_IDirectInput2A,riid) ||
313             IsEqualGUID(&IID_IDirectInput7A,riid)) {
314                 IDirectInputAImpl_AddRef(iface);
315                 *ppobj = This;
316                 return 0;
317         }
318         TRACE("Unsupported interface !\n");
319         return E_FAIL;
320 }
321
322 static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj) {
323         IDirectInputImpl *This = (IDirectInputImpl *)iface;
324
325         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
326         if (IsEqualGUID(&IID_IUnknown,riid) ||
327             IsEqualGUID(&IID_IDirectInputW,riid) ||
328             IsEqualGUID(&IID_IDirectInput2W,riid) ||
329             IsEqualGUID(&IID_IDirectInput7W,riid)) {
330                 IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
331                 *ppobj = This;
332                 return 0;
333         }
334         TRACE("Unsupported interface !\n");
335         return E_FAIL;
336 }
337
338 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
339         LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
340         LPUNKNOWN punk
341 ) {
342         IDirectInputImpl *This = (IDirectInputImpl *)iface;
343         HRESULT ret_value = DIERR_DEVICENOTREG;
344         int i;
345
346         TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
347
348         if (pdev == NULL) {
349                 WARN("invalid pointer: pdev == NULL\n");
350                 return E_POINTER;
351         }
352
353         if (rguid == NULL) {
354                 WARN("invalid pointer: rguid == NULL\n");
355                 return E_POINTER;
356         }
357
358         /* Loop on all the devices to see if anyone matches the given GUID */
359         for (i = 0; i < NB_DINPUT_DEVICES; i++) {
360           HRESULT ret;
361           if (!dinput_devices[i]->create_deviceA) continue;
362           if ((ret = dinput_devices[i]->create_deviceA(This, rguid, NULL, pdev)) == DI_OK)
363             return DI_OK;
364
365           if (ret == DIERR_NOINTERFACE)
366             ret_value = DIERR_NOINTERFACE;
367         }
368
369         return ret_value;
370 }
371
372 static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7A iface, 
373                                                      REFGUID rguid, LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk) {
374         IDirectInputImpl *This = (IDirectInputImpl *)iface;
375         HRESULT ret_value = DIERR_DEVICENOTREG;
376         int i;
377
378         TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
379
380         /* Loop on all the devices to see if anyone matches the given GUID */
381         for (i = 0; i < NB_DINPUT_DEVICES; i++) {
382           HRESULT ret;
383           if (!dinput_devices[i]->create_deviceW) continue;
384           if ((ret = dinput_devices[i]->create_deviceW(This, rguid, NULL, pdev)) == DI_OK)
385             return DI_OK;
386
387           if (ret == DIERR_NOINTERFACE)
388             ret_value = DIERR_NOINTERFACE;
389         }
390
391         return ret_value;
392 }
393
394 static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {
395         return DIERR_ALREADYINITIALIZED;
396 }
397
398 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,
399                                                         REFGUID rguid) {
400   IDirectInputImpl *This = (IDirectInputImpl *)iface;
401
402   FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
403
404   return DI_OK;
405 }
406
407 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
408                                                         HWND hwndOwner,
409                                                         DWORD dwFlags) {
410   IDirectInputImpl *This = (IDirectInputImpl *)iface;
411   FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
412
413   return DI_OK;
414 }
415
416 static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
417                                                     LPCSTR pszName, LPGUID pguidInstance) {
418   IDirectInputImpl *This = (IDirectInputImpl *)iface;
419   FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance);
420
421   return DI_OK;
422 }
423
424 static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
425                                                     LPCWSTR pszName, LPGUID pguidInstance) {
426   IDirectInputImpl *This = (IDirectInputImpl *)iface;
427   FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), debugstr_w(pszName), pguidInstance);
428
429   return DI_OK;
430 }
431
432 static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
433                                                         REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
434 {
435   IDirectInputImpl *This = (IDirectInputImpl *)iface;
436   HRESULT ret_value = DIERR_DEVICENOTREG;
437   int i;
438
439   TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
440
441   /* Loop on all the devices to see if anyone matches the given GUID */
442   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
443     HRESULT ret;
444     if (!dinput_devices[i]->create_deviceA) continue;
445     if ((ret = dinput_devices[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
446       return DI_OK;
447
448     if (ret == DIERR_NOINTERFACE)
449       ret_value = DIERR_NOINTERFACE;
450   }
451
452   return ret_value;
453 }
454
455 static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
456                                                         REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
457 {
458   IDirectInputImpl *This = (IDirectInputImpl *)iface;
459   HRESULT ret_value = DIERR_DEVICENOTREG;
460   int i;
461
462   TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
463
464   /* Loop on all the devices to see if anyone matches the given GUID */
465   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
466     HRESULT ret;
467     if (!dinput_devices[i]->create_deviceW) continue;
468     if ((ret = dinput_devices[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
469       return DI_OK;
470
471     if (ret == DIERR_NOINTERFACE)
472       ret_value = DIERR_NOINTERFACE;
473   }
474
475   return ret_value;
476 }
477
478 static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj) {
479       IDirectInputImpl *This = (IDirectInputImpl *)iface;
480
481       TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
482       if (IsEqualGUID(&IID_IUnknown,riid) ||
483           IsEqualGUID(&IID_IDirectInput8A,riid)) {
484               IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
485               *ppobj = This;
486               return 0;
487       }
488       TRACE("Unsupported interface !\n");
489       return E_NOINTERFACE;
490 }
491
492 static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj) {
493       IDirectInputImpl *This = (IDirectInputImpl *)iface;
494
495       TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
496       if (IsEqualGUID(&IID_IUnknown,riid) ||
497           IsEqualGUID(&IID_IDirectInput8W,riid)) {
498               IDirectInputAImpl_AddRef((LPDIRECTINPUT7A) iface);
499               *ppobj = This;
500               return 0;
501       }
502       TRACE("Unsupported interface !\n");
503       return E_NOINTERFACE;
504 }
505
506 static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
507       LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
508       LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
509       LPVOID pvRef, DWORD dwFlags
510 )
511 {
512       IDirectInputImpl *This = (IDirectInputImpl *)iface;
513
514       FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, ptszUserName, lpdiActionFormat,
515             lpCallback, pvRef, dwFlags);
516       return 0;
517 }
518
519 static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
520       LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,
521       LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,
522       LPVOID pvRef, DWORD dwFlags
523 )
524 {
525       IDirectInputImpl *This = (IDirectInputImpl *)iface;
526
527       FIXME("(this=%p,%s,%p,%p,%p,%04lx): stub\n", This, debugstr_w(ptszUserName), lpdiActionFormat,
528             lpCallback, pvRef, dwFlags);
529       return 0;
530 }
531
532 static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
533       LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
534       LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
535 )
536 {
537       IDirectInputImpl *This = (IDirectInputImpl *)iface;
538
539       FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
540             dwFlags, pvRefData);
541       return 0;
542 }
543
544 static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
545       LPDIRECTINPUT8W iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
546       LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
547 )
548 {
549       IDirectInputImpl *This = (IDirectInputImpl *)iface;
550
551       FIXME("(this=%p,%p,%p,%04lx,%p): stub\n", This, lpdiCallback, lpdiCDParams,
552             dwFlags, pvRefData);
553       return 0;
554 }
555
556 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
557 # define XCAST(fun)   (typeof(ddi7avt.fun))
558 #else
559 # define XCAST(fun)     (void*)
560 #endif
561
562 static IDirectInput7AVtbl ddi7avt = {
563         XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,
564         XCAST(AddRef)IDirectInputAImpl_AddRef,
565         XCAST(Release)IDirectInputAImpl_Release,
566         XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
567         XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
568         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
569         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
570         XCAST(Initialize)IDirectInputAImpl_Initialize,
571         XCAST(FindDevice)IDirectInput2AImpl_FindDevice,
572         XCAST(CreateDeviceEx)IDirectInput7AImpl_CreateDeviceEx
573 };
574
575 #undef XCAST
576 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
577 # define XCAST(fun)   (typeof(ddi7wvt.fun))
578 #else
579 # define XCAST(fun)     (void*)
580 #endif
581
582 static IDirectInput7WVtbl ddi7wvt = {
583         XCAST(QueryInterface)IDirectInputWImpl_QueryInterface,
584         XCAST(AddRef)IDirectInputAImpl_AddRef,
585         XCAST(Release)IDirectInputAImpl_Release,
586         XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,
587         XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,
588         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
589         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
590         XCAST(Initialize)IDirectInputAImpl_Initialize,
591         XCAST(FindDevice)IDirectInput2WImpl_FindDevice,
592         XCAST(CreateDeviceEx)IDirectInput7WImpl_CreateDeviceEx
593 };
594 #undef XCAST
595
596 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
597 # define XCAST(fun)     (typeof(ddi8avt.fun))
598 #else
599 # define XCAST(fun)     (void*)
600 #endif
601
602 static IDirectInput8AVtbl ddi8avt = {
603         XCAST(QueryInterface)IDirectInput8AImpl_QueryInterface,
604         XCAST(AddRef)IDirectInputAImpl_AddRef,
605         XCAST(Release)IDirectInputAImpl_Release,
606         XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
607         XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
608         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
609         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
610         XCAST(Initialize)IDirectInputAImpl_Initialize,
611         XCAST(FindDevice)IDirectInput2AImpl_FindDevice,
612         XCAST(EnumDevicesBySemantics)IDirectInput8AImpl_EnumDevicesBySemantics,
613         XCAST(ConfigureDevices)IDirectInput8AImpl_ConfigureDevices
614 };
615 #undef XCAST
616
617 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
618 # define XCAST(fun)     (typeof(ddi8wvt.fun))
619 #else
620 # define XCAST(fun)     (void*)
621 #endif
622 static IDirectInput8WVtbl ddi8wvt = {
623         XCAST(QueryInterface)IDirectInput8WImpl_QueryInterface,
624         XCAST(AddRef)IDirectInputAImpl_AddRef,
625         XCAST(Release)IDirectInputAImpl_Release,
626         XCAST(CreateDevice)IDirectInputWImpl_CreateDevice,
627         XCAST(EnumDevices)IDirectInputWImpl_EnumDevices,
628         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
629         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
630         XCAST(Initialize)IDirectInputAImpl_Initialize,
631         XCAST(FindDevice)IDirectInput2WImpl_FindDevice,
632         XCAST(EnumDevicesBySemantics)IDirectInput8WImpl_EnumDevicesBySemantics,
633         XCAST(ConfigureDevices)IDirectInput8WImpl_ConfigureDevices
634 };
635 #undef XCAST
636
637 /*******************************************************************************
638  * DirectInput ClassFactory
639  */
640 typedef struct
641 {
642     /* IUnknown fields */
643     IClassFactoryVtbl          *lpVtbl;
644     DWORD                       ref;
645 } IClassFactoryImpl;
646
647 static HRESULT WINAPI DICF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
648         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
649
650         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
651         return E_NOINTERFACE;
652 }
653
654 static ULONG WINAPI DICF_AddRef(LPCLASSFACTORY iface) {
655         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
656         return InterlockedIncrement(&(This->ref));
657 }
658
659 static ULONG WINAPI DICF_Release(LPCLASSFACTORY iface) {
660         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
661         /* static class, won't be  freed */
662         return InterlockedDecrement(&(This->ref));
663 }
664
665 static HRESULT WINAPI DICF_CreateInstance(
666         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
667 ) {
668         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
669
670         TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
671         if ( IsEqualGUID( &IID_IDirectInputA, riid ) ||
672              IsEqualGUID( &IID_IDirectInputW, riid ) ||
673              IsEqualGUID( &IID_IDirectInput2A, riid ) ||
674              IsEqualGUID( &IID_IDirectInput2W, riid ) ||
675              IsEqualGUID( &IID_IDirectInput7A, riid ) ||
676              IsEqualGUID( &IID_IDirectInput7W, riid ) ||
677              IsEqualGUID( &IID_IDirectInput8A, riid ) ||
678              IsEqualGUID( &IID_IDirectInput8W, riid ) ) {
679                 /* FIXME: reuse already created dinput if present? */
680                 return DirectInputCreateEx(0,0,riid,ppobj,pOuter);
681         }
682
683         FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);    
684         return E_NOINTERFACE;
685 }
686
687 static HRESULT WINAPI DICF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
688         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
689         FIXME("(%p)->(%d),stub!\n",This,dolock);
690         return S_OK;
691 }
692
693 static IClassFactoryVtbl DICF_Vtbl = {
694         DICF_QueryInterface,
695         DICF_AddRef,
696         DICF_Release,
697         DICF_CreateInstance,
698         DICF_LockServer
699 };
700 static IClassFactoryImpl DINPUT_CF = {&DICF_Vtbl, 1 };
701
702 /***********************************************************************
703  *              DllCanUnloadNow (DINPUT.@)
704  */
705 HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
706 {
707     FIXME("(void): stub\n");
708
709     return S_FALSE;
710 }
711
712 /***********************************************************************
713  *              DllGetClassObject (DINPUT.@)
714  */
715 HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,
716                                         LPVOID *ppv)
717 {
718     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
719     if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) {
720         *ppv = (LPVOID)&DINPUT_CF;
721         IClassFactory_AddRef((IClassFactory*)*ppv);
722     return S_OK;
723     }
724
725     FIXME("(%s,%s,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
726     return CLASS_E_CLASSNOTAVAILABLE;
727 }