Fixes buffer overrun problems with GetDIBits.
[wine.git] / windows / dinput.c
blob47220a385fa6b899246fd977d1f0db77939a68b1
1 /* DirectInput
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
6 */
7 /* Status:
9 * - Tomb Raider 2 Demo:
10 * Playable using keyboard only.
11 * - WingCommander Prophecy Demo:
12 * Doesn't get Input Focus.
14 * - Fallout : works great in X and DGA mode
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.)
21 #include "config.h"
22 #include <string.h>
23 #include <unistd.h>
24 #include <assert.h>
25 #include <sys/signal.h>
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/obj_base.h"
30 #include "gdi.h"
31 #include "dinput.h"
32 #include "debug.h"
33 #include "message.h"
35 #include "mouse.h"
36 #include "ts_xlib.h"
37 #include "sysmetrics.h"
38 #include "x11drv.h"
40 extern BYTE InputKeyStateTable[256];
41 extern int min_keycode, max_keycode;
42 extern WORD keyc2vkey[256];
44 static ICOM_VTABLE(IDirectInputA) ddiavt;
45 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
46 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
48 typedef struct IDirectInputAImpl IDirectInputAImpl;
49 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
50 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
51 typedef struct SysMouseAImpl SysMouseAImpl;
53 struct IDirectInputDevice2AImpl
55 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
56 DWORD ref;
57 GUID guid;
60 struct SysKeyboardAImpl
62 /* IDirectInputDevice2AImpl */
63 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
64 DWORD ref;
65 GUID guid;
66 /* SysKeyboardAImpl */
67 BYTE keystate[256];
70 struct SysMouseAImpl
72 /* IDirectInputDevice2AImpl */
73 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
74 DWORD ref;
75 GUID guid;
76 /* SysMouseAImpl */
77 BYTE absolute;
78 /* Previous position for relative moves */
79 LONG prevX, prevY;
80 LPMOUSE_EVENT_PROC prev_handler;
81 HWND32 win;
82 int xwin;
83 DWORD win_centerX, win_centerY;
84 LPDIDEVICEOBJECTDATA data_queue;
85 int queue_pos, queue_len;
86 int need_warp;
87 int acquired;
91 /* UIDs for Wine "drivers".
92 When enumerating each device supporting DInput, they have two UIDs :
93 - the 'windows' UID
94 - a vendor UID */
95 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
96 0x9e573ed8,
97 0x7734,
98 0x11d2,
99 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
101 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
102 0x0ab8648a,
103 0x7735,
104 0x11d2,
105 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
108 /* FIXME: This is ugly and not thread safe :/ */
109 static IDirectInputDevice2A* current_lock = NULL;
111 /******************************************************************************
112 * Various debugging tools
114 static void _dump_cooperativelevel(DWORD dwFlags) {
115 int i;
116 const struct {
117 DWORD mask;
118 char *name;
119 } flags[] = {
120 #define FE(x) { x, #x},
121 FE(DISCL_BACKGROUND)
122 FE(DISCL_EXCLUSIVE)
123 FE(DISCL_FOREGROUND)
124 FE(DISCL_NONEXCLUSIVE)
126 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
127 if (flags[i].mask & dwFlags)
128 DUMP("%s ",flags[i].name);
129 DUMP("\n");
132 struct IDirectInputAImpl
134 ICOM_VTABLE(IDirectInputA)* lpvtbl;
135 DWORD ref;
138 /******************************************************************************
139 * DirectInputCreate32A
141 HRESULT WINAPI DirectInputCreate32A(HINSTANCE32 hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
143 IDirectInputAImpl* This;
144 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
145 (DWORD)hinst,dwVersion,ppDI,punkOuter
147 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
148 This->ref = 1;
149 This->lpvtbl = &ddiavt;
150 *ppDI=(IDirectInputA*)This;
151 return 0;
153 /******************************************************************************
154 * IDirectInputA_EnumDevices
156 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
157 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACK32A lpCallback,
158 LPVOID pvRef, DWORD dwFlags
161 ICOM_THIS(IDirectInputAImpl,iface);
162 DIDEVICEINSTANCE32A devInstance;
163 int ret;
165 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
167 devInstance.dwSize = sizeof(DIDEVICEINSTANCE32A);
169 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
170 /* Return keyboard */
171 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
172 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
173 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
174 strcpy(devInstance.tszInstanceName, "Keyboard");
175 strcpy(devInstance.tszProductName, "Wine Keyboard");
177 ret = lpCallback(&devInstance, pvRef);
178 TRACE(dinput, "Keyboard registered\n");
180 if (ret == DIENUM_STOP)
181 return 0;
184 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
185 /* Return mouse */
186 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
187 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
188 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
189 strcpy(devInstance.tszInstanceName, "Mouse");
190 strcpy(devInstance.tszProductName, "Wine Mouse");
192 ret = lpCallback(&devInstance, pvRef);
193 TRACE(dinput, "Mouse registered\n");
196 /* Should also do joystick enumerations.... */
198 return 0;
201 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
203 ICOM_THIS(IDirectInputAImpl,iface);
204 return ++(This->ref);
207 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
209 ICOM_THIS(IDirectInputAImpl,iface);
210 if (!(--This->ref)) {
211 HeapFree(GetProcessHeap(),0,This);
212 return 0;
214 return This->ref;
217 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
218 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
219 LPUNKNOWN punk
221 ICOM_THIS(IDirectInputAImpl,iface);
222 char xbuf[50];
224 WINE_StringFromCLSID(rguid,xbuf);
225 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
226 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
227 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
228 SysKeyboardAImpl* newDevice;
229 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
230 newDevice->ref = 1;
231 newDevice->lpvtbl = &SysKeyboardAvt;
232 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
233 memset(newDevice->keystate,0,256);
234 *pdev=(IDirectInputDeviceA*)newDevice;
235 return DI_OK;
237 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
238 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
239 SysKeyboardAImpl* newDevice;
240 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
241 newDevice->ref = 1;
242 newDevice->lpvtbl = &SysMouseAvt;
243 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
244 *pdev=(IDirectInputDeviceA*)newDevice;
245 return DI_OK;
247 return E_FAIL;
250 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
251 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
253 ICOM_THIS(IDirectInputAImpl,iface);
254 char xbuf[50];
256 WINE_StringFromCLSID(riid,xbuf);
257 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
258 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
259 IDirectInputA_AddRef(iface);
260 *ppobj = This;
261 return 0;
263 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
264 IDirectInputA_AddRef(iface);
265 *ppobj = This;
266 return 0;
268 return E_FAIL;
271 static HRESULT WINAPI IDirectInputAImpl_Initialize(
272 LPDIRECTINPUTA iface,HINSTANCE32 hinst,DWORD x
274 return DIERR_ALREADYINITIALIZED;
277 static ICOM_VTABLE(IDirectInputA) ddiavt= {
278 IDirectInputAImpl_QueryInterface,
279 IDirectInputAImpl_AddRef,
280 IDirectInputAImpl_Release,
281 IDirectInputAImpl_CreateDevice,
282 IDirectInputAImpl_EnumDevices,
283 (void*)6,
284 (void*)7,
285 IDirectInputAImpl_Initialize
288 /******************************************************************************
289 * IDirectInputDeviceA
292 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
293 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
296 int i;
297 TRACE(dinput,"(this=%p,%p)\n",This,df);
299 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
300 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
301 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
302 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
303 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
305 for (i=0;i<df->dwNumObjs;i++) {
306 char xbuf[50];
308 if (df->rgodf[i].pguid)
309 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
310 else
311 strcpy(xbuf,"<no guid>");
312 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
313 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
314 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
315 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
318 return 0;
321 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
322 LPDIRECTINPUTDEVICE2A iface,HWND32 hwnd,DWORD dwflags
324 ICOM_THIS(IDirectInputDevice2AImpl,iface);
325 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
326 if (TRACE_ON(dinput))
327 _dump_cooperativelevel(dwflags);
328 return 0;
331 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
332 LPDIRECTINPUTDEVICE2A iface,HANDLE32 hnd
334 ICOM_THIS(IDirectInputDevice2AImpl,iface);
335 FIXME(dinput,"(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
336 return 0;
339 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
341 ICOM_THIS(IDirectInputDevice2AImpl,iface);
342 This->ref--;
343 if (This->ref)
344 return This->ref;
345 HeapFree(GetProcessHeap(),0,This);
346 return 0;
349 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
350 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
353 ICOM_THIS(SysKeyboardAImpl,iface);
354 char xbuf[50];
356 if (HIWORD(rguid))
357 WINE_StringFromCLSID(rguid,xbuf);
358 else
359 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
360 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
361 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
362 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
363 if (!HIWORD(rguid)) {
364 switch ((DWORD)rguid) {
365 case DIPROP_BUFFERSIZE: {
366 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
368 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
369 break;
371 default:
372 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
373 break;
376 return 0;
379 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
380 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
383 if (len==256) {
384 int keyc,vkey;
386 memset(ptr,0,256);
387 for (keyc=min_keycode;keyc<max_keycode;keyc++)
389 /* X keycode to virtual key */
390 vkey = keyc2vkey[keyc] & 0xFF;
391 /* The windows scancode is keyc-min_keycode */
392 if (InputKeyStateTable[vkey]&0x80) {
393 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
394 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
397 return 0;
399 WARN(dinput,"whoops, SysKeyboardAImpl_GetDeviceState got len %ld?\n",len);
400 return 0;
403 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
404 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
405 LPDWORD entries,DWORD flags
408 ICOM_THIS(SysKeyboardAImpl,iface);
409 int keyc,n,vkey,xentries;
411 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
412 This,dodsize,dod,entries,entries?*entries:0,flags);
413 EVENT_WaitNetEvent(FALSE,TRUE);
414 if (entries)
415 xentries = *entries;
416 else
417 xentries = 1;
419 n = 0;
421 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
423 /* X keycode to virtual key */
424 vkey = keyc2vkey[keyc] & 0xFF;
425 if (This->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
426 continue;
427 if (dod) {
428 /* add an entry */
429 dod[n].dwOfs = keyc-min_keycode; /* scancode */
430 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
431 dod[n].dwTimeStamp = 0; /* umm */
432 dod[n].dwSequence = 0; /* umm */
433 n++;
435 if (!(flags & DIGDD_PEEK))
436 This->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
440 if (n) fprintf(stderr,"%d entries\n",n);
441 *entries = n;
442 return 0;
445 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
447 ICOM_THIS(SysKeyboardAImpl,iface);
448 TRACE(dinput,"(this=%p): stub\n",This);
449 return 0;
452 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
454 ICOM_THIS(SysKeyboardAImpl,iface);
455 TRACE(dinput,"(this=%p): stub\n",This);
456 return 0;
459 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
460 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
463 ICOM_THIS(IDirectInputDevice2AImpl,iface);
464 char xbuf[50];
466 WINE_StringFromCLSID(riid,xbuf);
467 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
468 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
469 IDirectInputDevice2_AddRef(iface);
470 *ppobj = This;
471 return 0;
473 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
474 IDirectInputDevice2_AddRef(iface);
475 *ppobj = This;
476 return 0;
478 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
479 IDirectInputDevice2_AddRef(iface);
480 *ppobj = This;
481 return 0;
483 return E_FAIL;
486 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
487 LPDIRECTINPUTDEVICE2A iface)
489 ICOM_THIS(IDirectInputDevice2AImpl,iface);
490 return ++This->ref;
493 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
494 LPDIRECTINPUTDEVICE2A iface,
495 LPDIDEVCAPS lpDIDevCaps)
497 FIXME(dinput, "stub!\n");
498 return DI_OK;
501 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
502 LPDIRECTINPUTDEVICE2A iface,
503 LPDIENUMDEVICEOBJECTSCALLBACK32A lpCallback,
504 LPVOID lpvRef,
505 DWORD dwFlags)
507 FIXME(dinput, "stub!\n");
508 #if 0
509 if (lpCallback)
510 lpCallback(NULL, lpvRef);
511 #endif
512 return DI_OK;
515 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
516 LPDIRECTINPUTDEVICE2A iface,
517 REFGUID rguid,
518 LPDIPROPHEADER pdiph)
520 FIXME(dinput, "stub!\n");
521 return DI_OK;
524 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
525 LPDIRECTINPUTDEVICE2A iface,
526 LPDIDEVICEOBJECTINSTANCE32A pdidoi,
527 DWORD dwObj,
528 DWORD dwHow)
530 FIXME(dinput, "stub!\n");
531 return DI_OK;
534 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
535 LPDIRECTINPUTDEVICE2A iface,
536 LPDIDEVICEINSTANCE32A pdidi)
538 FIXME(dinput, "stub!\n");
539 return DI_OK;
542 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
543 LPDIRECTINPUTDEVICE2A iface,
544 HWND32 hwndOwner,
545 DWORD dwFlags)
547 FIXME(dinput, "stub!\n");
548 return DI_OK;
551 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
552 LPDIRECTINPUTDEVICE2A iface,
553 HINSTANCE32 hinst,
554 DWORD dwVersion,
555 REFGUID rguid)
557 FIXME(dinput, "stub!\n");
558 return DI_OK;
561 /******************************************************************************
562 * IDirectInputDevice2A
565 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
566 LPDIRECTINPUTDEVICE2A iface,
567 REFGUID rguid,
568 LPCDIEFFECT lpeff,
569 LPDIRECTINPUTEFFECT *ppdef,
570 LPUNKNOWN pUnkOuter)
572 FIXME(dinput, "stub!\n");
573 return DI_OK;
576 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
577 LPDIRECTINPUTDEVICE2A iface,
578 LPDIENUMEFFECTSCALLBACKA lpCallback,
579 LPVOID lpvRef,
580 DWORD dwFlags)
582 FIXME(dinput, "stub!\n");
583 if (lpCallback)
584 lpCallback(NULL, lpvRef);
585 return DI_OK;
588 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
589 LPDIRECTINPUTDEVICE2A iface,
590 LPDIEFFECTINFOA lpdei,
591 REFGUID rguid)
593 FIXME(dinput, "stub!\n");
594 return DI_OK;
597 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
598 LPDIRECTINPUTDEVICE2A iface,
599 LPDWORD pdwOut)
601 FIXME(dinput, "stub!\n");
602 return DI_OK;
605 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
606 LPDIRECTINPUTDEVICE2A iface,
607 DWORD dwFlags)
609 FIXME(dinput, "stub!\n");
610 return DI_OK;
613 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
614 LPDIRECTINPUTDEVICE2A iface,
615 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
616 LPVOID lpvRef,
617 DWORD dwFlags)
619 FIXME(dinput, "stub!\n");
620 if (lpCallback)
621 lpCallback(NULL, lpvRef);
622 return DI_OK;
625 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
626 LPDIRECTINPUTDEVICE2A iface,
627 LPDIEFFESCAPE lpDIEEsc)
629 FIXME(dinput, "stub!\n");
630 return DI_OK;
633 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
634 LPDIRECTINPUTDEVICE2A iface)
636 FIXME(dinput, "stub!\n");
637 return DI_OK;
640 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
641 LPDIRECTINPUTDEVICE2A iface,
642 DWORD cbObjectData,
643 LPDIDEVICEOBJECTDATA rgdod,
644 LPDWORD pdwInOut,
645 DWORD dwFlags)
647 FIXME(dinput, "stub!\n");
648 return DI_OK;
651 /******************************************************************************
652 * SysMouseA (DInput Mouse support)
655 /******************************************************************************
656 * Release : release the mouse buffer.
658 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
660 ICOM_THIS(SysMouseAImpl,iface);
662 This->ref--;
663 if (This->ref)
664 return This->ref;
666 /* Free the data queue */
667 if (This->data_queue != NULL)
668 HeapFree(GetProcessHeap(),0,This->data_queue);
670 /* Install the previous event handler (in case of releasing an aquired
671 mouse device) */
672 if (This->prev_handler != NULL)
673 MOUSE_Enable(This->prev_handler);
675 HeapFree(GetProcessHeap(),0,This);
676 return 0;
680 /******************************************************************************
681 * SetCooperativeLevel : store the window in which we will do our
682 * grabbing.
684 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
685 LPDIRECTINPUTDEVICE2A iface,HWND32 hwnd,DWORD dwflags
688 ICOM_THIS(SysMouseAImpl,iface);
690 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
692 if (TRACE_ON(dinput))
693 _dump_cooperativelevel(dwflags);
695 /* Store the window which asks for the mouse */
696 This->win = hwnd;
698 return 0;
702 /******************************************************************************
703 * SetDataFormat : the application can choose the format of the data
704 * the device driver sends back with GetDeviceState.
706 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
707 * in absolute and relative mode.
709 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
710 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
713 ICOM_THIS(SysMouseAImpl,iface);
714 int i;
716 TRACE(dinput,"(this=%p,%p)\n",This,df);
718 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
719 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
720 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
721 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
722 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
724 for (i=0;i<df->dwNumObjs;i++) {
725 char xbuf[50];
727 if (df->rgodf[i].pguid)
728 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
729 else
730 strcpy(xbuf,"<no guid>");
731 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
732 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
733 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
734 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
737 /* Check size of data format to prevent crashes if the applications
738 sends a smaller buffer */
739 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
740 FIXME(dinput, "non-standard mouse configuration not supported yet.");
741 return DIERR_INVALIDPARAM;
744 /* For the moment, ignore these fields and return always as if
745 c_dfDIMouse was passed as format... */
747 /* Check if the mouse is in absolute or relative mode */
748 if (df->dwFlags == DIDF_ABSAXIS)
749 This->absolute = 1;
750 else
751 This->absolute = 0;
753 return 0;
756 #define GEN_EVENT(offset,data,time,seq) \
758 if (This->queue_pos < This->queue_len) { \
759 This->data_queue[This->queue_pos].dwOfs = offset; \
760 This->data_queue[This->queue_pos].dwData = data; \
761 This->data_queue[This->queue_pos].dwTimeStamp = time; \
762 This->data_queue[This->queue_pos].dwSequence = seq; \
763 This->queue_pos++; \
767 /* Our private mouse event handler */
768 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
769 DWORD cButtons, DWORD dwExtraInfo )
771 DWORD posX, posY, keyState, time, extra;
772 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
774 if ( !IsBadReadPtr32( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
775 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
776 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
777 keyState = wme->keyState;
778 time = wme->time;
779 extra = (DWORD)wme->hWnd;
781 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
782 posX = (dx * SYSMETRICS_CXSCREEN) >> 16;
783 posY = (dy * SYSMETRICS_CYSCREEN) >> 16;
784 } else {
785 ERR(dinput, "Mouse event not supported...\n");
786 return ;
789 TRACE(dinput, " %ld %ld ", posX, posY);
791 if ( dwFlags & MOUSEEVENTF_MOVE ) {
792 if (This->absolute) {
793 if (posX != This->prevX)
794 GEN_EVENT(DIMOFS_X, posX, time, 0);
795 if (posY != This->prevY)
796 GEN_EVENT(DIMOFS_Y, posY, time, 0);
797 } else {
798 /* Relative mouse input : the real fun starts here... */
799 if (This->need_warp) {
800 if (posX != This->prevX)
801 GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
802 if (posY != This->prevY)
803 GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
804 } else {
805 /* This is the first time the event handler has been called after a
806 GetData of GetState. */
807 if (posX != This->win_centerX) {
808 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
809 This->need_warp = 1;
812 if (posY != This->win_centerY) {
813 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
814 This->need_warp = 1;
819 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
820 if (TRACE_ON(dinput))
821 DUMP(" LD ");
823 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
825 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
826 if (TRACE_ON(dinput))
827 DUMP(" LU ");
829 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
831 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
832 if (TRACE_ON(dinput))
833 DUMP(" RD ");
835 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
837 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
838 if (TRACE_ON(dinput))
839 DUMP(" RU ");
841 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
843 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
844 if (TRACE_ON(dinput))
845 DUMP(" MD ");
847 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
849 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
850 if (TRACE_ON(dinput))
851 DUMP(" MU ");
853 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
855 if (TRACE_ON(dinput))
856 DUMP("\n");
858 This->prevX = posX;
859 This->prevY = posY;
863 /******************************************************************************
864 * Acquire : gets exclusive control of the mouse
866 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
868 ICOM_THIS(SysMouseAImpl,iface);
869 RECT32 rect;
871 TRACE(dinput,"(this=%p)\n",This);
873 if (This->acquired == 0) {
874 /* This stores the current mouse handler.
875 FIXME : need to be fixed for native USER use */
876 This->prev_handler = mouse_event;
878 /* Store (in a global variable) the current lock */
879 current_lock = (IDirectInputDevice2A*)This;
881 /* Install our own mouse event handler */
882 MOUSE_Enable(dinput_mouse_event);
884 /* Get the window dimension and find the center */
885 GetWindowRect32(This->win, &rect);
886 This->xwin = ((X11DRV_WND_DATA *) WIN_FindWndPtr(This->win)->pDriverData)->window;
887 This->win_centerX = (rect.right - rect.left) / 2;
888 This->win_centerY = (rect.bottom - rect.top ) / 2;
889 /* Warp the mouse to the center of the window */
890 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
891 TSXWarpPointer(display, DefaultRootWindow(display),
892 This->xwin, 0, 0, 0, 0,
893 This->win_centerX, This->win_centerY);
895 This->acquired = 1;
897 return 0;
900 /******************************************************************************
901 * Unacquire : frees the mouse
903 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
905 ICOM_THIS(SysMouseAImpl,iface);
907 TRACE(dinput,"(this=%p)\n",This);
909 /* Reinstall previous mouse event handler */
910 MOUSE_Enable(This->prev_handler);
911 This->prev_handler = NULL;
913 /* No more locks */
914 current_lock = NULL;
916 /* Unacquire device */
917 This->acquired = 0;
919 return 0;
922 /******************************************************************************
923 * GetDeviceState : returns the "state" of the mouse.
925 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
926 * supported.
928 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
929 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
931 ICOM_THIS(SysMouseAImpl,iface);
932 DWORD rx, ry, state;
933 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
935 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",This,len,ptr);
937 /* Check if the buffer is big enough */
938 if (len < sizeof(struct DIMOUSESTATE)) {
939 FIXME(dinput, "unsupported state structure.");
940 return DIERR_INVALIDPARAM;
943 /* Get the mouse position */
944 EVENT_QueryPointer(&rx, &ry, &state);
945 TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
947 /* Fill the mouse state structure */
948 if (This->absolute) {
949 mstate->lX = rx;
950 mstate->lY = ry;
951 } else {
952 mstate->lX = rx - This->win_centerX;
953 mstate->lY = ry - This->win_centerY;
955 if ((mstate->lX != 0) || (mstate->lY != 0))
956 This->need_warp = 1;
958 mstate->lZ = 0;
959 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
960 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
961 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
962 mstate->rgbButtons[3] = 0x00;
964 /* Check if we need to do a mouse warping */
965 if (This->need_warp) {
966 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
967 TSXWarpPointer(display, DefaultRootWindow(display),
968 This->xwin, 0, 0, 0, 0,
969 This->win_centerX, This->win_centerY);
970 This->need_warp = 0;
973 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
974 mstate->lX, mstate->lY,
975 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
977 return 0;
980 /******************************************************************************
981 * GetDeviceState : gets buffered input data.
983 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
984 DWORD dodsize,
985 LPDIDEVICEOBJECTDATA dod,
986 LPDWORD entries,
987 DWORD flags
989 ICOM_THIS(SysMouseAImpl,iface);
991 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
992 This,dodsize,dod,entries,*entries,flags);
994 if (flags & DIGDD_PEEK)
995 TRACE(dinput, "DIGDD_PEEK\n");
997 if (dod == NULL) {
998 *entries = This->queue_pos;
999 This->queue_pos = 0;
1000 } else {
1001 /* Check for buffer overflow */
1002 if (This->queue_pos > *entries) {
1003 WARN(dinput, "Buffer overflow not handled properly yet...\n");
1004 This->queue_pos = *entries;
1006 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1007 ERR(dinput, "Wrong structure size !\n");
1008 return DIERR_INVALIDPARAM;
1011 /* Copy the buffered data into the application queue */
1012 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1014 /* Reset the event queue */
1015 This->queue_pos = 0;
1018 /* Check if we need to do a mouse warping */
1019 if (This->need_warp) {
1020 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1021 TSXWarpPointer(display, DefaultRootWindow(display),
1022 This->xwin, 0, 0, 0, 0,
1023 This->win_centerX, This->win_centerY);
1024 This->need_warp = 0;
1027 return 0;
1030 /******************************************************************************
1031 * SetProperty : change input device properties
1033 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1034 REFGUID rguid,
1035 LPCDIPROPHEADER ph)
1037 ICOM_THIS(SysMouseAImpl,iface);
1038 char xbuf[50];
1040 if (HIWORD(rguid))
1041 WINE_StringFromCLSID(rguid,xbuf);
1042 else
1043 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1045 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
1047 if (!HIWORD(rguid)) {
1048 switch ((DWORD)rguid) {
1049 case DIPROP_BUFFERSIZE: {
1050 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1052 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
1054 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1055 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1056 This->queue_pos = 0;
1057 This->queue_len = pd->dwData;
1058 break;
1060 default:
1061 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
1062 break;
1066 return 0;
1070 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt={
1071 IDirectInputDevice2AImpl_QueryInterface,
1072 IDirectInputDevice2AImpl_AddRef,
1073 IDirectInputDevice2AImpl_Release,
1074 IDirectInputDevice2AImpl_GetCapabilities,
1075 IDirectInputDevice2AImpl_EnumObjects,
1076 IDirectInputDevice2AImpl_GetProperty,
1077 SysKeyboardAImpl_SetProperty,
1078 SysKeyboardAImpl_Acquire,
1079 SysKeyboardAImpl_Unacquire,
1080 SysKeyboardAImpl_GetDeviceState,
1081 SysKeyboardAImpl_GetDeviceData,
1082 IDirectInputDevice2AImpl_SetDataFormat,
1083 IDirectInputDevice2AImpl_SetEventNotification,
1084 IDirectInputDevice2AImpl_SetCooperativeLevel,
1085 IDirectInputDevice2AImpl_GetObjectInfo,
1086 IDirectInputDevice2AImpl_GetDeviceInfo,
1087 IDirectInputDevice2AImpl_RunControlPanel,
1088 IDirectInputDevice2AImpl_Initialize,
1089 IDirectInputDevice2AImpl_CreateEffect,
1090 IDirectInputDevice2AImpl_EnumEffects,
1091 IDirectInputDevice2AImpl_GetEffectInfo,
1092 IDirectInputDevice2AImpl_GetForceFeedbackState,
1093 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1094 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1095 IDirectInputDevice2AImpl_Escape,
1096 IDirectInputDevice2AImpl_Poll,
1097 IDirectInputDevice2AImpl_SendDeviceData,
1100 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt={
1101 IDirectInputDevice2AImpl_QueryInterface,
1102 IDirectInputDevice2AImpl_AddRef,
1103 SysMouseAImpl_Release,
1104 IDirectInputDevice2AImpl_GetCapabilities,
1105 IDirectInputDevice2AImpl_EnumObjects,
1106 IDirectInputDevice2AImpl_GetProperty,
1107 SysMouseAImpl_SetProperty,
1108 SysMouseAImpl_Acquire,
1109 SysMouseAImpl_Unacquire,
1110 SysMouseAImpl_GetDeviceState,
1111 SysMouseAImpl_GetDeviceData,
1112 SysMouseAImpl_SetDataFormat,
1113 IDirectInputDevice2AImpl_SetEventNotification,
1114 SysMouseAImpl_SetCooperativeLevel,
1115 IDirectInputDevice2AImpl_GetObjectInfo,
1116 IDirectInputDevice2AImpl_GetDeviceInfo,
1117 IDirectInputDevice2AImpl_RunControlPanel,
1118 IDirectInputDevice2AImpl_Initialize,
1119 IDirectInputDevice2AImpl_CreateEffect,
1120 IDirectInputDevice2AImpl_EnumEffects,
1121 IDirectInputDevice2AImpl_GetEffectInfo,
1122 IDirectInputDevice2AImpl_GetForceFeedbackState,
1123 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1124 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1125 IDirectInputDevice2AImpl_Escape,
1126 IDirectInputDevice2AImpl_Poll,
1127 IDirectInputDevice2AImpl_SendDeviceData,