explorerframe: A spelling fix in a comment.
[wine.git] / dlls / dinput / device.c
bloba9ef2d4a3ddbab9699a77c0be4f3c4bb05d90761
1 /* DirectInput Device
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 /* This file contains all the Device specific functions that can be used as stubs
23 by real device implementations.
25 It also contains all the helper functions.
27 #include "config.h"
29 #include <stdarg.h>
30 #include <string.h>
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winreg.h"
36 #include "winuser.h"
37 #include "winerror.h"
38 #include "dinput.h"
39 #include "device_private.h"
40 #include "dinput_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
44 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
46 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface);
48 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
50 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface);
53 static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl *This)
55 return &This->IDirectInputDevice8A_iface;
57 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
59 return &This->IDirectInputDevice8W_iface;
62 /******************************************************************************
63 * Various debugging tools
65 static void _dump_cooperativelevel_DI(DWORD dwFlags) {
66 if (TRACE_ON(dinput)) {
67 unsigned int i;
68 static const struct {
69 DWORD mask;
70 const char *name;
71 } flags[] = {
72 #define FE(x) { x, #x}
73 FE(DISCL_BACKGROUND),
74 FE(DISCL_EXCLUSIVE),
75 FE(DISCL_FOREGROUND),
76 FE(DISCL_NONEXCLUSIVE),
77 FE(DISCL_NOWINKEY)
78 #undef FE
80 TRACE(" cooperative level : ");
81 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
82 if (flags[i].mask & dwFlags)
83 TRACE("%s ",flags[i].name);
84 TRACE("\n");
88 static void _dump_ObjectDataFormat_flags(DWORD dwFlags) {
89 unsigned int i;
90 static const struct {
91 DWORD mask;
92 const char *name;
93 } flags[] = {
94 #define FE(x) { x, #x}
95 FE(DIDOI_FFACTUATOR),
96 FE(DIDOI_FFEFFECTTRIGGER),
97 FE(DIDOI_POLLED),
98 FE(DIDOI_GUIDISUSAGE)
99 #undef FE
102 if (!dwFlags) return;
104 TRACE("Flags:");
106 /* First the flags */
107 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) {
108 if (flags[i].mask & dwFlags)
109 TRACE(" %s",flags[i].name);
112 /* Now specific values */
113 #define FE(x) case x: TRACE(" "#x); break
114 switch (dwFlags & DIDOI_ASPECTMASK) {
115 FE(DIDOI_ASPECTACCEL);
116 FE(DIDOI_ASPECTFORCE);
117 FE(DIDOI_ASPECTPOSITION);
118 FE(DIDOI_ASPECTVELOCITY);
120 #undef FE
124 static void _dump_EnumObjects_flags(DWORD dwFlags) {
125 if (TRACE_ON(dinput)) {
126 unsigned int i;
127 DWORD type, instance;
128 static const struct {
129 DWORD mask;
130 const char *name;
131 } flags[] = {
132 #define FE(x) { x, #x}
133 FE(DIDFT_RELAXIS),
134 FE(DIDFT_ABSAXIS),
135 FE(DIDFT_PSHBUTTON),
136 FE(DIDFT_TGLBUTTON),
137 FE(DIDFT_POV),
138 FE(DIDFT_COLLECTION),
139 FE(DIDFT_NODATA),
140 FE(DIDFT_FFACTUATOR),
141 FE(DIDFT_FFEFFECTTRIGGER),
142 FE(DIDFT_OUTPUT),
143 FE(DIDFT_VENDORDEFINED),
144 FE(DIDFT_ALIAS),
145 FE(DIDFT_OPTIONAL)
146 #undef FE
148 type = (dwFlags & 0xFF0000FF);
149 instance = ((dwFlags >> 8) & 0xFFFF);
150 TRACE("Type:");
151 if (type == DIDFT_ALL) {
152 TRACE(" DIDFT_ALL");
153 } else {
154 for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) {
155 if (flags[i].mask & type) {
156 type &= ~flags[i].mask;
157 TRACE(" %s",flags[i].name);
160 if (type) {
161 TRACE(" (unhandled: %08x)", type);
164 TRACE(" / Instance: ");
165 if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
166 TRACE("DIDFT_ANYINSTANCE");
167 } else {
168 TRACE("%3d", instance);
173 void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) {
174 if (TRACE_ON(dinput)) {
175 TRACE(" - dwObj = 0x%08x\n", diph->dwObj);
176 TRACE(" - dwHow = %s\n",
177 ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
178 ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
179 ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
183 void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) {
184 TRACE(" - enumerating : %s ('%s') - %2d - 0x%08x - %s - 0x%x\n",
185 debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, ddoi->tszName, ddoi->dwFlags);
188 void _dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW *ddoi) {
189 TRACE(" - enumerating : %s ('%s'), - %2d - 0x%08x - %s - 0x%x\n",
190 debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName), ddoi->dwFlags);
193 /* This function is a helper to convert a GUID into any possible DInput GUID out there */
194 const char *_dump_dinput_GUID(const GUID *guid) {
195 unsigned int i;
196 static const struct {
197 const GUID *guid;
198 const char *name;
199 } guids[] = {
200 #define FE(x) { &x, #x}
201 FE(GUID_XAxis),
202 FE(GUID_YAxis),
203 FE(GUID_ZAxis),
204 FE(GUID_RxAxis),
205 FE(GUID_RyAxis),
206 FE(GUID_RzAxis),
207 FE(GUID_Slider),
208 FE(GUID_Button),
209 FE(GUID_Key),
210 FE(GUID_POV),
211 FE(GUID_Unknown),
212 FE(GUID_SysMouse),
213 FE(GUID_SysKeyboard),
214 FE(GUID_Joystick),
215 FE(GUID_ConstantForce),
216 FE(GUID_RampForce),
217 FE(GUID_Square),
218 FE(GUID_Sine),
219 FE(GUID_Triangle),
220 FE(GUID_SawtoothUp),
221 FE(GUID_SawtoothDown),
222 FE(GUID_Spring),
223 FE(GUID_Damper),
224 FE(GUID_Inertia),
225 FE(GUID_Friction),
226 FE(GUID_CustomForce)
227 #undef FE
229 if (guid == NULL)
230 return "null GUID";
231 for (i = 0; i < (sizeof(guids) / sizeof(guids[0])); i++) {
232 if (IsEqualGUID(guids[i].guid, guid)) {
233 return guids[i].name;
236 return debugstr_guid(guid);
239 void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
240 unsigned int i;
242 TRACE("Dumping DIDATAFORMAT structure:\n");
243 TRACE(" - dwSize: %d\n", df->dwSize);
244 if (df->dwSize != sizeof(DIDATAFORMAT)) {
245 WARN("Non-standard DIDATAFORMAT structure size %d\n", df->dwSize);
247 TRACE(" - dwObjsize: %d\n", df->dwObjSize);
248 if (df->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) {
249 WARN("Non-standard DIOBJECTDATAFORMAT structure size %d\n", df->dwObjSize);
251 TRACE(" - dwFlags: 0x%08x (", df->dwFlags);
252 switch (df->dwFlags) {
253 case DIDF_ABSAXIS: TRACE("DIDF_ABSAXIS"); break;
254 case DIDF_RELAXIS: TRACE("DIDF_RELAXIS"); break;
255 default: TRACE("unknown"); break;
257 TRACE(")\n");
258 TRACE(" - dwDataSize: %d\n", df->dwDataSize);
259 TRACE(" - dwNumObjs: %d\n", df->dwNumObjs);
261 for (i = 0; i < df->dwNumObjs; i++) {
262 TRACE(" - Object %d:\n", i);
263 TRACE(" * GUID: %s ('%s')\n", debugstr_guid(df->rgodf[i].pguid), _dump_dinput_GUID(df->rgodf[i].pguid));
264 TRACE(" * dwOfs: %d\n", df->rgodf[i].dwOfs);
265 TRACE(" * dwType: 0x%08x\n", df->rgodf[i].dwType);
266 TRACE(" "); _dump_EnumObjects_flags(df->rgodf[i].dwType); TRACE("\n");
267 TRACE(" * dwFlags: 0x%08x\n", df->rgodf[i].dwFlags);
268 TRACE(" "); _dump_ObjectDataFormat_flags(df->rgodf[i].dwFlags); TRACE("\n");
272 /******************************************************************************
273 * Get the default and the app-specific config keys.
275 BOOL get_app_key(HKEY *defkey, HKEY *appkey)
277 char buffer[MAX_PATH+16];
278 DWORD len;
280 *appkey = 0;
282 /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */
283 if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", defkey))
284 *defkey = 0;
286 len = GetModuleFileNameA(0, buffer, MAX_PATH);
287 if (len && len < MAX_PATH)
289 HKEY tmpkey;
291 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */
292 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey))
294 char *p, *appname = buffer;
295 if ((p = strrchr(appname, '/'))) appname = p + 1;
296 if ((p = strrchr(appname, '\\'))) appname = p + 1;
297 strcat(appname, "\\DirectInput");
299 if (RegOpenKeyA(tmpkey, appname, appkey)) *appkey = 0;
300 RegCloseKey(tmpkey);
304 return *defkey || *appkey;
307 /******************************************************************************
308 * Get a config key from either the app-specific or the default config
310 DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
311 char *buffer, DWORD size )
313 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size ))
314 return 0;
316 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size ))
317 return 0;
319 return ERROR_FILE_NOT_FOUND;
322 /* Conversion between internal data buffer and external data buffer */
323 void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df)
325 int i;
326 const char *in_c = in;
327 char *out_c = out;
329 memset(out, 0, size);
330 if (df->dt == NULL) {
331 /* This means that the app uses Wine's internal data format */
332 memcpy(out, in, min(size, df->internal_format_size));
333 } else {
334 for (i = 0; i < df->size; i++) {
335 if (df->dt[i].offset_in >= 0) {
336 switch (df->dt[i].size) {
337 case 1:
338 TRACE("Copying (c) to %d from %d (value %d)\n",
339 df->dt[i].offset_out, df->dt[i].offset_in, *(in_c + df->dt[i].offset_in));
340 *(out_c + df->dt[i].offset_out) = *(in_c + df->dt[i].offset_in);
341 break;
343 case 2:
344 TRACE("Copying (s) to %d from %d (value %d)\n",
345 df->dt[i].offset_out, df->dt[i].offset_in, *((const short *)(in_c + df->dt[i].offset_in)));
346 *((short *)(out_c + df->dt[i].offset_out)) = *((const short *)(in_c + df->dt[i].offset_in));
347 break;
349 case 4:
350 TRACE("Copying (i) to %d from %d (value %d)\n",
351 df->dt[i].offset_out, df->dt[i].offset_in, *((const int *)(in_c + df->dt[i].offset_in)));
352 *((int *)(out_c + df->dt[i].offset_out)) = *((const int *)(in_c + df->dt[i].offset_in));
353 break;
355 default:
356 memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
357 break;
359 } else {
360 switch (df->dt[i].size) {
361 case 1:
362 TRACE("Copying (c) to %d default value %d\n",
363 df->dt[i].offset_out, df->dt[i].value);
364 *(out_c + df->dt[i].offset_out) = (char) df->dt[i].value;
365 break;
367 case 2:
368 TRACE("Copying (s) to %d default value %d\n",
369 df->dt[i].offset_out, df->dt[i].value);
370 *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
371 break;
373 case 4:
374 TRACE("Copying (i) to %d default value %d\n",
375 df->dt[i].offset_out, df->dt[i].value);
376 *((int *) (out_c + df->dt[i].offset_out)) = df->dt[i].value;
377 break;
379 default:
380 memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size);
381 break;
388 void release_DataFormat(DataFormat * format)
390 TRACE("Deleting DataFormat: %p\n", format);
392 HeapFree(GetProcessHeap(), 0, format->dt);
393 format->dt = NULL;
394 HeapFree(GetProcessHeap(), 0, format->offsets);
395 format->offsets = NULL;
396 HeapFree(GetProcessHeap(), 0, format->user_df);
397 format->user_df = NULL;
400 static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
402 if (idx < 0 || idx >= df->dwNumObjs) return NULL;
403 return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize);
406 /* dataformat_to_odf_by_type
407 * Find the Nth object of the selected type in the DataFormat
409 LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type)
411 int i, nfound = 0;
413 for (i=0; i < df->dwNumObjs; i++)
415 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(df, i);
417 if (odf->dwType & type)
419 if (n == nfound)
420 return odf;
422 nfound++;
426 return NULL;
429 static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format)
431 DataTransform *dt;
432 unsigned int i, j;
433 int same = 1;
434 int *done;
435 int index = 0;
436 DWORD next = 0;
438 if (!format->wine_df) return DIERR_INVALIDPARAM;
439 done = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, asked_format->dwNumObjs * sizeof(int));
440 dt = HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
441 if (!dt || !done) goto failed;
443 if (!(format->offsets = HeapAlloc(GetProcessHeap(), 0, format->wine_df->dwNumObjs * sizeof(int))))
444 goto failed;
446 if (!(format->user_df = HeapAlloc(GetProcessHeap(), 0, asked_format->dwSize)))
447 goto failed;
448 memcpy(format->user_df, asked_format, asked_format->dwSize);
450 TRACE("Creating DataTransform :\n");
452 for (i = 0; i < format->wine_df->dwNumObjs; i++)
454 format->offsets[i] = -1;
456 for (j = 0; j < asked_format->dwNumObjs; j++) {
457 if (done[j] == 1)
458 continue;
460 if (/* Check if the application either requests any GUID and if not, it if matches
461 * the GUID of the Wine object.
463 ((asked_format->rgodf[j].pguid == NULL) ||
464 (format->wine_df->rgodf[i].pguid == NULL) ||
465 (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
467 (/* Then check if it accepts any instance id, and if not, if it matches Wine's
468 * instance id.
470 ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) ||
471 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentioned in no DX docs, but it works fine - tested on WinXP */
472 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType)))
474 ( /* Then if the asked type matches the one Wine provides */
475 DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
477 done[j] = 1;
479 TRACE("Matching :\n");
480 TRACE(" - Asked (%d) :\n", j);
481 TRACE(" * GUID: %s ('%s')\n",
482 debugstr_guid(asked_format->rgodf[j].pguid),
483 _dump_dinput_GUID(asked_format->rgodf[j].pguid));
484 TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
485 TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
486 TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
487 TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
488 TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
490 TRACE(" - Wine (%d) :\n", i);
491 TRACE(" * GUID: %s ('%s')\n",
492 debugstr_guid(format->wine_df->rgodf[i].pguid),
493 _dump_dinput_GUID(format->wine_df->rgodf[i].pguid));
494 TRACE(" * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs);
495 TRACE(" * dwType: 0x%08x\n", format->wine_df->rgodf[i].dwType);
496 TRACE(" "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n");
497 TRACE(" * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags);
498 TRACE(" "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n");
500 if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON)
501 dt[index].size = sizeof(BYTE);
502 else
503 dt[index].size = sizeof(DWORD);
504 dt[index].offset_in = format->wine_df->rgodf[i].dwOfs;
505 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
506 format->offsets[i] = asked_format->rgodf[j].dwOfs;
507 dt[index].value = 0;
508 next = next + dt[index].size;
510 if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out)
511 same = 0;
513 index++;
514 break;
519 TRACE("Setting to default value :\n");
520 for (j = 0; j < asked_format->dwNumObjs; j++) {
521 if (done[j] == 0) {
522 TRACE(" - Asked (%d) :\n", j);
523 TRACE(" * GUID: %s ('%s')\n",
524 debugstr_guid(asked_format->rgodf[j].pguid),
525 _dump_dinput_GUID(asked_format->rgodf[j].pguid));
526 TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
527 TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
528 TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
529 TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
530 TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
532 if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
533 dt[index].size = sizeof(BYTE);
534 else
535 dt[index].size = sizeof(DWORD);
536 dt[index].offset_in = -1;
537 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
538 if (asked_format->rgodf[j].dwType & DIDFT_POV)
539 dt[index].value = -1;
540 else
541 dt[index].value = 0;
542 index++;
544 same = 0;
548 format->internal_format_size = format->wine_df->dwDataSize;
549 format->size = index;
550 if (same) {
551 HeapFree(GetProcessHeap(), 0, dt);
552 dt = NULL;
554 format->dt = dt;
556 HeapFree(GetProcessHeap(), 0, done);
558 return DI_OK;
560 failed:
561 HeapFree(GetProcessHeap(), 0, done);
562 HeapFree(GetProcessHeap(), 0, dt);
563 format->dt = NULL;
564 HeapFree(GetProcessHeap(), 0, format->offsets);
565 format->offsets = NULL;
566 HeapFree(GetProcessHeap(), 0, format->user_df);
567 format->user_df = NULL;
569 return DIERR_OUTOFMEMORY;
572 /* find an object by its offset in a data format */
573 static int offset_to_object(const DataFormat *df, int offset)
575 int i;
577 if (!df->offsets) return -1;
579 for (i = 0; i < df->wine_df->dwNumObjs; i++)
580 if (df->offsets[i] == offset) return i;
582 return -1;
585 int id_to_object(LPCDIDATAFORMAT df, int id)
587 int i;
589 id &= 0x00ffffff;
590 for (i = 0; i < df->dwNumObjs; i++)
591 if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id)
592 return i;
594 return -1;
597 static int id_to_offset(const DataFormat *df, int id)
599 int obj = id_to_object(df->wine_df, id);
601 return obj >= 0 && df->offsets ? df->offsets[obj] : -1;
604 int find_property(const DataFormat *df, LPCDIPROPHEADER ph)
606 switch (ph->dwHow)
608 case DIPH_BYID: return id_to_object(df->wine_df, ph->dwObj);
609 case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj);
611 FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow);
613 return -1;
616 static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic)
618 DWORD type = (0x0000ff00 & dwSemantic) >> 8;
619 DWORD offset = 0x000000ff & dwSemantic;
620 DWORD obj_instance = 0;
621 BOOL found = FALSE;
622 int i;
624 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
626 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
628 if (odf->dwOfs == offset)
630 obj_instance = DIDFT_GETINSTANCE(odf->dwType);
631 found = TRUE;
632 break;
636 if (!found) return 0;
638 if (type & DIDFT_AXIS) type = DIDFT_RELAXIS;
639 if (type & DIDFT_BUTTON) type = DIDFT_PSHBUTTON;
641 return type | (0x0000ff00 & (obj_instance << 8));
645 * get_mapping_key
646 * Retrieves an open registry key to save the mapping, parametrized for an username,
647 * specific device and specific action mapping guid.
649 static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid)
651 static const WCHAR subkey[] = {
652 'S','o','f','t','w','a','r','e','\\',
653 'W','i','n','e','\\',
654 'D','i','r','e','c','t','I','n','p','u','t','\\',
655 'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
656 HKEY hkey;
657 WCHAR *keyname;
659 keyname = HeapAlloc(GetProcessHeap(), 0,
660 sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
661 sprintfW(keyname, subkey, username, device, guid);
663 /* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
664 if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
665 hkey = 0;
667 HeapFree(GetProcessHeap(), 0, keyname);
669 return hkey;
672 static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
674 WCHAR *guid_str = NULL;
675 DIDEVICEINSTANCEW didev;
676 HKEY hkey;
677 int i;
679 didev.dwSize = sizeof(didev);
680 IDirectInputDevice8_GetDeviceInfo(iface, &didev);
682 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
683 return DI_SETTINGSNOTSAVED;
685 hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
687 if (!hkey)
689 CoTaskMemFree(guid_str);
690 return DI_SETTINGSNOTSAVED;
693 /* Write each of the actions mapped for this device.
694 Format is "dwSemantic"="dwObjID" and key is of type REG_DWORD
696 for (i = 0; i < lpdiaf->dwNumActions; i++)
698 static const WCHAR format[] = {'%','x','\0'};
699 WCHAR label[9];
701 if (IsEqualGUID(&didev.guidInstance, &lpdiaf->rgoAction[i].guidInstance) &&
702 lpdiaf->rgoAction[i].dwHow != DIAH_UNMAPPED)
704 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
705 RegSetValueExW(hkey, label, 0, REG_DWORD, (const BYTE*) &lpdiaf->rgoAction[i].dwObjID, sizeof(DWORD));
709 RegCloseKey(hkey);
710 CoTaskMemFree(guid_str);
712 return DI_OK;
715 static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
717 HKEY hkey;
718 WCHAR *guid_str;
719 DIDEVICEINSTANCEW didev;
720 int i, mapped = 0;
722 didev.dwSize = sizeof(didev);
723 IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev);
725 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
726 return FALSE;
728 hkey = get_mapping_key(didev.tszInstanceName, username, guid_str);
730 if (!hkey)
732 CoTaskMemFree(guid_str);
733 return FALSE;
736 /* Try to read each action in the DIACTIONFORMAT from registry */
737 for (i = 0; i < lpdiaf->dwNumActions; i++)
739 static const WCHAR format[] = {'%','x','\0'};
740 DWORD id, size = sizeof(DWORD);
741 WCHAR label[9];
743 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
745 if (!RegQueryValueExW(hkey, label, 0, NULL, (LPBYTE) &id, &size))
747 lpdiaf->rgoAction[i].dwObjID = id;
748 lpdiaf->rgoAction[i].guidInstance = didev.guidInstance;
749 lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
750 mapped += 1;
754 RegCloseKey(hkey);
755 CoTaskMemFree(guid_str);
757 return mapped > 0;
760 HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
762 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
763 WCHAR username[MAX_PATH];
764 DWORD username_size = MAX_PATH;
765 int i;
766 BOOL load_success = FALSE, has_actions = FALSE;
768 /* Unless asked the contrary by these flags, try to load a previous mapping */
769 if (!(dwFlags & DIDBAM_HWDEFAULTS))
771 /* Retrieve logged user name if necessary */
772 if (lpszUserName == NULL)
773 GetUserNameW(username, &username_size);
774 else
775 lstrcpynW(username, lpszUserName, MAX_PATH);
777 load_success = load_mapping_settings(This, lpdiaf, username);
780 if (load_success) return DI_OK;
782 for (i=0; i < lpdiaf->dwNumActions; i++)
784 /* Don't touch a user configured action */
785 if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue;
787 if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask)
789 DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
790 DWORD type = DIDFT_GETTYPE(obj_id);
791 DWORD inst = DIDFT_GETINSTANCE(obj_id);
793 LPDIOBJECTDATAFORMAT odf;
795 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
796 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
798 /* Make sure the object exists */
799 odf = dataformat_to_odf_by_type(df, inst, type);
801 if (odf != NULL)
803 lpdiaf->rgoAction[i].dwObjID = obj_id;
804 lpdiaf->rgoAction[i].guidInstance = This->guid;
805 lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
806 has_actions = TRUE;
809 else if (!(dwFlags & DIDBAM_PRESERVE))
811 /* We must clear action data belonging to other devices */
812 memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
813 lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
817 if (!has_actions) return DI_NOEFFECT;
819 return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
822 HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df)
824 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
825 DIDATAFORMAT data_format;
826 DIOBJECTDATAFORMAT *obj_df = NULL;
827 DIPROPDWORD dp;
828 DIPROPRANGE dpr;
829 DIPROPSTRING dps;
830 WCHAR username[MAX_PATH];
831 DWORD username_size = MAX_PATH;
832 int i, action = 0, num_actions = 0;
833 unsigned int offset = 0;
835 if (This->acquired) return DIERR_ACQUIRED;
837 data_format.dwSize = sizeof(data_format);
838 data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
839 data_format.dwFlags = DIDF_RELAXIS;
840 data_format.dwDataSize = lpdiaf->dwDataSize;
842 /* Count the actions */
843 for (i=0; i < lpdiaf->dwNumActions; i++)
844 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
845 num_actions++;
847 if (num_actions == 0) return DI_NOEFFECT;
849 This->num_actions = num_actions;
851 /* Construct the dataformat and actionmap */
852 obj_df = HeapAlloc(GetProcessHeap(), 0, sizeof(DIOBJECTDATAFORMAT)*num_actions);
853 data_format.rgodf = (LPDIOBJECTDATAFORMAT)obj_df;
854 data_format.dwNumObjs = num_actions;
856 HeapFree(GetProcessHeap(), 0, This->action_map);
857 This->action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions);
859 for (i = 0; i < lpdiaf->dwNumActions; i++)
861 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
863 DWORD inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID);
864 DWORD type = DIDFT_GETTYPE(lpdiaf->rgoAction[i].dwObjID);
865 LPDIOBJECTDATAFORMAT obj;
867 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
868 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
870 obj = dataformat_to_odf_by_type(df, inst, type);
872 memcpy(&obj_df[action], obj, df->dwObjSize);
874 This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
875 This->action_map[action].offset = offset;
876 obj_df[action].dwOfs = offset;
877 offset += (type & DIDFT_BUTTON) ? 1 : 4;
879 action++;
883 IDirectInputDevice8_SetDataFormat(iface, &data_format);
885 HeapFree(GetProcessHeap(), 0, obj_df);
887 /* Set the device properties according to the action format */
888 dpr.diph.dwSize = sizeof(DIPROPRANGE);
889 dpr.lMin = lpdiaf->lAxisMin;
890 dpr.lMax = lpdiaf->lAxisMax;
891 dpr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
892 dpr.diph.dwHow = DIPH_DEVICE;
893 IDirectInputDevice8_SetProperty(iface, DIPROP_RANGE, &dpr.diph);
895 if (lpdiaf->dwBufferSize > 0)
897 dp.diph.dwSize = sizeof(DIPROPDWORD);
898 dp.dwData = lpdiaf->dwBufferSize;
899 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
900 dp.diph.dwHow = DIPH_DEVICE;
901 IDirectInputDevice8_SetProperty(iface, DIPROP_BUFFERSIZE, &dp.diph);
904 /* Retrieve logged user name if necessary */
905 if (lpszUserName == NULL)
906 GetUserNameW(username, &username_size);
907 else
908 lstrcpynW(username, lpszUserName, MAX_PATH);
910 dps.diph.dwSize = sizeof(dps);
911 dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
912 dps.diph.dwObj = 0;
913 dps.diph.dwHow = DIPH_DEVICE;
914 if (dwFlags & DIDSAM_NOUSER)
915 dps.wsz[0] = '\0';
916 else
917 lstrcpynW(dps.wsz, username, sizeof(dps.wsz)/sizeof(WCHAR));
918 IDirectInputDevice8_SetProperty(iface, DIPROP_USERNAME, &dps.diph);
920 /* Save the settings to disk */
921 save_mapping_settings(iface, lpdiaf, username);
923 return DI_OK;
926 /******************************************************************************
927 * queue_event - add new event to the ring queue
930 void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
932 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
933 int next_pos, ofs = id_to_offset(&This->data_format, inst_id);
935 /* Event is being set regardless of the queue state */
936 if (This->hEvent) SetEvent(This->hEvent);
938 if (!This->queue_len || This->overflow || ofs < 0) return;
940 next_pos = (This->queue_head + 1) % This->queue_len;
941 if (next_pos == This->queue_tail)
943 TRACE(" queue overflowed\n");
944 This->overflow = TRUE;
945 return;
948 TRACE(" queueing %d at offset %d (queue head %d / size %d)\n",
949 data, ofs, This->queue_head, This->queue_len);
951 This->data_queue[This->queue_head].dwOfs = ofs;
952 This->data_queue[This->queue_head].dwData = data;
953 This->data_queue[This->queue_head].dwTimeStamp = time;
954 This->data_queue[This->queue_head].dwSequence = seq;
956 /* Set uAppData by means of action mapping */
957 if (This->num_actions > 0)
959 int i;
960 for (i=0; i < This->num_actions; i++)
962 if (This->action_map[i].offset == ofs)
964 TRACE("Offset %d mapped to uAppData %lu\n", ofs, This->action_map[i].uAppData);
965 This->data_queue[This->queue_head].uAppData = This->action_map[i].uAppData;
966 break;
971 This->queue_head = next_pos;
972 /* Send event if asked */
975 /******************************************************************************
976 * Acquire
979 HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
981 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
982 HRESULT res;
984 TRACE("(%p)\n", This);
986 if (!This->data_format.user_df) return DIERR_INVALIDPARAM;
987 if (This->dwCoopLevel & DISCL_FOREGROUND && This->win != GetForegroundWindow())
988 return DIERR_OTHERAPPHASPRIO;
990 EnterCriticalSection(&This->crit);
991 res = This->acquired ? S_FALSE : DI_OK;
992 This->acquired = 1;
993 if (res == DI_OK)
994 check_dinput_hooks(iface);
995 LeaveCriticalSection(&This->crit);
997 return res;
1000 HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
1002 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1003 return IDirectInputDevice2WImpl_Acquire(IDirectInputDevice8W_from_impl(This));
1007 /******************************************************************************
1008 * Unacquire
1011 HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
1013 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1014 HRESULT res;
1016 TRACE("(%p)\n", This);
1018 EnterCriticalSection(&This->crit);
1019 res = !This->acquired ? DI_NOEFFECT : DI_OK;
1020 This->acquired = 0;
1021 if (res == DI_OK)
1022 check_dinput_hooks(iface);
1023 LeaveCriticalSection(&This->crit);
1025 return res;
1028 HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
1030 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1031 return IDirectInputDevice2WImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
1034 /******************************************************************************
1035 * IDirectInputDeviceA
1038 HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df)
1040 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1041 HRESULT res = DI_OK;
1043 if (!df) return E_POINTER;
1044 TRACE("(%p) %p\n", This, df);
1045 _dump_DIDATAFORMAT(df);
1047 if (df->dwSize != sizeof(DIDATAFORMAT)) return DIERR_INVALIDPARAM;
1048 if (This->acquired) return DIERR_ACQUIRED;
1050 EnterCriticalSection(&This->crit);
1052 release_DataFormat(&This->data_format);
1053 res = create_DataFormat(df, &This->data_format);
1055 LeaveCriticalSection(&This->crit);
1056 return res;
1059 HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
1061 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1062 return IDirectInputDevice2WImpl_SetDataFormat(IDirectInputDevice8W_from_impl(This), df);
1065 /******************************************************************************
1066 * SetCooperativeLevel
1068 * Set cooperative level and the source window for the events.
1070 HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags)
1072 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1074 TRACE("(%p) %p,0x%08x\n", This, hwnd, dwflags);
1075 _dump_cooperativelevel_DI(dwflags);
1077 if ((dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == 0 ||
1078 (dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE) ||
1079 (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == 0 ||
1080 (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == (DISCL_FOREGROUND | DISCL_BACKGROUND))
1081 return DIERR_INVALIDPARAM;
1083 if (hwnd && GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) return E_HANDLE;
1085 if (!hwnd && dwflags == (DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))
1086 hwnd = GetDesktopWindow();
1088 if (!IsWindow(hwnd)) return E_HANDLE;
1090 /* For security reasons native does not allow exclusive background level
1091 for mouse and keyboard only */
1092 if (dwflags & DISCL_EXCLUSIVE && dwflags & DISCL_BACKGROUND &&
1093 (IsEqualGUID(&This->guid, &GUID_SysMouse) ||
1094 IsEqualGUID(&This->guid, &GUID_SysKeyboard)))
1095 return DIERR_UNSUPPORTED;
1097 /* Store the window which asks for the mouse */
1098 EnterCriticalSection(&This->crit);
1099 This->win = hwnd;
1100 This->dwCoopLevel = dwflags;
1101 LeaveCriticalSection(&This->crit);
1103 return DI_OK;
1106 HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
1108 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1109 return IDirectInputDevice2WImpl_SetCooperativeLevel(IDirectInputDevice8W_from_impl(This), hwnd, dwflags);
1112 /******************************************************************************
1113 * SetEventNotification : specifies event to be sent on state change
1115 HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE event)
1117 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1119 TRACE("(%p) %p\n", This, event);
1121 EnterCriticalSection(&This->crit);
1122 This->hEvent = event;
1123 LeaveCriticalSection(&This->crit);
1124 return DI_OK;
1127 HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
1129 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1130 return IDirectInputDevice2WImpl_SetEventNotification(IDirectInputDevice8W_from_impl(This), event);
1134 ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
1136 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1137 ULONG ref = InterlockedDecrement(&(This->ref));
1139 TRACE("(%p) releasing from %d\n", This, ref + 1);
1141 if (ref) return ref;
1143 IDirectInputDevice_Unacquire(iface);
1144 /* Reset the FF state, free all effects, etc */
1145 IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET);
1147 HeapFree(GetProcessHeap(), 0, This->data_queue);
1149 /* Free data format */
1150 HeapFree(GetProcessHeap(), 0, This->data_format.wine_df->rgodf);
1151 HeapFree(GetProcessHeap(), 0, This->data_format.wine_df);
1152 release_DataFormat(&This->data_format);
1154 /* Free action mapping */
1155 HeapFree(GetProcessHeap(), 0, This->action_map);
1157 EnterCriticalSection( &This->dinput->crit );
1158 list_remove( &This->entry );
1159 LeaveCriticalSection( &This->dinput->crit );
1161 IDirectInput_Release(&This->dinput->IDirectInput7A_iface);
1162 This->crit.DebugInfo->Spare[0] = 0;
1163 DeleteCriticalSection(&This->crit);
1165 HeapFree(GetProcessHeap(), 0, This);
1167 return DI_OK;
1170 ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
1172 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1173 return IDirectInputDevice2WImpl_Release(IDirectInputDevice8W_from_impl(This));
1176 HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj)
1178 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1180 TRACE("(%p this=%p,%s,%p)\n", iface, This, debugstr_guid(riid), ppobj);
1181 if (IsEqualGUID(&IID_IUnknown, riid) ||
1182 IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
1183 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
1184 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
1185 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
1187 IDirectInputDevice2_AddRef(iface);
1188 *ppobj = IDirectInputDevice8A_from_impl(This);
1189 return DI_OK;
1191 if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
1192 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
1193 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
1194 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
1196 IDirectInputDevice2_AddRef(iface);
1197 *ppobj = IDirectInputDevice8W_from_impl(This);
1198 return DI_OK;
1201 WARN("Unsupported interface!\n");
1202 return E_FAIL;
1205 HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
1207 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1208 return IDirectInputDevice2WImpl_QueryInterface(IDirectInputDevice8W_from_impl(This), riid, ppobj);
1211 ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
1213 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1214 return InterlockedIncrement(&This->ref);
1217 ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
1219 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1220 return IDirectInputDevice2WImpl_AddRef(IDirectInputDevice8W_from_impl(This));
1223 HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
1224 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
1226 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1227 DIDEVICEOBJECTINSTANCEA ddoi;
1228 int i;
1230 TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
1231 TRACE(" - flags = ");
1232 _dump_EnumObjects_flags(dwFlags);
1233 TRACE("\n");
1235 /* Only the fields till dwFFMaxForce are relevant */
1236 memset(&ddoi, 0, sizeof(ddoi));
1237 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
1239 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
1241 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
1243 if (dwFlags != DIDFT_ALL && !(dwFlags & DIDFT_GETTYPE(odf->dwType))) continue;
1244 if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
1245 continue;
1247 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
1250 return DI_OK;
1253 HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
1254 LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
1256 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1257 DIDEVICEOBJECTINSTANCEW ddoi;
1258 int i;
1260 TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
1261 TRACE(" - flags = ");
1262 _dump_EnumObjects_flags(dwFlags);
1263 TRACE("\n");
1265 /* Only the fields till dwFFMaxForce are relevant */
1266 memset(&ddoi, 0, sizeof(ddoi));
1267 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, dwFFMaxForce);
1269 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
1271 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
1273 if (dwFlags != DIDFT_ALL && !(dwFlags & DIDFT_GETTYPE(odf->dwType))) continue;
1274 if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
1275 continue;
1277 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
1280 return DI_OK;
1283 /******************************************************************************
1284 * GetProperty
1287 HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1289 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1291 TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
1292 _dump_DIPROPHEADER(pdiph);
1294 if (!IS_DIPROP(rguid)) return DI_OK;
1296 switch (LOWORD(rguid))
1298 case (DWORD_PTR) DIPROP_BUFFERSIZE:
1300 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1302 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1304 pd->dwData = This->queue_len;
1305 TRACE("buffersize = %d\n", pd->dwData);
1306 break;
1308 case (DWORD_PTR) DIPROP_USERNAME:
1310 LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph;
1312 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
1314 lstrcpynW(ps->wsz, This->username, sizeof(ps->wsz)/sizeof(WCHAR));
1315 break;
1317 case (DWORD_PTR) DIPROP_VIDPID:
1318 FIXME("DIPROP_VIDPID not implemented\n");
1319 return DIERR_UNSUPPORTED;
1320 default:
1321 FIXME("Unknown property %s\n", debugstr_guid(rguid));
1322 return DIERR_INVALIDPARAM;
1325 return DI_OK;
1328 HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1330 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1331 return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
1334 /******************************************************************************
1335 * SetProperty
1338 HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
1339 LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
1341 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1343 TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
1344 _dump_DIPROPHEADER(pdiph);
1346 if (!IS_DIPROP(rguid)) return DI_OK;
1348 switch (LOWORD(rguid))
1350 case (DWORD_PTR) DIPROP_AXISMODE:
1352 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;
1354 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1355 if (pdiph->dwHow == DIPH_DEVICE && pdiph->dwObj) return DIERR_INVALIDPARAM;
1356 if (This->acquired) return DIERR_ACQUIRED;
1357 if (pdiph->dwHow != DIPH_DEVICE) return DIERR_UNSUPPORTED;
1358 if (!This->data_format.user_df) return DI_OK;
1360 TRACE("Axis mode: %s\n", pd->dwData == DIPROPAXISMODE_ABS ? "absolute" :
1361 "relative");
1363 EnterCriticalSection(&This->crit);
1364 This->data_format.user_df->dwFlags &= ~DIDFT_AXIS;
1365 This->data_format.user_df->dwFlags |= pd->dwData == DIPROPAXISMODE_ABS ?
1366 DIDF_ABSAXIS : DIDF_RELAXIS;
1367 LeaveCriticalSection(&This->crit);
1368 break;
1370 case (DWORD_PTR) DIPROP_BUFFERSIZE:
1372 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;
1374 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1375 if (This->acquired) return DIERR_ACQUIRED;
1377 TRACE("buffersize = %d\n", pd->dwData);
1379 EnterCriticalSection(&This->crit);
1380 HeapFree(GetProcessHeap(), 0, This->data_queue);
1382 This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0,
1383 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1384 This->queue_head = This->queue_tail = This->overflow = 0;
1385 This->queue_len = pd->dwData;
1387 LeaveCriticalSection(&This->crit);
1388 break;
1390 case (DWORD_PTR) DIPROP_USERNAME:
1392 LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph;
1394 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
1396 lstrcpynW(This->username, ps->wsz, sizeof(This->username)/sizeof(WCHAR));
1397 break;
1399 default:
1400 WARN("Unknown property %s\n", debugstr_guid(rguid));
1401 return DIERR_UNSUPPORTED;
1404 return DI_OK;
1407 HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty(
1408 LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
1410 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1411 return IDirectInputDevice2WImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
1414 HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
1415 LPDIRECTINPUTDEVICE8A iface,
1416 LPDIDEVICEOBJECTINSTANCEA pdidoi,
1417 DWORD dwObj,
1418 DWORD dwHow)
1420 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1421 DIDEVICEOBJECTINSTANCEW didoiW;
1422 HRESULT res;
1424 if (!pdidoi ||
1425 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) &&
1426 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A)))
1427 return DIERR_INVALIDPARAM;
1429 didoiW.dwSize = sizeof(didoiW);
1430 res = IDirectInputDevice2WImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow);
1431 if (res == DI_OK)
1433 DWORD dwSize = pdidoi->dwSize;
1435 memset(pdidoi, 0, pdidoi->dwSize);
1436 pdidoi->dwSize = dwSize;
1437 pdidoi->guidType = didoiW.guidType;
1438 pdidoi->dwOfs = didoiW.dwOfs;
1439 pdidoi->dwType = didoiW.dwType;
1440 pdidoi->dwFlags = didoiW.dwFlags;
1443 return res;
1446 HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
1447 LPDIRECTINPUTDEVICE8W iface,
1448 LPDIDEVICEOBJECTINSTANCEW pdidoi,
1449 DWORD dwObj,
1450 DWORD dwHow)
1452 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1453 DWORD dwSize;
1454 LPDIOBJECTDATAFORMAT odf;
1455 int idx = -1;
1457 TRACE("(%p) %d(0x%08x) -> %p\n", This, dwHow, dwObj, pdidoi);
1459 if (!pdidoi ||
1460 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW) &&
1461 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W)))
1462 return DIERR_INVALIDPARAM;
1464 switch (dwHow)
1466 case DIPH_BYOFFSET:
1467 if (!This->data_format.offsets) break;
1468 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
1469 if (This->data_format.offsets[idx] == dwObj) break;
1470 break;
1471 case DIPH_BYID:
1472 dwObj &= 0x00ffffff;
1473 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
1474 if ((dataformat_to_odf(This->data_format.wine_df, idx)->dwType & 0x00ffffff) == dwObj)
1475 break;
1476 break;
1478 case DIPH_BYUSAGE:
1479 FIXME("dwHow = DIPH_BYUSAGE not implemented\n");
1480 break;
1481 default:
1482 WARN("invalid parameter: dwHow = %08x\n", dwHow);
1483 return DIERR_INVALIDPARAM;
1485 if (idx < 0) return DIERR_OBJECTNOTFOUND;
1487 odf = dataformat_to_odf(This->data_format.wine_df, idx);
1488 dwSize = pdidoi->dwSize; /* save due to memset below */
1489 memset(pdidoi, 0, pdidoi->dwSize);
1490 pdidoi->dwSize = dwSize;
1491 if (odf->pguid) pdidoi->guidType = *odf->pguid;
1492 pdidoi->dwOfs = This->data_format.offsets ? This->data_format.offsets[idx] : odf->dwOfs;
1493 pdidoi->dwType = odf->dwType;
1494 pdidoi->dwFlags = odf->dwFlags;
1496 return DI_OK;
1499 HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize,
1500 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
1502 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1503 HRESULT ret = DI_OK;
1504 int len;
1506 TRACE("(%p) %p -> %p(%d) x%d, 0x%08x\n",
1507 This, dod, entries, entries ? *entries : 0, dodsize, flags);
1509 if (This->dinput->dwVersion == 0x0800 || dodsize == sizeof(DIDEVICEOBJECTDATA_DX3))
1511 if (!This->queue_len) return DIERR_NOTBUFFERED;
1512 if (!This->acquired) return DIERR_NOTACQUIRED;
1515 if (!This->queue_len)
1516 return DI_OK;
1517 if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
1518 return DIERR_INVALIDPARAM;
1520 IDirectInputDevice2_Poll(iface);
1521 EnterCriticalSection(&This->crit);
1523 len = This->queue_head - This->queue_tail;
1524 if (len < 0) len += This->queue_len;
1526 if ((*entries != INFINITE) && (len > *entries)) len = *entries;
1528 if (dod)
1530 int i;
1531 for (i = 0; i < len; i++)
1533 int n = (This->queue_tail + i) % This->queue_len;
1534 memcpy((char *)dod + dodsize * i, This->data_queue + n, dodsize);
1537 *entries = len;
1539 if (This->overflow && This->dinput->dwVersion == 0x0800)
1540 ret = DI_BUFFEROVERFLOW;
1542 if (!(flags & DIGDD_PEEK))
1544 /* Advance reading position */
1545 This->queue_tail = (This->queue_tail + len) % This->queue_len;
1546 This->overflow = FALSE;
1549 LeaveCriticalSection(&This->crit);
1551 TRACE("Returning %d events queued\n", *entries);
1552 return ret;
1555 HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize,
1556 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
1558 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1559 return IDirectInputDevice2WImpl_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags);
1562 HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
1564 FIXME("(this=%p,%p,0x%08x): stub!\n", iface, hwndOwner, dwFlags);
1566 return DI_OK;
1569 HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags)
1571 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1572 return IDirectInputDevice2WImpl_RunControlPanel(IDirectInputDevice8W_from_impl(This), hwndOwner, dwFlags);
1575 HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
1576 REFGUID rguid)
1578 FIXME("(this=%p,%p,%d,%s): stub!\n", iface, hinst, dwVersion, debugstr_guid(rguid));
1579 return DI_OK;
1582 HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion,
1583 REFGUID rguid)
1585 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1586 return IDirectInputDevice2WImpl_Initialize(IDirectInputDevice8W_from_impl(This), hinst, dwVersion, rguid);
1589 /******************************************************************************
1590 * IDirectInputDevice2A
1593 HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
1594 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
1596 FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
1598 FIXME("not available in the generic implementation\n");
1599 *ppdef = NULL;
1600 return DIERR_UNSUPPORTED;
1603 HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
1604 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
1606 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1607 return IDirectInputDevice2WImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter);
1610 HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1611 LPDIRECTINPUTDEVICE8A iface,
1612 LPDIENUMEFFECTSCALLBACKA lpCallback,
1613 LPVOID lpvRef,
1614 DWORD dwFlags)
1616 FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1617 iface, lpCallback, lpvRef, dwFlags);
1619 return DI_OK;
1622 HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
1623 LPDIRECTINPUTDEVICE8W iface,
1624 LPDIENUMEFFECTSCALLBACKW lpCallback,
1625 LPVOID lpvRef,
1626 DWORD dwFlags)
1628 FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1629 iface, lpCallback, lpvRef, dwFlags);
1631 return DI_OK;
1634 HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1635 LPDIRECTINPUTDEVICE8A iface,
1636 LPDIEFFECTINFOA lpdei,
1637 REFGUID rguid)
1639 FIXME("(this=%p,%p,%s): stub!\n",
1640 iface, lpdei, debugstr_guid(rguid));
1641 return DI_OK;
1644 HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
1645 LPDIRECTINPUTDEVICE8W iface,
1646 LPDIEFFECTINFOW lpdei,
1647 REFGUID rguid)
1649 FIXME("(this=%p,%p,%s): stub!\n",
1650 iface, lpdei, debugstr_guid(rguid));
1651 return DI_OK;
1654 HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
1656 FIXME("(this=%p,%p): stub!\n", iface, pdwOut);
1657 return DI_OK;
1660 HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
1662 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1663 return IDirectInputDevice2WImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut);
1666 HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
1668 TRACE("(%p) 0x%08x:\n", iface, dwFlags);
1669 return DI_NOEFFECT;
1672 HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
1674 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1675 return IDirectInputDevice2WImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags);
1678 HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
1679 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
1681 FIXME("(this=%p,%p,%p,0x%08x): stub!\n", iface, lpCallback, lpvRef, dwFlags);
1682 return DI_OK;
1685 HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
1686 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
1688 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1689 return IDirectInputDevice2WImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, lpvRef, dwFlags);
1692 HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
1694 FIXME("(this=%p,%p): stub!\n", iface, lpDIEEsc);
1695 return DI_OK;
1698 HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc)
1700 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1701 return IDirectInputDevice2WImpl_Escape(IDirectInputDevice8W_from_impl(This), lpDIEEsc);
1704 HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
1706 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1708 if (!This->acquired) return DIERR_NOTACQUIRED;
1710 check_dinput_events();
1711 return DI_OK;
1714 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
1716 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1717 return IDirectInputDevice2WImpl_Poll(IDirectInputDevice8W_from_impl(This));
1720 HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData,
1721 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
1722 DWORD dwFlags)
1724 FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n", iface, cbObjectData, rgdod, pdwInOut, dwFlags);
1726 return DI_OK;
1729 HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData,
1730 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
1731 DWORD dwFlags)
1733 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1734 return IDirectInputDevice2WImpl_SendDeviceData(IDirectInputDevice8W_from_impl(This), cbObjectData, rgdod,
1735 pdwInOut, dwFlags);
1738 HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
1739 LPCSTR lpszFileName,
1740 LPDIENUMEFFECTSINFILECALLBACK pec,
1741 LPVOID pvRef,
1742 DWORD dwFlags)
1744 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
1746 return DI_OK;
1749 HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
1750 LPCWSTR lpszFileName,
1751 LPDIENUMEFFECTSINFILECALLBACK pec,
1752 LPVOID pvRef,
1753 DWORD dwFlags)
1755 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
1757 return DI_OK;
1760 HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
1761 LPCSTR lpszFileName,
1762 DWORD dwEntries,
1763 LPDIFILEEFFECT rgDiFileEft,
1764 DWORD dwFlags)
1766 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
1768 return DI_OK;
1771 HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
1772 LPCWSTR lpszFileName,
1773 DWORD dwEntries,
1774 LPDIFILEEFFECT rgDiFileEft,
1775 DWORD dwFlags)
1777 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
1779 return DI_OK;
1782 HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
1783 LPDIACTIONFORMATW lpdiaf,
1784 LPCWSTR lpszUserName,
1785 DWORD dwFlags)
1787 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
1788 #define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
1789 X(DIDBAM_DEFAULT)
1790 X(DIDBAM_PRESERVE)
1791 X(DIDBAM_INITIALIZE)
1792 X(DIDBAM_HWDEFAULTS)
1793 #undef X
1795 return DI_OK;
1798 HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
1799 LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
1801 FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
1803 return DI_OK;
1806 HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
1807 LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
1809 FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
1811 return DI_OK;