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