wininet: Use proc instead of enum in FTPFINDNEXTW request.
[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     newDevice->base.data_format.wine_df = &c_dfDIKeyboard;
200     if (create_DataFormat(&c_dfDIKeyboard, &newDevice->base.data_format) == DI_OK)
201     {
202         IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput);
203         return newDevice;
204     }
205
206     HeapFree(GetProcessHeap(), 0, newDevice);
207     return NULL;
208 }
209
210
211 static HRESULT keyboarddev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev)
212 {
213   if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
214       (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
215     if ((riid == NULL) ||
216         IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
217         IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
218         IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
219         IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
220       *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
221       TRACE("Creating a Keyboard device (%p)\n", *pdev);
222       if (!*pdev) return DIERR_OUTOFMEMORY;
223       return DI_OK;
224     } else
225       return DIERR_NOINTERFACE;
226   }
227   return DIERR_DEVICENOTREG;
228 }
229
230 static HRESULT keyboarddev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev)
231 {
232   if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
233       (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
234     if ((riid == NULL) ||
235         IsEqualGUID(&IID_IDirectInputDeviceW,riid) ||
236         IsEqualGUID(&IID_IDirectInputDevice2W,riid) ||
237         IsEqualGUID(&IID_IDirectInputDevice7W,riid) ||
238         IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
239       *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysKeyboardWvt, dinput);
240       TRACE("Creating a Keyboard device (%p)\n", *pdev);
241       if (!*pdev) return DIERR_OUTOFMEMORY;
242       return DI_OK;
243     } else
244       return DIERR_NOINTERFACE;
245   }
246   return DIERR_DEVICENOTREG;
247 }
248
249 const struct dinput_device keyboard_device = {
250   "Wine keyboard driver",
251   keyboarddev_enum_deviceA,
252   keyboarddev_enum_deviceW,
253   keyboarddev_create_deviceA,
254   keyboarddev_create_deviceW
255 };
256
257 static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
258 {
259     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
260     ULONG ref;
261
262     ref = InterlockedDecrement(&This->base.ref);
263     if (ref) return ref;
264
265     set_dinput_hook(WH_KEYBOARD_LL, NULL);
266
267     HeapFree(GetProcessHeap(), 0, This->base.data_queue);
268     IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput);
269     DeleteCriticalSection(&This->base.crit);
270     HeapFree(GetProcessHeap(), 0, This);
271
272     return DI_OK;
273 }
274
275 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
276         LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
277 )
278 {
279     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
280     TRACE("(%p)->(%d,%p)\n", This, len, ptr);
281
282     if (!This->base.acquired) return DIERR_NOTACQUIRED;
283
284     if (len != WINE_DINPUT_KEYBOARD_MAX_KEYS)
285       return DIERR_INVALIDPARAM;
286
287     MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
288
289     EnterCriticalSection(&This->base.crit);
290
291     if (TRACE_ON(dinput)) {
292         int i;
293         for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
294             if (DInputKeyState[i] != 0x00) {
295                 TRACE(" - %02X: %02x\n", i, DInputKeyState[i]);
296             }
297         }
298     }
299     
300     memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS);
301     LeaveCriticalSection(&This->base.crit);
302
303     return DI_OK;
304 }
305
306 static HRESULT WINAPI SysKeyboardAImpl_EnumObjects(
307         LPDIRECTINPUTDEVICE8A iface,
308         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
309         LPVOID lpvRef,
310         DWORD dwFlags)
311 {
312     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
313     DIDEVICEOBJECTINSTANCEA ddoi;
314     int i;
315     
316     TRACE("(this=%p,%p,%p,%08x)\n", This, lpCallback, lpvRef, dwFlags);
317     if (TRACE_ON(dinput)) {
318         TRACE("  - flags = ");
319         _dump_EnumObjects_flags(dwFlags);
320         TRACE("\n");
321     }
322
323     /* Only the fields till dwFFMaxForce are relevant */
324     memset(&ddoi, 0, sizeof(ddoi));
325     ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
326
327     for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
328     {
329         if (!GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)))
330             continue;
331         ddoi.guidType = GUID_Key;
332         ddoi.dwOfs = i;
333         ddoi.dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_BUTTON;
334         _dump_OBJECTINSTANCEA(&ddoi);
335         if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
336     }
337     
338     return DI_OK;
339 }
340
341 static HRESULT WINAPI SysKeyboardWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
342                                                    LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
343                                                    LPVOID lpvRef,
344                                                    DWORD dwFlags)
345 {
346   SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
347
348   device_enumobjects_AtoWcb_data data;
349
350   data.lpCallBack = lpCallback;
351   data.lpvRef = lpvRef;
352
353   return SysKeyboardAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags);
354 }
355
356 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
357
358 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
359 {
360     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
361     HRESULT res;
362
363     TRACE("(%p)\n",This);
364
365     if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res;
366
367     if (current_lock != NULL) {
368         FIXME("Not more than one keyboard can be acquired at the same time.\n");
369         SysKeyboardAImpl_Unacquire((LPDIRECTINPUTDEVICE8A)current_lock);
370     }
371     current_lock = This;
372
373     set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback);
374
375     return DI_OK;
376 }
377
378 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
379 {
380     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
381     HRESULT res;
382
383     TRACE("(this=%p)\n",This);
384
385     if ((res = IDirectInputDevice2AImpl_Unacquire(iface)) != DI_OK) return res;
386
387     set_dinput_hook(WH_KEYBOARD_LL, NULL);
388
389     /* No more locks */
390     if (current_lock == This)
391         current_lock = NULL;
392     else
393         ERR("this != current_lock\n");
394
395     return DI_OK;
396 }
397
398 /******************************************************************************
399   *     GetCapabilities : get the device capablitites
400   */
401 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
402         LPDIRECTINPUTDEVICE8A iface,
403         LPDIDEVCAPS lpDIDevCaps)
404 {
405     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
406     DIDEVCAPS devcaps;
407
408     TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
409
410     if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
411         WARN("invalid parameter\n");
412         return DIERR_INVALIDPARAM;
413     }
414     
415     devcaps.dwSize = lpDIDevCaps->dwSize;
416     devcaps.dwFlags = DIDC_ATTACHED;
417     if (This->dinput->dwVersion >= 0x0800)
418         devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
419     else
420         devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
421     devcaps.dwAxes = 0;
422     devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS;
423     devcaps.dwPOVs = 0;
424     devcaps.dwFFSamplePeriod = 0;
425     devcaps.dwFFMinTimeResolution = 0;
426     devcaps.dwFirmwareRevision = 100;
427     devcaps.dwHardwareRevision = 100;
428     devcaps.dwFFDriverVersion = 0;
429
430     memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
431     
432     return DI_OK;
433 }
434
435 /******************************************************************************
436   *     GetObjectInfo : get information about a device object such as a button
437   *                     or axis
438   */
439 static HRESULT WINAPI
440 SysKeyboardAImpl_GetObjectInfo(
441         LPDIRECTINPUTDEVICE8A iface,
442         LPDIDEVICEOBJECTINSTANCEA pdidoi,
443         DWORD dwObj,
444         DWORD dwHow)
445 {
446     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
447     DIDEVICEOBJECTINSTANCEA ddoi;
448     DWORD dwSize = pdidoi->dwSize;
449     
450     TRACE("(this=%p,%p,%d,0x%08x)\n", This, pdidoi, dwObj, dwHow);
451
452     if (dwHow == DIPH_BYID) {
453         WARN(" querying by id not supported yet...\n");
454         return DI_OK;
455     }
456
457     memset(pdidoi, 0, dwSize);
458     memset(&ddoi, 0, sizeof(ddoi));
459
460     ddoi.dwSize = dwSize;
461     ddoi.guidType = GUID_Key;
462     ddoi.dwOfs = dwObj;
463     ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
464     if (!GetKeyNameTextA(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)))
465         return DIERR_OBJECTNOTFOUND;
466
467     /* And return our just filled device object instance structure */
468     memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
469     
470     _dump_OBJECTINSTANCEA(pdidoi);
471
472     return DI_OK;
473 }
474
475 static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
476                                                      LPDIDEVICEOBJECTINSTANCEW pdidoi,
477                                                      DWORD dwObj,
478                                                      DWORD dwHow)
479 {
480     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
481     DIDEVICEOBJECTINSTANCEW ddoi;
482     DWORD dwSize = pdidoi->dwSize;
483     
484     TRACE("(this=%p,%p,%d,0x%08x)\n", This, pdidoi, dwObj, dwHow);
485
486     if (dwHow == DIPH_BYID) {
487         WARN(" querying by id not supported yet...\n");
488         return DI_OK;
489     }
490
491     memset(pdidoi, 0, dwSize);
492     memset(&ddoi, 0, sizeof(ddoi));
493
494     ddoi.dwSize = dwSize;
495     ddoi.guidType = GUID_Key;
496     ddoi.dwOfs = dwObj;
497     ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON;
498     if (!GetKeyNameTextW(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)))
499         return DIERR_OBJECTNOTFOUND;
500
501     /* And return our just filled device object instance structure */
502     memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi)));
503     
504     _dump_OBJECTINSTANCEW(pdidoi);
505
506     return DI_OK;
507 }
508
509 /******************************************************************************
510   *     GetDeviceInfo : get information about a device's identity
511   */
512 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
513         LPDIRECTINPUTDEVICE8A iface,
514         LPDIDEVICEINSTANCEA pdidi)
515 {
516     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
517     TRACE("(this=%p,%p)\n", This, pdidi);
518
519     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
520         WARN(" dinput3 not supported yet...\n");
521         return DI_OK;
522     }
523
524     fill_keyboard_dideviceinstanceA(pdidi, This->dinput->dwVersion);
525     
526     return DI_OK;
527 }
528
529 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) 
530 {
531     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
532     TRACE("(this=%p,%p)\n", This, pdidi);
533
534     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
535         WARN(" dinput3 not supported yet...\n");
536         return DI_OK;
537     }
538
539     fill_keyboard_dideviceinstanceW(pdidi, This->dinput->dwVersion);
540     
541     return DI_OK;
542 }
543
544 static HRESULT WINAPI SysKeyboardAImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
545 {
546     SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
547
548     TRACE("(%p)\n",This);
549
550     if (!This->base.acquired) return DIERR_NOTACQUIRED;
551
552     MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
553     return DI_OK;
554 }
555
556 static const IDirectInputDevice8AVtbl SysKeyboardAvt =
557 {
558         IDirectInputDevice2AImpl_QueryInterface,
559         IDirectInputDevice2AImpl_AddRef,
560         SysKeyboardAImpl_Release,
561         SysKeyboardAImpl_GetCapabilities,
562         SysKeyboardAImpl_EnumObjects,
563         IDirectInputDevice2AImpl_GetProperty,
564         IDirectInputDevice2AImpl_SetProperty,
565         SysKeyboardAImpl_Acquire,
566         SysKeyboardAImpl_Unacquire,
567         SysKeyboardAImpl_GetDeviceState,
568         IDirectInputDevice2AImpl_GetDeviceData,
569         IDirectInputDevice2AImpl_SetDataFormat,
570         IDirectInputDevice2AImpl_SetEventNotification,
571         IDirectInputDevice2AImpl_SetCooperativeLevel,
572         SysKeyboardAImpl_GetObjectInfo,
573         SysKeyboardAImpl_GetDeviceInfo,
574         IDirectInputDevice2AImpl_RunControlPanel,
575         IDirectInputDevice2AImpl_Initialize,
576         IDirectInputDevice2AImpl_CreateEffect,
577         IDirectInputDevice2AImpl_EnumEffects,
578         IDirectInputDevice2AImpl_GetEffectInfo,
579         IDirectInputDevice2AImpl_GetForceFeedbackState,
580         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
581         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
582         IDirectInputDevice2AImpl_Escape,
583         SysKeyboardAImpl_Poll,
584         IDirectInputDevice2AImpl_SendDeviceData,
585         IDirectInputDevice7AImpl_EnumEffectsInFile,
586         IDirectInputDevice7AImpl_WriteEffectToFile,
587         IDirectInputDevice8AImpl_BuildActionMap,
588         IDirectInputDevice8AImpl_SetActionMap,
589         IDirectInputDevice8AImpl_GetImageInfo
590 };
591
592 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
593 # define XCAST(fun)     (typeof(SysKeyboardWvt.fun))
594 #else
595 # define XCAST(fun)     (void*)
596 #endif
597
598 static const IDirectInputDevice8WVtbl SysKeyboardWvt =
599 {
600         IDirectInputDevice2WImpl_QueryInterface,
601         XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
602         XCAST(Release)SysKeyboardAImpl_Release,
603         XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities,
604         SysKeyboardWImpl_EnumObjects,
605         XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty,
606         XCAST(SetProperty)IDirectInputDevice2AImpl_SetProperty,
607         XCAST(Acquire)SysKeyboardAImpl_Acquire,
608         XCAST(Unacquire)SysKeyboardAImpl_Unacquire,
609         XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState,
610         XCAST(GetDeviceData)IDirectInputDevice2AImpl_GetDeviceData,
611         XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
612         XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
613         XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
614         SysKeyboardWImpl_GetObjectInfo,
615         SysKeyboardWImpl_GetDeviceInfo,
616         XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
617         XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
618         XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
619         IDirectInputDevice2WImpl_EnumEffects,
620         IDirectInputDevice2WImpl_GetEffectInfo,
621         XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
622         XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
623         XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
624         XCAST(Escape)IDirectInputDevice2AImpl_Escape,
625         XCAST(Poll)SysKeyboardAImpl_Poll,
626         XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
627         IDirectInputDevice7WImpl_EnumEffectsInFile,
628         IDirectInputDevice7WImpl_WriteEffectToFile,
629         IDirectInputDevice8WImpl_BuildActionMap,
630         IDirectInputDevice8WImpl_SetActionMap,
631         IDirectInputDevice8WImpl_GetImageInfo
632 };
633 #undef XCAST