Added an unknown VxD error code.
[wine] / dlls / dinput / device.c
1 /*              DirectInput Device
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  *
6  */
7
8 /* This file contains all the Device specific functions that can be used as stubs
9    by real device implementations.
10
11    It also contains all the helper functions.
12 */
13 #include "config.h"
14
15 #include <string.h>
16 #include "debugtools.h"
17 #include "winbase.h"
18 #include "winerror.h"
19 #include "windef.h"
20 #include "dinput.h"
21 #include "device_private.h"
22
23 DEFAULT_DEBUG_CHANNEL(dinput);
24
25 /******************************************************************************
26  *      Various debugging tools
27  */
28 void _dump_cooperativelevel_DI(DWORD dwFlags) {
29   int   i;
30   const struct {
31     DWORD       mask;
32     char        *name;
33   } flags[] = {
34 #define FE(x) { x, #x},
35     FE(DISCL_BACKGROUND)
36     FE(DISCL_EXCLUSIVE)
37     FE(DISCL_FOREGROUND)
38     FE(DISCL_NONEXCLUSIVE)
39 #undef FE
40   };
41   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
42     if (flags[i].mask & dwFlags)
43       DPRINTF("%s ",flags[i].name);
44   DPRINTF("\n");
45 }
46
47 void _dump_EnumObjects_flags(DWORD dwFlags) {
48   int   i;
49   const struct {
50     DWORD       mask;
51     char        *name;
52   } flags[] = {
53 #define FE(x) { x, #x},
54     FE(DIDFT_ABSAXIS)
55     FE(DIDFT_ALL)
56     FE(DIDFT_AXIS)
57     FE(DIDFT_BUTTON)
58     FE(DIDFT_COLLECTION)
59     FE(DIDFT_FFACTUATOR)
60     FE(DIDFT_FFEFFECTTRIGGER)
61     FE(DIDFT_NOCOLLECTION)
62     FE(DIDFT_NODATA)
63     FE(DIDFT_OUTPUT)
64     FE(DIDFT_POV)
65     FE(DIDFT_PSHBUTTON)
66     FE(DIDFT_RELAXIS)
67     FE(DIDFT_TGLBUTTON)
68 #undef FE
69   };
70   if (dwFlags == DIDFT_ALL) {
71     DPRINTF("DIDFT_ALL");
72     return;
73   }
74   for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
75     if (flags[i].mask & dwFlags)
76       DPRINTF("%s ",flags[i].name);
77   if (dwFlags & DIDFT_INSTANCEMASK)
78     DPRINTF("Instance(%04lx) ", dwFlags >> 8);
79 }
80
81 void _dump_DIPROPHEADER(DIPROPHEADER *diph) {
82   DPRINTF("  - dwObj = 0x%08lx\n", diph->dwObj);
83   DPRINTF("  - dwHow = %s\n",
84           ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
85            ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
86             ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
87 }
88
89 void _dump_OBJECTINSTANCEA(DIDEVICEOBJECTINSTANCEA *ddoi) {
90   if (TRACE_ON(dinput)) {
91     DPRINTF("    - enumerating : 0x%08lx - %2ld - 0x%08lx - %s\n",
92             ddoi->guidType.Data1, ddoi->dwOfs, ddoi->dwType, ddoi->tszName);
93   }
94 }
95
96 /* Conversion between internal data buffer and external data buffer */
97 void fill_DataFormat(void *out, void *in, DataFormat *df) {
98   int i;
99   char *in_c = (char *) in;
100   char *out_c = (char *) out;
101
102   if (df->dt == NULL) {
103     /* This means that the app uses Wine's internal data format */
104     memcpy(out, in, df->internal_format_size);
105   } else {
106     for (i = 0; i < df->size; i++) {
107       if (df->dt[i].offset_in >= 0) {
108         switch (df->dt[i].size) {
109         case 1:
110           TRACE("Copying (c) to %d from %d (value %d)\n",
111                 df->dt[i].offset_out, df->dt[i].offset_in, *((char *) (in_c + df->dt[i].offset_in)));
112           *((char *) (out_c + df->dt[i].offset_out)) = *((char *) (in_c + df->dt[i].offset_in));
113           break;
114         
115         case 2:
116           TRACE("Copying (s) to %d from %d (value %d)\n",
117                 df->dt[i].offset_out, df->dt[i].offset_in, *((short *) (in_c + df->dt[i].offset_in)));
118           *((short *) (out_c + df->dt[i].offset_out)) = *((short *) (in_c + df->dt[i].offset_in));
119           break;
120         
121         case 4:
122           TRACE("Copying (i) to %d from %d (value %d)\n",
123                 df->dt[i].offset_out, df->dt[i].offset_in, *((int *) (in_c + df->dt[i].offset_in)));
124           *((int *) (out_c + df->dt[i].offset_out)) = *((int *) (in_c + df->dt[i].offset_in));
125           break;
126         
127         default:
128           memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
129         }
130       } else {
131         switch (df->dt[i].size) {
132         case 1:
133           TRACE("Copying (c) to %d default value %d\n",
134                 df->dt[i].offset_out, df->dt[i].value);
135           *((char *) (out_c + df->dt[i].offset_out)) = (char) df->dt[i].value;
136           break;
137         
138         case 2:
139           TRACE("Copying (s) to %d default value %d\n",
140                 df->dt[i].offset_out, df->dt[i].value);
141           *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
142           break;
143         
144         case 4:
145           TRACE("Copying (i) to %d default value %d\n",
146                 df->dt[i].offset_out, df->dt[i].value);
147           *((int *) (out_c + df->dt[i].offset_out)) = (int) df->dt[i].value;
148           break;
149         
150         default:
151           memset((out_c + df->dt[i].offset_out), df->dt[i].size, 0);
152         }
153       }
154     }
155   }
156 }
157
158 DataFormat *create_DataFormat(DIDATAFORMAT *wine_format, LPCDIDATAFORMAT asked_format, int *offset) {
159   DataFormat *ret;
160   DataTransform *dt;
161   int i, j;
162   int same = 1;
163   int *done;
164   int index = 0;
165   
166   ret = (DataFormat *) HeapAlloc(GetProcessHeap(), 0, sizeof(DataFormat));
167   
168   done = (int *) HeapAlloc(GetProcessHeap(), 0, sizeof(int) * asked_format->dwNumObjs);
169   memset(done, 0, sizeof(int) * asked_format->dwNumObjs);
170
171   dt = (DataTransform *) HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
172
173   TRACE("Creating DataTransorm : \n");
174   
175   for (i = 0; i < wine_format->dwNumObjs; i++) {
176     offset[i] = -1;
177     
178     for (j = 0; j < asked_format->dwNumObjs; j++) {
179       if (done[j] == 1)
180         continue;
181       
182       if (((asked_format->rgodf[j].pguid == NULL) || (IsEqualGUID(wine_format->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
183           &&
184           (wine_format->rgodf[i].dwType & asked_format->rgodf[j].dwType)) {
185
186         done[j] = 1;
187
188         TRACE("Matching : \n"); 
189         TRACE("   - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
190               j, debugstr_guid(asked_format->rgodf[j].pguid), 
191               asked_format->rgodf[j].dwOfs,
192               DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
193         
194         TRACE("   - Wine  (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
195               j, debugstr_guid(wine_format->rgodf[i].pguid), 
196               wine_format->rgodf[i].dwOfs,
197               DIDFT_GETTYPE(wine_format->rgodf[i].dwType), DIDFT_GETINSTANCE(wine_format->rgodf[i].dwType));
198         
199         if (wine_format->rgodf[i].dwType & DIDFT_BUTTON)
200           dt[index].size = sizeof(BYTE);
201         else
202           dt[index].size = sizeof(DWORD);
203         dt[index].offset_in  = wine_format ->rgodf[i].dwOfs;
204         dt[index].offset_out = asked_format->rgodf[j].dwOfs;
205         dt[index].value = 0;
206         index++;
207         
208         if (wine_format->rgodf[i].dwOfs != asked_format->rgodf[j].dwOfs)
209           same = 0;
210
211         offset[i] = asked_format->rgodf[j].dwOfs;
212         break;
213       }
214     }
215
216     if (j == asked_format->dwNumObjs)
217       same = 0;
218   }
219
220   TRACE("Setting to default value :\n");
221   for (j = 0; j < asked_format->dwNumObjs; j++) {
222     if (done[j] == 0) {
223       TRACE(" - Asked (%d) : %s - Ofs = %3ld - (Type = 0x%02x | Instance = %04x)\n",
224             j, debugstr_guid(asked_format->rgodf[j].pguid), 
225             asked_format->rgodf[j].dwOfs,
226             DIDFT_GETTYPE(asked_format->rgodf[j].dwType), DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType));
227
228       
229       if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
230         dt[index].size = sizeof(BYTE);
231       else
232         dt[index].size = sizeof(DWORD);
233       dt[index].offset_in  = -1;
234       dt[index].offset_out = asked_format->rgodf[j].dwOfs;
235       dt[index].value = 0;
236       index++;
237
238       same = 0;
239     }
240   }
241
242   ret->internal_format_size = wine_format->dwDataSize;
243   ret->size = index;
244   if (same) {
245     ret->dt = NULL;
246     HeapFree(GetProcessHeap(), 0, dt);
247   } else {
248     ret->dt = dt;
249   }
250   
251   HeapFree(GetProcessHeap(), 0, done);
252
253   return ret;
254 }
255
256 /******************************************************************************
257  *      IDirectInputDeviceA
258  */
259
260 HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
261         LPDIRECTINPUTDEVICE2A iface,LPCDIDATAFORMAT df
262 ) {
263   int i;
264   ICOM_THIS(IDirectInputDevice2AImpl,iface);
265
266   TRACE("(this=%p,%p)\n",This,df);
267   
268   TRACE("df.dwSize=%ld\n",df->dwSize);
269   TRACE("(df.dwObjsize=%ld)\n",df->dwObjSize);
270   TRACE("(df.dwFlags=0x%08lx)\n",df->dwFlags);
271   TRACE("(df.dwDataSize=%ld)\n",df->dwDataSize);
272   TRACE("(df.dwNumObjs=%ld)\n",df->dwNumObjs);
273   
274   for (i=0;i<df->dwNumObjs;i++) {
275     TRACE("df.rgodf[%d].guid %s\n",i,debugstr_guid(df->rgodf[i].pguid));
276     TRACE("df.rgodf[%d].dwOfs %ld\n",i,df->rgodf[i].dwOfs);
277     TRACE("dwType 0x%02x,dwInstance %d\n",DIDFT_GETTYPE(df->rgodf[i].dwType),DIDFT_GETINSTANCE(df->rgodf[i].dwType));
278     TRACE("df.rgodf[%d].dwFlags 0x%08lx\n",i,df->rgodf[i].dwFlags);
279   }
280   return 0;
281 }
282
283 HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
284         LPDIRECTINPUTDEVICE2A iface,HWND hwnd,DWORD dwflags
285 ) {
286         ICOM_THIS(IDirectInputDevice2AImpl,iface);
287         TRACE("(this=%p,0x%08lx,0x%08lx)\n",This,(DWORD)hwnd,dwflags);
288         if (TRACE_ON(dinput))
289           _dump_cooperativelevel_DI(dwflags);
290         return 0;
291 }
292
293 HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
294         LPDIRECTINPUTDEVICE2A iface,HANDLE hnd
295 ) {
296         ICOM_THIS(IDirectInputDevice2AImpl,iface);
297         FIXME("(this=%p,0x%08lx): stub\n",This,(DWORD)hnd);
298         return 0;
299 }
300
301 ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE2A iface)
302 {
303         ICOM_THIS(IDirectInputDevice2AImpl,iface);
304         This->ref--;
305         if (This->ref)
306                 return This->ref;
307         HeapFree(GetProcessHeap(),0,This);
308         return 0;
309 }
310
311 HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
312         LPDIRECTINPUTDEVICE2A iface,REFIID riid,LPVOID *ppobj
313 )
314 {
315         ICOM_THIS(IDirectInputDevice2AImpl,iface);
316
317         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
318         if (IsEqualGUID(&IID_IUnknown,riid)) {
319                 IDirectInputDevice2_AddRef(iface);
320                 *ppobj = This;
321                 return 0;
322         }
323         if (IsEqualGUID(&IID_IDirectInputDeviceA,riid)) {
324                 IDirectInputDevice2_AddRef(iface);
325                 *ppobj = This;
326                 return 0;
327         }
328         if (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) {
329                 IDirectInputDevice2_AddRef(iface);
330                 *ppobj = This;
331                 return 0;
332         }
333         TRACE("Unsupported interface !\n");
334         return E_FAIL;
335 }
336
337 ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
338         LPDIRECTINPUTDEVICE2A iface)
339 {
340         ICOM_THIS(IDirectInputDevice2AImpl,iface);
341         return ++This->ref;
342 }
343
344 HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
345         LPDIRECTINPUTDEVICE2A iface,
346         LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
347         LPVOID lpvRef,
348         DWORD dwFlags)
349 {
350         FIXME("(this=%p,%p,%p,%08lx): stub!\n", iface, lpCallback, lpvRef, dwFlags);
351         if (TRACE_ON(dinput)) {
352           DPRINTF("  - flags = ");
353           _dump_EnumObjects_flags(dwFlags);
354           DPRINTF("\n");
355         }
356         
357         return DI_OK;
358 }
359         
360 HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
361         LPDIRECTINPUTDEVICE2A iface,
362         REFGUID rguid,
363         LPDIPROPHEADER pdiph)
364 {
365         FIXME("(this=%p,%s,%p): stub!\n",
366               iface, debugstr_guid(rguid), pdiph);
367         
368         if (TRACE_ON(dinput))
369           _dump_DIPROPHEADER(pdiph);
370         
371         return DI_OK;
372 }
373
374 HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
375         LPDIRECTINPUTDEVICE2A iface,
376         LPDIDEVICEOBJECTINSTANCEA pdidoi,
377         DWORD dwObj,
378         DWORD dwHow)
379 {
380         FIXME("(this=%p,%p,%ld,0x%08lx): stub!\n",
381               iface, pdidoi, dwObj, dwHow);
382         
383         return DI_OK;
384 }
385         
386 HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
387         LPDIRECTINPUTDEVICE2A iface,
388         LPDIDEVICEINSTANCEA pdidi)
389 {
390         FIXME("(this=%p,%p): stub!\n",
391               iface, pdidi);
392         
393         return DI_OK;
394 }
395         
396 HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
397         LPDIRECTINPUTDEVICE2A iface,
398         HWND hwndOwner,
399         DWORD dwFlags)
400 {
401   FIXME("(this=%p,0x%08x,0x%08lx): stub!\n",
402         iface, hwndOwner, dwFlags);
403         
404         return DI_OK;
405 }
406         
407 HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
408         LPDIRECTINPUTDEVICE2A iface,
409         HINSTANCE hinst,
410         DWORD dwVersion,
411         REFGUID rguid)
412 {
413         FIXME("(this=%p,%d,%ld,%s): stub!\n",
414               iface, hinst, dwVersion, debugstr_guid(rguid));
415         return DI_OK;
416 }
417         
418 /******************************************************************************
419  *      IDirectInputDevice2A
420  */
421
422 HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
423         LPDIRECTINPUTDEVICE2A iface,
424         REFGUID rguid,
425         LPCDIEFFECT lpeff,
426         LPDIRECTINPUTEFFECT *ppdef,
427         LPUNKNOWN pUnkOuter)
428 {
429         FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
430               iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
431         return DI_OK;
432 }
433
434 HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
435         LPDIRECTINPUTDEVICE2A iface,
436         LPDIENUMEFFECTSCALLBACKA lpCallback,
437         LPVOID lpvRef,
438         DWORD dwFlags)
439 {
440         FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
441               iface, lpCallback, lpvRef, dwFlags);
442         
443         if (lpCallback)
444                 lpCallback(NULL, lpvRef);
445         return DI_OK;
446 }
447
448 HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
449         LPDIRECTINPUTDEVICE2A iface,
450         LPDIEFFECTINFOA lpdei,
451         REFGUID rguid)
452 {
453         FIXME("(this=%p,%p,%s): stub!\n",
454               iface, lpdei, debugstr_guid(rguid));
455         return DI_OK;
456 }
457
458 HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
459         LPDIRECTINPUTDEVICE2A iface,
460         LPDWORD pdwOut)
461 {
462         FIXME("(this=%p,%p): stub!\n",
463               iface, pdwOut);
464         return DI_OK;
465 }
466
467 HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
468         LPDIRECTINPUTDEVICE2A iface,
469         DWORD dwFlags)
470 {
471         FIXME("(this=%p,0x%08lx): stub!\n",
472               iface, dwFlags);
473         return DI_OK;
474 }
475
476 HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
477         LPDIRECTINPUTDEVICE2A iface,
478         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
479         LPVOID lpvRef,
480         DWORD dwFlags)
481 {
482         FIXME("(this=%p,%p,%p,0x%08lx): stub!\n",
483               iface, lpCallback, lpvRef, dwFlags);
484         if (lpCallback)
485                 lpCallback(NULL, lpvRef);
486         return DI_OK;
487 }
488
489 HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
490         LPDIRECTINPUTDEVICE2A iface,
491         LPDIEFFESCAPE lpDIEEsc)
492 {
493         FIXME("(this=%p,%p): stub!\n",
494               iface, lpDIEEsc);
495         return DI_OK;
496 }
497
498 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
499         LPDIRECTINPUTDEVICE2A iface)
500 {
501         FIXME("(this=%p): stub!\n",
502               iface);
503         return DI_OK;
504 }
505
506 HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
507         LPDIRECTINPUTDEVICE2A iface,
508         DWORD cbObjectData,
509         LPDIDEVICEOBJECTDATA rgdod,
510         LPDWORD pdwInOut,
511         DWORD dwFlags)
512 {
513         FIXME("(this=%p,0x%08lx,%p,%p,0x%08lx): stub!\n",
514               iface, cbObjectData, rgdod, pdwInOut, dwFlags);
515         
516         return DI_OK;
517 }
518
519 HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE7A iface,
520                                                           LPCSTR lpszFileName,
521                                                           LPDIENUMEFFECTSINFILECALLBACK pec,
522                                                           LPVOID pvRef,
523                                                           DWORD dwFlags)
524 {
525   FIXME("(%p)->(%s,%p,%p,%08lx): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
526
527   return DI_OK;
528 }
529
530 HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE7A iface,
531                                                           LPCSTR lpszFileName,
532                                                           DWORD dwEntries,
533                                                           LPDIFILEEFFECT rgDiFileEft,
534                                                           DWORD dwFlags)
535 {
536   FIXME("(%p)->(%s,%08lx,%p,%08lx): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
537   
538   return DI_OK;
539 }