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