Remove included color.h.
[wine] / windows / dinput.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  *
5  * Additions (mouse support) Copyright 1998 Lionel Ulmer
6  */
7 /* Status:
8  *
9  * - Tomb Raider 2 Demo:
10  *   Playable using keyboard only.
11  * - WingCommander Prophecy Demo:
12  *   Doesn't get Input Focus.
13  * 
14  * - Fallout : works great in X and DGA mode
15  *
16  * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
17  *        (The current implementation is currently only a proof of concept and
18  *         an utter mess.)
19  */
20
21 #include "config.h"
22 #include <string.h>
23 #include <unistd.h>
24 #include <assert.h>
25 #include <X11/Xlib.h>
26 #include <sys/signal.h>
27
28 #include "windows.h"
29 #include "winerror.h"
30 #include "shell.h"
31 #include "ole.h"
32 #include "compobj.h"
33 #include "interfaces.h"
34 #include "gdi.h"
35 #include "heap.h"
36 #include "win.h"
37 #include "dinput.h"
38 #include "debug.h"
39 #include "message.h"
40
41 extern BYTE InputKeyStateTable[256];
42 extern int min_keycode, max_keycode;
43 extern WORD keyc2vkey[256];
44
45 static IDirectInputA_VTable ddiavt;
46 static IDirectInputDeviceA_VTable SysKeyboardAvt;
47 static IDirectInputDeviceA_VTable SysMouseAvt;
48
49 /* UIDs for Wine "drivers".
50    When enumerating each device supporting DInput, they have two UIDs :
51     - the 'windows' UID
52     - a vendor UID */
53 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
54   0x9e573ed8,
55   0x7734,
56   0x11d2,
57   {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
58 };
59 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
60   0x0ab8648a,
61   0x7735,
62   0x11d2,
63   {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
64 };
65
66 /******************************************************************************
67  *      DirectInputCreate32A
68  */
69 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUT32A *ppDI, LPUNKNOWN punkOuter) {
70         TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
71                 (DWORD)hinst,dwVersion,ppDI,punkOuter
72         );
73         (*ppDI) = (LPDIRECTINPUT32A)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInput32A));
74         (*ppDI)->ref = 1;
75         (*ppDI)->lpvtbl = &ddiavt;
76         return 0;
77 }
78 /******************************************************************************
79  *      IDirectInputA_EnumDevices
80  */
81 static HRESULT WINAPI IDirectInputA_EnumDevices(
82         LPDIRECTINPUT32A this, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
83         LPVOID pvRef, DWORD dwFlags
84 ) {
85   DIDEVICEINSTANCE32A devInstance;
86   int ret;
87
88   TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", this, dwDevType, lpCallback, pvRef, dwFlags);
89
90   devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
91   
92   if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
93   /* Return keyboard */
94     devInstance.guidInstance = GUID_SysKeyboard;         /* DInput's GUID */
95     devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
96     devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
97   strcpy(devInstance.tszInstanceName, "Keyboard");
98   strcpy(devInstance.tszProductName, "Wine Keyboard");
99   
100   ret = lpCallback(&devInstance, pvRef);
101     TRACE(dinput, "Keyboard registered\n");
102   
103     if (ret == DIENUM_STOP)
104     return 0;
105   }
106   
107   if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
108   /* Return mouse */
109     devInstance.guidInstance = GUID_SysMouse;         /* DInput's GUID */
110     devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
111     devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
112   strcpy(devInstance.tszInstanceName, "Mouse");
113   strcpy(devInstance.tszProductName, "Wine Mouse");
114   
115   ret = lpCallback(&devInstance, pvRef);
116     TRACE(dinput, "Mouse registered\n");
117   }
118
119   /* Should also do joystick enumerations.... */
120   
121         return 0;
122 }
123
124 static ULONG WINAPI IDirectInputA_AddRef(LPDIRECTINPUT32A this) {
125         return ++(this->ref);
126 }
127
128 static ULONG WINAPI IDirectInputA_Release(LPDIRECTINPUT32A this) {
129         if (!(--this->ref)) {
130                 HeapFree(GetProcessHeap(),0,this);
131                 return 0;
132         }
133         return this->ref;
134 }
135
136 static HRESULT WINAPI IDirectInputA_CreateDevice(
137         LPDIRECTINPUT32A this,REFGUID rguid,LPDIRECTINPUTDEVICE32A* pdev,
138         LPUNKNOWN punk
139 ) {
140         char    xbuf[50];
141         
142         WINE_StringFromCLSID(rguid,xbuf);
143         FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",this,xbuf,pdev,punk);
144         if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) ||          /* Generic Keyboard */
145             (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
146                 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboard32A));
147                 (*pdev)->ref = 1;
148                 (*pdev)->lpvtbl = &SysKeyboardAvt;
149                 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
150                 memset(((LPSYSKEYBOARD32A)(*pdev))->keystate,0,256);
151                 return 0;
152         }
153         if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) ||             /* Generic Mouse */
154             (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Mouse */
155                 *pdev = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouse32A));
156                 (*pdev)->ref = 1;
157                 (*pdev)->lpvtbl = &SysMouseAvt;
158                 memcpy(&((*pdev)->guid),rguid,sizeof(*rguid));
159                 return 0;
160         }
161         return E_FAIL;
162 }
163
164 static HRESULT WINAPI IDirectInputA_QueryInterface(
165         LPDIRECTINPUT32A this,REFIID riid,LPVOID *ppobj
166 ) {
167         char    xbuf[50];
168
169         WINE_StringFromCLSID(riid,xbuf);
170         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
171         if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
172                 this->lpvtbl->fnAddRef(this);
173                 *ppobj = this;
174                 return 0;
175         }
176         if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
177                 this->lpvtbl->fnAddRef(this);
178                 *ppobj = this;
179                 return 0;
180         }
181         return E_FAIL;
182 }
183
184 static HRESULT WINAPI IDirectInputA_Initialize(
185         LPDIRECTINPUT32A this,HINSTANCE32 hinst,DWORD x
186 ) {
187         return DIERR_ALREADYINITIALIZED;
188 }
189
190 static IDirectInputA_VTable ddiavt= {
191         IDirectInputA_QueryInterface,
192         IDirectInputA_AddRef,
193         IDirectInputA_Release,
194         IDirectInputA_CreateDevice,
195         IDirectInputA_EnumDevices,
196         (void*)6,
197         (void*)7,
198         IDirectInputA_Initialize
199 };
200
201 /******************************************************************************
202  *      IDirectInputDeviceA
203  */
204 static HRESULT WINAPI IDirectInputDeviceA_SetDataFormat(
205         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
206 ) {
207         /*
208         int i;
209         TRACE(dinput,"(this=%p,%p)\n",this,df);
210
211         TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
212         TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
213         TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
214         TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
215         TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
216
217         for (i=0;i<df->dwNumObjs;i++) {
218                 char    xbuf[50];
219
220                 if (df->rgodf[i].pguid)
221                         WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
222                 else
223                         strcpy(xbuf,"<no guid>");
224                 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
225                 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
226                 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
227                 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
228         }
229         */
230         return 0;
231 }
232
233 static HRESULT WINAPI IDirectInputDeviceA_SetCooperativeLevel(
234         LPDIRECTINPUTDEVICE32A this,HWND32 hwnd,DWORD dwflags
235 ) {
236         FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",this,(DWORD)hwnd,dwflags);
237         return 0;
238 }
239
240 static HRESULT WINAPI IDirectInputDeviceA_SetProperty(
241         LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
242 ) {
243         char    xbuf[50];
244
245         if (HIWORD(rguid))
246                 WINE_StringFromCLSID(rguid,xbuf);
247         else
248                 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
249         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
250         if (!HIWORD(rguid)) {
251                 switch ((DWORD)rguid) {
252                 case DIPROP_BUFFERSIZE: {
253                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
254
255                         TRACE(dinput,"buffersize = %ld\n",pd->dwData);
256                         break;
257                 }
258                 default:
259                         WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
260                         break;
261                 }
262         }
263         return 0;
264 }
265
266 static HRESULT WINAPI IDirectInputDeviceA_SetEventNotification(
267         LPDIRECTINPUTDEVICE32A this,HANDLE32 hnd
268 ) {
269         FIXME(dinput,"(this=%p,0x%08lx): stub\n",this,(DWORD)hnd);
270         return 0;
271 }
272
273 static HRESULT WINAPI IDirectInputDeviceA_GetDeviceData(
274         LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
275         LPDWORD entries,DWORD flags
276 ) {
277   TRACE(dinput,"IDirectInputDeviceA(%p)->GetDeviceData(%ld,%p,%p(0x%08lx),0x%08lx)\n",
278         this,dodsize,dod,entries,*entries,flags);
279         return 0;
280 }
281
282
283 static HRESULT WINAPI IDirectInputDeviceA_Acquire(LPDIRECTINPUTDEVICE32A this) {
284         TRACE(dinput,"(this=%p): stub\n",this);
285         return 0;
286 }
287
288 static HRESULT WINAPI IDirectInputDeviceA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
289         TRACE(dinput,"(this=%p): stub\n",this);
290         return 0;
291 }
292
293 static ULONG WINAPI IDirectInputDeviceA_Release(LPDIRECTINPUTDEVICE32A this) {
294         this->ref--;
295         if (this->ref)
296                 return this->ref;
297         HeapFree(GetProcessHeap(),0,this);
298         return 0;
299 }
300
301 static HRESULT WINAPI SysKeyboardA_SetProperty(
302         LPDIRECTINPUTDEVICE32A this,REFGUID rguid,LPCDIPROPHEADER ph
303 ) {
304         char                    xbuf[50];
305
306         if (HIWORD(rguid))
307                 WINE_StringFromCLSID(rguid,xbuf);
308         else
309                 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
310         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ph);
311         TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
312             ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
313         if (!HIWORD(rguid)) {
314                 switch ((DWORD)rguid) {
315                 case DIPROP_BUFFERSIZE: {
316                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
317
318                         TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
319                         break;
320                 }
321                 default:
322                         WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
323                         break;
324                 }
325         }
326         return 0;
327 }
328
329 static HRESULT WINAPI SysKeyboardA_GetDeviceState(
330         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
331 ) {
332         if (len==256) {
333                 int keyc,vkey;
334
335                 memset(ptr,0,256);
336                 for (keyc=min_keycode;keyc<max_keycode;keyc++)
337                 {
338                     /* X keycode to virtual key */
339                     vkey = keyc2vkey[keyc] & 0xFF;
340                     /* The windows scancode is keyc-min_keycode */
341                     if (InputKeyStateTable[vkey]&0x80) {
342                         ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
343                         ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
344                     }
345                 }
346                 return 0;
347         }
348         WARN(dinput,"whoops, SysKeyboardA_GetDeviceState got len %ld?\n",len);
349         return 0;
350 }
351
352 static HRESULT WINAPI SysKeyboardA_GetDeviceData(
353         LPDIRECTINPUTDEVICE32A this,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
354         LPDWORD entries,DWORD flags
355 ) {
356         int                     keyc,n,vkey,xentries;
357         LPSYSKEYBOARD32A        kthis = (LPSYSKEYBOARD32A)this;
358
359         TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
360                 this,dodsize,dod,entries,entries?*entries:0,flags);
361         EVENT_WaitNetEvent(FALSE,TRUE);
362         if (entries)
363                 xentries = *entries; 
364         else
365                 xentries = 1;
366
367         n = 0;
368
369         for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
370         {
371                     /* X keycode to virtual key */
372                     vkey = keyc2vkey[keyc] & 0xFF;
373                     if (kthis->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
374                         continue;
375                 if (dod) {
376                         /* add an entry */
377                         dod[n].dwOfs            = keyc-min_keycode; /* scancode */
378                         dod[n].dwData           = InputKeyStateTable[vkey]&0x80;
379                         dod[n].dwTimeStamp      = 0; /* umm */
380                         dod[n].dwSequence       = 0; /* umm */
381                         n++;
382                 }
383                 if (!(flags & DIGDD_PEEK))
384                         kthis->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
385                     
386         }
387         
388         if (n) fprintf(stderr,"%d entries\n",n);
389         *entries = n;
390         return 0;
391 }
392
393 static HRESULT WINAPI SysKeyboardA_Acquire(LPDIRECTINPUTDEVICE32A this) {
394         TRACE(dinput,"(this=%p): stub\n",this);
395         return 0;
396 }
397
398 static HRESULT WINAPI SysKeyboardA_Unacquire(LPDIRECTINPUTDEVICE32A this) {
399         TRACE(dinput,"(this=%p): stub\n",this);
400         return 0;
401 }
402
403 static HRESULT WINAPI IDirectInputDeviceA_QueryInterface(
404         LPDIRECTINPUTDEVICE32A this,REFIID riid,LPVOID *ppobj
405 ) {
406         char    xbuf[50];
407
408         WINE_StringFromCLSID(riid,xbuf);
409         TRACE(dinput,"(this=%p,%s,%p)\n",this,xbuf,ppobj);
410         if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
411                 this->lpvtbl->fnAddRef(this);
412                 *ppobj = this;
413                 return 0;
414         }
415         if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
416                 this->lpvtbl->fnAddRef(this);
417                 *ppobj = this;
418                 return 0;
419         }
420         return E_FAIL;
421 }
422
423 /******************************************************************************
424  *      SysMouseA (DInput Mouse support)
425  */
426
427 /******************************************************************************
428   *     SetDataFormat : the application can choose the format of the data
429   *   the device driver sends back with GetDeviceState.
430   *
431   *   For the moment, only the "standard" configuration (c_dfDIMouse) is supported
432   *   in absolute and relative mode.
433   */
434 static HRESULT WINAPI SysMouseA_SetDataFormat(
435         LPDIRECTINPUTDEVICE32A this,LPCDIDATAFORMAT df
436 ) {
437   int i;
438   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
439   
440   TRACE(dinput,"(this=%p,%p)\n",this,df);
441
442   TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
443   TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
444   TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
445   TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
446   TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
447
448   for (i=0;i<df->dwNumObjs;i++) {
449     char        xbuf[50];
450     
451     if (df->rgodf[i].pguid)
452       WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
453     else
454       strcpy(xbuf,"<no guid>");
455     TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
456     TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
457     TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
458     TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
459   }
460
461   /* Check size of data format to prevent crashes if the applications
462      sends a smaller buffer */
463   if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
464     FIXME(dinput, "non-standard mouse configuration not supported yet.");
465     return DIERR_INVALIDPARAM;
466   }
467   
468   /* For the moment, ignore these fields and return always as if
469      c_dfDIMouse was passed as format... */
470   if (df->dwFlags == DIDF_ABSAXIS)
471     mthis->absolute = 1;
472   else {
473     Window rw, cr;
474     int rx, ry, cx, cy;
475     unsigned int mask;
476     
477     /* We need to get the initial "previous" position to be able
478        to return deltas */
479     mthis->absolute = 0;
480   
481     /* Get the mouse position */
482     TSXQueryPointer(display, rootWindow, &rw, &cr,
483                     &rx, &ry, &cx, &cy, &mask);
484     /* Fill the initial mouse state structure */
485     mthis->prevX = rx;
486     mthis->prevY = ry;
487   }
488   
489   return 0;
490 }
491
492 /******************************************************************************
493   *     GetDeviceState : returns the "state" of the mouse.
494   *
495   *   For the moment, only the "standard" return structure (DIMOUSESTATE) is
496   *   supported.
497   */
498 static HRESULT WINAPI SysMouseA_GetDeviceState(
499         LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr
500 ) {
501   Window rw, cr;
502   int rx, ry, cx, cy;
503   unsigned int mask;
504   struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
505   LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this;
506   
507   TRACE(dinput,"(this=%p,0x%08lx,%p): \n",this,len,ptr);
508   
509   /* Check if the buffer is big enough */
510   if (len < sizeof(struct DIMOUSESTATE)) {
511     FIXME(dinput, "unsupported state structure.");
512     return DIERR_INVALIDPARAM;
513   }
514   
515   /* Get the mouse position */
516   TSXQueryPointer(display, rootWindow, &rw, &cr,
517                   &rx, &ry, &cx, &cy, &mask);
518   TRACE(dinput,"(X:%d - Y:%d)\n", rx, ry);
519
520   /* Fill the mouse state structure */
521   if (mthis->absolute) {
522     mstate->lX = rx;
523     mstate->lY = ry;
524   } else {
525     mstate->lX = rx - mthis->prevX;
526     mstate->lY = ry - mthis->prevY;
527     /* Fill the previous positions */
528     mthis->prevX = rx;
529     mthis->prevY = ry;
530   }
531   mstate->lZ = 0;
532   mstate->rgbButtons[0] = (mask & Button1Mask ? 0xFF : 0x00);
533   mstate->rgbButtons[1] = (mask & Button3Mask ? 0xFF : 0x00); /* Windows button two is X button 3 */
534   mstate->rgbButtons[2] = (mask & Button2Mask ? 0xFF : 0x00);
535   mstate->rgbButtons[3] = (mask & Button4Mask ? 0xFF : 0x00);
536   
537   return 0;
538 }
539
540
541
542 static IDirectInputDeviceA_VTable SysKeyboardAvt={
543         IDirectInputDeviceA_QueryInterface,
544         (void*)2,
545         IDirectInputDeviceA_Release,
546         (void*)4,
547         (void*)5,
548         (void*)6,
549         SysKeyboardA_SetProperty,
550         SysKeyboardA_Acquire,
551         SysKeyboardA_Unacquire,
552         SysKeyboardA_GetDeviceState,
553         SysKeyboardA_GetDeviceData,
554         IDirectInputDeviceA_SetDataFormat,
555         IDirectInputDeviceA_SetEventNotification,
556         IDirectInputDeviceA_SetCooperativeLevel,
557         (void*)15,
558         (void*)16,
559         (void*)17,
560         (void*)18,
561 };
562
563 static IDirectInputDeviceA_VTable SysMouseAvt={
564         IDirectInputDeviceA_QueryInterface,
565         (void*)2,
566         IDirectInputDeviceA_Release,
567         (void*)4,
568         (void*)5,
569         (void*)6,
570         IDirectInputDeviceA_SetProperty,
571         IDirectInputDeviceA_Acquire,
572         IDirectInputDeviceA_Unacquire,
573         SysMouseA_GetDeviceState,
574         IDirectInputDeviceA_GetDeviceData,
575         SysMouseA_SetDataFormat,
576         IDirectInputDeviceA_SetEventNotification,
577         IDirectInputDeviceA_SetCooperativeLevel,
578         (void*)15,
579         (void*)16,
580         (void*)17,
581         (void*)18,
582 };