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 "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" 41 42 WINE_DEFAULT_DEBUG_CHANNEL(dinput); 43 44 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface) 45 { 46 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface); 47 } 48 static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) 49 { 50 return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface); 51 } 52 53 static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl *This) 54 { 55 return &This->IDirectInputDevice8A_iface; 56 } 57 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This) 58 { 59 return &This->IDirectInputDevice8W_iface; 60 } 61 62 /****************************************************************************** 63 * Various debugging tools 64 */ 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 79 }; 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"); 85 } 86 } 87 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 100 }; 101 102 if (!dwFlags) return; 103 104 TRACE("Flags:"); 105 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); 110 } 111 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); 119 } 120 #undef FE 121 122 } 123 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 147 }; 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); 158 } 159 } 160 if (type) { 161 TRACE(" (unhandled: %08x)", type); 162 } 163 } 164 TRACE(" / Instance: "); 165 if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) { 166 TRACE("DIDFT_ANYINSTANCE"); 167 } else { 168 TRACE("%3d", instance); 169 } 170 } 171 } 172 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"))); 180 } 181 } 182 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); 186 } 187 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); 191 } 192 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 228 }; 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; 234 } 235 } 236 return debugstr_guid(guid); 237 } 238 239 void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) { 240 unsigned int i; 241 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); 246 } 247 TRACE(" - dwObjsize: %d\n", df->dwObjSize); 248 if (df->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) { 249 WARN("Non-standard DIOBJECTDATAFORMAT structure size %d\n", df->dwObjSize); 250 } 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; 256 } 257 TRACE(")\n"); 258 TRACE(" - dwDataSize: %d\n", df->dwDataSize); 259 TRACE(" - dwNumObjs: %d\n", df->dwNumObjs); 260 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"); 269 } 270 } 271 272 /****************************************************************************** 273 * Get the default and the app-specific config keys. 274 */ 275 BOOL get_app_key(HKEY *defkey, HKEY *appkey) 276 { 277 char buffer[MAX_PATH+16]; 278 DWORD len; 279 280 *appkey = 0; 281 282 /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */ 283 if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", defkey)) 284 *defkey = 0; 285 286 len = GetModuleFileNameA(0, buffer, MAX_PATH); 287 if (len && len < MAX_PATH) 288 { 289 HKEY tmpkey; 290 291 /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */ 292 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey)) 293 { 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"); 298 299 if (RegOpenKeyA(tmpkey, appname, appkey)) *appkey = 0; 300 RegCloseKey(tmpkey); 301 } 302 } 303 304 return *defkey || *appkey; 305 } 306 307 /****************************************************************************** 308 * Get a config key from either the app-specific or the default config 309 */ 310 DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, 311 char *buffer, DWORD size ) 312 { 313 if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) 314 return 0; 315 316 if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) 317 return 0; 318 319 return ERROR_FILE_NOT_FOUND; 320 } 321 322 /* Conversion between internal data buffer and external data buffer */ 323 void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df) 324 { 325 int i; 326 const char *in_c = in; 327 char *out_c = out; 328 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; 342 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; 348 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; 354 355 default: 356 memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size); 357 break; 358 } 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; 366 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; 372 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; 378 379 default: 380 memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size); 381 break; 382 } 383 } 384 } 385 } 386 } 387 388 void release_DataFormat(DataFormat * format) 389 { 390 TRACE("Deleting DataFormat: %p\n", format); 391 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; 398 } 399 400 static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx) 401 { 402 if (idx < 0 || idx >= df->dwNumObjs) return NULL; 403 return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize); 404 } 405 406 /* dataformat_to_odf_by_type 407 * Find the Nth object of the selected type in the DataFormat 408 */ 409 LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) 410 { 411 int i, nfound = 0; 412 413 for (i=0; i < df->dwNumObjs; i++) 414 { 415 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(df, i); 416 417 if (odf->dwType & type) 418 { 419 if (n == nfound) 420 return odf; 421 422 nfound++; 423 } 424 } 425 426 return NULL; 427 } 428 429 static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format) 430 { 431 DataTransform *dt; 432 unsigned int i, j; 433 int same = 1; 434 int *done; 435 int index = 0; 436 DWORD next = 0; 437 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; 442 443 if (!(format->offsets = HeapAlloc(GetProcessHeap(), 0, format->wine_df->dwNumObjs * sizeof(int)))) 444 goto failed; 445 446 if (!(format->user_df = HeapAlloc(GetProcessHeap(), 0, asked_format->dwSize))) 447 goto failed; 448 memcpy(format->user_df, asked_format, asked_format->dwSize); 449 450 TRACE("Creating DataTransform :\n"); 451 452 for (i = 0; i < format->wine_df->dwNumObjs; i++) 453 { 454 format->offsets[i] = -1; 455 456 for (j = 0; j < asked_format->dwNumObjs; j++) { 457 if (done[j] == 1) 458 continue; 459 460 if (/* Check if the application either requests any GUID and if not, it if matches 461 * the GUID of the Wine object. 462 */ 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))) 466 && 467 (/* Then check if it accepts any instance id, and if not, if it matches Wine's 468 * instance id. 469 */ 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))) 473 && 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)) 476 { 477 done[j] = 1; 478 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"); 489 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"); 499 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; 509 510 if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out) 511 same = 0; 512 513 index++; 514 break; 515 } 516 } 517 } 518 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"); 531 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++; 543 544 same = 0; 545 } 546 } 547 548 format->internal_format_size = format->wine_df->dwDataSize; 549 format->size = index; 550 if (same) { 551 HeapFree(GetProcessHeap(), 0, dt); 552 dt = NULL; 553 } 554 format->dt = dt; 555 556 HeapFree(GetProcessHeap(), 0, done); 557 558 return DI_OK; 559 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; 568 569 return DIERR_OUTOFMEMORY; 570 } 571 572 /* find an object by its offset in a data format */ 573 static int offset_to_object(const DataFormat *df, int offset) 574 { 575 int i; 576 577 if (!df->offsets) return -1; 578 579 for (i = 0; i < df->wine_df->dwNumObjs; i++) 580 if (df->offsets[i] == offset) return i; 581 582 return -1; 583 } 584 585 int id_to_object(LPCDIDATAFORMAT df, int id) 586 { 587 int i; 588 589 id &= 0x00ffffff; 590 for (i = 0; i < df->dwNumObjs; i++) 591 if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id) 592 return i; 593 594 return -1; 595 } 596 597 static int id_to_offset(const DataFormat *df, int id) 598 { 599 int obj = id_to_object(df->wine_df, id); 600 601 return obj >= 0 && df->offsets ? df->offsets[obj] : -1; 602 } 603 604 int find_property(const DataFormat *df, LPCDIPROPHEADER ph) 605 { 606 switch (ph->dwHow) 607 { 608 case DIPH_BYID: return id_to_object(df->wine_df, ph->dwObj); 609 case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj); 610 } 611 FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow); 612 613 return -1; 614 } 615 616 static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic) 617 { 618 DWORD type = (0x0000ff00 & dwSemantic) >> 8; 619 DWORD offset = 0x000000ff & dwSemantic; 620 DWORD obj_instance = 0; 621 BOOL found = FALSE; 622 int i; 623 624 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++) 625 { 626 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i); 627 628 if (odf->dwOfs == offset) 629 { 630 obj_instance = DIDFT_GETINSTANCE(odf->dwType); 631 found = TRUE; 632 break; 633 } 634 } 635 636 if (!found) return 0; 637 638 if (type & DIDFT_AXIS) type = DIDFT_RELAXIS; 639 if (type & DIDFT_BUTTON) type = DIDFT_PSHBUTTON; 640 641 return type | (0x0000ff00 & (obj_instance << 8)); 642 } 643 644 /* 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. 648 */ 649 static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) 650 { 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; 658 659 keyname = HeapAlloc(GetProcessHeap(), 0, 660 sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid))); 661 sprintfW(keyname, subkey, username, device, guid); 662 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; 666 667 HeapFree(GetProcessHeap(), 0, keyname); 668 669 return hkey; 670 } 671 672 static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) 673 { 674 WCHAR *guid_str = NULL; 675 DIDEVICEINSTANCEW didev; 676 HKEY hkey; 677 int i; 678 679 didev.dwSize = sizeof(didev); 680 IDirectInputDevice8_GetDeviceInfo(iface, &didev); 681 682 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK) 683 return DI_SETTINGSNOTSAVED; 684 685 hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str); 686 687 if (!hkey) 688 { 689 CoTaskMemFree(guid_str); 690 return DI_SETTINGSNOTSAVED; 691 } 692 693 /* Write each of the actions mapped for this device. 694 Format is "dwSemantic"="dwObjID" and key is of type REG_DWORD 695 */ 696 for (i = 0; i < lpdiaf->dwNumActions; i++) 697 { 698 static const WCHAR format[] = {'%','x','\0'}; 699 WCHAR label[9]; 700 701 if (IsEqualGUID(&didev.guidInstance, &lpdiaf->rgoAction[i].guidInstance) && 702 lpdiaf->rgoAction[i].dwHow != DIAH_UNMAPPED) 703 { 704 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic); 705 RegSetValueExW(hkey, label, 0, REG_DWORD, (const BYTE*) &lpdiaf->rgoAction[i].dwObjID, sizeof(DWORD)); 706 } 707 } 708 709 RegCloseKey(hkey); 710 CoTaskMemFree(guid_str); 711 712 return DI_OK; 713 } 714 715 static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) 716 { 717 HKEY hkey; 718 WCHAR *guid_str; 719 DIDEVICEINSTANCEW didev; 720 int i, mapped = 0; 721 722 didev.dwSize = sizeof(didev); 723 IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev); 724 725 if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK) 726 return FALSE; 727 728 hkey = get_mapping_key(didev.tszInstanceName, username, guid_str); 729 730 if (!hkey) 731 { 732 CoTaskMemFree(guid_str); 733 return FALSE; 734 } 735 736 /* Try to read each action in the DIACTIONFORMAT from registry */ 737 for (i = 0; i < lpdiaf->dwNumActions; i++) 738 { 739 static const WCHAR format[] = {'%','x','\0'}; 740 DWORD id, size = sizeof(DWORD); 741 WCHAR label[9]; 742 743 sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic); 744 745 if (!RegQueryValueExW(hkey, label, 0, NULL, (LPBYTE) &id, &size)) 746 { 747 lpdiaf->rgoAction[i].dwObjID = id; 748 lpdiaf->rgoAction[i].guidInstance = didev.guidInstance; 749 lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT; 750 mapped += 1; 751 } 752 } 753 754 RegCloseKey(hkey); 755 CoTaskMemFree(guid_str); 756 757 return mapped > 0; 758 } 759 760 HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) 761 { 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; 767 768 /* Unless asked the contrary by these flags, try to load a previous mapping */ 769 if (!(dwFlags & DIDBAM_HWDEFAULTS)) 770 { 771 /* Retrieve logged user name if necessary */ 772 if (lpszUserName == NULL) 773 GetUserNameW(username, &username_size); 774 else 775 lstrcpynW(username, lpszUserName, MAX_PATH); 776 777 load_success = load_mapping_settings(This, lpdiaf, username); 778 } 779 780 if (load_success) return DI_OK; 781 782 for (i=0; i < lpdiaf->dwNumActions; i++) 783 { 784 /* Don't touch a user configured action */ 785 if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue; 786 787 if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask) 788 { 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); 792 793 LPDIOBJECTDATAFORMAT odf; 794 795 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON; 796 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS; 797 798 /* Make sure the object exists */ 799 odf = dataformat_to_odf_by_type(df, inst, type); 800 801 if (odf != NULL) 802 { 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; 807 } 808 } 809 else if (!(dwFlags & DIDBAM_PRESERVE)) 810 { 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; 814 } 815 } 816 817 if (!has_actions) return DI_NOEFFECT; 818 819 return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags); 820 } 821 822 HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) 823 { 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; 834 835 if (This->acquired) return DIERR_ACQUIRED; 836 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; 841 842 /* Count the actions */ 843 for (i=0; i < lpdiaf->dwNumActions; i++) 844 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance)) 845 num_actions++; 846 847 if (num_actions == 0) return DI_NOEFFECT; 848 849 This->num_actions = num_actions; 850 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; 855 856 HeapFree(GetProcessHeap(), 0, This->action_map); 857 This->action_map = HeapAlloc(GetProcessHeap(), 0, sizeof(ActionMap)*num_actions); 858 859 for (i = 0; i < lpdiaf->dwNumActions; i++) 860 { 861 if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance)) 862 { 863 DWORD inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID); 864 DWORD type = DIDFT_GETTYPE(lpdiaf->rgoAction[i].dwObjID); 865 LPDIOBJECTDATAFORMAT obj; 866 867 if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON; 868 if (type == DIDFT_RELAXIS) type = DIDFT_AXIS; 869 870 obj = dataformat_to_odf_by_type(df, inst, type); 871 872 memcpy(&obj_df[action], obj, df->dwObjSize); 873 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; 878 879 action++; 880 } 881 } 882 883 IDirectInputDevice8_SetDataFormat(iface, &data_format); 884 885 HeapFree(GetProcessHeap(), 0, obj_df); 886 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); 894 895 if (lpdiaf->dwBufferSize > 0) 896 { 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); 902 } 903 904 /* Retrieve logged user name if necessary */ 905 if (lpszUserName == NULL) 906 GetUserNameW(username, &username_size); 907 else 908 lstrcpynW(username, lpszUserName, MAX_PATH); 909 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); 919 920 /* Save the settings to disk */ 921 save_mapping_settings(iface, lpdiaf, username); 922 923 return DI_OK; 924 } 925 926 /****************************************************************************** 927 * queue_event - add new event to the ring queue 928 */ 929 930 void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq) 931 { 932 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 933 int next_pos, ofs = id_to_offset(&This->data_format, inst_id); 934 935 /* Event is being set regardless of the queue state */ 936 if (This->hEvent) SetEvent(This->hEvent); 937 938 if (!This->queue_len || This->overflow || ofs < 0) return; 939 940 next_pos = (This->queue_head + 1) % This->queue_len; 941 if (next_pos == This->queue_tail) 942 { 943 TRACE(" queue overflowed\n"); 944 This->overflow = TRUE; 945 return; 946 } 947 948 TRACE(" queueing %d at offset %d (queue head %d / size %d)\n", 949 data, ofs, This->queue_head, This->queue_len); 950 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; 955 956 /* Set uAppData by means of action mapping */ 957 if (This->num_actions > 0) 958 { 959 int i; 960 for (i=0; i < This->num_actions; i++) 961 { 962 if (This->action_map[i].offset == ofs) 963 { 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; 967 } 968 } 969 } 970 971 This->queue_head = next_pos; 972 /* Send event if asked */ 973 } 974 975 /****************************************************************************** 976 * Acquire 977 */ 978 979 HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) 980 { 981 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 982 HRESULT res; 983 984 TRACE("(%p)\n", This); 985 986 if (!This->data_format.user_df) return DIERR_INVALIDPARAM; 987 if (This->dwCoopLevel & DISCL_FOREGROUND && This->win != GetForegroundWindow()) 988 return DIERR_OTHERAPPHASPRIO; 989 990 EnterCriticalSection(&This->crit); 991 res = This->acquired ? S_FALSE : DI_OK; 992 This->acquired = 1; 993 LeaveCriticalSection(&This->crit); 994 if (res == DI_OK) 995 check_dinput_hooks(iface, TRUE); 996 997 return res; 998 } 999 1000 HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) 1001 { 1002 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1003 return IDirectInputDevice2WImpl_Acquire(IDirectInputDevice8W_from_impl(This)); 1004 } 1005 1006 1007 /****************************************************************************** 1008 * Unacquire 1009 */ 1010 1011 HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) 1012 { 1013 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1014 HRESULT res; 1015 1016 TRACE("(%p)\n", This); 1017 1018 EnterCriticalSection(&This->crit); 1019 res = !This->acquired ? DI_NOEFFECT : DI_OK; 1020 This->acquired = 0; 1021 LeaveCriticalSection(&This->crit); 1022 if (res == DI_OK) 1023 check_dinput_hooks(iface, FALSE); 1024 1025 return res; 1026 } 1027 1028 HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) 1029 { 1030 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1031 return IDirectInputDevice2WImpl_Unacquire(IDirectInputDevice8W_from_impl(This)); 1032 } 1033 1034 /****************************************************************************** 1035 * IDirectInputDeviceA 1036 */ 1037 1038 HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df) 1039 { 1040 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1041 HRESULT res = DI_OK; 1042 1043 if (!df) return E_POINTER; 1044 TRACE("(%p) %p\n", This, df); 1045 _dump_DIDATAFORMAT(df); 1046 1047 if (df->dwSize != sizeof(DIDATAFORMAT)) return DIERR_INVALIDPARAM; 1048 if (This->acquired) return DIERR_ACQUIRED; 1049 1050 EnterCriticalSection(&This->crit); 1051 1052 release_DataFormat(&This->data_format); 1053 res = create_DataFormat(df, &This->data_format); 1054 1055 LeaveCriticalSection(&This->crit); 1056 return res; 1057 } 1058 1059 HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df) 1060 { 1061 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1062 return IDirectInputDevice2WImpl_SetDataFormat(IDirectInputDevice8W_from_impl(This), df); 1063 } 1064 1065 /****************************************************************************** 1066 * SetCooperativeLevel 1067 * 1068 * Set cooperative level and the source window for the events. 1069 */ 1070 HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags) 1071 { 1072 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1073 1074 TRACE("(%p) %p,0x%08x\n", This, hwnd, dwflags); 1075 _dump_cooperativelevel_DI(dwflags); 1076 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; 1082 1083 if (hwnd && GetWindowLongW(hwnd, GWL_STYLE) & WS_CHILD) return E_HANDLE; 1084 1085 if (!hwnd && dwflags == (DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)) 1086 hwnd = GetDesktopWindow(); 1087 1088 if (!IsWindow(hwnd)) return E_HANDLE; 1089 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; 1096 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); 1102 1103 return DI_OK; 1104 } 1105 1106 HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags) 1107 { 1108 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1109 return IDirectInputDevice2WImpl_SetCooperativeLevel(IDirectInputDevice8W_from_impl(This), hwnd, dwflags); 1110 } 1111 1112 /****************************************************************************** 1113 * SetEventNotification : specifies event to be sent on state change 1114 */ 1115 HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE event) 1116 { 1117 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1118 1119 TRACE("(%p) %p\n", This, event); 1120 1121 EnterCriticalSection(&This->crit); 1122 This->hEvent = event; 1123 LeaveCriticalSection(&This->crit); 1124 return DI_OK; 1125 } 1126 1127 HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event) 1128 { 1129 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1130 return IDirectInputDevice2WImpl_SetEventNotification(IDirectInputDevice8W_from_impl(This), event); 1131 } 1132 1133 1134 ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface) 1135 { 1136 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1137 ULONG ref = InterlockedDecrement(&(This->ref)); 1138 1139 TRACE("(%p) releasing from %d\n", This, ref + 1); 1140 1141 if (ref) return ref; 1142 1143 IDirectInputDevice_Unacquire(iface); 1144 /* Reset the FF state, free all effects, etc */ 1145 IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET); 1146 1147 HeapFree(GetProcessHeap(), 0, This->data_queue); 1148 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); 1153 1154 /* Free action mapping */ 1155 HeapFree(GetProcessHeap(), 0, This->action_map); 1156 1157 EnterCriticalSection( &This->dinput->crit ); 1158 list_remove( &This->entry ); 1159 LeaveCriticalSection( &This->dinput->crit ); 1160 1161 IDirectInput_Release(&This->dinput->IDirectInput7A_iface); 1162 This->crit.DebugInfo->Spare[0] = 0; 1163 DeleteCriticalSection(&This->crit); 1164 1165 HeapFree(GetProcessHeap(), 0, This); 1166 1167 return DI_OK; 1168 } 1169 1170 ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface) 1171 { 1172 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1173 return IDirectInputDevice2WImpl_Release(IDirectInputDevice8W_from_impl(This)); 1174 } 1175 1176 HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj) 1177 { 1178 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1179 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)) 1186 { 1187 IDirectInputDevice2_AddRef(iface); 1188 *ppobj = IDirectInputDevice8A_from_impl(This); 1189 return DI_OK; 1190 } 1191 if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) || 1192 IsEqualGUID(&IID_IDirectInputDevice2W, riid) || 1193 IsEqualGUID(&IID_IDirectInputDevice7W, riid) || 1194 IsEqualGUID(&IID_IDirectInputDevice8W, riid)) 1195 { 1196 IDirectInputDevice2_AddRef(iface); 1197 *ppobj = IDirectInputDevice8W_from_impl(This); 1198 return DI_OK; 1199 } 1200 1201 WARN("Unsupported interface!\n"); 1202 return E_FAIL; 1203 } 1204 1205 HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj) 1206 { 1207 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1208 return IDirectInputDevice2WImpl_QueryInterface(IDirectInputDevice8W_from_impl(This), riid, ppobj); 1209 } 1210 1211 ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface) 1212 { 1213 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1214 return InterlockedIncrement(&This->ref); 1215 } 1216 1217 ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface) 1218 { 1219 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1220 return IDirectInputDevice2WImpl_AddRef(IDirectInputDevice8W_from_impl(This)); 1221 } 1222 1223 HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface, 1224 LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags) 1225 { 1226 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1227 DIDEVICEOBJECTINSTANCEA ddoi; 1228 int i; 1229 1230 TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags); 1231 TRACE(" - flags = "); 1232 _dump_EnumObjects_flags(dwFlags); 1233 TRACE("\n"); 1234 1235 /* Only the fields till dwFFMaxForce are relevant */ 1236 memset(&ddoi, 0, sizeof(ddoi)); 1237 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce); 1238 1239 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++) 1240 { 1241 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i); 1242 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; 1246 1247 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break; 1248 } 1249 1250 return DI_OK; 1251 } 1252 1253 HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, 1254 LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags) 1255 { 1256 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1257 DIDEVICEOBJECTINSTANCEW ddoi; 1258 int i; 1259 1260 TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags); 1261 TRACE(" - flags = "); 1262 _dump_EnumObjects_flags(dwFlags); 1263 TRACE("\n"); 1264 1265 /* Only the fields till dwFFMaxForce are relevant */ 1266 memset(&ddoi, 0, sizeof(ddoi)); 1267 ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, dwFFMaxForce); 1268 1269 for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++) 1270 { 1271 LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i); 1272 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; 1276 1277 if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break; 1278 } 1279 1280 return DI_OK; 1281 } 1282 1283 /****************************************************************************** 1284 * GetProperty 1285 */ 1286 1287 HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) 1288 { 1289 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1290 1291 TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); 1292 _dump_DIPROPHEADER(pdiph); 1293 1294 if (!IS_DIPROP(rguid)) return DI_OK; 1295 1296 switch (LOWORD(rguid)) 1297 { 1298 case (DWORD_PTR) DIPROP_BUFFERSIZE: 1299 { 1300 LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; 1301 1302 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; 1303 1304 pd->dwData = This->queue_len; 1305 TRACE("buffersize = %d\n", pd->dwData); 1306 break; 1307 } 1308 case (DWORD_PTR) DIPROP_USERNAME: 1309 { 1310 LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph; 1311 struct DevicePlayer *device_player; 1312 1313 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM; 1314 1315 LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players, 1316 struct DevicePlayer, entry) 1317 { 1318 if (IsEqualGUID(&device_player->instance_guid, &This->guid)) 1319 { 1320 if (*device_player->username) 1321 { 1322 lstrcpynW(ps->wsz, device_player->username, sizeof(ps->wsz)/sizeof(WCHAR)); 1323 return DI_OK; 1324 } 1325 else break; 1326 } 1327 } 1328 return S_FALSE; 1329 } 1330 case (DWORD_PTR) DIPROP_VIDPID: 1331 FIXME("DIPROP_VIDPID not implemented\n"); 1332 return DIERR_UNSUPPORTED; 1333 default: 1334 FIXME("Unknown property %s\n", debugstr_guid(rguid)); 1335 return DIERR_INVALIDPARAM; 1336 } 1337 1338 return DI_OK; 1339 } 1340 1341 HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) 1342 { 1343 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1344 return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); 1345 } 1346 1347 /****************************************************************************** 1348 * SetProperty 1349 */ 1350 1351 HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( 1352 LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER pdiph) 1353 { 1354 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1355 1356 TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); 1357 _dump_DIPROPHEADER(pdiph); 1358 1359 if (!IS_DIPROP(rguid)) return DI_OK; 1360 1361 switch (LOWORD(rguid)) 1362 { 1363 case (DWORD_PTR) DIPROP_AXISMODE: 1364 { 1365 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph; 1366 1367 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; 1368 if (pdiph->dwHow == DIPH_DEVICE && pdiph->dwObj) return DIERR_INVALIDPARAM; 1369 if (This->acquired) return DIERR_ACQUIRED; 1370 if (pdiph->dwHow != DIPH_DEVICE) return DIERR_UNSUPPORTED; 1371 if (!This->data_format.user_df) return DI_OK; 1372 1373 TRACE("Axis mode: %s\n", pd->dwData == DIPROPAXISMODE_ABS ? "absolute" : 1374 "relative"); 1375 1376 EnterCriticalSection(&This->crit); 1377 This->data_format.user_df->dwFlags &= ~DIDFT_AXIS; 1378 This->data_format.user_df->dwFlags |= pd->dwData == DIPROPAXISMODE_ABS ? 1379 DIDF_ABSAXIS : DIDF_RELAXIS; 1380 LeaveCriticalSection(&This->crit); 1381 break; 1382 } 1383 case (DWORD_PTR) DIPROP_BUFFERSIZE: 1384 { 1385 LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph; 1386 1387 if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM; 1388 if (This->acquired) return DIERR_ACQUIRED; 1389 1390 TRACE("buffersize = %d\n", pd->dwData); 1391 1392 EnterCriticalSection(&This->crit); 1393 HeapFree(GetProcessHeap(), 0, This->data_queue); 1394 1395 This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0, 1396 pd->dwData * sizeof(DIDEVICEOBJECTDATA)); 1397 This->queue_head = This->queue_tail = This->overflow = 0; 1398 This->queue_len = pd->dwData; 1399 1400 LeaveCriticalSection(&This->crit); 1401 break; 1402 } 1403 case (DWORD_PTR) DIPROP_USERNAME: 1404 { 1405 LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph; 1406 struct DevicePlayer *device_player; 1407 BOOL found = FALSE; 1408 1409 if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM; 1410 1411 LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players, 1412 struct DevicePlayer, entry) 1413 { 1414 if (IsEqualGUID(&device_player->instance_guid, &This->guid)) 1415 { 1416 found = TRUE; 1417 break; 1418 } 1419 } 1420 if (!found && (device_player = 1421 HeapAlloc(GetProcessHeap(), 0, sizeof(struct DevicePlayer)))) 1422 { 1423 list_add_tail(&This->dinput->device_players, &device_player->entry); 1424 device_player->instance_guid = This->guid; 1425 } 1426 if (device_player) 1427 lstrcpynW(device_player->username, ps->wsz, 1428 sizeof(device_player->username)/sizeof(WCHAR)); 1429 break; 1430 } 1431 default: 1432 WARN("Unknown property %s\n", debugstr_guid(rguid)); 1433 return DIERR_UNSUPPORTED; 1434 } 1435 1436 return DI_OK; 1437 } 1438 1439 HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty( 1440 LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph) 1441 { 1442 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1443 return IDirectInputDevice2WImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); 1444 } 1445 1446 HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo( 1447 LPDIRECTINPUTDEVICE8A iface, 1448 LPDIDEVICEOBJECTINSTANCEA pdidoi, 1449 DWORD dwObj, 1450 DWORD dwHow) 1451 { 1452 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1453 DIDEVICEOBJECTINSTANCEW didoiW; 1454 HRESULT res; 1455 1456 if (!pdidoi || 1457 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) && 1458 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A))) 1459 return DIERR_INVALIDPARAM; 1460 1461 didoiW.dwSize = sizeof(didoiW); 1462 res = IDirectInputDevice2WImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow); 1463 if (res == DI_OK) 1464 { 1465 DWORD dwSize = pdidoi->dwSize; 1466 1467 memset(pdidoi, 0, pdidoi->dwSize); 1468 pdidoi->dwSize = dwSize; 1469 pdidoi->guidType = didoiW.guidType; 1470 pdidoi->dwOfs = didoiW.dwOfs; 1471 pdidoi->dwType = didoiW.dwType; 1472 pdidoi->dwFlags = didoiW.dwFlags; 1473 } 1474 1475 return res; 1476 } 1477 1478 HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo( 1479 LPDIRECTINPUTDEVICE8W iface, 1480 LPDIDEVICEOBJECTINSTANCEW pdidoi, 1481 DWORD dwObj, 1482 DWORD dwHow) 1483 { 1484 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1485 DWORD dwSize; 1486 LPDIOBJECTDATAFORMAT odf; 1487 int idx = -1; 1488 1489 TRACE("(%p) %d(0x%08x) -> %p\n", This, dwHow, dwObj, pdidoi); 1490 1491 if (!pdidoi || 1492 (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW) && 1493 pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W))) 1494 return DIERR_INVALIDPARAM; 1495 1496 switch (dwHow) 1497 { 1498 case DIPH_BYOFFSET: 1499 if (!This->data_format.offsets) break; 1500 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--) 1501 if (This->data_format.offsets[idx] == dwObj) break; 1502 break; 1503 case DIPH_BYID: 1504 dwObj &= 0x00ffffff; 1505 for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--) 1506 if ((dataformat_to_odf(This->data_format.wine_df, idx)->dwType & 0x00ffffff) == dwObj) 1507 break; 1508 break; 1509 1510 case DIPH_BYUSAGE: 1511 FIXME("dwHow = DIPH_BYUSAGE not implemented\n"); 1512 break; 1513 default: 1514 WARN("invalid parameter: dwHow = %08x\n", dwHow); 1515 return DIERR_INVALIDPARAM; 1516 } 1517 if (idx < 0) return DIERR_OBJECTNOTFOUND; 1518 1519 odf = dataformat_to_odf(This->data_format.wine_df, idx); 1520 dwSize = pdidoi->dwSize; /* save due to memset below */ 1521 memset(pdidoi, 0, pdidoi->dwSize); 1522 pdidoi->dwSize = dwSize; 1523 if (odf->pguid) pdidoi->guidType = *odf->pguid; 1524 pdidoi->dwOfs = This->data_format.offsets ? This->data_format.offsets[idx] : odf->dwOfs; 1525 pdidoi->dwType = odf->dwType; 1526 pdidoi->dwFlags = odf->dwFlags; 1527 1528 return DI_OK; 1529 } 1530 1531 HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize, 1532 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags) 1533 { 1534 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1535 HRESULT ret = DI_OK; 1536 int len; 1537 1538 TRACE("(%p) %p -> %p(%d) x%d, 0x%08x\n", 1539 This, dod, entries, entries ? *entries : 0, dodsize, flags); 1540 1541 if (This->dinput->dwVersion == 0x0800 || dodsize == sizeof(DIDEVICEOBJECTDATA_DX3)) 1542 { 1543 if (!This->queue_len) return DIERR_NOTBUFFERED; 1544 if (!This->acquired) return DIERR_NOTACQUIRED; 1545 } 1546 1547 if (!This->queue_len) 1548 return DI_OK; 1549 if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) 1550 return DIERR_INVALIDPARAM; 1551 1552 IDirectInputDevice2_Poll(iface); 1553 EnterCriticalSection(&This->crit); 1554 1555 len = This->queue_head - This->queue_tail; 1556 if (len < 0) len += This->queue_len; 1557 1558 if ((*entries != INFINITE) && (len > *entries)) len = *entries; 1559 1560 if (dod) 1561 { 1562 int i; 1563 for (i = 0; i < len; i++) 1564 { 1565 int n = (This->queue_tail + i) % This->queue_len; 1566 memcpy((char *)dod + dodsize * i, This->data_queue + n, dodsize); 1567 } 1568 } 1569 *entries = len; 1570 1571 if (This->overflow && This->dinput->dwVersion == 0x0800) 1572 ret = DI_BUFFEROVERFLOW; 1573 1574 if (!(flags & DIGDD_PEEK)) 1575 { 1576 /* Advance reading position */ 1577 This->queue_tail = (This->queue_tail + len) % This->queue_len; 1578 This->overflow = FALSE; 1579 } 1580 1581 LeaveCriticalSection(&This->crit); 1582 1583 TRACE("Returning %d events queued\n", *entries); 1584 return ret; 1585 } 1586 1587 HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize, 1588 LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags) 1589 { 1590 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1591 return IDirectInputDevice2WImpl_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags); 1592 } 1593 1594 HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags) 1595 { 1596 FIXME("(this=%p,%p,0x%08x): stub!\n", iface, hwndOwner, dwFlags); 1597 1598 return DI_OK; 1599 } 1600 1601 HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags) 1602 { 1603 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1604 return IDirectInputDevice2WImpl_RunControlPanel(IDirectInputDevice8W_from_impl(This), hwndOwner, dwFlags); 1605 } 1606 1607 HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion, 1608 REFGUID rguid) 1609 { 1610 FIXME("(this=%p,%p,%d,%s): stub!\n", iface, hinst, dwVersion, debugstr_guid(rguid)); 1611 return DI_OK; 1612 } 1613 1614 HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion, 1615 REFGUID rguid) 1616 { 1617 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1618 return IDirectInputDevice2WImpl_Initialize(IDirectInputDevice8W_from_impl(This), hinst, dwVersion, rguid); 1619 } 1620 1621 /****************************************************************************** 1622 * IDirectInputDevice2A 1623 */ 1624 1625 HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff, 1626 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) 1627 { 1628 FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter); 1629 1630 FIXME("not available in the generic implementation\n"); 1631 *ppdef = NULL; 1632 return DIERR_UNSUPPORTED; 1633 } 1634 1635 HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff, 1636 LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) 1637 { 1638 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1639 return IDirectInputDevice2WImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter); 1640 } 1641 1642 HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects( 1643 LPDIRECTINPUTDEVICE8A iface, 1644 LPDIENUMEFFECTSCALLBACKA lpCallback, 1645 LPVOID lpvRef, 1646 DWORD dwFlags) 1647 { 1648 FIXME("(this=%p,%p,%p,0x%08x): stub!\n", 1649 iface, lpCallback, lpvRef, dwFlags); 1650 1651 return DI_OK; 1652 } 1653 1654 HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects( 1655 LPDIRECTINPUTDEVICE8W iface, 1656 LPDIENUMEFFECTSCALLBACKW lpCallback, 1657 LPVOID lpvRef, 1658 DWORD dwFlags) 1659 { 1660 FIXME("(this=%p,%p,%p,0x%08x): stub!\n", 1661 iface, lpCallback, lpvRef, dwFlags); 1662 1663 return DI_OK; 1664 } 1665 1666 HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo( 1667 LPDIRECTINPUTDEVICE8A iface, 1668 LPDIEFFECTINFOA lpdei, 1669 REFGUID rguid) 1670 { 1671 FIXME("(this=%p,%p,%s): stub!\n", 1672 iface, lpdei, debugstr_guid(rguid)); 1673 return DI_OK; 1674 } 1675 1676 HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo( 1677 LPDIRECTINPUTDEVICE8W iface, 1678 LPDIEFFECTINFOW lpdei, 1679 REFGUID rguid) 1680 { 1681 FIXME("(this=%p,%p,%s): stub!\n", 1682 iface, lpdei, debugstr_guid(rguid)); 1683 return DI_OK; 1684 } 1685 1686 HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) 1687 { 1688 FIXME("(this=%p,%p): stub!\n", iface, pdwOut); 1689 return DI_OK; 1690 } 1691 1692 HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut) 1693 { 1694 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1695 return IDirectInputDevice2WImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut); 1696 } 1697 1698 HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) 1699 { 1700 TRACE("(%p) 0x%08x:\n", iface, dwFlags); 1701 return DI_NOEFFECT; 1702 } 1703 1704 HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags) 1705 { 1706 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1707 return IDirectInputDevice2WImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags); 1708 } 1709 1710 HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface, 1711 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags) 1712 { 1713 FIXME("(this=%p,%p,%p,0x%08x): stub!\n", iface, lpCallback, lpvRef, dwFlags); 1714 return DI_OK; 1715 } 1716 1717 HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface, 1718 LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags) 1719 { 1720 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1721 return IDirectInputDevice2WImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, lpvRef, dwFlags); 1722 } 1723 1724 HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc) 1725 { 1726 FIXME("(this=%p,%p): stub!\n", iface, lpDIEEsc); 1727 return DI_OK; 1728 } 1729 1730 HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc) 1731 { 1732 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1733 return IDirectInputDevice2WImpl_Escape(IDirectInputDevice8W_from_impl(This), lpDIEEsc); 1734 } 1735 1736 HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface) 1737 { 1738 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface); 1739 1740 if (!This->acquired) return DIERR_NOTACQUIRED; 1741 1742 check_dinput_events(); 1743 return DI_OK; 1744 } 1745 1746 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface) 1747 { 1748 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1749 return IDirectInputDevice2WImpl_Poll(IDirectInputDevice8W_from_impl(This)); 1750 } 1751 1752 HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData, 1753 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, 1754 DWORD dwFlags) 1755 { 1756 FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n", iface, cbObjectData, rgdod, pdwInOut, dwFlags); 1757 1758 return DI_OK; 1759 } 1760 1761 HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData, 1762 LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, 1763 DWORD dwFlags) 1764 { 1765 IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface); 1766 return IDirectInputDevice2WImpl_SendDeviceData(IDirectInputDevice8W_from_impl(This), cbObjectData, rgdod, 1767 pdwInOut, dwFlags); 1768 } 1769 1770 HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface, 1771 LPCSTR lpszFileName, 1772 LPDIENUMEFFECTSINFILECALLBACK pec, 1773 LPVOID pvRef, 1774 DWORD dwFlags) 1775 { 1776 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags); 1777 1778 return DI_OK; 1779 } 1780 1781 HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface, 1782 LPCWSTR lpszFileName, 1783 LPDIENUMEFFECTSINFILECALLBACK pec, 1784 LPVOID pvRef, 1785 DWORD dwFlags) 1786 { 1787 FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags); 1788 1789 return DI_OK; 1790 } 1791 1792 HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface, 1793 LPCSTR lpszFileName, 1794 DWORD dwEntries, 1795 LPDIFILEEFFECT rgDiFileEft, 1796 DWORD dwFlags) 1797 { 1798 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags); 1799 1800 return DI_OK; 1801 } 1802 1803 HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface, 1804 LPCWSTR lpszFileName, 1805 DWORD dwEntries, 1806 LPDIFILEEFFECT rgDiFileEft, 1807 DWORD dwFlags) 1808 { 1809 FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags); 1810 1811 return DI_OK; 1812 } 1813 1814 HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, 1815 LPDIACTIONFORMATW lpdiaf, 1816 LPCWSTR lpszUserName, 1817 DWORD dwFlags) 1818 { 1819 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); 1820 #define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n"); 1821 X(DIDBAM_DEFAULT) 1822 X(DIDBAM_PRESERVE) 1823 X(DIDBAM_INITIALIZE) 1824 X(DIDBAM_HWDEFAULTS) 1825 #undef X 1826 1827 return DI_OK; 1828 } 1829 1830 HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface, 1831 LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) 1832 { 1833 FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader); 1834 1835 return DI_OK; 1836 } 1837 1838 HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface, 1839 LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) 1840 { 1841 FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader); 1842 1843 return DI_OK; 1844 } 1845