Added missing GDI heap unlock.
[wine/gsoc_dplay.git] / windows / dinput.c
blob35e2d3f8408c7d5d266f91f0d14e4cea767883f1
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 "dinput.h"
31 #include "debug.h"
32 #include "message.h"
33 #include "display.h"
34 #include "mouse.h"
36 DEFAULT_DEBUG_CHANNEL(dinput)
38 extern BYTE InputKeyStateTable[256];
39 extern int min_keycode, max_keycode;
40 extern WORD keyc2vkey[256];
42 static ICOM_VTABLE(IDirectInputA) ddiavt;
43 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
44 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt;
46 typedef struct IDirectInputAImpl IDirectInputAImpl;
47 typedef struct IDirectInputDevice2AImpl IDirectInputDevice2AImpl;
48 typedef struct SysKeyboardAImpl SysKeyboardAImpl;
49 typedef struct SysMouseAImpl SysMouseAImpl;
51 struct IDirectInputDevice2AImpl
53 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
54 DWORD ref;
55 GUID guid;
58 struct SysKeyboardAImpl
60 /* IDirectInputDevice2AImpl */
61 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
62 DWORD ref;
63 GUID guid;
64 /* SysKeyboardAImpl */
65 BYTE keystate[256];
68 struct SysMouseAImpl
70 /* IDirectInputDevice2AImpl */
71 ICOM_VTABLE(IDirectInputDevice2A)* lpvtbl;
72 DWORD ref;
73 GUID guid;
74 /* SysMouseAImpl */
75 BYTE absolute;
76 /* Previous position for relative moves */
77 LONG prevX, prevY;
78 LPMOUSE_EVENT_PROC prev_handler;
79 HWND win;
80 DWORD win_centerX, win_centerY;
81 LPDIDEVICEOBJECTDATA data_queue;
82 int queue_pos, queue_len;
83 int need_warp;
84 int acquired;
88 /* UIDs for Wine "drivers".
89 When enumerating each device supporting DInput, they have two UIDs :
90 - the 'windows' UID
91 - a vendor UID */
92 static GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */
93 0x9e573ed8,
94 0x7734,
95 0x11d2,
96 {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
98 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
99 0x0ab8648a,
100 0x7735,
101 0x11d2,
102 {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
105 /* FIXME: This is ugly and not thread safe :/ */
106 static IDirectInputDevice2A* current_lock = NULL;
108 /******************************************************************************
109 * Various debugging tools
111 static void _dump_cooperativelevel(DWORD dwFlags) {
112 int i;
113 const struct {
114 DWORD mask;
115 char *name;
116 } flags[] = {
117 #define FE(x) { x, #x},
118 FE(DISCL_BACKGROUND)
119 FE(DISCL_EXCLUSIVE)
120 FE(DISCL_FOREGROUND)
121 FE(DISCL_NONEXCLUSIVE)
123 for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
124 if (flags[i].mask & dwFlags)
125 DUMP("%s ",flags[i].name);
126 DUMP("\n");
129 struct IDirectInputAImpl
131 ICOM_VTABLE(IDirectInputA)* lpvtbl;
132 DWORD ref;
135 /******************************************************************************
136 * DirectInputCreate32A
138 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
140 IDirectInputAImpl* This;
141 TRACE(dinput, "(0x%08lx,%04lx,%p,%p)\n",
142 (DWORD)hinst,dwVersion,ppDI,punkOuter
144 This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
145 This->ref = 1;
146 This->lpvtbl = &ddiavt;
147 *ppDI=(IDirectInputA*)This;
148 return 0;
150 /******************************************************************************
151 * IDirectInputA_EnumDevices
153 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
154 LPDIRECTINPUTA iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
155 LPVOID pvRef, DWORD dwFlags
158 ICOM_THIS(IDirectInputAImpl,iface);
159 DIDEVICEINSTANCEA devInstance;
160 int ret;
162 TRACE(dinput, "(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
164 devInstance.dwSize = sizeof(DIDEVICEINSTANCEA);
166 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
167 /* Return keyboard */
168 devInstance.guidInstance = GUID_SysKeyboard; /* DInput's GUID */
169 devInstance.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
170 devInstance.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
171 strcpy(devInstance.tszInstanceName, "Keyboard");
172 strcpy(devInstance.tszProductName, "Wine Keyboard");
174 ret = lpCallback(&devInstance, pvRef);
175 TRACE(dinput, "Keyboard registered\n");
177 if (ret == DIENUM_STOP)
178 return 0;
181 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
182 /* Return mouse */
183 devInstance.guidInstance = GUID_SysMouse; /* DInput's GUID */
184 devInstance.guidProduct = DInput_Wine_Mouse_GUID; /* Vendor's GUID */
185 devInstance.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_UNKNOWN << 8);
186 strcpy(devInstance.tszInstanceName, "Mouse");
187 strcpy(devInstance.tszProductName, "Wine Mouse");
189 ret = lpCallback(&devInstance, pvRef);
190 TRACE(dinput, "Mouse registered\n");
193 /* Should also do joystick enumerations.... */
195 return 0;
198 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUTA iface)
200 ICOM_THIS(IDirectInputAImpl,iface);
201 return ++(This->ref);
204 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUTA iface)
206 ICOM_THIS(IDirectInputAImpl,iface);
207 if (!(--This->ref)) {
208 HeapFree(GetProcessHeap(),0,This);
209 return 0;
211 return This->ref;
214 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
215 LPDIRECTINPUTA iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
216 LPUNKNOWN punk
218 ICOM_THIS(IDirectInputAImpl,iface);
219 char xbuf[50];
221 WINE_StringFromCLSID(rguid,xbuf);
222 FIXME(dinput,"(this=%p,%s,%p,%p): stub\n",This,xbuf,pdev,punk);
223 if ((!memcmp(&GUID_SysKeyboard,rguid,sizeof(GUID_SysKeyboard))) || /* Generic Keyboard */
224 (!memcmp(&DInput_Wine_Keyboard_GUID,rguid,sizeof(GUID_SysKeyboard)))) { /* Wine Keyboard */
225 SysKeyboardAImpl* newDevice;
226 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
227 newDevice->ref = 1;
228 newDevice->lpvtbl = &SysKeyboardAvt;
229 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
230 memset(newDevice->keystate,0,256);
231 *pdev=(IDirectInputDeviceA*)newDevice;
232 return DI_OK;
234 if ((!memcmp(&GUID_SysMouse,rguid,sizeof(GUID_SysMouse))) || /* Generic Mouse */
235 (!memcmp(&DInput_Wine_Mouse_GUID,rguid,sizeof(GUID_SysMouse)))) { /* Wine Mouse */
236 SysKeyboardAImpl* newDevice;
237 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseAImpl));
238 newDevice->ref = 1;
239 newDevice->lpvtbl = &SysMouseAvt;
240 memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
241 *pdev=(IDirectInputDeviceA*)newDevice;
242 return DI_OK;
244 return E_FAIL;
247 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
248 LPDIRECTINPUTA iface,REFIID riid,LPVOID *ppobj
250 ICOM_THIS(IDirectInputAImpl,iface);
251 char xbuf[50];
253 WINE_StringFromCLSID(riid,xbuf);
254 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
255 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
256 IDirectInputA_AddRef(iface);
257 *ppobj = This;
258 return 0;
260 if (!memcmp(&IID_IDirectInputA,riid,sizeof(*riid))) {
261 IDirectInputA_AddRef(iface);
262 *ppobj = This;
263 return 0;
265 return E_FAIL;
268 static HRESULT WINAPI IDirectInputAImpl_Initialize(
269 LPDIRECTINPUTA iface,HINSTANCE hinst,DWORD x
271 return DIERR_ALREADYINITIALIZED;
274 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUTA iface,
275 REFGUID rguid) {
276 ICOM_THIS(IDirectInputAImpl,iface);
277 char xbuf[50];
279 WINE_StringFromCLSID(rguid,xbuf);
280 FIXME(dinput,"(%p)->(%s): stub\n",This,xbuf);
282 return DI_OK;
285 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUTA iface,
286 HWND hwndOwner,
287 DWORD dwFlags) {
288 ICOM_THIS(IDirectInputAImpl,iface);
289 FIXME(dinput,"(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
291 return DI_OK;
294 static ICOM_VTABLE(IDirectInputA) ddiavt =
296 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
297 IDirectInputAImpl_QueryInterface,
298 IDirectInputAImpl_AddRef,
299 IDirectInputAImpl_Release,
300 IDirectInputAImpl_CreateDevice,
301 IDirectInputAImpl_EnumDevices,
302 IDirectInputAImpl_GetDeviceStatus,
303 IDirectInputAImpl_RunControlPanel,
304 IDirectInputAImpl_Initialize
307 /******************************************************************************
308 * IDirectInputDeviceA
311 static HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
312 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
315 int i;
316 TRACE(dinput,"(this=%p,%p)\n",This,df);
318 TRACE(dinput,"df.dwSize=%ld\n",df->dwSize);
319 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
320 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
321 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
322 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
324 for (i=0;i<df->dwNumObjs;i++) {
325 char xbuf[50];
327 if (df->rgodf[i].pguid)
328 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
329 else
330 strcpy(xbuf,"<no guid>");
331 TRACE(dinput,"df.rgodf[%d].guid %s\n",i,xbuf);
332 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
333 TRACE(dinput,"dwType 0x%02lx,dwInstance %ld\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
334 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
337 return 0;
340 static HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
341 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
343 ICOM_THIS(IDirectInputDevice2AImpl,iface);
344 FIXME(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
345 if (TRACE_ON(dinput))
346 _dump_cooperativelevel(dwflags);
347 return 0;
350 static HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
351 LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
353 ICOM_THIS(IDirectInputDevice2AImpl,iface);
354 FIXME(dinput,"(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
355 return 0;
358 static ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
360 ICOM_THIS(IDirectInputDevice2AImpl,iface);
361 This->ref--;
362 if (This->ref)
363 return This->ref;
364 HeapFree(GetProcessHeap(),0,This);
365 return 0;
368 static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
369 LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
372 ICOM_THIS(SysKeyboardAImpl,iface);
373 char xbuf[50];
375 if (HIWORD(rguid))
376 WINE_StringFromCLSID(rguid,xbuf);
377 else
378 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
379 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
380 TRACE(dinput,"(size=%ld,headersize=%ld,obj=%ld,how=%ld\n",
381 ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow);
382 if (!HIWORD(rguid)) {
383 switch ((DWORD)rguid) {
384 case (DWORD) DIPROP_BUFFERSIZE: {
385 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
387 TRACE(dinput,"(buffersize=%ld)\n",pd->dwData);
388 break;
390 default:
391 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
392 break;
395 return 0;
398 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
399 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
402 if (len==256) {
403 int keyc,vkey;
405 memset(ptr,0,256);
406 for (keyc=min_keycode;keyc<max_keycode;keyc++)
408 /* X keycode to virtual key */
409 vkey = keyc2vkey[keyc] & 0xFF;
410 /* The windows scancode is keyc-min_keycode */
411 if (InputKeyStateTable[vkey]&0x80) {
412 ((LPBYTE)ptr)[keyc-min_keycode]=0x80;
413 ((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
416 return 0;
418 WARN(dinput,"whoops, SysKeyboardAImpl_GetDeviceState got len %ld?\n",len);
419 return 0;
422 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
423 LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
424 LPDWORD entries,DWORD flags
427 ICOM_THIS(SysKeyboardAImpl,iface);
428 int keyc,n,vkey,xentries;
430 TRACE(dinput,"(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
431 This,dodsize,dod,entries,entries?*entries:0,flags);
433 /* FIXME !!! */
435 EVENT_Synchronize( FALSE );
437 if (entries)
438 xentries = *entries;
439 else
440 xentries = 1;
442 n = 0;
444 for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
446 /* X keycode to virtual key */
447 vkey = keyc2vkey[keyc] & 0xFF;
448 if (This->keystate[vkey] == (InputKeyStateTable[vkey]&0x80))
449 continue;
450 if (dod) {
451 /* add an entry */
452 dod[n].dwOfs = keyc-min_keycode; /* scancode */
453 dod[n].dwData = InputKeyStateTable[vkey]&0x80;
454 dod[n].dwTimeStamp = 0; /* umm */
455 dod[n].dwSequence = 0; /* umm */
456 n++;
458 if (!(flags & DIGDD_PEEK))
459 This->keystate[vkey] = InputKeyStateTable[vkey]&0x80;
463 if (n) fprintf(stderr,"%d entries\n",n);
464 *entries = n;
465 return 0;
468 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
470 ICOM_THIS(SysKeyboardAImpl,iface);
471 TRACE(dinput,"(this=%p): stub\n",This);
472 return 0;
475 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
477 ICOM_THIS(SysKeyboardAImpl,iface);
478 TRACE(dinput,"(this=%p): stub\n",This);
479 return 0;
482 static HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
483 LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
486 ICOM_THIS(IDirectInputDevice2AImpl,iface);
487 char xbuf[50];
489 WINE_StringFromCLSID(riid,xbuf);
490 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ppobj);
491 if (!memcmp(&IID_IUnknown,riid,sizeof(*riid))) {
492 IDirectInputDevice2_AddRef(iface);
493 *ppobj = This;
494 return 0;
496 if (!memcmp(&IID_IDirectInputDeviceA,riid,sizeof(*riid))) {
497 IDirectInputDevice2_AddRef(iface);
498 *ppobj = This;
499 return 0;
501 if (!memcmp(&IID_IDirectInputDevice2A,riid,sizeof(*riid))) {
502 IDirectInputDevice2_AddRef(iface);
503 *ppobj = This;
504 return 0;
506 return E_FAIL;
509 static ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
510 LPDIRECTINPUTDEVICE2A iface)
512 ICOM_THIS(IDirectInputDevice2AImpl,iface);
513 return ++This->ref;
516 static HRESULT WINAPI IDirectInputDevice2AImpl_GetCapabilities(
517 LPDIRECTINPUTDEVICE2A iface,
518 LPDIDEVCAPS lpDIDevCaps)
520 FIXME(dinput, "stub!\n");
521 return DI_OK;
524 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
525 LPDIRECTINPUTDEVICE2A iface,
526 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
527 LPVOID lpvRef,
528 DWORD dwFlags)
530 FIXME(dinput, "stub!\n");
531 #if 0
532 if (lpCallback)
533 lpCallback(NULL, lpvRef);
534 #endif
535 return DI_OK;
538 static HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
539 LPDIRECTINPUTDEVICE2A iface,
540 REFGUID rguid,
541 LPDIPROPHEADER pdiph)
543 FIXME(dinput, "stub!\n");
544 return DI_OK;
547 static HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
548 LPDIRECTINPUTDEVICE2A iface,
549 LPDIDEVICEOBJECTINSTANCEA pdidoi,
550 DWORD dwObj,
551 DWORD dwHow)
553 FIXME(dinput, "stub!\n");
554 return DI_OK;
557 static HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
558 LPDIRECTINPUTDEVICE2A iface,
559 LPDIDEVICEINSTANCEA pdidi)
561 FIXME(dinput, "stub!\n");
562 return DI_OK;
565 static HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
566 LPDIRECTINPUTDEVICE2A iface,
567 HWND hwndOwner,
568 DWORD dwFlags)
570 FIXME(dinput, "stub!\n");
571 return DI_OK;
574 static HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
575 LPDIRECTINPUTDEVICE2A iface,
576 HINSTANCE hinst,
577 DWORD dwVersion,
578 REFGUID rguid)
580 FIXME(dinput, "stub!\n");
581 return DI_OK;
584 /******************************************************************************
585 * IDirectInputDevice2A
588 static HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
589 LPDIRECTINPUTDEVICE2A iface,
590 REFGUID rguid,
591 LPCDIEFFECT lpeff,
592 LPDIRECTINPUTEFFECT *ppdef,
593 LPUNKNOWN pUnkOuter)
595 FIXME(dinput, "stub!\n");
596 return DI_OK;
599 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
600 LPDIRECTINPUTDEVICE2A iface,
601 LPDIENUMEFFECTSCALLBACKA lpCallback,
602 LPVOID lpvRef,
603 DWORD dwFlags)
605 FIXME(dinput, "stub!\n");
606 if (lpCallback)
607 lpCallback(NULL, lpvRef);
608 return DI_OK;
611 static HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
612 LPDIRECTINPUTDEVICE2A iface,
613 LPDIEFFECTINFOA lpdei,
614 REFGUID rguid)
616 FIXME(dinput, "stub!\n");
617 return DI_OK;
620 static HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
621 LPDIRECTINPUTDEVICE2A iface,
622 LPDWORD pdwOut)
624 FIXME(dinput, "stub!\n");
625 return DI_OK;
628 static HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
629 LPDIRECTINPUTDEVICE2A iface,
630 DWORD dwFlags)
632 FIXME(dinput, "stub!\n");
633 return DI_OK;
636 static HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
637 LPDIRECTINPUTDEVICE2A iface,
638 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
639 LPVOID lpvRef,
640 DWORD dwFlags)
642 FIXME(dinput, "stub!\n");
643 if (lpCallback)
644 lpCallback(NULL, lpvRef);
645 return DI_OK;
648 static HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
649 LPDIRECTINPUTDEVICE2A iface,
650 LPDIEFFESCAPE lpDIEEsc)
652 FIXME(dinput, "stub!\n");
653 return DI_OK;
656 static HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
657 LPDIRECTINPUTDEVICE2A iface)
659 FIXME(dinput, "stub!\n");
660 return DI_OK;
663 static HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
664 LPDIRECTINPUTDEVICE2A iface,
665 DWORD cbObjectData,
666 LPDIDEVICEOBJECTDATA rgdod,
667 LPDWORD pdwInOut,
668 DWORD dwFlags)
670 FIXME(dinput, "stub!\n");
671 return DI_OK;
674 /******************************************************************************
675 * SysMouseA (DInput Mouse support)
678 /******************************************************************************
679 * Release : release the mouse buffer.
681 static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE2A iface)
683 ICOM_THIS(SysMouseAImpl,iface);
685 This->ref--;
686 if (This->ref)
687 return This->ref;
689 /* Free the data queue */
690 if (This->data_queue != NULL)
691 HeapFree(GetProcessHeap(),0,This->data_queue);
693 /* Install the previous event handler (in case of releasing an aquired
694 mouse device) */
695 if (This->prev_handler != NULL)
696 MOUSE_Enable(This->prev_handler);
698 HeapFree(GetProcessHeap(),0,This);
699 return 0;
703 /******************************************************************************
704 * SetCooperativeLevel : store the window in which we will do our
705 * grabbing.
707 static HRESULT WINAPI SysMouseAImpl_SetCooperativeLevel(
708 LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
711 ICOM_THIS(SysMouseAImpl,iface);
713 TRACE(dinput,"(this=%p,0x%08lx,0x%08lx): stub\n",This,(DWORD)hwnd,dwflags);
715 if (TRACE_ON(dinput))
716 _dump_cooperativelevel(dwflags);
718 /* Store the window which asks for the mouse */
719 This->win = hwnd;
721 return 0;
725 /******************************************************************************
726 * SetDataFormat : the application can choose the format of the data
727 * the device driver sends back with GetDeviceState.
729 * For the moment, only the "standard" configuration (c_dfDIMouse) is supported
730 * in absolute and relative mode.
732 static HRESULT WINAPI SysMouseAImpl_SetDataFormat(
733 LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
736 ICOM_THIS(SysMouseAImpl,iface);
737 int i;
739 TRACE(dinput,"(this=%p,%p)\n",This,df);
741 TRACE(dinput,"(df.dwSize=%ld)\n",df->dwSize);
742 TRACE(dinput,"(df.dwObjsize=%ld)\n",df->dwObjSize);
743 TRACE(dinput,"(df.dwFlags=0x%08lx)\n",df->dwFlags);
744 TRACE(dinput,"(df.dwDataSize=%ld)\n",df->dwDataSize);
745 TRACE(dinput,"(df.dwNumObjs=%ld)\n",df->dwNumObjs);
747 for (i=0;i<df->dwNumObjs;i++) {
748 char xbuf[50];
750 if (df->rgodf[i].pguid)
751 WINE_StringFromCLSID(df->rgodf[i].pguid,xbuf);
752 else
753 strcpy(xbuf,"<no guid>");
754 TRACE(dinput,"df.rgodf[%d].guid %s (%p)\n",i,xbuf, df->rgodf[i].pguid);
755 TRACE(dinput,"df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
756 TRACE(dinput,"dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
757 TRACE(dinput,"df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
760 /* Check size of data format to prevent crashes if the applications
761 sends a smaller buffer */
762 if (df->dwDataSize != sizeof(struct DIMOUSESTATE)) {
763 FIXME(dinput, "non-standard mouse configuration not supported yet.");
764 return DIERR_INVALIDPARAM;
767 /* For the moment, ignore these fields and return always as if
768 c_dfDIMouse was passed as format... */
770 /* Check if the mouse is in absolute or relative mode */
771 if (df->dwFlags == DIDF_ABSAXIS)
772 This->absolute = 1;
773 else
774 This->absolute = 0;
776 return 0;
779 #define GEN_EVENT(offset,data,time,seq) \
781 if (This->queue_pos < This->queue_len) { \
782 This->data_queue[This->queue_pos].dwOfs = offset; \
783 This->data_queue[This->queue_pos].dwData = data; \
784 This->data_queue[This->queue_pos].dwTimeStamp = time; \
785 This->data_queue[This->queue_pos].dwSequence = seq; \
786 This->queue_pos++; \
790 /* Our private mouse event handler */
791 static void WINAPI dinput_mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
792 DWORD cButtons, DWORD dwExtraInfo )
794 DWORD posX, posY, keyState, time, extra;
795 SysMouseAImpl* This = (SysMouseAImpl*) current_lock;
797 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
798 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC ) {
799 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
800 keyState = wme->keyState;
801 time = wme->time;
802 extra = (DWORD)wme->hWnd;
804 assert( dwFlags & MOUSEEVENTF_ABSOLUTE );
805 posX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
806 posY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
807 } else {
808 ERR(dinput, "Mouse event not supported...\n");
809 return ;
812 TRACE(dinput, " %ld %ld ", posX, posY);
814 if ( dwFlags & MOUSEEVENTF_MOVE ) {
815 if (This->absolute) {
816 if (posX != This->prevX)
817 GEN_EVENT(DIMOFS_X, posX, time, 0);
818 if (posY != This->prevY)
819 GEN_EVENT(DIMOFS_Y, posY, time, 0);
820 } else {
821 /* Relative mouse input : the real fun starts here... */
822 if (This->need_warp) {
823 if (posX != This->prevX)
824 GEN_EVENT(DIMOFS_X, posX - This->prevX, time, 0);
825 if (posY != This->prevY)
826 GEN_EVENT(DIMOFS_Y, posY - This->prevY, time, 0);
827 } else {
828 /* This is the first time the event handler has been called after a
829 GetData of GetState. */
830 if (posX != This->win_centerX) {
831 GEN_EVENT(DIMOFS_X, posX - This->win_centerX, time, 0);
832 This->need_warp = 1;
835 if (posY != This->win_centerY) {
836 GEN_EVENT(DIMOFS_Y, posY - This->win_centerY, time, 0);
837 This->need_warp = 1;
842 if ( dwFlags & MOUSEEVENTF_LEFTDOWN ) {
843 if (TRACE_ON(dinput))
844 DUMP(" LD ");
846 GEN_EVENT(DIMOFS_BUTTON0, 0xFF, time, 0);
848 if ( dwFlags & MOUSEEVENTF_LEFTUP ) {
849 if (TRACE_ON(dinput))
850 DUMP(" LU ");
852 GEN_EVENT(DIMOFS_BUTTON0, 0x00, time, 0);
854 if ( dwFlags & MOUSEEVENTF_RIGHTDOWN ) {
855 if (TRACE_ON(dinput))
856 DUMP(" RD ");
858 GEN_EVENT(DIMOFS_BUTTON1, 0xFF, time, 0);
860 if ( dwFlags & MOUSEEVENTF_RIGHTUP ) {
861 if (TRACE_ON(dinput))
862 DUMP(" RU ");
864 GEN_EVENT(DIMOFS_BUTTON1, 0x00, time, 0);
866 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN ) {
867 if (TRACE_ON(dinput))
868 DUMP(" MD ");
870 GEN_EVENT(DIMOFS_BUTTON2, 0xFF, time, 0);
872 if ( dwFlags & MOUSEEVENTF_MIDDLEUP ) {
873 if (TRACE_ON(dinput))
874 DUMP(" MU ");
876 GEN_EVENT(DIMOFS_BUTTON2, 0x00, time, 0);
878 if (TRACE_ON(dinput))
879 DUMP("\n");
881 This->prevX = posX;
882 This->prevY = posY;
886 /******************************************************************************
887 * Acquire : gets exclusive control of the mouse
889 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
891 ICOM_THIS(SysMouseAImpl,iface);
892 RECT rect;
894 TRACE(dinput,"(this=%p)\n",This);
896 if (This->acquired == 0) {
897 POINT point;
899 /* This stores the current mouse handler. */
900 This->prev_handler = mouse_event;
902 /* Store (in a global variable) the current lock */
903 current_lock = (IDirectInputDevice2A*)This;
905 /* Install our own mouse event handler */
906 MOUSE_Enable(dinput_mouse_event);
908 /* Get the window dimension and find the center */
909 GetWindowRect(This->win, &rect);
910 This->win_centerX = (rect.right - rect.left) / 2;
911 This->win_centerY = (rect.bottom - rect.top ) / 2;
913 /* Warp the mouse to the center of the window */
914 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
915 point.x = This->win_centerX;
916 point.y = This->win_centerY;
917 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
918 DISPLAY_MoveCursor(point.x, point.y);
920 This->acquired = 1;
922 return 0;
925 /******************************************************************************
926 * Unacquire : frees the mouse
928 static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
930 ICOM_THIS(SysMouseAImpl,iface);
932 TRACE(dinput,"(this=%p)\n",This);
934 /* Reinstall previous mouse event handler */
935 MOUSE_Enable(This->prev_handler);
936 This->prev_handler = NULL;
938 /* No more locks */
939 current_lock = NULL;
941 /* Unacquire device */
942 This->acquired = 0;
944 return 0;
947 /******************************************************************************
948 * GetDeviceState : returns the "state" of the mouse.
950 * For the moment, only the "standard" return structure (DIMOUSESTATE) is
951 * supported.
953 static HRESULT WINAPI SysMouseAImpl_GetDeviceState(
954 LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
956 ICOM_THIS(SysMouseAImpl,iface);
957 DWORD rx, ry, state;
958 struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr;
960 TRACE(dinput,"(this=%p,0x%08lx,%p): \n",This,len,ptr);
962 /* Check if the buffer is big enough */
963 if (len < sizeof(struct DIMOUSESTATE)) {
964 FIXME(dinput, "unsupported state structure.");
965 return DIERR_INVALIDPARAM;
968 /* Get the mouse position */
969 EVENT_QueryPointer(&rx, &ry, &state);
970 TRACE(dinput,"(X:%ld - Y:%ld)\n", rx, ry);
972 /* Fill the mouse state structure */
973 if (This->absolute) {
974 mstate->lX = rx;
975 mstate->lY = ry;
976 } else {
977 mstate->lX = rx - This->win_centerX;
978 mstate->lY = ry - This->win_centerY;
980 if ((mstate->lX != 0) || (mstate->lY != 0))
981 This->need_warp = 1;
983 mstate->lZ = 0;
984 mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00);
985 mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00);
986 mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00);
987 mstate->rgbButtons[3] = 0x00;
989 /* Check if we need to do a mouse warping */
990 if (This->need_warp) {
991 POINT point;
993 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
994 point.x = This->win_centerX;
995 point.y = This->win_centerY;
996 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
997 DISPLAY_MoveCursor(point.x, point.y);
999 This->need_warp = 0;
1002 TRACE(dinput, "(X: %ld - Y: %ld L: %02x M: %02x R: %02x)\n",
1003 mstate->lX, mstate->lY,
1004 mstate->rgbButtons[0], mstate->rgbButtons[2], mstate->rgbButtons[1]);
1006 return 0;
1009 /******************************************************************************
1010 * GetDeviceState : gets buffered input data.
1012 static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE2A iface,
1013 DWORD dodsize,
1014 LPDIDEVICEOBJECTDATA dod,
1015 LPDWORD entries,
1016 DWORD flags
1018 ICOM_THIS(SysMouseAImpl,iface);
1020 TRACE(dinput,"(%p)->(%ld,%p,%p(0x%08lx),0x%08lx)\n",
1021 This,dodsize,dod,entries,*entries,flags);
1023 if (flags & DIGDD_PEEK)
1024 TRACE(dinput, "DIGDD_PEEK\n");
1026 if (dod == NULL) {
1027 *entries = This->queue_pos;
1028 This->queue_pos = 0;
1029 } else {
1030 /* Check for buffer overflow */
1031 if (This->queue_pos > *entries) {
1032 WARN(dinput, "Buffer overflow not handled properly yet...\n");
1033 This->queue_pos = *entries;
1035 if (dodsize != sizeof(DIDEVICEOBJECTDATA)) {
1036 ERR(dinput, "Wrong structure size !\n");
1037 return DIERR_INVALIDPARAM;
1040 TRACE(dinput, "Application retrieving %d event(s).\n", This->queue_pos);
1042 /* Copy the buffered data into the application queue */
1043 memcpy(dod, This->data_queue, This->queue_pos * dodsize);
1045 /* Reset the event queue */
1046 This->queue_pos = 0;
1049 /* Check if we need to do a mouse warping */
1050 if (This->need_warp) {
1051 POINT point;
1053 TRACE(dinput, "Warping mouse to %ld - %ld\n", This->win_centerX, This->win_centerY);
1054 point.x = This->win_centerX;
1055 point.y = This->win_centerY;
1056 MapWindowPoints(This->win, HWND_DESKTOP, &point, 1);
1057 DISPLAY_MoveCursor(point.x, point.y);
1059 This->need_warp = 0;
1062 return 0;
1065 /******************************************************************************
1066 * SetProperty : change input device properties
1068 static HRESULT WINAPI SysMouseAImpl_SetProperty(LPDIRECTINPUTDEVICE2A iface,
1069 REFGUID rguid,
1070 LPCDIPROPHEADER ph)
1072 ICOM_THIS(SysMouseAImpl,iface);
1073 char xbuf[50];
1075 if (HIWORD(rguid))
1076 WINE_StringFromCLSID(rguid,xbuf);
1077 else
1078 sprintf(xbuf,"<special guid %ld>",(DWORD)rguid);
1080 TRACE(dinput,"(this=%p,%s,%p)\n",This,xbuf,ph);
1082 if (!HIWORD(rguid)) {
1083 switch ((DWORD)rguid) {
1084 case (DWORD) DIPROP_BUFFERSIZE: {
1085 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
1087 TRACE(dinput,"buffersize = %ld\n",pd->dwData);
1089 This->data_queue = (LPDIDEVICEOBJECTDATA)HeapAlloc(GetProcessHeap(),0,
1090 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1091 This->queue_pos = 0;
1092 This->queue_len = pd->dwData;
1093 break;
1095 default:
1096 WARN(dinput,"Unknown type %ld\n",(DWORD)rguid);
1097 break;
1101 return 0;
1105 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
1107 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1108 IDirectInputDevice2AImpl_QueryInterface,
1109 IDirectInputDevice2AImpl_AddRef,
1110 IDirectInputDevice2AImpl_Release,
1111 IDirectInputDevice2AImpl_GetCapabilities,
1112 IDirectInputDevice2AImpl_EnumObjects,
1113 IDirectInputDevice2AImpl_GetProperty,
1114 SysKeyboardAImpl_SetProperty,
1115 SysKeyboardAImpl_Acquire,
1116 SysKeyboardAImpl_Unacquire,
1117 SysKeyboardAImpl_GetDeviceState,
1118 SysKeyboardAImpl_GetDeviceData,
1119 IDirectInputDevice2AImpl_SetDataFormat,
1120 IDirectInputDevice2AImpl_SetEventNotification,
1121 IDirectInputDevice2AImpl_SetCooperativeLevel,
1122 IDirectInputDevice2AImpl_GetObjectInfo,
1123 IDirectInputDevice2AImpl_GetDeviceInfo,
1124 IDirectInputDevice2AImpl_RunControlPanel,
1125 IDirectInputDevice2AImpl_Initialize,
1126 IDirectInputDevice2AImpl_CreateEffect,
1127 IDirectInputDevice2AImpl_EnumEffects,
1128 IDirectInputDevice2AImpl_GetEffectInfo,
1129 IDirectInputDevice2AImpl_GetForceFeedbackState,
1130 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1131 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1132 IDirectInputDevice2AImpl_Escape,
1133 IDirectInputDevice2AImpl_Poll,
1134 IDirectInputDevice2AImpl_SendDeviceData,
1137 static ICOM_VTABLE(IDirectInputDevice2A) SysMouseAvt =
1139 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1140 IDirectInputDevice2AImpl_QueryInterface,
1141 IDirectInputDevice2AImpl_AddRef,
1142 SysMouseAImpl_Release,
1143 IDirectInputDevice2AImpl_GetCapabilities,
1144 IDirectInputDevice2AImpl_EnumObjects,
1145 IDirectInputDevice2AImpl_GetProperty,
1146 SysMouseAImpl_SetProperty,
1147 SysMouseAImpl_Acquire,
1148 SysMouseAImpl_Unacquire,
1149 SysMouseAImpl_GetDeviceState,
1150 SysMouseAImpl_GetDeviceData,
1151 SysMouseAImpl_SetDataFormat,
1152 IDirectInputDevice2AImpl_SetEventNotification,
1153 SysMouseAImpl_SetCooperativeLevel,
1154 IDirectInputDevice2AImpl_GetObjectInfo,
1155 IDirectInputDevice2AImpl_GetDeviceInfo,
1156 IDirectInputDevice2AImpl_RunControlPanel,
1157 IDirectInputDevice2AImpl_Initialize,
1158 IDirectInputDevice2AImpl_CreateEffect,
1159 IDirectInputDevice2AImpl_EnumEffects,
1160 IDirectInputDevice2AImpl_GetEffectInfo,
1161 IDirectInputDevice2AImpl_GetForceFeedbackState,
1162 IDirectInputDevice2AImpl_SendForceFeedbackCommand,
1163 IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
1164 IDirectInputDevice2AImpl_Escape,
1165 IDirectInputDevice2AImpl_Poll,
1166 IDirectInputDevice2AImpl_SendDeviceData,