Removed some unnecessary #includes and dll dependencies.
[wine] / dlls / dinput / dinput_main.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  *
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 <stdio.h>
23 #include <string.h>
24 #include <time.h>
25 #include <unistd.h>
26 #include <assert.h>
27 #ifdef HAVE_SYS_SIGNAL_H
28 # include <sys/signal.h>
29 #endif
30 #include <sys/time.h>
31 #include <sys/fcntl.h>
32 #include <sys/ioctl.h>
33 #include <errno.h>
34 #ifdef HAVE_SYS_ERRNO_H
35 # include <sys/errno.h>
36 #endif
37 #ifdef HAVE_LINUX_JOYSTICK_H
38 # include <linux/joystick.h>
39 # define JOYDEV "/dev/js0"
40 #endif
41
42 #include "debugtools.h"
43 #include "input.h"
44 #include "user.h"
45 #include "mouse.h"
46 #include "winbase.h"
47 #include "winerror.h"
48 #include "windef.h"
49 #include "wingdi.h"
50 #include "winuser.h"
51
52 #include "initguid.h"
53 #include "dinput.h"
54
55 DEFAULT_DEBUG_CHANNEL(dinput);
56
57 /* Wine mouse driver object instances */
58 #define WINE_MOUSE_X_AXIS_INSTANCE 0x0001
59 #define WINE_MOUSE_Y_AXIS_INSTANCE 0x0002
60 #define WINE_MOUSE_L_BUTTON_INSTANCE 0x0004
61 #define WINE_MOUSE_R_BUTTON_INSTANCE 0x0008
62 #define WINE_MOUSE_M_BUTTON_INSTANCE 0x0010
63
64 /* Wine joystick driver object instances */
65 #define WINE_JOYSTICK_AXIS_BASE   0
66 #define WINE_JOYSTICK_BUTTON_BASE 8
67
68 extern BYTE InputKeyStateTable[256];
69 extern int min_keycode, max_keycode;
70 extern WORD keyc2vkey[256];
71
72 /* Routines to do DataFormat / WineFormat conversions */
73 typedef struct {
74   int size;
75   int offset_in;
76   int offset_out;
77   int value;
78 } DataTransform;
79
80 typedef struct {
81   int size;
82   int internal_format_size;
83   DataTransform *dt;
84 } DataFormat;
85
86 /* ------------------------------- */
87 /* Wine mouse internal data format */
88 /* ------------------------------- */
89
90 /* Constants used to access the offset array */
91 #define WINE_MOUSE_X_POSITION 0
92 #define WINE_MOUSE_Y_POSITION 1
93 #define WINE_MOUSE_L_POSITION 2
94 #define WINE_MOUSE_R_POSITION 3
95 #define WINE_MOUSE_M_POSITION 4
96
97 typedef struct {
98   LONG lX;
99   LONG lY;
100   BYTE rgbButtons[4];
101 } Wine_InternalMouseData;
102
103 #define WINE_INTERNALMOUSE_NUM_OBJS 5
104
105 static DIOBJECTDATAFORMAT Wine_InternalMouseObjectFormat[WINE_INTERNALMOUSE_NUM_OBJS] = {
106   { &GUID_XAxis,   FIELD_OFFSET(Wine_InternalMouseData, lX),
107       DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
108   { &GUID_YAxis,   FIELD_OFFSET(Wine_InternalMouseData, lY),
109       DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS, 0 },
110   { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 0,
111       DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
112   { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 1,
113       DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 },
114   { &GUID_Button, (FIELD_OFFSET(Wine_InternalMouseData, rgbButtons)) + 2,
115       DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON, 0 }
116 };
117
118 static DIDATAFORMAT Wine_InternalMouseFormat = {
119   0, /* dwSize - unused */
120   0, /* dwObjsize - unused */
121   0, /* dwFlags - unused */
122   sizeof(Wine_InternalMouseData),
123   WINE_INTERNALMOUSE_NUM_OBJS, /* dwNumObjs */
124   Wine_InternalMouseObjectFormat
125 };
126
127 static ICOM_VTABLE(IDirectInputA) ddiavt;
128 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
129 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
130
131 typedef struct IDirectInputAImpl IDirectInputAImpl;
132 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
133 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
134 typedef struct SysMouseAImpl SysMouseAImpl;
135
136 struct IDirectInputDevice2AImpl
137 {
138         ICOM_VFIELD(IDirectInputDevice2A);
139         DWORD                           ref;
140         GUID                            guid;
141 };
142
143 struct SysKeyboardAImpl
144 {
145         /* IDirectInputDevice2AImpl */
146         ICOM_VFIELD(IDirectInputDevice2A);
147         DWORD                           ref;
148         GUID                            guid;
149         /* SysKeyboardAImpl */
150         BYTE                            keystate[256];
151         KEYBOARD_CONFIG                 initial_config;
152         int                             acquired;
153 };
154
155 #ifdef HAVE_LINUX_22_JOYSTICK_API
156 typedef struct JoystickAImpl JoystickAImpl;
157 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt;
158 struct JoystickAImpl
159 {
160         /* IDirectInputDevice2AImpl */
161         ICOM_VFIELD(IDirectInputDevice2A);
162         DWORD                           ref;
163         GUID                            guid;
164
165         /* joystick private */
166         int                             joyfd;
167         LPDIDATAFORMAT                  df;
168         HANDLE                          hEvent;
169         LONG                            lMin,lMax,deadzone;
170         LPDIDEVICEOBJECTDATA            data_queue;
171         int                             queue_pos, queue_len;
172         DIJOYSTATE                      js;
173 };
174 #endif
175
176 typedef enum {
177   WARP_NEEDED,  /* Warping is needed */
178   WARP_STARTED, /* Warping has been done, waiting for the warp event */
179   WARP_DONE     /* Warping has been done */
180 } WARP_STATUS;
181
182 struct SysMouseAImpl
183 {
184         /* IDirectInputDevice2AImpl */
185         ICOM_VFIELD(IDirectInputDevice2A);
186         DWORD                           ref;
187         GUID                            guid;
188
189         /* The current data format and the conversion between internal
190            and external data formats */
191         LPDIDATAFORMAT                  df;
192         DataFormat                     *wine_df;
193         int                             offset_array[5];
194         
195         /* SysMouseAImpl */
196         BYTE                            absolute;
197         /* Previous position for relative moves */
198         LONG                            prevX, prevY;
199         LPMOUSE_EVENT_PROC              prev_handler;
200         HWND                            win;
201         DWORD                           win_centerX, win_centerY;
202         LPDIDEVICEOBJECTDATA            data_queue;
203         int                             queue_pos, queue_len;
204         WARP_STATUS                     need_warp;
205         int                             acquired;
206         HANDLE                          hEvent;
207         CRITICAL_SECTION                crit;
208
209         /* This is for mouse reporting. */
210         Wine_InternalMouseData          m_state;
211 };
212
213 static int evsequence=0;
214
215
216 /* UIDs for Wine "drivers".
217    When enumerating each device supporting DInput, they have two UIDs :
218     - the 'windows' UID
219     - a vendor UID */
220 #ifdef HAVE_LINUX_22_JOYSTICK_API
221 static GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
222   0x9e573ed9,
223   0x7734,
224   0x11d2,
225   {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
226 };
227 #endif
228 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
229   0x9e573ed8,
230   0x7734,
231   0x11d2,
232   {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
233 };
234 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
235   0x0ab8648a,
236   0x7735,
237   0x11d2,
238   {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
239 };
240
241 /* FIXME: This is ugly and not thread safe :/ */
242 static IDirectInputDevice2A* current_lock = NULL;
243
244 /******************************************************************************
245  *      Various debugging tools
246  */
247 static void _dump_cooperativelevel(DWORD dwFlags) {
248   int   i;
249   const struct {
250     DWORD       mask;
251     char        *name;
252   } flags[] = {
253 #define FE(x) { x, #x},
254     FE(DISCL_BACKGROUND)
255     FE(DISCL_EXCLUSIVE)
256     FE(DISCL_FOREGROUND)
257     FE(DISCL_NONEXCLUSIVE)
258 #undef FE
259   };
260   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
261     if (flags[i].mask & dwFlags)
262       DPRINTF("%s ",flags[i].name);
263   DPRINTF("\n");
264 }
265
266 static void _dump_EnumObjects_flags(DWORD dwFlags) {
267   int   i;
268   const struct {
269     DWORD       mask;
270     char        *name;
271   } flags[] = {
272 #define FE(x) { x, #x},
273     FE(DIDFT_ABSAXIS)
274     FE(DIDFT_ALL)
275     FE(DIDFT_AXIS)
276     FE(DIDFT_BUTTON)
277     FE(DIDFT_COLLECTION)
278     FE(DIDFT_FFACTUATOR)
279     FE(DIDFT_FFEFFECTTRIGGER)
280     FE(DIDFT_NOCOLLECTION)
281     FE(DIDFT_NODATA)
282     FE(DIDFT_OUTPUT)
283     FE(DIDFT_POV)
284     FE(DIDFT_PSHBUTTON)
285     FE(DIDFT_RELAXIS)
286     FE(DIDFT_TGLBUTTON)
287 #undef FE
288   };
289   if (dwFlags == DIDFT_ALL) {
290     DPRINTF("DIDFT_ALL");
291     return;
292   }
293   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
294     if (flags[i].mask & dwFlags)
295       DPRINTF("%s ",flags[i].name);
296   if (dwFlags & DIDFT_INSTANCEMASK)
297     DPRINTF("Instance(%04lx) ", dwFlags >> 8);
298 }
299
300 static void _dump_DIPROPHEADER(DIPROPHEADER *diph) {
301   DPRINTF("  - dwObj = 0x%08lx\n", diph->dwObj);
302   DPRINTF("  - dwHow = %s\n",
303           ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
304            ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
305             ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
306 }
307
308 static void _dump_OBJECTINSTANCEA(DIDEVICEOBJECTINSTANCEA *ddoi) {
309   if (TRACE_ON(dinput)) {
310     DPRINTF("    - enumerating : 0x%08lx - %2ld - 0x%08lx - %s\n",
311             ddoi->guidType.Data1, ddoi->dwOfs, ddoi->dwType, ddoi->tszName);
312   }
313 }
314
315 struct IDirectInputAImpl
316 {
317         ICOM_VFIELD(IDirectInputA);
318         DWORD                   ref;
319 };
320
321 /* Conversion between internal data buffer and external data buffer */
322 static void fill_DataFormat(void *out, void *in, DataFormat *df) {
323   int i;
324   char *in_c = (char *) in;
325   char *out_c = (char *) out;
326
327   if (df->dt == NULL) {
328     /* This means that the app uses Wine's internal data format */
329     memcpy(out, in, df->internal_format_size);
330   } else {
331     for (i = 0; i < df->size; i++) {
332       if (df->dt[i].offset_in >= 0) {
333         switch (df->dt[i].size) {
334         case 1:
335           TRACE("Copying (c) to %d from %d (value %d)\n",
336                 df->dt[i].offset_out, df->dt[i].offset_in, *((char *) (in_c + df->dt[i].offset_in)));
337           *((char *) (out_c + df->dt[i].offset_out)) = *((char *) (in_c + df->dt[i].offset_in));
338           break;
339         
340         case 2:
341           TRACE("Copying (s) to %d from %d (value %d)\n",
342                 df->dt[i].offset_out, df->dt[i].offset_in, *((short *) (in_c + df->dt[i].offset_in)));
343           *((short *) (out_c + df->dt[i].offset_out)) = *((short *) (in_c + df->dt[i].offset_in));
344           break;
345         
346         case 4:
347           TRACE("Copying (i) to %d from %d (value %d)\n",
348                 df->dt[i].offset_out, df->dt[i].offset_in, *((int *) (in_c + df->dt[i].offset_in)));
349           *((int *) (out_c + df->dt[i].offset_out)) = *((int *) (in_c + df->dt[i].offset_in));
350           break;
351         
352         default:
353           memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
354         }
355       } else {
356         switch (df->dt[i].size) {
357         case 1:
358           TRACE("Copying (c) to %d default value %d\n",
359                 df->dt[i].offset_out, df->dt[i].value);
360           *((char *) (out_c + df->dt[i].offset_out)) = (char) df->dt[i].value;
361           break;
362         
363         case 2:
364           TRACE("Copying (s) to %d default value %d\n",
365                 df->dt[i].offset_out, df->dt[i].value);
366           *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
367           break;
368         
369         case 4:
370           TRACE("Copying (i) to %d default value %d\n",
371                 df->dt[i].offset_out, df->dt[i].value);
372           *((int *) (out_c + df->dt[i].offset_out)) = (int) df->dt[i].value;
373           break;
374         
375         default:
376           memset((out_c + df->dt[i].offset_out), df->dt[i].size, 0);
377         }
378       }
379     }
380   }
381 }
382
383 static DataFormat *create_DataFormat(DIDATAFORMAT *wine_format, LPCDIDATAFORMAT asked_format, int *offset) {
384   DataFormat *ret;
385   DataTransform *dt;
386   int i, j;
387   int same = 1;
388   int *done;
389   int index = 0;
390   
391   ret = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
392   
393   done = (int *) HeapAlloc(GetProcessHeap(), 0, sizeof(int) * asked_format->dwNumObjs);
394   memset(done, 0, sizeof(int) * asked_format->dwNumObjs);
395
396   dt = (DataTransform *) HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
397
398   TRACE("Creating DataTransorm : \n");
399   
400   for (i = 0; i < wine_format->dwNumObjs; i++) {
401     offset[i] = -1;
402     
403     for (j = 0; j < asked_format->dwNumObjs; j++) {
404       if (done[j] == 1)
405         continue;
406       
407       if (((asked_format->rgodf[j].pguid == NULL) || (IsEqualGUID(wine_format->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
408           &&
409           (wine_format->rgodf[i].dwType & asked_format->rgodf[j].dwType)) {
410
411         done[j] = 1;
412
413         TRACE("Matching : \n"); 
414         TRACE("   - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
415               j, debugstr_guid(asked_format->rgodf[j].pguid), 
416               asked_format->rgodf[j].dwOfs,
417               DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
418         
419         TRACE("   - Wine  (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
420               j, debugstr_guid(wine_format->rgodf[i].pguid), 
421               wine_format->rgodf[i].dwOfs,
422               DIDFT_GETTYPE(wine_format->rgodf[i].dwType), DIDFT_GETINSTANCE(wine_format->rgodf[i].dwType));
423         
424         if (wine_format->rgodf[i].dwType & DIDFT_BUTTON)
425           dt[index].size = sizeof(BYTE);
426         else
427           dt[index].size = sizeof(DWORD);
428         dt[index].offset_in  = wine_format ->rgodf[i].dwOfs;
429         dt[index].offset_out = asked_format->rgodf[j].dwOfs;
430         dt[index].value = 0;
431         index++;
432         
433         if (wine_format->rgodf[i].dwOfs != asked_format->rgodf[j].dwOfs)
434           same = 0;
435
436         offset[i] = asked_format->rgodf[j].dwOfs;
437         break;
438       }
439     }
440
441     if (j == asked_format->dwNumObjs)
442       same = 0;
443   }
444
445   TRACE("Setting to default value :\n");
446   for (j = 0; j < asked_format->dwNumObjs; j++) {
447     if (done[j] == 0) {
448       TRACE(" - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
449             j, debugstr_guid(asked_format->rgodf[j].pguid), 
450             asked_format->rgodf[j].dwOfs,
451             DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
452
453       
454       if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
455         dt[index].size = sizeof(BYTE);
456       else
457         dt[index].size = sizeof(DWORD);
458       dt[index].offset_in  = -1;
459       dt[index].offset_out = asked_format->rgodf[j].dwOfs;
460       dt[index].value = 0;
461       index++;
462
463       same = 0;
464     }
465   }
466
467   ret->internal_format_size = wine_format->dwDataSize;
468   ret->size = index;
469   if (same) {
470     ret->dt = NULL;
471     HeapFree(GetProcessHeap(), 0, dt);
472   } else {
473     ret->dt = dt;
474   }
475   
476   HeapFree(GetProcessHeap(), 0, done);
477
478   return ret;
479 }
480
481 /******************************************************************************
482  *      DirectInputCreateA
483  */
484 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
485 {
486         IDirectInputAImpl* This;
487         TRACE("(0x%08lx,%04lx,%p,%p)\n",
488                 (DWORD)hinst,dwVersion,ppDI,punkOuter
489         );
490         This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
491         This->ref = 1;
492         ICOM_VTBL(This) = &ddiavt;
493         *ppDI=(IDirectInputA*)This;
494         return 0;
495 }
496 /******************************************************************************
497  *      IDirectInputA_EnumDevices
498  */
499 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
500         LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
501         LPVOID pvRef, DWORD dwFlags
502 )
503 {
504         ICOM_THIS(IDirectInputAImpl,iface);
505         DIDEVICEINSTANCEA devInstance;
506         int ret;
507
508         TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
509
510         devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
511         if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
512                 /* Return keyboard */
513                 devInstance.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
514                 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
515                 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
516                 strcpy(devInstance.tszInstanceName, "Keyboard");
517                 strcpy(devInstance.tszProductName, "Wine Keyboard");
518
519                 ret = lpCallback(&devInstance, pvRef);
520                 TRACE("Keyboard registered\n");
521                 if (ret == DIENUM_STOP)
522                         return 0;
523         }
524   
525         if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_MOUSE)) {
526                 /* Return mouse */
527                 devInstance.guidInstance = GUID_SysMouse;/* DInput's GUID */
528                 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
529                 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
530                 strcpy(devInstance.tszInstanceName, "Mouse");
531                 strcpy(devInstance.tszProductName, "Wine Mouse");
532
533                 ret = lpCallback(&devInstance, pvRef);
534                 TRACE("Mouse registered\n");
535                 if (ret == DIENUM_STOP)
536                         return 0;
537         }
538         if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_JOYSTICK)) {
539                 /* check whether we have a joystick */
540 #ifdef HAVE_LINUX_22_JOYSTICK_API
541                 if (    (access(JOYDEV,O_RDONLY)!=-1)           ||
542                         (errno!=ENODEV && errno!=ENOENT)
543                 ) {
544                     /* Return joystick */
545                     devInstance.guidInstance    = GUID_Joystick;
546                     devInstance.guidProduct     = DInput_Wine_Joystick_GUID;
547                     /* we only support traditional joysticks for now */
548                     devInstance.dwDevType       = DIDEVTYPE_JOYSTICK | DIDEVTYPEJOYSTICK_TRADITIONAL;
549                     strcpy(devInstance.tszInstanceName, "Joystick");
550                     /* ioctl JSIOCGNAME(len) */
551                     strcpy(devInstance.tszProductName,  "Wine Joystick");
552
553                     ret = lpCallback(&devInstance,pvRef);
554                     TRACE("Joystick registered\n");
555                     if (ret == DIENUM_STOP)
556                             return 0;
557                 }
558 #endif
559         }
560         return 0;
561 }
562
563 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
564 {
565         ICOM_THIS(IDirectInputAImpl,iface);
566         return ++(This->ref);
567 }
568
569 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
570 {
571         ICOM_THIS(IDirectInputAImpl,iface);
572         if (!(--This->ref)) {
573                 HeapFree(GetProcessHeap(),0,This);
574                 return 0;
575         }
576         return This->ref;
577 }
578
579 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
580         LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
581         LPUNKNOWN punk
582 ) {
583         ICOM_THIS(IDirectInputAImpl,iface);
584         
585         TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
586         if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
587             (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
588                 SysKeyboardAImpl* newDevice;
589                 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
590                 newDevice->ref = 1;
591                 ICOM_VTBL(newDevice) = &SysKeyboardAvt;
592                 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
593                 memset(newDevice->keystate,0,256);
594                 *pdev=(IDirectInputDeviceA*)newDevice;
595
596                 TRACE("Creating a Keyboard device (%p)\n", newDevice);
597                 return DI_OK;
598         }
599         if ((IsEqualGUID(&GUID_SysMouse,rguid)) ||             /* Generic Mouse */
600             (IsEqualGUID(&DInput_Wine_Mouse_GUID,rguid))) { /* Wine Mouse */
601                 SysMouseAImpl* newDevice;
602                 int offset_array[5] = {
603                   FIELD_OFFSET(Wine_InternalMouseData, lX),
604                   FIELD_OFFSET(Wine_InternalMouseData, lY),
605                   FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 0,
606                   FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 1,
607                   FIELD_OFFSET(Wine_InternalMouseData, rgbButtons) + 2
608                 };
609                 
610                 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
611                 newDevice->ref = 1;
612                 ICOM_VTBL(newDevice) = &SysMouseAvt;
613                 InitializeCriticalSection(&(newDevice->crit));
614                 MakeCriticalSectionGlobal(&(newDevice->crit));
615                 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
616                 *pdev=(IDirectInputDeviceA*)newDevice;
617
618                 /* Per default, Wine uses its internal data format */
619                 newDevice->df = &Wine_InternalMouseFormat;
620                 memcpy(newDevice->offset_array, offset_array, 5 * sizeof(int));
621                 newDevice->wine_df = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
622                 newDevice->wine_df->size = 0;
623                 newDevice->wine_df->internal_format_size = Wine_InternalMouseFormat.dwDataSize;
624                 newDevice->wine_df->dt = NULL;
625                 
626                 TRACE("Creating a Mouse device (%p)\n", newDevice);
627                 return DI_OK;
628         }
629 #ifdef HAVE_LINUX_22_JOYSTICK_API
630         if ((IsEqualGUID(&GUID_Joystick,rguid)) ||
631             (IsEqualGUID(&DInput_Wine_Joystick_GUID,rguid))) {
632                 JoystickAImpl* newDevice;
633                 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickAImpl));
634                 newDevice->ref          = 1;
635                 ICOM_VTBL(newDevice)    = &JoystickAvt;
636                 newDevice->joyfd        = -1;
637                 newDevice->lMin = -32768;
638                 newDevice->lMax = +32767;
639                 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
640                 *pdev=(IDirectInputDeviceA*)newDevice;
641
642                 TRACE("Creating a Joystick device (%p)\n", newDevice);
643                 return DI_OK;
644         }
645 #endif
646         return E_FAIL;
647 }
648
649 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
650         LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
651 ) {
652         ICOM_THIS(IDirectInputAImpl,iface);
653
654         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
655         if (IsEqualGUID(&IID_IUnknown,riid)) {
656                 IDirectInputA_AddRef(iface);
657                 *ppobj = This;
658                 return 0;
659         }
660         if (IsEqualGUID(&IID_IDirectInputA,riid)) {
661                 IDirectInputA_AddRef(iface);
662                 *ppobj = This;
663                 return 0;
664         }
665         TRACE("Unsupported interface !\n");
666         return E_FAIL;
667 }
668
669 static HRESULT WINAPI IDirectInputAImpl_Initialize(
670         LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
671 ) {
672         return DIERR_ALREADYINITIALIZED;
673 }
674
675 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
676                                                         REFGUID rguid) {
677   ICOM_THIS(IDirectInputAImpl,iface);
678   
679   FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
680   
681   return DI_OK;
682 }
683
684 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
685                                                         HWND hwndOwner,
686                                                         DWORD dwFlags) {
687   ICOM_THIS(IDirectInputAImpl,iface);
688   FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
689   
690   return DI_OK;
691 }
692
693 static ICOM_VTABLE(IDirectInputA) ddiavt = 
694 {
695         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
696         IDirectInputAImpl_QueryInterface,
697         IDirectInputAImpl_AddRef,
698         IDirectInputAImpl_Release,
699         IDirectInputAImpl_CreateDevice,
700         IDirectInputAImpl_EnumDevices,
701         IDirectInputAImpl_GetDeviceStatus,
702         IDirectInputAImpl_RunControlPanel,
703         IDirectInputAImpl_Initialize
704 };
705
706 /******************************************************************************
707  *      IDirectInputDeviceA
708  */
709
710 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
711         LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
712 ) {
713         /*
714         int i;
715         TRACE(dinput,"(this=%p,%p)\n",This,df);
716
717         TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
718         TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
719         TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
720         TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
721         TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
722
723         for (i=0;i<df->dwNumObjs;i++) {
724                 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,debugstr_guid(df->rgodf[i].pguid));
725                 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
726                 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
727                 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
728         }
729         */
730         return 0;
731 }
732
733 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
734         LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
735 ) {
736         ICOM_THIS(IDirectInputDevice2AImpl,iface);
737         TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
738         if (TRACE_ON(dinput))
739           _dump_cooperativelevel(dwflags);
740         return 0;
741 }
742
743 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
744         LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
745 ) {
746         ICOM_THIS(IDirectInputDevice2AImpl,iface);
747         FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
748         return 0;
749 }
750
751 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
752 {
753         ICOM_THIS(IDirectInputDevice2AImpl,iface);
754         This->ref--;
755         if (This->ref)
756                 return This->ref;
757         HeapFree(GetProcessHeap(),0,This);
758         return 0;
759 }
760
761 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
762         LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
763 )
764 {
765         ICOM_THIS(SysKeyboardAImpl,iface);
766
767         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
768         TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
769             ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
770         if (!HIWORD(rguid)) {
771                 switch ((DWORD)rguid) {
772                 case (DWORD) DIPROP_BUFFERSIZE: {
773                         LPCDIPROPDWORD  pd = (LPCDIPROPDWORD)ph;
774
775                         TRACE("(buffersize=%ld)\n",pd->dwData);
776                         break;
777                 }
778                 default:
779                         WARN("Unknown type %ld\n",(DWORD)rguid);
780                         break;
781                 }
782         }
783         return 0;
784 }
785
786 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
787         LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
788 )
789 {
790         return USER_Driver->pGetDIState(len, ptr)?DI_OK:E_FAIL;
791 }
792
793 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
794         LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
795         LPDWORD entries,DWORD flags
796 )
797 {
798         ICOM_THIS(SysKeyboardAImpl,iface);
799         HRESULT ret;
800         int     i;
801
802         TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
803               This,dodsize,dod,entries,entries?*entries:0,flags);
804
805         ret=USER_Driver->pGetDIData(
806                 This->keystate, dodsize, dod, entries, flags)?DI_OK:E_FAIL;
807         for (i=0;i<*entries;i++) {
808                 dod[i].dwTimeStamp = GetTickCount();
809                 dod[i].dwSequence = evsequence++;
810         }
811         return ret;
812 }
813
814 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
815 {
816         ICOM_THIS(SysKeyboardAImpl,iface);
817         
818         TRACE("(this=%p)\n",This);
819         
820         if (This->acquired == 0) {
821           KEYBOARD_CONFIG no_auto;
822           
823           /* Save the original config */
824           USER_Driver->pGetKeyboardConfig(&(This->initial_config));
825           
826           /* Now, remove auto-repeat */
827           no_auto.auto_repeat = FALSE;
828           USER_Driver->pSetKeyboardConfig(&no_auto, WINE_KEYBOARD_CONFIG_AUTO_REPEAT);
829
830           This->acquired = 1;
831         }
832         
833         return DI_OK;
834 }
835
836 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
837 {
838         ICOM_THIS(SysKeyboardAImpl,iface);
839         TRACE("(this=%p)\n",This);
840
841         if (This->acquired == 1) {
842           /* Restore the original configuration */
843           USER_Driver->pSetKeyboardConfig(&(This->initial_config), 0xFFFFFFFF);
844           This->acquired = 0;
845         } else {
846           ERR("Unacquiring a not-acquired device !!!\n");
847         }
848
849         return DI_OK;
850 }
851
852 /******************************************************************************
853   *     GetCapabilities : get the device capablitites
854   */
855 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
856         LPDIRECTINPUTDEVICE2A iface,
857         LPDIDEVCAPS lpDIDevCaps)
858 {
859   ICOM_THIS(SysMouseAImpl,iface);
860
861   TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
862
863   if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
864     lpDIDevCaps->dwFlags = DIDC_ATTACHED;
865     lpDIDevCaps->dwDevType = DIDEVTYPE_KEYBOARD;
866     lpDIDevCaps->dwAxes = 0;
867     lpDIDevCaps->dwButtons = 0;
868     lpDIDevCaps->dwPOVs = 0;
869     lpDIDevCaps->dwFFSamplePeriod = 0;
870     lpDIDevCaps->dwFFMinTimeResolution = 0;
871     lpDIDevCaps->dwFirmwareRevision = 100;
872     lpDIDevCaps->dwHardwareRevision = 100;
873     lpDIDevCaps->dwFFDriverVersion = 0;
874   } else {
875     /* DirectX 3.0 */
876     FIXME("DirectX 3.0 not supported....\n");
877   }
878   
879   return DI_OK;
880 }
881
882 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
883         LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
884 )
885 {
886         ICOM_THIS(IDirectInputDevice2AImpl,iface);
887
888         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
889         if (IsEqualGUID(&IID_IUnknown,riid)) {
890                 IDirectInputDevice2_AddRef(iface);
891                 *ppobj = This;
892                 return 0;
893         }
894         if (IsEqualGUID(&IID_IDirectInputDeviceA,riid)) {
895                 IDirectInputDevice2_AddRef(iface);
896                 *ppobj = This;
897                 return 0;
898         }
899         if (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) {
900                 IDirectInputDevice2_AddRef(iface);
901                 *ppobj = This;
902                 return 0;
903         }
904         TRACE("Unsupported interface !\n");
905         return E_FAIL;
906 }
907
908 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
909         LPDIRECTINPUTDEVICE2A iface)
910 {
911         ICOM_THIS(IDirectInputDevice2AImpl,iface);
912         return ++This->ref;
913 }
914
915 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
916         LPDIRECTINPUTDEVICE2A iface,
917         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
918         LPVOID lpvRef,
919         DWORD dwFlags)
920 {
921         FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
922         if (TRACE_ON(dinput)) {
923           DPRINTF("  - flags = ");
924           _dump_EnumObjects_flags(dwFlags);
925           DPRINTF("\n");
926         }
927         
928         return DI_OK;
929 }
930         
931 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
932         LPDIRECTINPUTDEVICE2A iface,
933         REFGUID rguid,
934         LPDIPROPHEADER pdiph)
935 {
936         FIXME("(this=%p,%s,%p): stub!\n",
937               iface, debugstr_guid(rguid), pdiph);
938         
939         if (TRACE_ON(dinput))
940           _dump_DIPROPHEADER(pdiph);
941         
942         return DI_OK;
943 }
944
945 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
946         LPDIRECTINPUTDEVICE2A iface,
947         LPDIDEVICEOBJECTINSTANCEA pdidoi,
948         DWORD dwObj,
949         DWORD dwHow)
950 {
951         FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
952               iface, pdidoi, dwObj, dwHow);
953         
954         return DI_OK;
955 }
956         
957 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
958         LPDIRECTINPUTDEVICE2A iface,
959         LPDIDEVICEINSTANCEA pdidi)
960 {
961         FIXME("(this=%p,%p): stub!\n",
962               iface, pdidi);
963         
964         return DI_OK;
965 }
966         
967 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
968         LPDIRECTINPUTDEVICE2A iface,
969         HWND hwndOwner,
970         DWORD dwFlags)
971 {
972   FIXME("(this=%p,0x%08x,0x%08lx): stub!\n",
973         iface, hwndOwner, dwFlags);
974         
975         return DI_OK;
976 }
977         
978 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
979         LPDIRECTINPUTDEVICE2A iface,
980         HINSTANCE hinst,
981         DWORD dwVersion,
982         REFGUID rguid)
983 {
984         FIXME("(this=%p,%d,%ld,%s): stub!\n",
985               iface, hinst, dwVersion, debugstr_guid(rguid));
986         return DI_OK;
987 }
988         
989 /******************************************************************************
990  *      IDirectInputDevice2A
991  */
992
993 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
994         LPDIRECTINPUTDEVICE2A iface,
995         REFGUID rguid,
996         LPCDIEFFECT lpeff,
997         LPDIRECTINPUTEFFECT *ppdef,
998         LPUNKNOWN pUnkOuter)
999 {
1000         FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
1001               iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
1002         return DI_OK;
1003 }
1004
1005 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1006         LPDIRECTINPUTDEVICE2A iface,
1007         LPDIENUMEFFECTSCALLBACKA lpCallback,
1008         LPVOID lpvRef,
1009         DWORD dwFlags)
1010 {
1011         FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
1012               iface, lpCallback, lpvRef, dwFlags);
1013         
1014         if (lpCallback)
1015                 lpCallback(NULL, lpvRef);
1016         return DI_OK;
1017 }
1018
1019 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1020         LPDIRECTINPUTDEVICE2A iface,
1021         LPDIEFFECTINFOA lpdei,
1022         REFGUID rguid)
1023 {
1024         FIXME("(this=%p,%p,%s): stub!\n",
1025               iface, lpdei, debugstr_guid(rguid));
1026         return DI_OK;
1027 }
1028
1029 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
1030         LPDIRECTINPUTDEVICE2A iface,
1031         LPDWORD pdwOut)
1032 {
1033         FIXME("(this=%p,%p): stub!\n",
1034               iface, pdwOut);
1035         return DI_OK;
1036 }
1037
1038 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
1039         LPDIRECTINPUTDEVICE2A iface,
1040         DWORD dwFlags)
1041 {
1042         FIXME("(this=%p,0x%08lx): stub!\n",
1043               iface, dwFlags);
1044         return DI_OK;
1045 }
1046
1047 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
1048         LPDIRECTINPUTDEVICE2A iface,
1049         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
1050         LPVOID lpvRef,
1051         DWORD dwFlags)
1052 {
1053         FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
1054               iface, lpCallback, lpvRef, dwFlags);
1055         if (lpCallback)
1056                 lpCallback(NULL, lpvRef);
1057         return DI_OK;
1058 }
1059
1060 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
1061         LPDIRECTINPUTDEVICE2A iface,
1062         LPDIEFFESCAPE lpDIEEsc)
1063 {
1064         FIXME("(this=%p,%p): stub!\n",
1065               iface, lpDIEEsc);
1066         return DI_OK;
1067 }
1068
1069 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
1070         LPDIRECTINPUTDEVICE2A iface)
1071 {
1072         FIXME("(this=%p): stub!\n",
1073               iface);
1074         return DI_OK;
1075 }
1076
1077 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
1078         LPDIRECTINPUTDEVICE2A iface,
1079         DWORD cbObjectData,
1080         LPDIDEVICEOBJECTDATA rgdod,
1081         LPDWORD pdwInOut,
1082         DWORD dwFlags)
1083 {
1084         FIXME("(this=%p,0x%08lx,%p,%p,0x%08lx): stub!\n",
1085               iface, cbObjectData, rgdod, pdwInOut, dwFlags);
1086         
1087         return DI_OK;
1088 }
1089
1090 /******************************************************************************
1091  *      SysMouseA (DInput Mouse support)
1092  */
1093
1094 /******************************************************************************
1095   *     Release : release the mouse buffer.
1096   */
1097 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1098 {
1099         ICOM_THIS(SysMouseAImpl,iface);
1100
1101         This->ref--;
1102         if (This->ref)
1103                 return This->ref;
1104
1105         /* Free the data queue */
1106         if (This->data_queue != NULL)
1107           HeapFree(GetProcessHeap(),0,This->data_queue);
1108
1109         /* Install the previous event handler (in case of releasing an aquired
1110            mouse device) */
1111         if (This->prev_handler != NULL)
1112           MOUSE_Enable(This->prev_handler);
1113         DeleteCriticalSection(&(This->crit));
1114
1115         /* Free the DataFormat */
1116         if (This->df != &(Wine_InternalMouseFormat)) {
1117           HeapFree(GetProcessHeap(), 0, This->df->rgodf);
1118           HeapFree(GetProcessHeap(), 0, This->df);
1119         }
1120         
1121         HeapFree(GetProcessHeap(),0,This);
1122         return 0;
1123 }
1124
1125
1126 /******************************************************************************
1127   *     SetCooperativeLevel : store the window in which we will do our
1128   *   grabbing.
1129   */
1130 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
1131         LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
1132 )
1133 {
1134   ICOM_THIS(SysMouseAImpl,iface);
1135
1136   TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
1137
1138   if (TRACE_ON(dinput))
1139     _dump_cooperativelevel(dwflags);
1140
1141   /* Store the window which asks for the mouse */
1142   This->win = hwnd;
1143   
1144   return 0;
1145 }
1146
1147
1148 /******************************************************************************
1149   *     SetDataFormat : the application can choose the format of the data
1150   *   the device driver sends back with GetDeviceState.
1151   *
1152   *   For the moment, only the "standard" configuration (c_dfDIMouse) is supported
1153   *   in absolute and relative mode.
1154   */
1155 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
1156         LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1157 )
1158 {
1159   ICOM_THIS(SysMouseAImpl,iface);
1160   int i;
1161   
1162   TRACE("(this=%p,%p)\n",This,df);
1163
1164   TRACE("(df.dwSize=%ld)\n",df->dwSize);
1165   TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1166   TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1167   TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1168   TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1169
1170   for (i=0;i<df->dwNumObjs;i++) {
1171
1172     TRACE("df.rgodf[%d].guid %s (%p)\n",i, debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
1173     TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1174     TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1175     TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1176   }
1177
1178   /* Check if the mouse is in absolute or relative mode */
1179   if (df->dwFlags == DIDF_ABSAXIS)
1180     This->absolute = 1;
1181   else if (df->dwFlags == DIDF_RELAXIS)
1182     This->absolute = 0;
1183   else
1184     ERR("Neither absolute nor relative flag set.");
1185   
1186   /* Store the new data format */
1187   This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
1188   memcpy(This->df, df, df->dwSize);
1189   This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
1190   memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
1191
1192   /* Prepare all the data-conversion filters */
1193   This->wine_df = create_DataFormat(&(Wine_InternalMouseFormat), df, This->offset_array);
1194   
1195   return 0;
1196 }
1197
1198 #define GEN_EVENT(offset,data,xtime,seq)                                        \
1199 {                                                                               \
1200   /* If queue_len > 0, queuing is requested -> TRACE the event queued */        \
1201   if (This->queue_len > 0) {                                                    \
1202     TRACE(" queueing %d at offset %d (queue pos %d / size %d)\n",               \
1203           (int) (data), (int) (offset),                                         \
1204           (int) (This->queue_pos), (int) (This->queue_len));                    \
1205                                                                                 \
1206     if ((offset >= 0) && (This->queue_pos < This->queue_len)) {                 \
1207       This->data_queue[This->queue_pos].dwOfs = offset;                         \
1208       This->data_queue[This->queue_pos].dwData = data;                          \
1209       This->data_queue[This->queue_pos].dwTimeStamp = xtime;                    \
1210       This->data_queue[This->queue_pos].dwSequence = seq;                       \
1211       This->queue_pos++;                                                        \
1212     }                                                                           \
1213   }                                                                             \
1214 }
1215
1216   
1217 /* Our private mouse event handler */
1218 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
1219                                       DWORD cButtons, DWORD dwExtraInfo )
1220 {
1221   long posX = -1, posY = -1;
1222   DWORD keyState, xtime, extra;
1223   SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
1224   
1225   EnterCriticalSection(&(This->crit));
1226   /* Mouse moved -> send event if asked */
1227   if (This->hEvent)
1228     SetEvent(This->hEvent);
1229   
1230   if (   !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
1231       && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
1232     WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
1233     keyState = wme->keyState;
1234     xtime = wme->time;
1235     extra = (DWORD)wme->hWnd;
1236     
1237     if (dwFlags & MOUSEEVENTF_MOVE) {
1238       if (dwFlags & MOUSEEVENTF_ABSOLUTE) {
1239         posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
1240         posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
1241
1242         if (This->absolute) {
1243           if (posX != This->prevX)
1244             GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX, xtime, 0);
1245           if (posY != This->prevY)
1246             GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY, xtime, 0);
1247         } else {
1248           /* Now, warp handling */
1249           if ((This->need_warp == WARP_STARTED) &&
1250               (posX == This->win_centerX) && (posX == This->win_centerX)) {
1251             /* Warp has been done... */
1252             This->need_warp = WARP_DONE;
1253             LeaveCriticalSection(&(This->crit));
1254             return;
1255           }
1256                   
1257           /* Relative mouse input with absolute mouse event : the real fun starts here... */
1258           if ((This->need_warp == WARP_NEEDED) ||
1259               (This->need_warp == WARP_STARTED)) {
1260             if (posX != This->prevX)
1261               GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->prevX, xtime, evsequence++);
1262             if (posY != This->prevY)
1263               GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->prevY, xtime, evsequence++);
1264           } else {
1265             /* This is the first time the event handler has been called after a
1266                GetData of GetState. */
1267             if (posX != This->win_centerX) {
1268               GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX - This->win_centerX, xtime, evsequence++);
1269               This->need_warp = WARP_NEEDED;
1270             }
1271             
1272             if (posY != This->win_centerY) {
1273               GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY - This->win_centerY, xtime, evsequence++);
1274               This->need_warp = WARP_NEEDED;
1275             }
1276           }
1277         }
1278
1279         This->prevX = posX;
1280         This->prevY = posY;
1281         
1282         if (This->absolute) {
1283           This->m_state.lX = posX;
1284           This->m_state.lY = posY;
1285         } else {
1286           This->m_state.lX = posX - This->win_centerX;
1287           This->m_state.lY = posY - This->win_centerY;
1288         }
1289       } else {
1290         /* Mouse reporting is in relative mode */
1291         posX = (long) dx;
1292         posY = (long) dy;
1293
1294         if (This->absolute) {
1295           long aposX, aposY;
1296           
1297           aposX = This->m_state.lX + posX;
1298           if (aposX < 0)
1299             aposX = 0;
1300           if (aposX >= GetSystemMetrics(SM_CXSCREEN))
1301             aposX = GetSystemMetrics(SM_CXSCREEN);
1302           
1303           aposY = This->m_state.lY + posY;
1304           if (aposY < 0)
1305             aposY = 0;
1306           if (aposY >= GetSystemMetrics(SM_CYSCREEN))
1307             aposY = GetSystemMetrics(SM_CYSCREEN);
1308           
1309           if (posX != 0)
1310             GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], aposX, xtime, evsequence++);
1311           if (posY != 0)
1312             GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], aposY, xtime, evsequence++);
1313
1314           This->m_state.lX = aposX;
1315           This->m_state.lY = aposY;
1316         } else {
1317           if (posX != 0)
1318             GEN_EVENT(This->offset_array[WINE_MOUSE_X_POSITION], posX, xtime, evsequence++);
1319           if (posY != 0)
1320             GEN_EVENT(This->offset_array[WINE_MOUSE_Y_POSITION], posY, xtime, evsequence++);
1321
1322           This->m_state.lX = posX;
1323           This->m_state.lY = posY;
1324         }
1325       }
1326     }
1327   } else {
1328     ERR("Mouse event not supported...\n");
1329     LeaveCriticalSection(&(This->crit));
1330     return ;
1331   }
1332
1333   if (TRACE_ON(dinput)) {
1334     if (dwFlags & MOUSEEVENTF_MOVE)
1335       TRACE(" %ld %ld (%s)", posX, posY,
1336             (dwFlags & MOUSEEVENTF_ABSOLUTE ? "abs" : "rel"));
1337     
1338     if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) DPRINTF(" LD ");
1339     if ( dwFlags & MOUSEEVENTF_LEFTUP )   DPRINTF(" LU ");
1340
1341     if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) DPRINTF(" RD ");
1342     if ( dwFlags & MOUSEEVENTF_RIGHTUP )   DPRINTF(" RU ");
1343
1344     if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) DPRINTF(" MD ");
1345     if ( dwFlags & MOUSEEVENTF_MIDDLEUP )   DPRINTF(" MU ");
1346
1347     if (!(This->absolute)) DPRINTF(" W=%d ", This->need_warp);
1348     
1349     DPRINTF("\n");
1350   }
1351
1352   
1353   if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
1354     GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0xFF, xtime, evsequence++);
1355     This->m_state.rgbButtons[0] = 0xFF;
1356   }
1357   if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
1358     GEN_EVENT(This->offset_array[WINE_MOUSE_L_POSITION], 0x00, xtime, evsequence++);
1359     This->m_state.rgbButtons[0] = 0x00;
1360   }
1361   if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
1362     GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0xFF, xtime, evsequence++);
1363     This->m_state.rgbButtons[1] = 0xFF;
1364   }
1365   if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
1366     GEN_EVENT(This->offset_array[WINE_MOUSE_R_POSITION], 0x00, xtime, evsequence++);
1367     This->m_state.rgbButtons[1] = 0x00;
1368   }
1369   if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
1370     GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0xFF, xtime, evsequence++);
1371     This->m_state.rgbButtons[2] = 0xFF;
1372   }
1373   if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
1374     GEN_EVENT(This->offset_array[WINE_MOUSE_M_POSITION], 0x00, xtime, evsequence++);
1375     This->m_state.rgbButtons[2] = 0x00;
1376   }
1377
1378   TRACE("(X: %ld - Y: %ld   L: %02x M: %02x R: %02x)\n",
1379         This->m_state.lX, This->m_state.lY,
1380         This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
1381   
1382   LeaveCriticalSection(&(This->crit));
1383 }
1384
1385
1386 /******************************************************************************
1387   *     Acquire : gets exclusive control of the mouse
1388   */
1389 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1390 {
1391   ICOM_THIS(SysMouseAImpl,iface);
1392   RECT  rect;
1393   
1394   TRACE("(this=%p)\n",This);
1395
1396   if (This->acquired == 0) {
1397     POINT       point;
1398     
1399     /* This stores the current mouse handler. */
1400     This->prev_handler = mouse_event;
1401     
1402     /* Store (in a global variable) the current lock */
1403     current_lock = (IDirectInputDevice2A*)This;
1404
1405     /* Init the mouse state */
1406     if (This->absolute) {
1407       This->m_state.lX = PosX;
1408       This->m_state.lY = PosY;
1409
1410       This->prevX = PosX;
1411       This->prevY = PosY;
1412     } else {
1413       This->m_state.lX = 0;
1414       This->m_state.lY = 0;
1415     }
1416     This->m_state.rgbButtons[0] = (MouseButtonsStates[0] ? 0xFF : 0x00);
1417     This->m_state.rgbButtons[1] = (MouseButtonsStates[1] ? 0xFF : 0x00);
1418     This->m_state.rgbButtons[2] = (MouseButtonsStates[2] ? 0xFF : 0x00);
1419
1420     /* Install our own mouse event handler */
1421     MOUSE_Enable(dinput_mouse_event);
1422     
1423     /* Get the window dimension and find the center */
1424     GetWindowRect(This->win, &rect);
1425     This->win_centerX = (rect.right  - rect.left) / 2;
1426     This->win_centerY = (rect.bottom - rect.top ) / 2;
1427
1428     /* Warp the mouse to the center of the window */
1429     if (This->absolute == 0) {
1430       TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1431       point.x = This->win_centerX;
1432       point.y = This->win_centerY;
1433       MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1434       USER_Driver->pMoveCursor( point.x, point.y );
1435       This->need_warp = WARP_STARTED;
1436     }
1437
1438     This->acquired = 1;
1439   }
1440   return 0;
1441 }
1442
1443 /******************************************************************************
1444   *     Unacquire : frees the mouse
1445   */
1446 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1447 {
1448   ICOM_THIS(SysMouseAImpl,iface);
1449
1450   TRACE("(this=%p)\n",This);
1451
1452   /* Reinstall previous mouse event handler */
1453   MOUSE_Enable(This->prev_handler);
1454   This->prev_handler = NULL;
1455   
1456   /* No more locks */
1457   current_lock = NULL;
1458
1459   /* Unacquire device */
1460   This->acquired = 0;
1461   
1462   return 0;
1463 }
1464
1465 /******************************************************************************
1466   *     GetDeviceState : returns the "state" of the mouse.
1467   *
1468   *   For the moment, only the "standard" return structure (DIMOUSESTATE) is
1469   *   supported.
1470   */
1471 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
1472         LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1473 ) {
1474   ICOM_THIS(SysMouseAImpl,iface);
1475   
1476   EnterCriticalSection(&(This->crit));
1477   TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr);
1478   
1479   /* Copy the current mouse state */
1480   fill_DataFormat(ptr, &(This->m_state), This->wine_df);
1481   
1482   /* Initialize the buffer when in relative mode */
1483   if (This->absolute == 0) {
1484     This->m_state.lX = 0;
1485     This->m_state.lY = 0;
1486   }
1487   
1488   /* Check if we need to do a mouse warping */
1489   if (This->need_warp == WARP_NEEDED) {
1490     POINT point;
1491
1492     TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1493     point.x = This->win_centerX;
1494     point.y = This->win_centerY;
1495     MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1496     USER_Driver->pMoveCursor( point.x, point.y );
1497
1498     This->need_warp = WARP_STARTED;
1499   }
1500
1501   LeaveCriticalSection(&(This->crit));
1502   
1503   TRACE("(X: %ld - Y: %ld   L: %02x M: %02x R: %02x)\n",
1504         This->m_state.lX, This->m_state.lY,
1505         This->m_state.rgbButtons[0], This->m_state.rgbButtons[2], This->m_state.rgbButtons[1]);
1506   
1507   return 0;
1508 }
1509
1510 /******************************************************************************
1511   *     GetDeviceState : gets buffered input data.
1512   */
1513 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1514                                               DWORD dodsize,
1515                                               LPDIDEVICEOBJECTDATA dod,
1516                                               LPDWORD entries,
1517                                               DWORD flags
1518 ) {
1519   ICOM_THIS(SysMouseAImpl,iface);
1520   
1521   EnterCriticalSection(&(This->crit));
1522   TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags);
1523
1524   if (flags & DIGDD_PEEK)
1525     FIXME("DIGDD_PEEK\n");
1526
1527   if (dod == NULL) {
1528     *entries = This->queue_pos;
1529     This->queue_pos = 0;
1530   } else {
1531     /* Check for buffer overflow */
1532     if (This->queue_pos > *entries) {
1533       WARN("Buffer overflow not handled properly yet...\n");
1534       This->queue_pos = *entries;
1535     }
1536     if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1537       ERR("Wrong structure size !\n");
1538       LeaveCriticalSection(&(This->crit));
1539       return DIERR_INVALIDPARAM;
1540     }
1541
1542     if (This->queue_pos)
1543         TRACE("Application retrieving %d event(s).\n", This->queue_pos); 
1544     
1545     /* Copy the buffered data into the application queue */
1546     memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1547     *entries = This->queue_pos;
1548
1549     /* Reset the event queue */
1550     This->queue_pos = 0;
1551   }
1552   LeaveCriticalSection(&(This->crit));
1553   
1554   /* Check if we need to do a mouse warping */
1555   if (This->need_warp == WARP_NEEDED) {
1556     POINT point;
1557
1558     TRACE("Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1559     point.x = This->win_centerX;
1560     point.y = This->win_centerY;
1561     MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1562
1563     USER_Driver->pMoveCursor( point.x, point.y );
1564
1565     This->need_warp = WARP_STARTED;
1566   }
1567   return 0;
1568 }
1569
1570 /******************************************************************************
1571   *     SetProperty : change input device properties
1572   */
1573 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1574                                             REFGUID rguid,
1575                                             LPCDIPROPHEADER ph)
1576 {
1577   ICOM_THIS(SysMouseAImpl,iface);
1578
1579   TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1580   
1581   if (!HIWORD(rguid)) {
1582     switch ((DWORD)rguid) {
1583     case (DWORD) DIPROP_BUFFERSIZE: {
1584       LPCDIPROPDWORD    pd = (LPCDIPROPDWORD)ph;
1585       
1586       TRACE("buffersize = %ld\n",pd->dwData);
1587
1588       This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1589                                                           pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1590       This->queue_pos  = 0;
1591       This->queue_len  = pd->dwData;
1592       break;
1593     }
1594     default:
1595       FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1596       break;
1597     }
1598   }
1599   
1600   return 0;
1601 }
1602
1603 /******************************************************************************
1604   *     GetProperty : get input device properties
1605   */
1606 static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface,
1607                                                 REFGUID rguid,
1608                                                 LPDIPROPHEADER pdiph)
1609 {
1610   ICOM_THIS(SysMouseAImpl,iface);
1611
1612   TRACE("(this=%p,%s,%p): stub!\n",
1613         iface, debugstr_guid(rguid), pdiph);
1614
1615   if (TRACE_ON(dinput))
1616     _dump_DIPROPHEADER(pdiph);
1617   
1618   if (!HIWORD(rguid)) {
1619     switch ((DWORD)rguid) {
1620     case (DWORD) DIPROP_BUFFERSIZE: {
1621       LPDIPROPDWORD     pd = (LPDIPROPDWORD)pdiph;
1622       
1623       TRACE(" return buffersize = %d\n",This->queue_len);
1624       pd->dwData = This->queue_len;
1625       break;
1626     }
1627
1628     case (DWORD) DIPROP_RANGE: {
1629       LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
1630
1631       if ((pdiph->dwHow == DIPH_BYID) &&
1632           ((pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS)) ||
1633            (pdiph->dwObj == (DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS)))) {
1634         /* Querying the range of either the X or the Y axis.  As I do
1635            not know the range, do as if the range where
1636            unrestricted...*/
1637         pr->lMin = DIPROPRANGE_NOMIN;
1638         pr->lMax = DIPROPRANGE_NOMAX;
1639       }
1640       
1641       break;
1642     }
1643       
1644     default:
1645       FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1646       break;
1647     }
1648   }
1649   
1650   
1651   return DI_OK;
1652 }
1653
1654
1655
1656 /******************************************************************************
1657   *     SetEventNotification : specifies event to be sent on state change
1658   */
1659 static HRESULT WINAPI SysMouseAImpl_SetEventNotification(LPDIRECTINPUTDEVICE2A iface,
1660                                                          HANDLE hnd) {
1661   ICOM_THIS(SysMouseAImpl,iface);
1662
1663   TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
1664
1665   This->hEvent = hnd;
1666
1667   return DI_OK;
1668 }
1669
1670 /******************************************************************************
1671   *     GetCapabilities : get the device capablitites
1672   */
1673 static HRESULT WINAPI SysMouseAImpl_GetCapabilities(
1674         LPDIRECTINPUTDEVICE2A iface,
1675         LPDIDEVCAPS lpDIDevCaps)
1676 {
1677   ICOM_THIS(SysMouseAImpl,iface);
1678
1679   TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
1680
1681   if (lpDIDevCaps->dwSize == sizeof(DIDEVCAPS)) {
1682     lpDIDevCaps->dwFlags = DIDC_ATTACHED;
1683     lpDIDevCaps->dwDevType = DIDEVTYPE_MOUSE;
1684     lpDIDevCaps->dwAxes = 2;
1685     lpDIDevCaps->dwButtons = 3;
1686     lpDIDevCaps->dwPOVs = 0;
1687     lpDIDevCaps->dwFFSamplePeriod = 0;
1688     lpDIDevCaps->dwFFMinTimeResolution = 0;
1689     lpDIDevCaps->dwFirmwareRevision = 100;
1690     lpDIDevCaps->dwHardwareRevision = 100;
1691     lpDIDevCaps->dwFFDriverVersion = 0;
1692   } else {
1693     /* DirectX 3.0 */
1694     FIXME("DirectX 3.0 not supported....\n");
1695   }
1696   
1697   return DI_OK;
1698 }
1699
1700
1701 /******************************************************************************
1702   *     EnumObjects : enumerate the different buttons and axis...
1703   */
1704 static HRESULT WINAPI SysMouseAImpl_EnumObjects(
1705         LPDIRECTINPUTDEVICE2A iface,
1706         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
1707         LPVOID lpvRef,
1708         DWORD dwFlags)
1709 {
1710   ICOM_THIS(SysMouseAImpl,iface);
1711   DIDEVICEOBJECTINSTANCEA ddoi;
1712   
1713   TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
1714   if (TRACE_ON(dinput)) {
1715     DPRINTF("  - flags = ");
1716     _dump_EnumObjects_flags(dwFlags);
1717     DPRINTF("\n");
1718   }
1719
1720   /* Only the fields till dwFFMaxForce are relevant */
1721   ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
1722     
1723   /* In a mouse, we have : two relative axis and three buttons */
1724   if ((dwFlags == DIDFT_ALL) ||
1725       (dwFlags & DIDFT_AXIS)) {
1726     /* X axis */
1727     ddoi.guidType = GUID_XAxis;
1728     ddoi.dwOfs = This->offset_array[WINE_MOUSE_X_POSITION];
1729     ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS;
1730     strcpy(ddoi.tszName, "X-Axis");
1731     _dump_OBJECTINSTANCEA(&ddoi);
1732     if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1733     
1734     /* Y axis */
1735     ddoi.guidType = GUID_YAxis;
1736     ddoi.dwOfs = This->offset_array[WINE_MOUSE_Y_POSITION];
1737     ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS;
1738     strcpy(ddoi.tszName, "Y-Axis");
1739     _dump_OBJECTINSTANCEA(&ddoi);
1740     if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1741   }
1742
1743   if ((dwFlags == DIDFT_ALL) ||
1744       (dwFlags & DIDFT_BUTTON)) {
1745     ddoi.guidType = GUID_Button;
1746
1747     /* Left button */
1748     ddoi.dwOfs = This->offset_array[WINE_MOUSE_L_POSITION];
1749     ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_L_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1750     strcpy(ddoi.tszName, "Left-Button");
1751     _dump_OBJECTINSTANCEA(&ddoi);
1752     if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1753
1754     /* Right button */
1755     ddoi.dwOfs = This->offset_array[WINE_MOUSE_R_POSITION];
1756     ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_R_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1757     strcpy(ddoi.tszName, "Right-Button");
1758     _dump_OBJECTINSTANCEA(&ddoi);
1759     if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1760
1761     /* Middle button */
1762     ddoi.dwOfs = This->offset_array[WINE_MOUSE_M_POSITION];
1763     ddoi.dwType = DIDFT_MAKEINSTANCE(WINE_MOUSE_M_BUTTON_INSTANCE) | DIDFT_PSHBUTTON;
1764     strcpy(ddoi.tszName, "Middle-Button");
1765     _dump_OBJECTINSTANCEA(&ddoi);
1766     if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
1767   }
1768
1769   return DI_OK;
1770 }
1771         
1772
1773
1774 #ifdef HAVE_LINUX_22_JOYSTICK_API
1775 /******************************************************************************
1776  *      Joystick
1777  */
1778 static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
1779 {
1780         ICOM_THIS(JoystickAImpl,iface);
1781
1782         This->ref--;
1783         if (This->ref)
1784                 return This->ref;
1785
1786         /* Free the data queue */
1787         if (This->data_queue != NULL)
1788           HeapFree(GetProcessHeap(),0,This->data_queue);
1789         
1790         /* Free the DataFormat */
1791         HeapFree(GetProcessHeap(), 0, This->df);
1792         
1793         HeapFree(GetProcessHeap(),0,This);
1794         return 0;
1795 }
1796
1797 /******************************************************************************
1798   *   SetDataFormat : the application can choose the format of the data
1799   *   the device driver sends back with GetDeviceState.
1800   */
1801 static HRESULT WINAPI JoystickAImpl_SetDataFormat(
1802         LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
1803 )
1804 {
1805   ICOM_THIS(JoystickAImpl,iface);
1806   int i;
1807   
1808   TRACE("(this=%p,%p)\n",This,df);
1809
1810   TRACE("(df.dwSize=%ld)\n",df->dwSize);
1811   TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
1812   TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
1813   TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
1814   TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
1815
1816   for (i=0;i<df->dwNumObjs;i++) {
1817     TRACE("df.rgodf[%d].guid %s (%p)\n",i,debugstr_guid(df->rgodf[i].pguid), df->rgodf[i].pguid);
1818     TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
1819     TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
1820     TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
1821   }
1822   
1823   /* Store the new data format */
1824   This->df = HeapAlloc(GetProcessHeap(),0,df->dwSize);
1825   memcpy(This->df, df, df->dwSize);
1826   This->df->rgodf = HeapAlloc(GetProcessHeap(),0,df->dwNumObjs*df->dwObjSize);
1827   memcpy(This->df->rgodf,df->rgodf,df->dwNumObjs*df->dwObjSize);
1828   
1829   return 0;
1830 }
1831
1832 /******************************************************************************
1833   *     Acquire : gets exclusive control of the joystick
1834   */
1835 static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
1836 {
1837     ICOM_THIS(JoystickAImpl,iface);
1838   
1839     TRACE("(this=%p)\n",This);
1840     if (This->joyfd!=-1)
1841         return 0;
1842     This->joyfd=open(JOYDEV,O_RDONLY);
1843     if (This->joyfd==-1)
1844         return DIERR_NOTFOUND;
1845     return 0;
1846 }
1847
1848 /******************************************************************************
1849   *     Unacquire : frees the joystick
1850   */
1851 static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
1852 {
1853     ICOM_THIS(JoystickAImpl,iface);
1854
1855     TRACE("(this=%p)\n",This);
1856     if (This->joyfd!=-1) {
1857         close(This->joyfd);
1858         This->joyfd = -1;
1859     }
1860     return 0;
1861 }
1862
1863 #define map_axis(val) ((val+32768)*(This->lMax-This->lMin)/65536+This->lMin)
1864
1865 static void joy_polldev(JoystickAImpl *This) {
1866     struct timeval tv;
1867     fd_set      readfds;
1868     struct      js_event jse;
1869
1870     if (This->joyfd==-1)
1871         return;
1872     while (1) {
1873         memset(&tv,0,sizeof(tv));
1874         FD_ZERO(&readfds);FD_SET(This->joyfd,&readfds);
1875         if (1>select(This->joyfd+1,&readfds,NULL,NULL,&tv))
1876             return;
1877         /* we have one event, so we can read */
1878         if (sizeof(jse)!=read(This->joyfd,&jse,sizeof(jse))) {
1879             return;
1880         }
1881         TRACE("js_event: type 0x%x, number %d, value %d\n",jse.type,jse.number,jse.value);
1882         if (jse.type & JS_EVENT_BUTTON) {
1883             GEN_EVENT(DIJOFS_BUTTON(jse.number),jse.value?0x80:0x00,jse.time,evsequence++);
1884             This->js.rgbButtons[jse.number] = jse.value?0x80:0x00;
1885         }
1886         if (jse.type & JS_EVENT_AXIS) {
1887             switch (jse.number) {
1888             case 0:
1889                 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1890                 This->js.lX = map_axis(jse.value);
1891                 break;
1892             case 1:
1893                 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1894                 This->js.lY = map_axis(jse.value);
1895                 break;
1896             case 2:
1897                 GEN_EVENT(jse.number*4,jse.value,jse.time,evsequence++);
1898                 This->js.lZ = map_axis(jse.value);
1899                 break;
1900             default:
1901                 FIXME("more then 3 axes (%d) not handled!\n",jse.number);
1902                 break;
1903             }
1904         }
1905     }
1906 }
1907
1908 /******************************************************************************
1909   *     GetDeviceState : returns the "state" of the joystick.
1910   *
1911   */
1912 static HRESULT WINAPI JoystickAImpl_GetDeviceState(
1913         LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
1914 ) {
1915     ICOM_THIS(JoystickAImpl,iface);
1916   
1917     joy_polldev(This);
1918     TRACE("(this=%p,0x%08lx,%p)\n",This,len,ptr);
1919     if (len != sizeof(DIJOYSTATE)) {
1920         FIXME("len %ld is not sizeof(DIJOYSTATE), unsupported format.\n",len);
1921     }
1922     memcpy(ptr,&(This->js),len);
1923     This->queue_pos = 0;
1924     return 0;
1925 }
1926
1927 /******************************************************************************
1928   *     GetDeviceState : gets buffered input data.
1929   */
1930 static HRESULT WINAPI JoystickAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1931                                               DWORD dodsize,
1932                                               LPDIDEVICEOBJECTDATA dod,
1933                                               LPDWORD entries,
1934                                               DWORD flags
1935 ) {
1936   ICOM_THIS(JoystickAImpl,iface);
1937   
1938   FIXME("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx),STUB!\n",This,dodsize,*entries,flags);
1939
1940   joy_polldev(This);
1941   if (flags & DIGDD_PEEK)
1942     FIXME("DIGDD_PEEK\n");
1943
1944   if (dod == NULL) {
1945   } else {
1946   }
1947   return 0;
1948 }
1949
1950 /******************************************************************************
1951   *     SetProperty : change input device properties
1952   */
1953 static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1954                                             REFGUID rguid,
1955                                             LPCDIPROPHEADER ph)
1956 {
1957   ICOM_THIS(JoystickAImpl,iface);
1958
1959   FIXME("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
1960   FIXME("ph.dwSize = %ld, ph.dwHeaderSize =%ld, ph.dwObj = %ld, ph.dwHow= %ld\n",ph->dwSize, ph->dwHeaderSize,ph->dwObj,ph->dwHow);
1961   
1962   if (!HIWORD(rguid)) {
1963     switch ((DWORD)rguid) {
1964     case (DWORD) DIPROP_BUFFERSIZE: {
1965       LPCDIPROPDWORD    pd = (LPCDIPROPDWORD)ph;
1966
1967       FIXME("buffersize = %ld\n",pd->dwData);
1968       break;
1969     }
1970     case (DWORD)DIPROP_RANGE: {
1971       LPCDIPROPRANGE    pr = (LPCDIPROPRANGE)ph;
1972
1973       FIXME("proprange(%ld,%ld)\n",pr->lMin,pr->lMax);
1974       This->lMin = pr->lMin;
1975       This->lMax = pr->lMax;
1976       break;
1977     }
1978     case (DWORD)DIPROP_DEADZONE: {
1979       LPCDIPROPDWORD    pd = (LPCDIPROPDWORD)ph;
1980
1981       FIXME("deadzone(%ld)\n",pd->dwData);
1982       This->deadzone = pd->dwData;
1983       break;
1984     }
1985     default:
1986       FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
1987       break;
1988     }
1989   }
1990   return 0;
1991 }
1992
1993 /******************************************************************************
1994   *     SetEventNotification : specifies event to be sent on state change
1995   */
1996 static HRESULT WINAPI JoystickAImpl_SetEventNotification(
1997         LPDIRECTINPUTDEVICE2A iface, HANDLE hnd
1998 ) {
1999     ICOM_THIS(JoystickAImpl,iface);
2000
2001     TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
2002     This->hEvent = hnd;
2003     return DI_OK;
2004 }
2005
2006 static HRESULT WINAPI JoystickAImpl_GetCapabilities(
2007         LPDIRECTINPUTDEVICE2A iface,
2008         LPDIDEVCAPS lpDIDevCaps)
2009 {
2010     ICOM_THIS(JoystickAImpl,iface);
2011     BYTE        axes,buttons;
2012     int         xfd = This->joyfd;
2013
2014     TRACE("%p->(%p)\n",iface,lpDIDevCaps);
2015     if (xfd==-1)
2016         xfd = open(JOYDEV,O_RDONLY);
2017     lpDIDevCaps->dwFlags        = DIDC_ATTACHED;
2018     lpDIDevCaps->dwDevType      = DIDEVTYPE_JOYSTICK;
2019 #ifdef JSIOCGAXES
2020     if (-1==ioctl(xfd,JSIOCGAXES,&axes))
2021         axes = 2;
2022     lpDIDevCaps->dwAxes = axes;
2023 #endif
2024 #ifdef JSIOCGBUTTONS
2025     if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
2026         buttons = 2;
2027     lpDIDevCaps->dwButtons = buttons;
2028 #endif
2029     if (xfd!=This->joyfd)
2030         close(xfd);
2031     return DI_OK;
2032 }
2033 static HRESULT WINAPI JoystickAImpl_Poll(LPDIRECTINPUTDEVICE2A iface) {
2034     ICOM_THIS(JoystickAImpl,iface);
2035     TRACE("(),stub!\n");
2036
2037     joy_polldev(This);
2038     return DI_OK;
2039 }
2040
2041 /******************************************************************************
2042   *     EnumObjects : enumerate the different buttons and axis...
2043   */
2044 static HRESULT WINAPI JoystickAImpl_EnumObjects(
2045         LPDIRECTINPUTDEVICE2A iface,
2046         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
2047         LPVOID lpvRef,
2048         DWORD dwFlags)
2049 {
2050   ICOM_THIS(JoystickAImpl,iface);
2051   DIDEVICEOBJECTINSTANCEA ddoi;
2052   int xfd = This->joyfd;
2053
2054   TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags);
2055   if (TRACE_ON(dinput)) {
2056     DPRINTF("  - flags = ");
2057     _dump_EnumObjects_flags(dwFlags);
2058     DPRINTF("\n");
2059   }
2060
2061   /* Only the fields till dwFFMaxForce are relevant */
2062   ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
2063     
2064   /* For the joystick, do as is done in the GetCapabilities function */
2065   if ((dwFlags == DIDFT_ALL) ||
2066       (dwFlags & DIDFT_AXIS)) {
2067     BYTE axes, i;
2068     
2069 #ifdef JSIOCGAXES
2070     if (-1==ioctl(xfd,JSIOCGAXES,&axes))
2071       axes = 2;
2072 #endif
2073
2074     for (i = 0; i < axes; i++) {
2075       switch (i) {
2076       case 0:
2077         ddoi.guidType = GUID_XAxis;
2078         ddoi.dwOfs = DIJOFS_X;
2079         break;
2080       case 1:
2081         ddoi.guidType = GUID_YAxis;
2082         ddoi.dwOfs = DIJOFS_Y;
2083         break;
2084       case 2:
2085         ddoi.guidType = GUID_ZAxis;
2086         ddoi.dwOfs = DIJOFS_Z;
2087         break;
2088       default:
2089         ddoi.guidType = GUID_Unknown;
2090         ddoi.dwOfs = DIJOFS_Z + (i - 2) * sizeof(LONG);
2091       }
2092       ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << i) << WINE_JOYSTICK_AXIS_BASE) | DIDFT_ABSAXIS;
2093       sprintf(ddoi.tszName, "%d-Axis", i);
2094       _dump_OBJECTINSTANCEA(&ddoi);
2095       if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
2096     }
2097   }
2098
2099   if ((dwFlags == DIDFT_ALL) ||
2100       (dwFlags & DIDFT_BUTTON)) {
2101     BYTE buttons, i;
2102     
2103 #ifdef JSIOCGBUTTONS
2104     if (-1==ioctl(xfd,JSIOCGAXES,&buttons))
2105       buttons = 2;
2106 #endif
2107   
2108     /* The DInput SDK says that GUID_Button is only for mouse buttons but well... */
2109     ddoi.guidType = GUID_Button;
2110     
2111     for (i = 0; i < buttons; i++) {
2112       ddoi.dwOfs = DIJOFS_BUTTON(i);
2113       ddoi.dwType = DIDFT_MAKEINSTANCE((0x0001 << i) << WINE_JOYSTICK_BUTTON_BASE) | DIDFT_PSHBUTTON;
2114       sprintf(ddoi.tszName, "%d-Button", i);
2115       _dump_OBJECTINSTANCEA(&ddoi);
2116       if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK;
2117     }
2118   }
2119
2120   if (xfd!=This->joyfd)
2121     close(xfd);
2122
2123   return DI_OK;
2124 }
2125
2126 /******************************************************************************
2127   *     GetProperty : get input device properties
2128   */
2129 static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE2A iface,
2130                                                 REFGUID rguid,
2131                                                 LPDIPROPHEADER pdiph)
2132 {
2133   ICOM_THIS(JoystickAImpl,iface);
2134
2135   TRACE("(this=%p,%s,%p): stub!\n",
2136         iface, debugstr_guid(rguid), pdiph);
2137
2138   if (TRACE_ON(dinput))
2139     _dump_DIPROPHEADER(pdiph);
2140   
2141   if (!HIWORD(rguid)) {
2142     switch ((DWORD)rguid) {
2143     case (DWORD) DIPROP_BUFFERSIZE: {
2144       LPDIPROPDWORD     pd = (LPDIPROPDWORD)pdiph;
2145       
2146       TRACE(" return buffersize = %d\n",This->queue_len);
2147       pd->dwData = This->queue_len;
2148       break;
2149     }
2150
2151     case (DWORD) DIPROP_RANGE: {
2152       LPDIPROPRANGE pr = (LPDIPROPRANGE) pdiph;
2153
2154       if ((pdiph->dwHow == DIPH_BYID) &&
2155           (pdiph->dwObj & DIDFT_ABSAXIS)) {
2156         /* The app is querying the current range of the axis : return the lMin and lMax values */
2157         pr->lMin = This->lMin;
2158         pr->lMax = This->lMax;
2159       }
2160       
2161       break;
2162     }
2163       
2164     default:
2165       FIXME("Unknown type %ld (%s)\n",(DWORD)rguid,debugstr_guid(rguid));
2166       break;
2167     }
2168   }
2169   
2170   
2171   return DI_OK;
2172 }
2173
2174 #endif
2175
2176 /****************************************************************************/
2177 /****************************************************************************/
2178
2179 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt = 
2180 {
2181         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2182         IDirectInputDevice2AImpl_QueryInterface,
2183         IDirectInputDevice2AImpl_AddRef,
2184         IDirectInputDevice2AImpl_Release,
2185         SysKeyboardAImpl_GetCapabilities,
2186         IDirectInputDevice2AImpl_EnumObjects,
2187         IDirectInputDevice2AImpl_GetProperty,
2188         SysKeyboardAImpl_SetProperty,
2189         SysKeyboardAImpl_Acquire,
2190         SysKeyboardAImpl_Unacquire,
2191         SysKeyboardAImpl_GetDeviceState,
2192         SysKeyboardAImpl_GetDeviceData,
2193         IDirectInputDevice2AImpl_SetDataFormat,
2194         IDirectInputDevice2AImpl_SetEventNotification,
2195         IDirectInputDevice2AImpl_SetCooperativeLevel,
2196         IDirectInputDevice2AImpl_GetObjectInfo,
2197         IDirectInputDevice2AImpl_GetDeviceInfo,
2198         IDirectInputDevice2AImpl_RunControlPanel,
2199         IDirectInputDevice2AImpl_Initialize,
2200         IDirectInputDevice2AImpl_CreateEffect,
2201         IDirectInputDevice2AImpl_EnumEffects,
2202         IDirectInputDevice2AImpl_GetEffectInfo,
2203         IDirectInputDevice2AImpl_GetForceFeedbackState,
2204         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2205         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2206         IDirectInputDevice2AImpl_Escape,
2207         IDirectInputDevice2AImpl_Poll,
2208         IDirectInputDevice2AImpl_SendDeviceData,
2209 };
2210
2211 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt = 
2212 {
2213         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2214         IDirectInputDevice2AImpl_QueryInterface,
2215         IDirectInputDevice2AImpl_AddRef,
2216         SysMouseAImpl_Release,
2217         SysMouseAImpl_GetCapabilities,
2218         SysMouseAImpl_EnumObjects,
2219         SysMouseAImpl_GetProperty,
2220         SysMouseAImpl_SetProperty,
2221         SysMouseAImpl_Acquire,
2222         SysMouseAImpl_Unacquire,
2223         SysMouseAImpl_GetDeviceState,
2224         SysMouseAImpl_GetDeviceData,
2225         SysMouseAImpl_SetDataFormat,
2226         SysMouseAImpl_SetEventNotification,
2227         SysMouseAImpl_SetCooperativeLevel,
2228         IDirectInputDevice2AImpl_GetObjectInfo,
2229         IDirectInputDevice2AImpl_GetDeviceInfo,
2230         IDirectInputDevice2AImpl_RunControlPanel,
2231         IDirectInputDevice2AImpl_Initialize,
2232         IDirectInputDevice2AImpl_CreateEffect,
2233         IDirectInputDevice2AImpl_EnumEffects,
2234         IDirectInputDevice2AImpl_GetEffectInfo,
2235         IDirectInputDevice2AImpl_GetForceFeedbackState,
2236         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2237         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2238         IDirectInputDevice2AImpl_Escape,
2239         IDirectInputDevice2AImpl_Poll,
2240         IDirectInputDevice2AImpl_SendDeviceData,
2241 };
2242
2243 #ifdef HAVE_LINUX_22_JOYSTICK_API
2244 static ICOM_VTABLE(IDirectInputDevice2A) JoystickAvt = 
2245 {
2246         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2247         IDirectInputDevice2AImpl_QueryInterface,
2248         IDirectInputDevice2AImpl_AddRef,
2249         JoystickAImpl_Release,
2250         JoystickAImpl_GetCapabilities,
2251         JoystickAImpl_EnumObjects,
2252         JoystickAImpl_GetProperty,
2253         JoystickAImpl_SetProperty,
2254         JoystickAImpl_Acquire,
2255         JoystickAImpl_Unacquire,
2256         JoystickAImpl_GetDeviceState,
2257         JoystickAImpl_GetDeviceData,
2258         JoystickAImpl_SetDataFormat,
2259         JoystickAImpl_SetEventNotification,
2260         IDirectInputDevice2AImpl_SetCooperativeLevel,
2261         IDirectInputDevice2AImpl_GetObjectInfo,
2262         IDirectInputDevice2AImpl_GetDeviceInfo,
2263         IDirectInputDevice2AImpl_RunControlPanel,
2264         IDirectInputDevice2AImpl_Initialize,
2265         IDirectInputDevice2AImpl_CreateEffect,
2266         IDirectInputDevice2AImpl_EnumEffects,
2267         IDirectInputDevice2AImpl_GetEffectInfo,
2268         IDirectInputDevice2AImpl_GetForceFeedbackState,
2269         IDirectInputDevice2AImpl_SendForceFeedbackCommand,
2270         IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
2271         IDirectInputDevice2AImpl_Escape,
2272         JoystickAImpl_Poll,
2273         IDirectInputDevice2AImpl_SendDeviceData,
2274 };
2275 #endif
2276
2277 /***********************************************************************
2278  *              DllCanUnloadNow (DINPUT.@)
2279  */
2280 HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
2281 {
2282     FIXME("(void): stub\n");
2283
2284     return S_FALSE;
2285 }
2286
2287 /***********************************************************************
2288  *              DllGetClassObject (DINPUT.@)
2289  */
2290 HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,
2291                                         LPVOID *ppv)
2292 {
2293     FIXME("(%p, %p, %p): stub\n", debugstr_guid(rclsid), 
2294           debugstr_guid(riid), ppv);
2295
2296     return CLASS_E_CLASSNOTAVAILABLE;
2297 }
2298
2299 /***********************************************************************
2300  *              DllRegisterServer (DINPUT.@)
2301  */
2302 HRESULT WINAPI DINPUT_DllRegisterServer(void)
2303 {
2304     FIXME("(void): stub\n");
2305
2306     return S_OK;
2307 }
2308
2309 /***********************************************************************
2310  *              DllUnregisterServer (DINPUT.@)
2311  */
2312 HRESULT WINAPI DINPUT_DllUnregisterServer(void)
2313 {
2314     FIXME("(void): stub\n");
2315
2316     return S_OK;
2317 }