1 /* DirectInput Device
2 *
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998,1999 Lionel Ulmer
5 *
6 *
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.
11 *
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.
16 *
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
20 */
21
22 /* This file contains all the Device specific functions that can be used as stubs
23 by real device implementations.
24
25 It also contains all the helper functions.
26 */
27 #include "config.h"
28
29 #include <stdarg.h>
30 #include <string.h>
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33 #include "wine/heap.h"
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
37 #include "winuser.h"
38 #include "winerror.h"
39 #include "dinput.h"
40 #include "device_private.h"
41 #include "dinput_private.h"
42
43 #define WM_WINE_NOTIFY_ACTIVITY WM_USER
44
45 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
46
impl_from_IDirectInputDevice8A(IDirectInputDevice8A * iface)47 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
48 {
49 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface);
50 }
impl_from_IDirectInputDevice8W(IDirectInputDevice8W * iface)51 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
52 {
53 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface);
54 }
55
IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl * This)56 static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl *This)
57 {
58 return &This->IDirectInputDevice8A_iface;
59 }
IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl * This)60 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
61 {
62 return &This->IDirectInputDevice8W_iface;
63 }
64
65 /******************************************************************************
66 * Various debugging tools
67 */
_dump_cooperativelevel_DI(DWORD dwFlags)68 static void _dump_cooperativelevel_DI(DWORD dwFlags) {
69 if (TRACE_ON(dinput)) {
70 unsigned int i;
71 static const struct {
72 DWORD mask;
73 const char *name;
74 } flags[] = {
75 #define FE(x) { x, #x}
76 FE(DISCL_BACKGROUND),
77 FE(DISCL_EXCLUSIVE),
78 FE(DISCL_FOREGROUND),
79 FE(DISCL_NONEXCLUSIVE),
80 FE(DISCL_NOWINKEY)
81 #undef FE
82 };
83 TRACE(" cooperative level : ");
84 for (i = 0; i < ARRAY_SIZE(flags); i++)
85 if (flags[i].mask & dwFlags)
86 TRACE("%s ",flags[i].name);
87 TRACE("\n");
88 }
89 }
90
_dump_ObjectDataFormat_flags(DWORD dwFlags)91 static void _dump_ObjectDataFormat_flags(DWORD dwFlags) {
92 unsigned int i;
93 static const struct {
94 DWORD mask;
95 const char *name;
96 } flags[] = {
97 #define FE(x) { x, #x}
98 FE(DIDOI_FFACTUATOR),
99 FE(DIDOI_FFEFFECTTRIGGER),
100 FE(DIDOI_POLLED),
101 FE(DIDOI_GUIDISUSAGE)
102 #undef FE
103 };
104
105 if (!dwFlags) return;
106
107 TRACE("Flags:");
108
109 /* First the flags */
110 for (i = 0; i < ARRAY_SIZE(flags); i++) {
111 if (flags[i].mask & dwFlags)
112 TRACE(" %s",flags[i].name);
113 }
114
115 /* Now specific values */
116 #define FE(x) case x: TRACE(" "#x); break
117 switch (dwFlags & DIDOI_ASPECTMASK) {
118 FE(DIDOI_ASPECTACCEL);
119 FE(DIDOI_ASPECTFORCE);
120 FE(DIDOI_ASPECTPOSITION);
121 FE(DIDOI_ASPECTVELOCITY);
122 }
123 #undef FE
124
125 }
126
_dump_EnumObjects_flags(DWORD dwFlags)127 static void _dump_EnumObjects_flags(DWORD dwFlags) {
128 if (TRACE_ON(dinput)) {
129 unsigned int i;
130 DWORD type, instance;
131 static const struct {
132 DWORD mask;
133 const char *name;
134 } flags[] = {
135 #define FE(x) { x, #x}
136 FE(DIDFT_RELAXIS),
137 FE(DIDFT_ABSAXIS),
138 FE(DIDFT_PSHBUTTON),
139 FE(DIDFT_TGLBUTTON),
140 FE(DIDFT_POV),
141 FE(DIDFT_COLLECTION),
142 FE(DIDFT_NODATA),
143 FE(DIDFT_FFACTUATOR),
144 FE(DIDFT_FFEFFECTTRIGGER),
145 FE(DIDFT_OUTPUT),
146 FE(DIDFT_VENDORDEFINED),
147 FE(DIDFT_ALIAS),
148 FE(DIDFT_OPTIONAL)
149 #undef FE
150 };
151 type = (dwFlags & 0xFF0000FF);
152 instance = ((dwFlags >> 8) & 0xFFFF);
153 TRACE("Type:");
154 if (type == DIDFT_ALL) {
155 TRACE(" DIDFT_ALL");
156 } else {
157 for (i = 0; i < ARRAY_SIZE(flags); i++) {
158 if (flags[i].mask & type) {
159 type &= ~flags[i].mask;
160 TRACE(" %s",flags[i].name);
161 }
162 }
163 if (type) {
164 TRACE(" (unhandled: %08x)", type);
165 }
166 }
167 TRACE(" / Instance: ");
168 if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
169 TRACE("DIDFT_ANYINSTANCE");
170 } else {
171 TRACE("%3d", instance);
172 }
173 }
174 }
175
_dump_DIPROPHEADER(LPCDIPROPHEADER diph)176 void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) {
177 if (TRACE_ON(dinput)) {
178 TRACE(" - dwObj = 0x%08x\n", diph->dwObj);
179 TRACE(" - dwHow = %s\n",
180 ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
181 ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
182 ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
183 }
184 }
185
_dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA * ddoi)186 void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) {
187 TRACE(" - enumerating : %s ('%s') - %2d - 0x%08x - %s - 0x%x\n",
188 debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, ddoi->tszName, ddoi->dwFlags);
189 }
190
_dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW * ddoi)191 void _dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW *ddoi) {
192 TRACE(" - enumerating : %s ('%s'), - %2d - 0x%08x - %s - 0x%x\n",
193 debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName), ddoi->dwFlags);
194 }
195
196 /* This function is a helper to convert a GUID into any possible DInput GUID out there */
_dump_dinput_GUID(const GUID * guid)197 const char *_dump_dinput_GUID(const GUID *guid) {
198 unsigned int i;
199 static const struct {
200 const GUID *guid;
201 const char *name;
202 } guids[] = {
203 #define FE(x) { &x, #x}
204 FE(GUID_XAxis),
205 FE(GUID_YAxis),
206 FE(GUID_ZAxis),
207 FE(GUID_RxAxis),
208 FE(GUID_RyAxis),
209 FE(GUID_RzAxis),
210 FE(GUID_Slider),
211 FE(GUID_Button),
212 FE(GUID_Key),
213 FE(GUID_POV),
214 FE(GUID_Unknown),
215 FE(GUID_SysMouse),
216 FE(GUID_SysKeyboard),
217 FE(GUID_Joystick),
218 FE(GUID_ConstantForce),
219 FE(GUID_RampForce),
220 FE(GUID_Square),
221 FE(GUID_Sine),
222 FE(GUID_Triangle),
223 FE(GUID_SawtoothUp),
224 FE(GUID_SawtoothDown),
225 FE(GUID_Spring),
226 FE(GUID_Damper),
227 FE(GUID_Inertia),
228 FE(GUID_Friction),
229 FE(GUID_CustomForce)
230 #undef FE
231 };
232 if (guid == NULL)
233 return "null GUID";
234 for (i = 0; i < ARRAY_SIZE(guids); i++) {
235 if (IsEqualGUID(guids[i].guid, guid)) {
236 return guids[i].name;
237 }
238 }
239 return debugstr_guid(guid);
240 }
241
_dump_DIDATAFORMAT(const DIDATAFORMAT * df)242 void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
243 unsigned int i;
244
245 TRACE("Dumping DIDATAFORMAT structure:\n");
246 TRACE(" - dwSize: %d\n", df->dwSize);
247 if (df->dwSize != sizeof(DIDATAFORMAT)) {
248 WARN("Non-standard DIDATAFORMAT structure size %d\n", df->dwSize);
249 }
250 TRACE(" - dwObjsize: %d\n", df->dwObjSize);
251 if (df->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) {
252 WARN("Non-standard DIOBJECTDATAFORMAT structure size %d\n", df->dwObjSize);
253 }
254 TRACE(" - dwFlags: 0x%08x (", df->dwFlags);
255 switch (df->dwFlags) {
256 case DIDF_ABSAXIS: TRACE("DIDF_ABSAXIS"); break;
257 case DIDF_RELAXIS: TRACE("DIDF_RELAXIS"); break;
258 default: TRACE("unknown"); break;
259 }
260 TRACE(")\n");
261 TRACE(" - dwDataSize: %d\n", df->dwDataSize);
262 TRACE(" - dwNumObjs: %d\n", df->dwNumObjs);
263
264 for (i = 0; i < df->dwNumObjs; i++) {
265 TRACE(" - Object %d:\n", i);
266 TRACE(" * GUID: %s ('%s')\n", debugstr_guid(df->rgodf[i].pguid), _dump_dinput_GUID(df->rgodf[i].pguid));
267 TRACE(" * dwOfs: %d\n", df->rgodf[i].dwOfs);
268 TRACE(" * dwType: 0x%08x\n", df->rgodf[i].dwType);
269 TRACE(" "); _dump_EnumObjects_flags(df->rgodf[i].dwType); TRACE("\n");
270 TRACE(" * dwFlags: 0x%08x\n", df->rgodf[i].dwFlags);
271 TRACE(" "); _dump_ObjectDataFormat_flags(df->rgodf[i].dwFlags); TRACE("\n");
272 }
273 }
274
275 /******************************************************************************
276 * Get the default and the app-specific config keys.
277 */
get_app_key(HKEY * defkey,HKEY * appkey)278 BOOL get_app_key(HKEY *defkey, HKEY *appkey)
279 {
280 char buffer[MAX_PATH+16];
281 DWORD len;
282
283 *appkey = 0;
284
285 /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */
286 if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", defkey))
287 *defkey = 0;
288
289 len = GetModuleFileNameA(0, buffer, MAX_PATH);
290 if (len && len < MAX_PATH)
291 {
292 HKEY tmpkey;
293
294 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */
295 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey))
296 {
297 char *p, *appname = buffer;
298 if ((p = strrchr(appname, '/'))) appname = p + 1;
299 if ((p = strrchr(appname, '\\'))) appname = p + 1;
300 strcat(appname, "\\DirectInput");
301
302 if (RegOpenKeyA(tmpkey, appname, appkey)) *appkey = 0;
303 RegCloseKey(tmpkey);
304 }
305 }
306
307 return *defkey || *appkey;
308 }
309
310 /******************************************************************************
311 * Get a config key from either the app-specific or the default config
312 */
get_config_key(HKEY defkey,HKEY appkey,const char * name,char * buffer,DWORD size)313 DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
314 char *buffer, DWORD size )
315 {
316 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size ))
317 return 0;
318
319 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size ))
320 return 0;
321
322 return ERROR_FILE_NOT_FOUND;
323 }
324
325 /* Conversion between internal data buffer and external data buffer */
fill_DataFormat(void * out,DWORD size,const void * in,const DataFormat * df)326 void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df)
327 {
328 int i;
329 const char *in_c = in;
330 char *out_c = out;
331
332 memset(out, 0, size);
333 if (df->dt == NULL) {
334 /* This means that the app uses Wine's internal data format */
335 memcpy(out, in, min(size, df->internal_format_size));
336 } else {
337 for (i = 0; i < df->size; i++) {
338 if (df->dt[i].offset_in >= 0) {
339 switch (df->dt[i].size) {
340 case 1:
341 TRACE("Copying (c) to %d from %d (value %d)\n",
342 df->dt[i].offset_out, df->dt[i].offset_in, *(in_c + df->dt[i].offset_in));
343 *(out_c + df->dt[i].offset_out) = *(in_c + df->dt[i].offset_in);
344 break;
345
346 case 2:
347 TRACE("Copying (s) to %d from %d (value %d)\n",
348 df->dt[i].offset_out, df->dt[i].offset_in, *((const short *)(in_c + df->dt[i].offset_in)));
349 *((short *)(out_c + df->dt[i].offset_out)) = *((const short *)(in_c + df->dt[i].offset_in));
350 break;
351
352 case 4:
353 TRACE("Copying (i) to %d from %d (value %d)\n",
354 df->dt[i].offset_out, df->dt[i].offset_in, *((const int *)(in_c + df->dt[i].offset_in)));
355 *((int *)(out_c + df->dt[i].offset_out)) = *((const int *)(in_c + df->dt[i].offset_in));
356 break;
357
358 default:
359 memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
360 break;
361 }
362 } else {
363 switch (df->dt[i].size) {
364 case 1:
365 TRACE("Copying (c) to %d default value %d\n",
366 df->dt[i].offset_out, df->dt[i].value);
367 *(out_c + df->dt[i].offset_out) = (char) df->dt[i].value;
368 break;
369
370 case 2:
371 TRACE("Copying (s) to %d default value %d\n",
372 df->dt[i].offset_out, df->dt[i].value);
373 *((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
374 break;
375
376 case 4:
377 TRACE("Copying (i) to %d default value %d\n",
378 df->dt[i].offset_out, df->dt[i].value);
379 *((int *) (out_c + df->dt[i].offset_out)) = df->dt[i].value;
380 break;
381
382 default:
383 memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size);
384 break;
385 }
386 }
387 }
388 }
389 }
390
release_DataFormat(DataFormat * format)391 void release_DataFormat(DataFormat * format)
392 {
393 TRACE("Deleting DataFormat: %p\n", format);
394
395 HeapFree(GetProcessHeap(), 0, format->dt);
396 format->dt = NULL;
397 HeapFree(GetProcessHeap(), 0, format->offsets);
398 format->offsets = NULL;
399 HeapFree(GetProcessHeap(), 0, format->user_df);
400 format->user_df = NULL;
401 }
402
dataformat_to_odf(LPCDIDATAFORMAT df,int idx)403 static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
404 {
405 if (idx < 0 || idx >= df->dwNumObjs) return NULL;
406 return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize);
407 }
408
409 /* dataformat_to_odf_by_type
410 * Find the Nth object of the selected type in the DataFormat
411 */
dataformat_to_odf_by_type(LPCDIDATAFORMAT df,int n,DWORD type)412 LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type)
413 {
414 int i, nfound = 0;
415
416 for (i=0; i < df->dwNumObjs; i++)
417 {
418 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(df, i);
419
420 if (odf->dwType & type)
421 {
422 if (n == nfound)
423 return odf;
424
425 nfound++;
426 }
427 }
428
429 return NULL;
430 }
431
create_DataFormat(LPCDIDATAFORMAT asked_format,DataFormat * format)432 static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format)
433 {
434 DataTransform *dt;
435 unsigned int i, j;
436 int same = 1;
437 int *done;
438 int index = 0;
439 DWORD next = 0;
440
441 if (!format->wine_df) return DIERR_INVALIDPARAM;
442 done = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, asked_format->dwNumObjs * sizeof(int));
443 dt = HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
444 if (!dt || !done) goto failed;
445
446 if (!(format->offsets = HeapAlloc(GetProcessHeap(), 0, format->wine_df->dwNumObjs * sizeof(int))))
447 goto failed;
448
449 if (!(format->user_df = HeapAlloc(GetProcessHeap(), 0, asked_format->dwSize)))
450 goto failed;
451 memcpy(format->user_df, asked_format, asked_format->dwSize);
452
453 TRACE("Creating DataTransform :\n");
454
455 for (i = 0; i < format->wine_df->dwNumObjs; i++)
456 {
457 format->offsets[i] = -1;
458
459 for (j = 0; j < asked_format->dwNumObjs; j++) {
460 if (done[j] == 1)
461 continue;
462
463 if (/* Check if the application either requests any GUID and if not, it if matches
464 * the GUID of the Wine object.
465 */
466 ((asked_format->rgodf[j].pguid == NULL) ||
467 (format->wine_df->rgodf[i].pguid == NULL) ||
468 (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
469 &&
470 (/* Then check if it accepts any instance id, and if not, if it matches Wine's
471 * instance id.
472 */
473 ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) ||
474 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentioned in no DX docs, but it works fine - tested on WinXP */
475 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType)))
476 &&
477 ( /* Then if the asked type matches the one Wine provides */
478 DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
479 {
480 done[j] = 1;
481
482 TRACE("Matching :\n");
483 TRACE(" - Asked (%d) :\n", j);
484 TRACE(" * GUID: %s ('%s')\n",
485 debugstr_guid(asked_format->rgodf[j].pguid),
486 _dump_dinput_GUID(asked_format->rgodf[j].pguid));
487 TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
488 TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
489 TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
490 TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
491 TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
492
493 TRACE(" - Wine (%d) :\n", i);
494 TRACE(" * GUID: %s ('%s')\n",
495 debugstr_guid(format->wine_df->rgodf[i].pguid),
496 _dump_dinput_GUID(format->wine_df->rgodf[i].pguid));
497 TRACE(" * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs);
498 TRACE(" * dwType: 0x%08x\n", format->wine_df->rgodf[i].dwType);
499 TRACE(" "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n");
500 TRACE(" * dwFlags: 0x%08x\n", format->wine_df->rgodf[i].dwFlags);
501 TRACE(" "); _dump_ObjectDataFormat_flags(format->wine_df->rgodf[i].dwFlags); TRACE("\n");
502
503 if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON)
504 dt[index].size = sizeof(BYTE);
505 else
506 dt[index].size = sizeof(DWORD);
507 dt[index].offset_in = format->wine_df->rgodf[i].dwOfs;
508 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
509 format->offsets[i] = asked_format->rgodf[j].dwOfs;
510 dt[index].value = 0;
511 next = next + dt[index].size;
512
513 if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out)
514 same = 0;
515
516 index++;
517 break;
518 }
519 }
520 }
521
522 TRACE("Setting to default value :\n");
523 for (j = 0; j < asked_format->dwNumObjs; j++) {
524 if (done[j] == 0) {
525 TRACE(" - Asked (%d) :\n", j);
526 TRACE(" * GUID: %s ('%s')\n",
527 debugstr_guid(asked_format->rgodf[j].pguid),
528 _dump_dinput_GUID(asked_format->rgodf[j].pguid));
529 TRACE(" * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
530 TRACE(" * dwType: 0x%08x\n", asked_format->rgodf[j].dwType);
531 TRACE(" "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
532 TRACE(" * dwFlags: 0x%08x\n", asked_format->rgodf[j].dwFlags);
533 TRACE(" "); _dump_ObjectDataFormat_flags(asked_format->rgodf[j].dwFlags); TRACE("\n");
534
535 if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
536 dt[index].size = sizeof(BYTE);
537 else
538 dt[index].size = sizeof(DWORD);
539 dt[index].offset_in = -1;
540 dt[index].offset_out = asked_format->rgodf[j].dwOfs;
541 if (asked_format->rgodf[j].dwType & DIDFT_POV)
542 dt[index].value = -1;
543 else
544 dt[index].value = 0;
545 index++;
546
547 same = 0;
548 }
549 }
550
551 format->internal_format_size = format->wine_df->dwDataSize;
552 format->size = index;
553 if (same) {
554 HeapFree(GetProcessHeap(), 0, dt);
555 dt = NULL;
556 }
557 format->dt = dt;
558
559 HeapFree(GetProcessHeap(), 0, done);
560
561 return DI_OK;
562
563 failed:
564 HeapFree(GetProcessHeap(), 0, done);
565 HeapFree(GetProcessHeap(), 0, dt);
566 format->dt = NULL;
567 HeapFree(GetProcessHeap(), 0, format->offsets);
568 format->offsets = NULL;
569 HeapFree(GetProcessHeap(), 0, format->user_df);
570 format->user_df = NULL;
571
572 return DIERR_OUTOFMEMORY;
573 }
574
575 /* find an object by its offset in a data format */
offset_to_object(const DataFormat * df,int offset)576 static int offset_to_object(const DataFormat *df, int offset)
577 {
578 int i;
579
580 if (!df->offsets) return -1;
581
582 for (i = 0; i < df->wine_df->dwNumObjs; i++)
583 if (df->offsets[i] == offset) return i;
584
585 return -1;
586 }
587
id_to_object(LPCDIDATAFORMAT df,int id)588 int id_to_object(LPCDIDATAFORMAT df, int id)
589 {
590 int i;
591
592 id &= 0x00ffffff;
593 for (i = 0; i < df->dwNumObjs; i++)
594 if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id)
595 return i;
596
597 return -1;
598 }
599
id_to_offset(const DataFormat * df,int id)600 static int id_to_offset(const DataFormat *df, int id)
601 {
602 int obj = id_to_object(df->wine_df, id);
603
604 return obj >= 0 && df->offsets ? df->offsets[obj] : -1;
605 }
606
find_property(const DataFormat * df,LPCDIPROPHEADER ph)607 int find_property(const DataFormat *df, LPCDIPROPHEADER ph)
608 {
609 switch (ph->dwHow)
610 {
611 case DIPH_BYID: return id_to_object(df->wine_df, ph->dwObj);
612 case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj);
613 }
614 FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow);
615
616 return -1;
617 }
618
semantic_to_obj_id(IDirectInputDeviceImpl * This,DWORD dwSemantic)619 static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic)
620 {
621 DWORD type = (0x0000ff00 & dwSemantic) >> 8;
622 DWORD offset = 0x000000ff & dwSemantic;
623 DWORD obj_instance = 0;
624 BOOL found = FALSE;
625 int i;
626
627 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
628 {
629 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
630
631 if (odf->dwOfs == offset)
632 {
633 obj_instance = DIDFT_GETINSTANCE(odf->dwType);
634 found = TRUE;
635 break;
636 }
637 }
638
639 if (!found) return 0;
640
641 if (type & DIDFT_AXIS) type = DIDFT_RELAXIS;
642 if (type & DIDFT_BUTTON) type = DIDFT_PSHBUTTON;
643
644 return type | (0x0000ff00 & (obj_instance << 8));
645 }
646
del_mapping_key(const WCHAR * device,const WCHAR * username,const WCHAR * guid)647 static void del_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) {
648 static const WCHAR subkey[] = {
649 'S','o','f','t','w','a','r','e','\\',
650 'W','i','n','e','\\',
651 'D','i','r','e','c','t','I','n','p','u','t','\\',
652 'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
653 WCHAR *keyname;
654
655 keyname = heap_alloc(sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
656 sprintfW(keyname, subkey, username, device, guid);
657
658 /* Remove old key mappings so there will be no overlapping mappings */
659 RegDeleteKeyW(HKEY_CURRENT_USER, keyname);
660
661 heap_free(keyname);
662 }
663
664 /*
665 * get_mapping_key
666 * Retrieves an open registry key to save the mapping, parametrized for an username,
667 * specific device and specific action mapping guid.
668 */
get_mapping_key(const WCHAR * device,const WCHAR * username,const WCHAR * guid,BOOL create)669 static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid, BOOL create)
670 {
671 static const WCHAR subkey[] = {
672 'S','o','f','t','w','a','r','e','\\',
673 'W','i','n','e','\\',
674 'D','i','r','e','c','t','I','n','p','u','t','\\',
675 'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
676 HKEY hkey;
677 WCHAR *keyname;
678
679 keyname = HeapAlloc(GetProcessHeap(), 0,
680 sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
681 sprintfW(keyname, subkey, username, device, guid);
682
683 /* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
684 if (create) {
685 if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
686 hkey = 0;
687 } else if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &hkey))
688 hkey = 0;
689
690 HeapFree(GetProcessHeap(), 0, keyname);
691
692 return hkey;
693 }
694
save_mapping_settings(IDirectInputDevice8W * iface,LPDIACTIONFORMATW lpdiaf,LPCWSTR lpszUsername)695 HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
696 {
697 WCHAR *guid_str = NULL;
698 DIDEVICEINSTANCEW didev;
699 HKEY hkey;
700 int i;
701
702 didev.dwSize = sizeof(didev);
703 IDirectInputDevice8_GetDeviceInfo(iface, &didev);
704
705 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
706 return DI_SETTINGSNOTSAVED;
707
708 del_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
709
710 hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str, TRUE);
711
712 if (!hkey)
713 {
714 CoTaskMemFree(guid_str);
715 return DI_SETTINGSNOTSAVED;
716 }
717
718 /* Write each of the actions mapped for this device.
719 Format is "dwSemantic"="dwObjID" and key is of type REG_DWORD
720 */
721 for (i = 0; i < lpdiaf->dwNumActions; i++)
722 {
723 static const WCHAR format[] = {'%','x','\0'};
724 WCHAR label[9];
725
726 if (IsEqualGUID(&didev.guidInstance, &lpdiaf->rgoAction[i].guidInstance) &&
727 lpdiaf->rgoAction[i].dwHow != DIAH_UNMAPPED)
728 {
729 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
730 RegSetValueExW(hkey, label, 0, REG_DWORD, (const BYTE*) &lpdiaf->rgoAction[i].dwObjID, sizeof(DWORD));
731 }
732 }
733
734 RegCloseKey(hkey);
735 CoTaskMemFree(guid_str);
736
737 return DI_OK;
738 }
739
load_mapping_settings(IDirectInputDeviceImpl * This,LPDIACTIONFORMATW lpdiaf,const WCHAR * username)740 BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
741 {
742 HKEY hkey;
743 WCHAR *guid_str;
744 DIDEVICEINSTANCEW didev;
745 int i;
746
747 didev.dwSize = sizeof(didev);
748 IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev);
749
750 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
751 return FALSE;
752
753 hkey = get_mapping_key(didev.tszInstanceName, username, guid_str, FALSE);
754
755 if (!hkey)
756 {
757 CoTaskMemFree(guid_str);
758 return FALSE;
759 }
760
761 /* Try to read each action in the DIACTIONFORMAT from registry */
762 for (i = 0; i < lpdiaf->dwNumActions; i++)
763 {
764 static const WCHAR format[] = {'%','x','\0'};
765 DWORD id, size = sizeof(DWORD);
766 WCHAR label[9];
767
768 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
769
770 if (!RegQueryValueExW(hkey, label, 0, NULL, (LPBYTE) &id, &size))
771 {
772 lpdiaf->rgoAction[i].dwObjID = id;
773 lpdiaf->rgoAction[i].guidInstance = didev.guidInstance;
774 lpdiaf->rgoAction[i].dwHow = DIAH_USERCONFIG;
775 }
776 else
777 {
778 memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
779 lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
780 }
781
782 }
783
784 RegCloseKey(hkey);
785 CoTaskMemFree(guid_str);
786
787 /* On Windows BuildActionMap can open empty mapping, so always return TRUE if get_mapping_key is success */
788 return TRUE;
789 }
790
_build_action_map(LPDIRECTINPUTDEVICE8W iface,LPDIACTIONFORMATW lpdiaf,LPCWSTR lpszUserName,DWORD dwFlags,DWORD devMask,LPCDIDATAFORMAT df)791 HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
792 {
793 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
794 WCHAR username[MAX_PATH];
795 DWORD username_size = MAX_PATH;
796 int i;
797 BOOL load_success = FALSE, has_actions = FALSE;
798
799 /* Unless asked the contrary by these flags, try to load a previous mapping */
800 if (!(dwFlags & DIDBAM_HWDEFAULTS))
801 {
802 /* Retrieve logged user name if necessary */
803 if (lpszUserName == NULL)
804 GetUserNameW(username, &username_size);
805 else
806 lstrcpynW(username, lpszUserName, MAX_PATH);
807
808 load_success = load_mapping_settings(This, lpdiaf, username);
809 }
810
811 if (load_success) {
812 /* Update dwCRC to track if action format has changed */
813 for (i=0; i < lpdiaf->dwNumActions; i++)
814 {
815 lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
816 lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
817 }
818 return DI_OK;
819 }
820
821 for (i=0; i < lpdiaf->dwNumActions; i++)
822 {
823 if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask)
824 {
825 DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
826 DWORD type = DIDFT_GETTYPE(obj_id);
827 DWORD inst = DIDFT_GETINSTANCE(obj_id);
828
829 LPDIOBJECTDATAFORMAT odf;
830
831 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
832 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
833
834 /* Make sure the object exists */
835 odf = dataformat_to_odf_by_type(df, inst, type);
836
837 if (odf != NULL)
838 {
839 lpdiaf->rgoAction[i].dwObjID = obj_id;
840 lpdiaf->rgoAction[i].guidInstance = This->guid;
841 lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
842 has_actions = TRUE;
843 }
844 }
845 else if (!(dwFlags & DIDBAM_PRESERVE))
846 {
847 /* We must clear action data belonging to other devices */
848 memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
849 lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
850 }
851 }
852
853 /* Update dwCRC to track if action format has changed */
854 lpdiaf->dwCRC = 0;
855 for (i=0; i < lpdiaf->dwNumActions; i++)
856 {
857 lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
858 lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
859 }
860
861 if (!has_actions) return DI_NOEFFECT;
862
863 return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
864 }
865
_set_action_map(LPDIRECTINPUTDEVICE8W iface,LPDIACTIONFORMATW lpdiaf,LPCWSTR lpszUserName,DWORD dwFlags,LPCDIDATAFORMAT df)866 HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df)
867 {
868 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
869 DIDATAFORMAT data_format;
870 DIOBJECTDATAFORMAT *obj_df = NULL;
871 DIPROPDWORD dp;
872 DIPROPRANGE dpr;
873 DIPROPSTRING dps;
874 WCHAR username[MAX_PATH];
875 DWORD username_size = MAX_PATH;
876 DWORD new_crc = 0;
877 int i, action = 0, num_actions = 0;
878 unsigned int offset = 0;
879
880 if (This->acquired) return DIERR_ACQUIRED;
881
882 data_format.dwSize = sizeof(data_format);
883 data_format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
884 data_format.dwFlags = DIDF_RELAXIS;
885 data_format.dwDataSize = lpdiaf->dwDataSize;
886
887 /* Calculate checksum for actionformat */
888 for (i=0; i < lpdiaf->dwNumActions; i++)
889 {
890 new_crc ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
891 new_crc ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
892 }
893
894 /* Count the actions */
895 for (i=0; i < lpdiaf->dwNumActions; i++)
896 {
897 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance) ||
898 (IsEqualGUID(&IID_NULL, &lpdiaf->rgoAction[i].guidInstance) &&
899 ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
900 (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */) ))
901 {
902 num_actions++;
903 }
904 }
905
906 /* Should return DI_NOEFFECT if we dont have any actions and actionformat has not changed */
907 if (num_actions == 0 && lpdiaf->dwCRC == new_crc && !(dwFlags & DIDSAM_FORCESAVE)) return DI_NOEFFECT;
908
909 /* update dwCRC to track if action format has changed */
910 lpdiaf->dwCRC = new_crc;
911
912 This->num_actions = num_actions;
913
914 /* Construct the dataformat and actionmap */
915 obj_df = HeapAlloc(GetProcessHeap(), 0, sizeof(DIOBJECTDATAFORMAT)*num_actions);
916 data_format.rgodf = (LPDIOBJECTDATAFORMAT)obj_df;
917 data_format.dwNumObjs = num_actions;
918
919 HeapFree(GetProcessHeap(), 0, This->action_map);
920 This->action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions);
921
922 for (i = 0; i < lpdiaf->dwNumActions; i++)
923 {
924 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
925 {
926 DWORD inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID);
927 DWORD type = DIDFT_GETTYPE(lpdiaf->rgoAction[i].dwObjID);
928 LPDIOBJECTDATAFORMAT obj;
929
930 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
931 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
932
933 obj = dataformat_to_odf_by_type(df, inst, type);
934
935 memcpy(&obj_df[action], obj, df->dwObjSize);
936
937 This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
938 This->action_map[action].offset = offset;
939 obj_df[action].dwOfs = offset;
940 offset += (type & DIDFT_BUTTON) ? 1 : 4;
941
942 action++;
943 }
944 else if ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
945 (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */)
946 {
947 DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
948 DWORD type = DIDFT_GETTYPE(obj_id);
949 DWORD inst = DIDFT_GETINSTANCE(obj_id);
950 LPDIOBJECTDATAFORMAT obj;
951
952 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
953 else if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
954
955 obj = dataformat_to_odf_by_type(df, inst, type);
956 TRACE("obj %p, inst 0x%08x, type 0x%08x\n", obj, inst, type);
957 if(obj)
958 {
959 memcpy(&obj_df[action], obj, df->dwObjSize);
960
961 This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
962 This->action_map[action].offset = offset;
963 obj_df[action].dwOfs = offset;
964 offset += (type & DIDFT_BUTTON) ? 1 : 4;
965
966 action++;
967 }
968 }
969 }
970
971 if (action == 0)
972 {
973 HeapFree(GetProcessHeap(), 0, obj_df);
974 return DI_NOEFFECT;
975 }
976 data_format.dwNumObjs = action;
977
978 IDirectInputDevice8_SetDataFormat(iface, &data_format);
979
980 HeapFree(GetProcessHeap(), 0, obj_df);
981
982 /* Set the device properties according to the action format */
983 dpr.diph.dwSize = sizeof(DIPROPRANGE);
984 dpr.lMin = lpdiaf->lAxisMin;
985 dpr.lMax = lpdiaf->lAxisMax;
986 dpr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
987 dpr.diph.dwHow = DIPH_DEVICE;
988 IDirectInputDevice8_SetProperty(iface, DIPROP_RANGE, &dpr.diph);
989
990 if (lpdiaf->dwBufferSize > 0)
991 {
992 dp.diph.dwSize = sizeof(DIPROPDWORD);
993 dp.dwData = lpdiaf->dwBufferSize;
994 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
995 dp.diph.dwHow = DIPH_DEVICE;
996 IDirectInputDevice8_SetProperty(iface, DIPROP_BUFFERSIZE, &dp.diph);
997 }
998
999 /* Retrieve logged user name if necessary */
1000 if (lpszUserName == NULL)
1001 GetUserNameW(username, &username_size);
1002 else
1003 lstrcpynW(username, lpszUserName, MAX_PATH);
1004
1005 dps.diph.dwSize = sizeof(dps);
1006 dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1007 dps.diph.dwObj = 0;
1008 dps.diph.dwHow = DIPH_DEVICE;
1009 if (dwFlags & DIDSAM_NOUSER)
1010 dps.wsz[0] = '\0';
1011 else
1012 lstrcpynW(dps.wsz, username, ARRAY_SIZE(dps.wsz));
1013 IDirectInputDevice8_SetProperty(iface, DIPROP_USERNAME, &dps.diph);
1014
1015 /* Save the settings to disk */
1016 save_mapping_settings(iface, lpdiaf, username);
1017
1018 return DI_OK;
1019 }
1020
1021 /******************************************************************************
1022 * queue_event - add new event to the ring queue
1023 */
1024
queue_event(LPDIRECTINPUTDEVICE8A iface,int inst_id,DWORD data,DWORD time,DWORD seq)1025 void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
1026 {
1027 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1028 int next_pos, ofs = id_to_offset(&This->data_format, inst_id);
1029
1030 /* Event is being set regardless of the queue state */
1031 if (This->hEvent) SetEvent(This->hEvent);
1032
1033 PostMessageW(GetDesktopWindow(), WM_WINE_NOTIFY_ACTIVITY, 0, 0);
1034
1035 if (!This->queue_len || This->overflow || ofs < 0) return;
1036
1037 next_pos = (This->queue_head + 1) % This->queue_len;
1038 if (next_pos == This->queue_tail)
1039 {
1040 TRACE(" queue overflowed\n");
1041 This->overflow = TRUE;
1042 return;
1043 }
1044
1045 TRACE(" queueing %d at offset %d (queue head %d / size %d)\n",
1046 data, ofs, This->queue_head, This->queue_len);
1047
1048 This->data_queue[This->queue_head].dwOfs = ofs;
1049 This->data_queue[This->queue_head].dwData = data;
1050 This->data_queue[This->queue_head].dwTimeStamp = time;
1051 This->data_queue[This->queue_head].dwSequence = seq;
1052
1053 /* Set uAppData by means of action mapping */
1054 if (This->num_actions > 0)
1055 {
1056 int i;
1057 for (i=0; i < This->num_actions; i++)
1058 {
1059 if (This->action_map[i].offset == ofs)
1060 {
1061 TRACE("Offset %d mapped to uAppData %lu\n", ofs, This->action_map[i].uAppData);
1062 This->data_queue[This->queue_head].uAppData = This->action_map[i].uAppData;
1063 break;
1064 }
1065 }
1066 }
1067
1068 This->queue_head = next_pos;
1069 /* Send event if asked */
1070 }
1071
1072 /******************************************************************************
1073 * Acquire
1074 */
1075
IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)1076 HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
1077 {
1078 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1079 HRESULT res;
1080
1081 TRACE("(%p)\n", This);
1082
1083 if (!This->data_format.user_df) return DIERR_INVALIDPARAM;
1084 if (This->dwCoopLevel & DISCL_FOREGROUND && This->win != GetForegroundWindow())
1085 return DIERR_OTHERAPPHASPRIO;
1086
1087 EnterCriticalSection(&This->crit);
1088 res = This->acquired ? S_FALSE : DI_OK;
1089 This->acquired = 1;
1090 LeaveCriticalSection(&This->crit);
1091 if (res == DI_OK)
1092 check_dinput_hooks(iface, TRUE);
1093
1094 return res;
1095 }
1096
IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)1097 HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
1098 {
1099 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1100 return IDirectInputDevice2WImpl_Acquire(IDirectInputDevice8W_from_impl(This));
1101 }
1102
1103
1104 /******************************************************************************
1105 * Unacquire
1106 */
1107
IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)1108 HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
1109 {
1110 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1111 HRESULT res;
1112
1113 TRACE("(%p)\n", This);
1114
1115 EnterCriticalSection(&This->crit);
1116 res = !This->acquired ? DI_NOEFFECT : DI_OK;
1117 This->acquired = 0;
1118 LeaveCriticalSection(&This->crit);
1119 if (res == DI_OK)
1120 check_dinput_hooks(iface, FALSE);
1121
1122 return res;
1123 }
1124
IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)1125 HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
1126 {
1127 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1128 return IDirectInputDevice2WImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
1129 }
1130
1131 /******************************************************************************
1132 * IDirectInputDeviceA
1133 */
1134
IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface,LPCDIDATAFORMAT df)1135 HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df)
1136 {
1137 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1138 HRESULT res = DI_OK;
1139
1140 if (!df) return E_POINTER;
1141 TRACE("(%p) %p\n", This, df);
1142 _dump_DIDATAFORMAT(df);
1143
1144 if (df->dwSize != sizeof(DIDATAFORMAT)) return DIERR_INVALIDPARAM;
1145 if (This->acquired) return DIERR_ACQUIRED;
1146
1147 EnterCriticalSection(&This->crit);
1148
1149 release_DataFormat(&This->data_format);
1150 res = create_DataFormat(df, &This->data_format);
1151
1152 LeaveCriticalSection(&This->crit);
1153 return res;
1154 }
1155
IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface,LPCDIDATAFORMAT df)1156 HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
1157 {
1158 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1159 return IDirectInputDevice2WImpl_SetDataFormat(IDirectInputDevice8W_from_impl(This), df);
1160 }
1161
1162 /******************************************************************************
1163 * SetCooperativeLevel
1164 *
1165 * Set cooperative level and the source window for the events.
1166 */
IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface,HWND hwnd,DWORD dwflags)1167 HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags)
1168 {
1169 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1170
1171 TRACE("(%p) %p,0x%08x\n", This, hwnd, dwflags);
1172 _dump_cooperativelevel_DI(dwflags);
1173
1174 if ((dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == 0 ||
1175 (dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE) ||
1176 (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == 0 ||
1177 (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == (DISCL_FOREGROUND | DISCL_BACKGROUND))
1178 return DIERR_INVALIDPARAM;
1179
1180 if (hwnd && GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) return E_HANDLE;
1181
1182 if (!hwnd && dwflags == (DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))
1183 hwnd = GetDesktopWindow();
1184
1185 if (!IsWindow(hwnd)) return E_HANDLE;
1186
1187 /* For security reasons native does not allow exclusive background level
1188 for mouse and keyboard only */
1189 if (dwflags & DISCL_EXCLUSIVE && dwflags & DISCL_BACKGROUND &&
1190 (IsEqualGUID(&This->guid, &GUID_SysMouse) ||
1191 IsEqualGUID(&This->guid, &GUID_SysKeyboard)))
1192 return DIERR_UNSUPPORTED;
1193
1194 /* Store the window which asks for the mouse */
1195 EnterCriticalSection(&This->crit);
1196 This->win = hwnd;
1197 This->dwCoopLevel = dwflags;
1198 LeaveCriticalSection(&This->crit);
1199
1200 return DI_OK;
1201 }
1202
IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface,HWND hwnd,DWORD dwflags)1203 HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
1204 {
1205 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1206 return IDirectInputDevice2WImpl_SetCooperativeLevel(IDirectInputDevice8W_from_impl(This), hwnd, dwflags);
1207 }
1208
1209 /******************************************************************************
1210 * SetEventNotification : specifies event to be sent on state change
1211 */
IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface,HANDLE event)1212 HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE event)
1213 {
1214 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1215
1216 TRACE("(%p) %p\n", This, event);
1217
1218 EnterCriticalSection(&This->crit);
1219 This->hEvent = event;
1220 LeaveCriticalSection(&This->crit);
1221 return DI_OK;
1222 }
1223
IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,HANDLE event)1224 HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
1225 {
1226 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1227 return IDirectInputDevice2WImpl_SetEventNotification(IDirectInputDevice8W_from_impl(This), event);
1228 }
1229
1230
IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)1231 ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
1232 {
1233 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1234 ULONG ref = InterlockedDecrement(&(This->ref));
1235
1236 TRACE("(%p) ref %d\n", This, ref);
1237
1238 if (ref) return ref;
1239
1240 IDirectInputDevice_Unacquire(iface);
1241 /* Reset the FF state, free all effects, etc */
1242 IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET);
1243
1244 HeapFree(GetProcessHeap(), 0, This->data_queue);
1245
1246 /* Free data format */
1247 HeapFree(GetProcessHeap(), 0, This->data_format.wine_df->rgodf);
1248 HeapFree(GetProcessHeap(), 0, This->data_format.wine_df);
1249 release_DataFormat(&This->data_format);
1250
1251 /* Free action mapping */
1252 HeapFree(GetProcessHeap(), 0, This->action_map);
1253
1254 EnterCriticalSection( &This->dinput->crit );
1255 list_remove( &This->entry );
1256 LeaveCriticalSection( &This->dinput->crit );
1257
1258 IDirectInput_Release(&This->dinput->IDirectInput7A_iface);
1259 This->crit.DebugInfo->Spare[0] = 0;
1260 DeleteCriticalSection(&This->crit);
1261
1262 HeapFree(GetProcessHeap(), 0, This);
1263
1264 return ref;
1265 }
1266
IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)1267 ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
1268 {
1269 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1270 return IDirectInputDevice2WImpl_Release(IDirectInputDevice8W_from_impl(This));
1271 }
1272
IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface,REFIID riid,LPVOID * ppobj)1273 HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj)
1274 {
1275 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1276
1277 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj);
1278 if (IsEqualGUID(&IID_IUnknown, riid) ||
1279 IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
1280 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
1281 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
1282 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
1283 {
1284 IDirectInputDevice2_AddRef(iface);
1285 *ppobj = IDirectInputDevice8A_from_impl(This);
1286 return DI_OK;
1287 }
1288 if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) ||
1289 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
1290 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
1291 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
1292 {
1293 IDirectInputDevice2_AddRef(iface);
1294 *ppobj = IDirectInputDevice8W_from_impl(This);
1295 return DI_OK;
1296 }
1297
1298 WARN("Unsupported interface!\n");
1299 return E_NOINTERFACE;
1300 }
1301
IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface,REFIID riid,LPVOID * ppobj)1302 HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
1303 {
1304 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1305 return IDirectInputDevice2WImpl_QueryInterface(IDirectInputDevice8W_from_impl(This), riid, ppobj);
1306 }
1307
IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)1308 ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
1309 {
1310 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1311 ULONG ref = InterlockedIncrement(&This->ref);
1312 TRACE( "(%p) ref %d\n", This, ref );
1313 return ref;
1314 }
1315
IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)1316 ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
1317 {
1318 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1319 return IDirectInputDevice2WImpl_AddRef(IDirectInputDevice8W_from_impl(This));
1320 }
1321
IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,LPVOID lpvRef,DWORD dwFlags)1322 HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
1323 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
1324 {
1325 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1326 DIDEVICEOBJECTINSTANCEA ddoi;
1327 int i;
1328
1329 TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
1330 TRACE(" - flags = ");
1331 _dump_EnumObjects_flags(dwFlags);
1332 TRACE("\n");
1333
1334 /* Only the fields till dwFFMaxForce are relevant */
1335 memset(&ddoi, 0, sizeof(ddoi));
1336 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
1337
1338 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
1339 {
1340 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
1341
1342 if (dwFlags != DIDFT_ALL && !(dwFlags & DIDFT_GETTYPE(odf->dwType))) continue;
1343 if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
1344 continue;
1345
1346 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
1347 }
1348
1349 return DI_OK;
1350 }
1351
IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,LPVOID lpvRef,DWORD dwFlags)1352 HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
1353 LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
1354 {
1355 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1356 DIDEVICEOBJECTINSTANCEW ddoi;
1357 int i;
1358
1359 TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
1360 TRACE(" - flags = ");
1361 _dump_EnumObjects_flags(dwFlags);
1362 TRACE("\n");
1363
1364 /* Only the fields till dwFFMaxForce are relevant */
1365 memset(&ddoi, 0, sizeof(ddoi));
1366 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, dwFFMaxForce);
1367
1368 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
1369 {
1370 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
1371
1372 if (dwFlags != DIDFT_ALL && !(dwFlags & DIDFT_GETTYPE(odf->dwType))) continue;
1373 if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
1374 continue;
1375
1376 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
1377 }
1378
1379 return DI_OK;
1380 }
1381
1382 /******************************************************************************
1383 * GetProperty
1384 */
1385
IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,REFGUID rguid,LPDIPROPHEADER pdiph)1386 HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1387 {
1388 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1389
1390 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
1391 _dump_DIPROPHEADER(pdiph);
1392
1393 if (!IS_DIPROP(rguid)) return DI_OK;
1394
1395 switch (LOWORD(rguid))
1396 {
1397 case (DWORD_PTR) DIPROP_BUFFERSIZE:
1398 {
1399 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
1400
1401 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1402
1403 pd->dwData = This->queue_len;
1404 TRACE("buffersize = %d\n", pd->dwData);
1405 break;
1406 }
1407 case (DWORD_PTR) DIPROP_USERNAME:
1408 {
1409 LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph;
1410 struct DevicePlayer *device_player;
1411
1412 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
1413
1414 LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players,
1415 struct DevicePlayer, entry)
1416 {
1417 if (IsEqualGUID(&device_player->instance_guid, &This->guid))
1418 {
1419 if (*device_player->username)
1420 {
1421 lstrcpynW(ps->wsz, device_player->username, ARRAY_SIZE(ps->wsz));
1422 return DI_OK;
1423 }
1424 else break;
1425 }
1426 }
1427 return S_FALSE;
1428 }
1429 case (DWORD_PTR) DIPROP_VIDPID:
1430 FIXME("DIPROP_VIDPID not implemented\n");
1431 return DIERR_UNSUPPORTED;
1432 default:
1433 FIXME("Unknown property %s\n", debugstr_guid(rguid));
1434 return DIERR_INVALIDPARAM;
1435 }
1436
1437 return DI_OK;
1438 }
1439
IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPDIPROPHEADER pdiph)1440 HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
1441 {
1442 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1443 return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
1444 }
1445
1446 /******************************************************************************
1447 * SetProperty
1448 */
1449
IDirectInputDevice2WImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface,REFGUID rguid,LPCDIPROPHEADER pdiph)1450 HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
1451 LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
1452 {
1453 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1454
1455 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
1456 _dump_DIPROPHEADER(pdiph);
1457
1458 if (!IS_DIPROP(rguid)) return DI_OK;
1459
1460 switch (LOWORD(rguid))
1461 {
1462 case (DWORD_PTR) DIPROP_AXISMODE:
1463 {
1464 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;
1465
1466 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1467 if (pdiph->dwHow == DIPH_DEVICE && pdiph->dwObj) return DIERR_INVALIDPARAM;
1468 if (This->acquired) return DIERR_ACQUIRED;
1469 if (pdiph->dwHow != DIPH_DEVICE) return DIERR_UNSUPPORTED;
1470 if (!This->data_format.user_df) return DI_OK;
1471
1472 TRACE("Axis mode: %s\n", pd->dwData == DIPROPAXISMODE_ABS ? "absolute" :
1473 "relative");
1474
1475 EnterCriticalSection(&This->crit);
1476 This->data_format.user_df->dwFlags &= ~DIDFT_AXIS;
1477 This->data_format.user_df->dwFlags |= pd->dwData == DIPROPAXISMODE_ABS ?
1478 DIDF_ABSAXIS : DIDF_RELAXIS;
1479 LeaveCriticalSection(&This->crit);
1480 break;
1481 }
1482 case (DWORD_PTR) DIPROP_BUFFERSIZE:
1483 {
1484 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;
1485
1486 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
1487 if (This->acquired) return DIERR_ACQUIRED;
1488
1489 TRACE("buffersize = %d\n", pd->dwData);
1490
1491 EnterCriticalSection(&This->crit);
1492 HeapFree(GetProcessHeap(), 0, This->data_queue);
1493
1494 This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0,
1495 pd->dwData * sizeof(DIDEVICEOBJECTDATA));
1496 This->queue_head = This->queue_tail = This->overflow = 0;
1497 This->queue_len = pd->dwData;
1498
1499 LeaveCriticalSection(&This->crit);
1500 break;
1501 }
1502 case (DWORD_PTR) DIPROP_USERNAME:
1503 {
1504 LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph;
1505 struct DevicePlayer *device_player;
1506 BOOL found = FALSE;
1507
1508 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
1509
1510 LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players,
1511 struct DevicePlayer, entry)
1512 {
1513 if (IsEqualGUID(&device_player->instance_guid, &This->guid))
1514 {
1515 found = TRUE;
1516 break;
1517 }
1518 }
1519 if (!found && (device_player =
1520 HeapAlloc(GetProcessHeap(), 0, sizeof(struct DevicePlayer))))
1521 {
1522 list_add_tail(&This->dinput->device_players, &device_player->entry);
1523 device_player->instance_guid = This->guid;
1524 }
1525 if (device_player)
1526 lstrcpynW(device_player->username, ps->wsz, ARRAY_SIZE(device_player->username));
1527 break;
1528 }
1529 default:
1530 WARN("Unknown property %s\n", debugstr_guid(rguid));
1531 return DIERR_UNSUPPORTED;
1532 }
1533
1534 return DI_OK;
1535 }
1536
IDirectInputDevice2AImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER pdiph)1537 HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty(
1538 LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
1539 {
1540 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1541 return IDirectInputDevice2WImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
1542 }
1543
IDirectInputDevice2AImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,LPDIDEVICEOBJECTINSTANCEA pdidoi,DWORD dwObj,DWORD dwHow)1544 HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
1545 LPDIRECTINPUTDEVICE8A iface,
1546 LPDIDEVICEOBJECTINSTANCEA pdidoi,
1547 DWORD dwObj,
1548 DWORD dwHow)
1549 {
1550 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1551 DIDEVICEOBJECTINSTANCEW didoiW;
1552 HRESULT res;
1553
1554 if (!pdidoi ||
1555 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) &&
1556 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A)))
1557 return DIERR_INVALIDPARAM;
1558
1559 didoiW.dwSize = sizeof(didoiW);
1560 res = IDirectInputDevice2WImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow);
1561 if (res == DI_OK)
1562 {
1563 DWORD dwSize = pdidoi->dwSize;
1564
1565 memset(pdidoi, 0, pdidoi->dwSize);
1566 pdidoi->dwSize = dwSize;
1567 pdidoi->guidType = didoiW.guidType;
1568 pdidoi->dwOfs = didoiW.dwOfs;
1569 pdidoi->dwType = didoiW.dwType;
1570 pdidoi->dwFlags = didoiW.dwFlags;
1571 }
1572
1573 return res;
1574 }
1575
IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,LPDIDEVICEOBJECTINSTANCEW pdidoi,DWORD dwObj,DWORD dwHow)1576 HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
1577 LPDIRECTINPUTDEVICE8W iface,
1578 LPDIDEVICEOBJECTINSTANCEW pdidoi,
1579 DWORD dwObj,
1580 DWORD dwHow)
1581 {
1582 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1583 DWORD dwSize;
1584 LPDIOBJECTDATAFORMAT odf;
1585 int idx = -1;
1586
1587 TRACE("(%p) %d(0x%08x) -> %p\n", This, dwHow, dwObj, pdidoi);
1588
1589 if (!pdidoi ||
1590 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW) &&
1591 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W)))
1592 return DIERR_INVALIDPARAM;
1593
1594 switch (dwHow)
1595 {
1596 case DIPH_BYOFFSET:
1597 if (!This->data_format.offsets) break;
1598 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
1599 if (This->data_format.offsets[idx] == dwObj) break;
1600 break;
1601 case DIPH_BYID:
1602 dwObj &= 0x00ffffff;
1603 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
1604 if ((dataformat_to_odf(This->data_format.wine_df, idx)->dwType & 0x00ffffff) == dwObj)
1605 break;
1606 break;
1607
1608 case DIPH_BYUSAGE:
1609 FIXME("dwHow = DIPH_BYUSAGE not implemented\n");
1610 break;
1611 default:
1612 WARN("invalid parameter: dwHow = %08x\n", dwHow);
1613 return DIERR_INVALIDPARAM;
1614 }
1615 if (idx < 0) return DIERR_OBJECTNOTFOUND;
1616
1617 odf = dataformat_to_odf(This->data_format.wine_df, idx);
1618 dwSize = pdidoi->dwSize; /* save due to memset below */
1619 memset(pdidoi, 0, pdidoi->dwSize);
1620 pdidoi->dwSize = dwSize;
1621 if (odf->pguid) pdidoi->guidType = *odf->pguid;
1622 pdidoi->dwOfs = This->data_format.offsets ? This->data_format.offsets[idx] : odf->dwOfs;
1623 pdidoi->dwType = odf->dwType;
1624 pdidoi->dwFlags = odf->dwFlags;
1625
1626 return DI_OK;
1627 }
1628
IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,LPDWORD entries,DWORD flags)1629 HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize,
1630 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
1631 {
1632 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1633 HRESULT ret = DI_OK;
1634 int len;
1635
1636 TRACE("(%p) %p -> %p(%d) x%d, 0x%08x\n",
1637 This, dod, entries, entries ? *entries : 0, dodsize, flags);
1638
1639 if (This->dinput->dwVersion == 0x0800 || dodsize == sizeof(DIDEVICEOBJECTDATA_DX3))
1640 {
1641 if (!This->queue_len) return DIERR_NOTBUFFERED;
1642 if (!This->acquired) return DIERR_NOTACQUIRED;
1643 }
1644
1645 if (!This->queue_len)
1646 return DI_OK;
1647 if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
1648 return DIERR_INVALIDPARAM;
1649
1650 IDirectInputDevice2_Poll(iface);
1651 EnterCriticalSection(&This->crit);
1652
1653 len = This->queue_head - This->queue_tail;
1654 if (len < 0) len += This->queue_len;
1655
1656 if ((*entries != INFINITE) && (len > *entries)) len = *entries;
1657
1658 if (dod)
1659 {
1660 int i;
1661 for (i = 0; i < len; i++)
1662 {
1663 int n = (This->queue_tail + i) % This->queue_len;
1664 memcpy((char *)dod + dodsize * i, This->data_queue + n, dodsize);
1665 }
1666 }
1667 *entries = len;
1668
1669 if (This->overflow && This->dinput->dwVersion == 0x0800)
1670 ret = DI_BUFFEROVERFLOW;
1671
1672 if (!(flags & DIGDD_PEEK))
1673 {
1674 /* Advance reading position */
1675 This->queue_tail = (This->queue_tail + len) % This->queue_len;
1676 This->overflow = FALSE;
1677 }
1678
1679 LeaveCriticalSection(&This->crit);
1680
1681 TRACE("Returning %d events queued\n", *entries);
1682 return ret;
1683 }
1684
IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,LPDWORD entries,DWORD flags)1685 HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize,
1686 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
1687 {
1688 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1689 return IDirectInputDevice2WImpl_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags);
1690 }
1691
IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface,HWND hwndOwner,DWORD dwFlags)1692 HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
1693 {
1694 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1695 FIXME("%p)->(%p,0x%08x): stub!\n", This, hwndOwner, dwFlags);
1696
1697 return DI_OK;
1698 }
1699
IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface,HWND hwndOwner,DWORD dwFlags)1700 HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags)
1701 {
1702 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1703 return IDirectInputDevice2WImpl_RunControlPanel(IDirectInputDevice8W_from_impl(This), hwndOwner, dwFlags);
1704 }
1705
IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface,HINSTANCE hinst,DWORD dwVersion,REFGUID rguid)1706 HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
1707 REFGUID rguid)
1708 {
1709 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1710 FIXME("(%p)->(%p,%d,%s): stub!\n", This, hinst, dwVersion, debugstr_guid(rguid));
1711 return DI_OK;
1712 }
1713
IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface,HINSTANCE hinst,DWORD dwVersion,REFGUID rguid)1714 HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion,
1715 REFGUID rguid)
1716 {
1717 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1718 return IDirectInputDevice2WImpl_Initialize(IDirectInputDevice8W_from_impl(This), hinst, dwVersion, rguid);
1719 }
1720
1721 /******************************************************************************
1722 * IDirectInputDevice2A
1723 */
1724
IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface,REFGUID rguid,LPCDIEFFECT lpeff,LPDIRECTINPUTEFFECT * ppdef,LPUNKNOWN pUnkOuter)1725 HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
1726 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
1727 {
1728 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1729 FIXME("(%p)->(%s,%p,%p,%p): stub!\n", This, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
1730
1731 FIXME("not available in the generic implementation\n");
1732 *ppdef = NULL;
1733 return DIERR_UNSUPPORTED;
1734 }
1735
IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIEFFECT lpeff,LPDIRECTINPUTEFFECT * ppdef,LPUNKNOWN pUnkOuter)1736 HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
1737 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
1738 {
1739 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1740 return IDirectInputDevice2WImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter);
1741 }
1742
IDirectInputDevice2AImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface,LPDIENUMEFFECTSCALLBACKA lpCallback,LPVOID lpvRef,DWORD dwFlags)1743 HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1744 LPDIRECTINPUTDEVICE8A iface,
1745 LPDIENUMEFFECTSCALLBACKA lpCallback,
1746 LPVOID lpvRef,
1747 DWORD dwFlags)
1748 {
1749 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1750 FIXME("%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
1751
1752 return DI_OK;
1753 }
1754
IDirectInputDevice2WImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,LPDIENUMEFFECTSCALLBACKW lpCallback,LPVOID lpvRef,DWORD dwFlags)1755 HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
1756 LPDIRECTINPUTDEVICE8W iface,
1757 LPDIENUMEFFECTSCALLBACKW lpCallback,
1758 LPVOID lpvRef,
1759 DWORD dwFlags)
1760 {
1761 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1762 FIXME("(%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
1763
1764 return DI_OK;
1765 }
1766
IDirectInputDevice2AImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface,LPDIEFFECTINFOA lpdei,REFGUID rguid)1767 HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1768 LPDIRECTINPUTDEVICE8A iface,
1769 LPDIEFFECTINFOA lpdei,
1770 REFGUID rguid)
1771 {
1772 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1773 FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
1774 return DI_OK;
1775 }
1776
IDirectInputDevice2WImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,LPDIEFFECTINFOW lpdei,REFGUID rguid)1777 HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
1778 LPDIRECTINPUTDEVICE8W iface,
1779 LPDIEFFECTINFOW lpdei,
1780 REFGUID rguid)
1781 {
1782 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1783 FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
1784 return DI_OK;
1785 }
1786
IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface,LPDWORD pdwOut)1787 HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
1788 {
1789 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1790 FIXME("(%p)->(%p): stub!\n", This, pdwOut);
1791 return DI_OK;
1792 }
1793
IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface,LPDWORD pdwOut)1794 HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
1795 {
1796 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1797 return IDirectInputDevice2WImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut);
1798 }
1799
IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface,DWORD dwFlags)1800 HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
1801 {
1802 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1803 TRACE("(%p)->(0x%08x)\n", This, dwFlags);
1804 return DI_NOEFFECT;
1805 }
1806
IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface,DWORD dwFlags)1807 HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
1808 {
1809 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1810 return IDirectInputDevice2WImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags);
1811 }
1812
IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,LPVOID lpvRef,DWORD dwFlags)1813 HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
1814 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
1815 {
1816 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1817 FIXME("(%p)0>(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
1818 return DI_OK;
1819 }
1820
IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,LPVOID lpvRef,DWORD dwFlags)1821 HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
1822 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
1823 {
1824 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1825 return IDirectInputDevice2WImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, lpvRef, dwFlags);
1826 }
1827
IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface,LPDIEFFESCAPE lpDIEEsc)1828 HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
1829 {
1830 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1831 FIXME("(%p)->(%p): stub!\n", This, lpDIEEsc);
1832 return DI_OK;
1833 }
1834
IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface,LPDIEFFESCAPE lpDIEEsc)1835 HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc)
1836 {
1837 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1838 return IDirectInputDevice2WImpl_Escape(IDirectInputDevice8W_from_impl(This), lpDIEEsc);
1839 }
1840
IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)1841 HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
1842 {
1843 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1844
1845 if (!This->acquired) return DIERR_NOTACQUIRED;
1846
1847 check_dinput_events();
1848 return DI_OK;
1849 }
1850
IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)1851 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
1852 {
1853 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1854 return IDirectInputDevice2WImpl_Poll(IDirectInputDevice8W_from_impl(This));
1855 }
1856
IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface,DWORD cbObjectData,LPCDIDEVICEOBJECTDATA rgdod,LPDWORD pdwInOut,DWORD dwFlags)1857 HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData,
1858 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
1859 DWORD dwFlags)
1860 {
1861 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1862 FIXME("(%p)->(0x%08x,%p,%p,0x%08x): stub!\n", This, cbObjectData, rgdod, pdwInOut, dwFlags);
1863
1864 return DI_OK;
1865 }
1866
IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface,DWORD cbObjectData,LPCDIDEVICEOBJECTDATA rgdod,LPDWORD pdwInOut,DWORD dwFlags)1867 HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData,
1868 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
1869 DWORD dwFlags)
1870 {
1871 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1872 return IDirectInputDevice2WImpl_SendDeviceData(IDirectInputDevice8W_from_impl(This), cbObjectData, rgdod,
1873 pdwInOut, dwFlags);
1874 }
1875
IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,LPCSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags)1876 HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
1877 LPCSTR lpszFileName,
1878 LPDIENUMEFFECTSINFILECALLBACK pec,
1879 LPVOID pvRef,
1880 DWORD dwFlags)
1881 {
1882 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1883 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, lpszFileName, pec, pvRef, dwFlags);
1884
1885 return DI_OK;
1886 }
1887
IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,LPCWSTR lpszFileName,LPDIENUMEFFECTSINFILECALLBACK pec,LPVOID pvRef,DWORD dwFlags)1888 HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
1889 LPCWSTR lpszFileName,
1890 LPDIENUMEFFECTSINFILECALLBACK pec,
1891 LPVOID pvRef,
1892 DWORD dwFlags)
1893 {
1894 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1895 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
1896
1897 return DI_OK;
1898 }
1899
IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,LPCSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags)1900 HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
1901 LPCSTR lpszFileName,
1902 DWORD dwEntries,
1903 LPDIFILEEFFECT rgDiFileEft,
1904 DWORD dwFlags)
1905 {
1906 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1907 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
1908
1909 return DI_OK;
1910 }
1911
IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,LPCWSTR lpszFileName,DWORD dwEntries,LPDIFILEEFFECT rgDiFileEft,DWORD dwFlags)1912 HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
1913 LPCWSTR lpszFileName,
1914 DWORD dwEntries,
1915 LPDIFILEEFFECT rgDiFileEft,
1916 DWORD dwFlags)
1917 {
1918 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1919 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
1920
1921 return DI_OK;
1922 }
1923
IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,LPDIACTIONFORMATW lpdiaf,LPCWSTR lpszUserName,DWORD dwFlags)1924 HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
1925 LPDIACTIONFORMATW lpdiaf,
1926 LPCWSTR lpszUserName,
1927 DWORD dwFlags)
1928 {
1929 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1930 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
1931 #define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
1932 X(DIDBAM_DEFAULT)
1933 X(DIDBAM_PRESERVE)
1934 X(DIDBAM_INITIALIZE)
1935 X(DIDBAM_HWDEFAULTS)
1936 #undef X
1937
1938 return DI_OK;
1939 }
1940
IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)1941 HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
1942 LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
1943 {
1944 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
1945 FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
1946
1947 return DI_OK;
1948 }
1949
IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)1950 HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
1951 LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
1952 {
1953 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
1954 FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
1955
1956 return DI_OK;
1957 }
1958