opengl32: Avoid generating a wrapper for internal functions when we can call the...
[wine] / dlls / dinput / keyboard.c
1 /*              DirectInput Keyboard device
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  * Copyright 2000-2001 TransGaming Technologies Inc.
6  * Copyright 2005 Raphael Junqueira
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winerror.h"
32 #include "dinput.h"
33
34 #include "dinput_private.h"
35 #include "device_private.h"
36 #include "wine/debug.h"
37 #include "wine/unicode.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
40
41 #define WINE_DINPUT_KEYBOARD_MAX_KEYS 256
42
43 static const IDirectInputDevice8AVtbl SysKeyboardAvt;
44 static const IDirectInputDevice8WVtbl SysKeyboardWvt;
45
46 typedef struct SysKeyboardImpl SysKeyboardImpl;
47 struct SysKeyboardImpl
48 {
49     struct IDirectInputDevice2AImpl base;
50
51     IDirectInputImpl*           dinput;
52 };
53
54 static SysKeyboardImpl* current_lock = NULL; 
55 /* Today's acquired device
56  * FIXME: currently this can be only one.
57  * Maybe this should be a linked list or st.
58  * I don't know what the rules are for multiple acquired keyboards,
59  * but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
60 */
61
62 static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDeviceState' */
63
64 LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
65 {
66     SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock;
67     int dik_code;
68     KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
69     BYTE new_diks;
70
71     TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
72
73     /* returns now if not HC_ACTION */
74     if (code != HC_ACTION) return CallNextHookEx(0, code, wparam, lparam);
75   
76     dik_code = hook->scanCode & 0xff;
77     if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
78
79     new_diks = hook->flags & LLKHF_UP ? 0 : 0x80;
80
81     /* returns now if key event already known */
82     if (new_diks == DInputKeyState[dik_code])
83         return CallNextHookEx(0, code, wparam, lparam);
84
85     DInputKeyState[dik_code] = new_diks;
86     TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
87       
88     EnterCriticalSection(&This->base.crit);
89     queue_event((LPDIRECTINPUTDEVICE8A)This, dik_code, new_diks, hook->time, This->dinput->evsequence++);
90     LeaveCriticalSection(&This->base.crit);
91
92     if (This->base.hEvent) SetEvent(This->base.hEvent);
93     
94     return CallNextHookEx(0, code, wparam, lparam);
95 }
96
97 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
98   0x0ab8648a,
99   0x7735,
100   0x11d2,
101   {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
102 };
103
104 static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
105     DWORD dwSize;
106     DIDEVICEINSTANCEA ddi;
107     
108     dwSize = lpddi->dwSize;
109
110     TRACE("%d %p\n", dwSize, lpddi);
111     
112     memset(lpddi, 0, dwSize);
113     memset(&ddi, 0, sizeof(ddi));
114
115     ddi.dwSize = dwSize;
116     ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
117     ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
118     if (version >= 0x0800)
119         ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
120     else
121         ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
122     strcpy(ddi.tszInstanceName, "Keyboard");
123     strcpy(ddi.tszProductName, "Wine Keyboard");
124
125     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
126 }
127
128 static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
129     DWORD dwSize;
130     DIDEVICEINSTANCEW ddi;
131     
132     dwSize = lpddi->dwSize;
133
134     TRACE("%d %p\n", dwSize, lpddi);
135     
136     memset(lpddi, 0, dwSize);
137     memset(&ddi, 0, sizeof(ddi));
138  
139     ddi.dwSize = dwSize;
140     ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
141     ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
142     if (version >= 0x0800)
143         ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
144     else
145         ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
146     MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH);
147     MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH);
148
149     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
150 }
151  
152 static BOOL keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
153 {
154   if (id != 0)
155     return FALSE;
156
157   if ((dwDevType == 0) ||
158       ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
159       (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
160     TRACE("Enumerating the Keyboard device\n");
161  
162     fill_keyboard_dideviceinstanceA(lpddi, version);
163     
164     return TRUE;
165   }
166
167   return FALSE;
168 }
169
170 static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
171 {
172   if (id != 0)
173     return FALSE;
174
175   if ((dwDevType == 0) ||
176       ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
177       (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
178     TRACE("Enumerating the Keyboard device\n");
179
180     fill_keyboard_dideviceinstanceW(lpddi, version);
181     
182     return TRUE;
183   }
184
185   return FALSE;
186 }
187
188 static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInputImpl *dinput)
189 {
190     SysKeyboardImpl* newDevice;
191
192     newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
193     newDevice->base.lpVtbl = kvt;
194     newDevice->base.ref = 1;
195     memcpy(&newDevice->base.guid, rguid, sizeof(*rguid));
196     newDevice->dinput = dinput;
197     InitializeCriticalSection(&newDevice->base.crit);
198
199     return newDevice;
200 }
201
202
203 static HRESULT keyboarddev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
204 {
205   if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
206       (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
207     if ((riid == NULL) ||
208         IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
209         IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
210         IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
211         IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
212       *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
213       TRACE("Creating a Keyboard device (%p)\n", *pdev);
214       return DI_OK;
215     } else
216       return DIERR_NOINTERFACE;
217   }
218   return DIERR_DEVICENOTREG;
219 }
220
221 static HRESULT keyboarddev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
222 {
223   if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
224       (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
225     if ((riid == NULL) ||
226         IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
227         IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
228         IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
229         IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
230       *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysKeyboardWvt, dinput);
231       TRACE("Creating a Keyboard device (%p)\n", *pdev);
232       return DI_OK;
233     } else
234       return DIERR_NOINTERFACE;
235   }
236   return DIERR_DEVICENOTREG;
237 }
238
239 const struct dinput_device keyboard_device = {
240   "Wine keyboard driver",
241   keyboarddev_enum_deviceA,
242   keyboarddev_enum_deviceW,
243   keyboarddev_create_deviceA,
244   keyboarddev_create_deviceW
245 };
246
247 static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
248 {
249     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
250     ULONG ref;
251
252     ref = InterlockedDecrement(&This->base.ref);
253     if (ref) return ref;
254
255     set_dinput_hook(WH_KEYBOARD_LL, NULL);
256
257     DeleteCriticalSection(&This->base.crit);
258     HeapFree(GetProcessHeap(), 0, This->base.data_queue);
259     HeapFree(GetProcessHeap(), 0, This);
260
261     return DI_OK;
262 }
263
264 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
265         LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
266 )
267 {
268     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
269     TRACE("(%p)->(%d,%p)\n", This, len, ptr);
270
271     if (!This->base.acquired) return DIERR_NOTACQUIRED;
272
273     if (len != WINE_DINPUT_KEYBOARD_MAX_KEYS)
274       return DIERR_INVALIDPARAM;
275
276     MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
277
278     EnterCriticalSection(&This->base.crit);
279
280     if (TRACE_ON(dinput)) {
281         int i;
282         for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
283             if (DInputKeyState[i] != 0x00) {
284                 TRACE(" - %02X: %02x\n", i, DInputKeyState[i]);
285             }
286         }
287     }
288     
289     memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS);
290     LeaveCriticalSection(&This->base.crit);
291
292     return DI_OK;
293 }
294
295 static HRESULT WINAPI SysKeyboardAImpl_EnumObjects(
296         LPDIRECTINPUTDEVICE8A iface,
297         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
298         LPVOID lpvRef,
299         DWORD dwFlags)
300 {
301     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
302     DIDEVICEOBJECTINSTANCEA ddoi;
303     int i;
304     
305     TRACE("(this=%p,%p,%p,%08x)\n", This, lpCallback, lpvRef, dwFlags);
306     if (TRACE_ON(dinput)) {
307         TRACE("  - flags = ");
308         _dump_EnumObjects_flags(dwFlags);
309         TRACE("\n");
310     }
311
312     /* Only the fields till dwFFMaxForce are relevant */
313     memset(&ddoi, 0, sizeof(ddoi));
314     ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
315
316     for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
317         /* Report 255 keys :-) */
318         ddoi.guidType = GUID_Key;
319         ddoi.dwOfs = i;
320         ddoi.dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_BUTTON;
321         GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
322         _dump_OBJECTINSTANCEA(&ddoi);
323         if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
324     }
325     
326     return DI_OK;
327 }
328
329 static HRESULT WINAPI SysKeyboardWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
330                                                    LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
331                                                    LPVOID lpvRef,
332                                                    DWORD dwFlags)
333 {
334   SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
335
336   device_enumobjects_AtoWcb_data data;
337
338   data.lpCallBack = lpCallback;
339   data.lpvRef = lpvRef;
340
341   return SysKeyboardAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
342 }
343
344 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
345
346 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
347 {
348     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
349     HRESULT res;
350
351     TRACE("(%p)\n",This);
352
353     if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res;
354
355     if (current_lock != NULL) {
356         FIXME("Not more than one keyboard can be acquired at the same time.\n");
357         SysKeyboardAImpl_Unacquire((LPDIRECTINPUTDEVICE8A)current_lock);
358     }
359     current_lock = This;
360
361     set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback);
362
363     return DI_OK;
364 }
365
366 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
367 {
368     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
369     HRESULT res;
370
371     TRACE("(this=%p)\n",This);
372
373     if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
374
375     set_dinput_hook(WH_KEYBOARD_LL, NULL);
376
377     /* No more locks */
378     if (current_lock == This)
379         current_lock = NULL;
380     else
381         ERR("this != current_lock\n");
382
383     return DI_OK;
384 }
385
386 /******************************************************************************
387   *     GetCapabilities : get the device capablitites
388   */
389 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
390         LPDIRECTINPUTDEVICE8A iface,
391         LPDIDEVCAPS lpDIDevCaps)
392 {
393     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
394     DIDEVCAPS devcaps;
395
396     TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
397
398     if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
399         WARN("invalid parameter\n");
400         return DIERR_INVALIDPARAM;
401     }
402     
403     devcaps.dwSize = lpDIDevCaps->dwSize;
404     devcaps.dwFlags = DIDC_ATTACHED;
405     if (This->dinput->dwVersion >= 0x0800)
406         devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
407     else
408         devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
409     devcaps.dwAxes = 0;
410     devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS;
411     devcaps.dwPOVs = 0;
412     devcaps.dwFFSamplePeriod = 0;
413     devcaps.dwFFMinTimeResolution = 0;
414     devcaps.dwFirmwareRevision = 100;
415     devcaps.dwHardwareRevision = 100;
416     devcaps.dwFFDriverVersion = 0;
417
418     memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
419     
420     return DI_OK;
421 }
422
423 /******************************************************************************
424   *     GetObjectInfo : get information about a device object such as a button
425   *                     or axis
426   */
427 static HRESULT WINAPI
428 SysKeyboardAImpl_GetObjectInfo(
429         LPDIRECTINPUTDEVICE8A iface,
430         LPDIDEVICEOBJECTINSTANCEA pdidoi,
431         DWORD dwObj,
432         DWORD dwHow)
433 {
434     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
435     DIDEVICEOBJECTINSTANCEA ddoi;
436     DWORD dwSize = pdidoi->dwSize;
437     
438     TRACE("(this=%p,%p,%d,0x%08x)\n", This, pdidoi, dwObj, dwHow);
439
440     if (dwHow == DIPH_BYID) {
441         WARN(" querying by id not supported yet...\n");
442         return DI_OK;
443     }
444
445     memset(pdidoi, 0, dwSize);
446     memset(&ddoi, 0, sizeof(ddoi));
447
448     ddoi.dwSize = dwSize;
449     ddoi.guidType = GUID_Key;
450     ddoi.dwOfs = dwObj;
451     ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
452     GetKeyNameTextA(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
453
454     /* And return our just filled device object instance structure */
455     memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
456     
457     _dump_OBJECTINSTANCEA(pdidoi);
458
459     return DI_OK;
460 }
461
462 static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
463                                                      LPDIDEVICEOBJECTINSTANCEW pdidoi,
464                                                      DWORD dwObj,
465                                                      DWORD dwHow)
466 {
467     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
468     DIDEVICEOBJECTINSTANCEW ddoi;
469     DWORD dwSize = pdidoi->dwSize;
470     
471     TRACE("(this=%p,%p,%d,0x%08x)\n", This, pdidoi, dwObj, dwHow);
472
473     if (dwHow == DIPH_BYID) {
474         WARN(" querying by id not supported yet...\n");
475         return DI_OK;
476     }
477
478     memset(pdidoi, 0, dwSize);
479     memset(&ddoi, 0, sizeof(ddoi));
480
481     ddoi.dwSize = dwSize;
482     ddoi.guidType = GUID_Key;
483     ddoi.dwOfs = dwObj;
484     ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
485     GetKeyNameTextW(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName));
486
487     /* And return our just filled device object instance structure */
488     memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
489     
490     _dump_OBJECTINSTANCEW(pdidoi);
491
492     return DI_OK;
493 }
494
495 /******************************************************************************
496   *     GetDeviceInfo : get information about a device's identity
497   */
498 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
499         LPDIRECTINPUTDEVICE8A iface,
500         LPDIDEVICEINSTANCEA pdidi)
501 {
502     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
503     TRACE("(this=%p,%p)\n", This, pdidi);
504
505     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
506         WARN(" dinput3 not supported yet...\n");
507         return DI_OK;
508     }
509
510     fill_keyboard_dideviceinstanceA(pdidi, This->dinput->dwVersion);
511     
512     return DI_OK;
513 }
514
515 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) 
516 {
517     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
518     TRACE("(this=%p,%p)\n", This, pdidi);
519
520     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
521         WARN(" dinput3 not supported yet...\n");
522         return DI_OK;
523     }
524
525     fill_keyboard_dideviceinstanceW(pdidi, This->dinput->dwVersion);
526     
527     return DI_OK;
528 }
529
530 static HRESULT WINAPI SysKeyboardAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
531 {
532     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
533
534     TRACE("(%p)\n",This);
535
536     if (!This->base.acquired) return DIERR_NOTACQUIRED;
537
538     MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
539     return DI_OK;
540 }
541
542 static const IDirectInputDevice8AVtbl SysKeyboardAvt =
543 {
544         IDirectInputDevice2AImpl_QueryInterface,
545         IDirectInputDevice2AImpl_AddRef,
546         SysKeyboardAImpl_Release,
547         SysKeyboardAImpl_GetCapabilities,
548         SysKeyboardAImpl_EnumObjects,
549         IDirectInputDevice2AImpl_GetProperty,
550         IDirectInputDevice2AImpl_SetProperty,
551         SysKeyboardAImpl_Acquire,
552         SysKeyboardAImpl_Unacquire,
553         SysKeyboardAImpl_GetDeviceState,
554         IDirectInputDevice2AImpl_GetDeviceData,
555         IDirectInputDevice2AImpl_SetDataFormat,
556         IDirectInputDevice2AImpl_SetEventNotification,
557         IDirectInputDevice2AImpl_SetCooperativeLevel,
558         SysKeyboardAImpl_GetObjectInfo,
559         SysKeyboardAImpl_GetDeviceInfo,
560         IDirectInputDevice2AImpl_RunControlPanel,
561         IDirectInputDevice2AImpl_Initialize,
562         IDirectInputDevice2AImpl_CreateEffect,
563         IDirectInputDevice2AImpl_EnumEffects,
564         IDirectInputDevice2AImpl_GetEffectInfo,
565         IDirectInputDevice2AImpl_GetForceFeedbackState,
566         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
567         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
568         IDirectInputDevice2AImpl_Escape,
569         SysKeyboardAImpl_Poll,
570         IDirectInputDevice2AImpl_SendDeviceData,
571         IDirectInputDevice7AImpl_EnumEffectsInFile,
572         IDirectInputDevice7AImpl_WriteEffectToFile,
573         IDirectInputDevice8AImpl_BuildActionMap,
574         IDirectInputDevice8AImpl_SetActionMap,
575         IDirectInputDevice8AImpl_GetImageInfo
576 };
577
578 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
579 # define XCAST(fun)     (typeof(SysKeyboardWvt.fun))
580 #else
581 # define XCAST(fun)     (void*)
582 #endif
583
584 static const IDirectInputDevice8WVtbl SysKeyboardWvt =
585 {
586         IDirectInputDevice2WImpl_QueryInterface,
587         XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
588         XCAST(Release)SysKeyboardAImpl_Release,
589         XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities,
590         SysKeyboardWImpl_EnumObjects,
591         XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty,
592         XCAST(SetProperty)IDirectInputDevice2AImpl_SetProperty,
593         XCAST(Acquire)SysKeyboardAImpl_Acquire,
594         XCAST(Unacquire)SysKeyboardAImpl_Unacquire,
595         XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState,
596         XCAST(GetDeviceData)IDirectInputDevice2AImpl_GetDeviceData,
597         XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
598         XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
599         XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
600         SysKeyboardWImpl_GetObjectInfo,
601         SysKeyboardWImpl_GetDeviceInfo,
602         XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
603         XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
604         XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
605         IDirectInputDevice2WImpl_EnumEffects,
606         IDirectInputDevice2WImpl_GetEffectInfo,
607         XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
608         XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
609         XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
610         XCAST(Escape)IDirectInputDevice2AImpl_Escape,
611         XCAST(Poll)SysKeyboardAImpl_Poll,
612         XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
613         IDirectInputDevice7WImpl_EnumEffectsInFile,
614         IDirectInputDevice7WImpl_WriteEffectToFile,
615         IDirectInputDevice8WImpl_BuildActionMap,
616         IDirectInputDevice8WImpl_SetActionMap,
617         IDirectInputDevice8WImpl_GetImageInfo
618 };
619 #undef XCAST