1 /* DirectInput Keyboard device 2 * 3 * Copyright 1998 Marcus Meissner 4 * Copyright 1998,1999 Lionel Ulmer 5 * Copyright 2000-2001 TransGaming Technologies Inc. 6 * Copyright 2005 Raphael Junqueira 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "config.h" 24 #include "wine/port.h" 25 26 #include <stdarg.h> 27 #include <string.h> 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winuser.h" 31 #include "winerror.h" 32 #include "dinput.h" 33 34 #include "dinput_private.h" 35 #include "device_private.h" 36 #include "wine/debug.h" 37 #include "wine/unicode.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(dinput); 40 41 #define WINE_DINPUT_KEYBOARD_MAX_KEYS 256 42 43 static const IDirectInputDevice8AVtbl SysKeyboardAvt; 44 static const IDirectInputDevice8WVtbl SysKeyboardWvt; 45 46 typedef struct SysKeyboardImpl SysKeyboardImpl; 47 struct SysKeyboardImpl 48 { 49 struct IDirectInputDeviceImpl base; 50 BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; 51 DWORD subtype; 52 }; 53 54 static inline SysKeyboardImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface) 55 { 56 return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), SysKeyboardImpl, base); 57 } 58 static inline SysKeyboardImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface) 59 { 60 return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), SysKeyboardImpl, base); 61 } 62 static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(SysKeyboardImpl *This) 63 { 64 return &This->base.IDirectInputDevice8A_iface; 65 } 66 static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysKeyboardImpl *This) 67 { 68 return &This->base.IDirectInputDevice8W_iface; 69 } 70 71 static BYTE map_dik_code(DWORD scanCode, DWORD vkCode, DWORD subType) 72 { 73 if (!scanCode) 74 scanCode = MapVirtualKeyW(vkCode, MAPVK_VK_TO_VSC); 75 76 if (subType == DIDEVTYPEKEYBOARD_JAPAN106) 77 { 78 switch (scanCode) 79 { 80 case 0x0d: /* ^ */ 81 scanCode = DIK_CIRCUMFLEX; 82 break; 83 case 0x1a: /* @ */ 84 scanCode = DIK_AT; 85 break; 86 case 0x1b: /* [ */ 87 scanCode = DIK_LBRACKET; 88 break; 89 case 0x28: /* : */ 90 scanCode = DIK_COLON; 91 break; 92 case 0x29: /* Hankaku/Zenkaku */ 93 scanCode = DIK_KANJI; 94 break; 95 case 0x2b: /* ] */ 96 scanCode = DIK_RBRACKET; 97 break; 98 case 0x73: /* \ */ 99 scanCode = DIK_BACKSLASH; 100 break; 101 } 102 } 103 return scanCode; 104 } 105 106 static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ) 107 { 108 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 109 int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE; 110 KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; 111 BYTE new_diks; 112 113 if (wparam != WM_KEYDOWN && wparam != WM_KEYUP && 114 wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP) 115 return 0; 116 117 TRACE("(%p) wp %08lx, lp %08lx, vk %02x, scan %02x\n", 118 iface, wparam, lparam, hook->vkCode, hook->scanCode); 119 120 switch (hook->vkCode) 121 { 122 /* R-Shift is special - it is an extended key with separate scan code */ 123 case VK_RSHIFT : dik_code = DIK_RSHIFT; break; 124 case VK_PAUSE : dik_code = DIK_PAUSE; break; 125 case VK_NUMLOCK : dik_code = DIK_NUMLOCK; break; 126 case VK_SUBTRACT: dik_code = DIK_SUBTRACT; break; 127 default: 128 dik_code = map_dik_code(hook->scanCode & 0xff, hook->vkCode, This->subtype); 129 if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; 130 } 131 new_diks = hook->flags & LLKHF_UP ? 0 : 0x80; 132 133 /* returns now if key event already known */ 134 if (new_diks == This->DInputKeyState[dik_code]) 135 return ret; 136 137 This->DInputKeyState[dik_code] = new_diks; 138 TRACE(" setting %02X to %02X\n", dik_code, This->DInputKeyState[dik_code]); 139 140 EnterCriticalSection(&This->base.crit); 141 queue_event(iface, DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON, 142 new_diks, GetCurrentTime(), This->base.dinput->evsequence++); 143 LeaveCriticalSection(&This->base.crit); 144 145 return ret; 146 } 147 148 static DWORD get_keyboard_subtype(void) 149 { 150 DWORD kbd_type, kbd_subtype, dev_subtype; 151 kbd_type = GetKeyboardType(0); 152 kbd_subtype = GetKeyboardType(1); 153 154 if (kbd_type == 4 || (kbd_type == 7 && kbd_subtype == 0)) 155 dev_subtype = DIDEVTYPEKEYBOARD_PCENH; 156 else if (kbd_type == 7 && kbd_subtype == 2) 157 dev_subtype = DIDEVTYPEKEYBOARD_JAPAN106; 158 else { 159 FIXME("Unknown keyboard type=%u, subtype=%u\n", kbd_type, kbd_subtype); 160 dev_subtype = DIDEVTYPEKEYBOARD_PCENH; 161 } 162 return dev_subtype; 163 } 164 165 static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, DWORD subtype) { 166 DWORD dwSize; 167 DIDEVICEINSTANCEA ddi; 168 169 dwSize = lpddi->dwSize; 170 171 TRACE("%d %p\n", dwSize, lpddi); 172 173 memset(lpddi, 0, dwSize); 174 memset(&ddi, 0, sizeof(ddi)); 175 176 ddi.dwSize = dwSize; 177 ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ 178 ddi.guidProduct = GUID_SysKeyboard; 179 if (version >= 0x0800) 180 ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (subtype << 8); 181 else 182 ddi.dwDevType = DIDEVTYPE_KEYBOARD | (subtype << 8); 183 strcpy(ddi.tszInstanceName, "Keyboard"); 184 strcpy(ddi.tszProductName, "Wine Keyboard"); 185 186 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); 187 } 188 189 static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, DWORD subtype) { 190 DWORD dwSize; 191 DIDEVICEINSTANCEW ddi; 192 193 dwSize = lpddi->dwSize; 194 195 TRACE("%d %p\n", dwSize, lpddi); 196 197 memset(lpddi, 0, dwSize); 198 memset(&ddi, 0, sizeof(ddi)); 199 200 ddi.dwSize = dwSize; 201 ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ 202 ddi.guidProduct = GUID_SysKeyboard; 203 if (version >= 0x0800) 204 ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (subtype << 8); 205 else 206 ddi.dwDevType = DIDEVTYPE_KEYBOARD | (subtype << 8); 207 MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH); 208 MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH); 209 210 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); 211 } 212 213 static HRESULT keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) 214 { 215 if (id != 0) 216 return E_FAIL; 217 218 if (dwFlags & DIEDFL_FORCEFEEDBACK) 219 return S_FALSE; 220 221 if ((dwDevType == 0) || 222 ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || 223 (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { 224 TRACE("Enumerating the Keyboard device\n"); 225 226 fill_keyboard_dideviceinstanceA(lpddi, version, get_keyboard_subtype()); 227 228 return S_OK; 229 } 230 231 return S_FALSE; 232 } 233 234 static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) 235 { 236 if (id != 0) 237 return E_FAIL; 238 239 if (dwFlags & DIEDFL_FORCEFEEDBACK) 240 return S_FALSE; 241 242 if ((dwDevType == 0) || 243 ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || 244 (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { 245 TRACE("Enumerating the Keyboard device\n"); 246 247 fill_keyboard_dideviceinstanceW(lpddi, version, get_keyboard_subtype()); 248 249 return S_OK; 250 } 251 252 return S_FALSE; 253 } 254 255 static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) 256 { 257 SysKeyboardImpl* newDevice; 258 LPDIDATAFORMAT df = NULL; 259 int i, idx = 0; 260 261 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl)); 262 newDevice->base.IDirectInputDevice8A_iface.lpVtbl = &SysKeyboardAvt; 263 newDevice->base.IDirectInputDevice8W_iface.lpVtbl = &SysKeyboardWvt; 264 newDevice->base.ref = 1; 265 memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); 266 newDevice->base.dinput = dinput; 267 newDevice->base.event_proc = KeyboardCallback; 268 InitializeCriticalSection(&newDevice->base.crit); 269 newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit"); 270 newDevice->subtype = get_keyboard_subtype(); 271 272 /* Create copy of default data format */ 273 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIKeyboard.dwSize))) goto failed; 274 memcpy(df, &c_dfDIKeyboard, c_dfDIKeyboard.dwSize); 275 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed; 276 277 for (i = 0; i < df->dwNumObjs; i++) 278 { 279 char buf[MAX_PATH]; 280 BYTE dik_code; 281 282 if (!GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), buf, sizeof(buf))) 283 continue; 284 285 dik_code = map_dik_code(i, 0, newDevice->subtype); 286 memcpy(&df->rgodf[idx], &c_dfDIKeyboard.rgodf[dik_code], df->dwObjSize); 287 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON; 288 } 289 df->dwNumObjs = idx; 290 291 newDevice->base.data_format.wine_df = df; 292 IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface); 293 294 EnterCriticalSection(&dinput->crit); 295 list_add_tail(&dinput->devices_list, &newDevice->base.entry); 296 LeaveCriticalSection(&dinput->crit); 297 298 return newDevice; 299 300 failed: 301 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); 302 HeapFree(GetProcessHeap(), 0, df); 303 HeapFree(GetProcessHeap(), 0, newDevice); 304 return NULL; 305 } 306 307 308 static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode) 309 { 310 TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode); 311 *pdev = NULL; 312 313 if (IsEqualGUID(&GUID_SysKeyboard, rguid)) /* Wine Keyboard */ 314 { 315 SysKeyboardImpl *This; 316 317 if (riid == NULL) 318 ;/* nothing */ 319 else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) || 320 IsEqualGUID(&IID_IDirectInputDevice2A, riid) || 321 IsEqualGUID(&IID_IDirectInputDevice7A, riid) || 322 IsEqualGUID(&IID_IDirectInputDevice8A, riid)) 323 { 324 unicode = 0; 325 } 326 else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) || 327 IsEqualGUID(&IID_IDirectInputDevice2W, riid) || 328 IsEqualGUID(&IID_IDirectInputDevice7W, riid) || 329 IsEqualGUID(&IID_IDirectInputDevice8W, riid)) 330 { 331 unicode = 1; 332 } 333 else 334 { 335 WARN("no interface\n"); 336 return DIERR_NOINTERFACE; 337 } 338 339 This = alloc_device(rguid, dinput); 340 TRACE("Created a Keyboard device (%p)\n", This); 341 342 if (!This) return DIERR_OUTOFMEMORY; 343 344 if (unicode) 345 *pdev = &This->base.IDirectInputDevice8W_iface; 346 else 347 *pdev = &This->base.IDirectInputDevice8A_iface; 348 349 return DI_OK; 350 } 351 352 return DIERR_DEVICENOTREG; 353 } 354 355 const struct dinput_device keyboard_device = { 356 "Wine keyboard driver", 357 keyboarddev_enum_deviceA, 358 keyboarddev_enum_deviceW, 359 keyboarddev_create_device 360 }; 361 362 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) 363 { 364 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 365 TRACE("(%p)->(%d,%p)\n", This, len, ptr); 366 367 if (!This->base.acquired) return DIERR_NOTACQUIRED; 368 369 if (len != This->base.data_format.user_df->dwDataSize ) 370 return DIERR_INVALIDPARAM; 371 372 check_dinput_events(); 373 374 EnterCriticalSection(&This->base.crit); 375 376 if (TRACE_ON(dinput)) { 377 int i; 378 for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { 379 if (This->DInputKeyState[i] != 0x00) 380 TRACE(" - %02X: %02x\n", i, This->DInputKeyState[i]); 381 } 382 } 383 384 fill_DataFormat(ptr, len, This->DInputKeyState, &This->base.data_format); 385 LeaveCriticalSection(&This->base.crit); 386 387 return DI_OK; 388 } 389 390 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr) 391 { 392 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 393 return SysKeyboardWImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr); 394 } 395 396 /****************************************************************************** 397 * GetCapabilities : get the device capabilities 398 */ 399 static HRESULT WINAPI SysKeyboardWImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) 400 { 401 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 402 DIDEVCAPS devcaps; 403 404 TRACE("(this=%p,%p)\n",This,lpDIDevCaps); 405 406 if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) { 407 WARN("invalid parameter\n"); 408 return DIERR_INVALIDPARAM; 409 } 410 411 devcaps.dwSize = lpDIDevCaps->dwSize; 412 devcaps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED; 413 if (This->base.dinput->dwVersion >= 0x0800) 414 devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (This->subtype << 8); 415 else 416 devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (This->subtype << 8); 417 devcaps.dwAxes = 0; 418 devcaps.dwButtons = This->base.data_format.wine_df->dwNumObjs; 419 devcaps.dwPOVs = 0; 420 devcaps.dwFFSamplePeriod = 0; 421 devcaps.dwFFMinTimeResolution = 0; 422 devcaps.dwFirmwareRevision = 100; 423 devcaps.dwHardwareRevision = 100; 424 devcaps.dwFFDriverVersion = 0; 425 426 memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize); 427 428 return DI_OK; 429 } 430 431 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps) 432 { 433 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 434 return SysKeyboardWImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps); 435 } 436 437 static DWORD map_dik_to_scan(DWORD dik_code, DWORD subtype) 438 { 439 if (dik_code == DIK_PAUSE || dik_code == DIK_NUMLOCK) dik_code ^= 0x80; 440 if (subtype == DIDEVTYPEKEYBOARD_JAPAN106) 441 { 442 switch (dik_code) 443 { 444 case DIK_CIRCUMFLEX: 445 dik_code = 0x0d; 446 break; 447 case DIK_AT: 448 dik_code = 0x1a; 449 break; 450 case DIK_LBRACKET: 451 dik_code = 0x1b; 452 break; 453 case DIK_COLON: 454 dik_code = 0x28; 455 break; 456 case DIK_KANJI: 457 dik_code = 0x29; 458 break; 459 case DIK_RBRACKET: 460 dik_code = 0x2b; 461 break; 462 case DIK_BACKSLASH: 463 dik_code = 0x73; 464 break; 465 } 466 } 467 468 return dik_code; 469 } 470 471 /****************************************************************************** 472 * GetObjectInfo : get information about a device object such as a button 473 * or axis 474 */ 475 static HRESULT WINAPI 476 SysKeyboardAImpl_GetObjectInfo( 477 LPDIRECTINPUTDEVICE8A iface, 478 LPDIDEVICEOBJECTINSTANCEA pdidoi, 479 DWORD dwObj, 480 DWORD dwHow) 481 { 482 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 483 HRESULT res; 484 LONG scan; 485 486 res = IDirectInputDevice2AImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); 487 if (res != DI_OK) return res; 488 489 scan = map_dik_to_scan(DIDFT_GETINSTANCE(pdidoi->dwType), This->subtype); 490 if (!GetKeyNameTextA((scan & 0x80) << 17 | (scan & 0x7f) << 16, 491 pdidoi->tszName, sizeof(pdidoi->tszName))) 492 return DIERR_OBJECTNOTFOUND; 493 494 _dump_OBJECTINSTANCEA(pdidoi); 495 return res; 496 } 497 498 static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 499 LPDIDEVICEOBJECTINSTANCEW pdidoi, 500 DWORD dwObj, 501 DWORD dwHow) 502 { 503 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 504 HRESULT res; 505 LONG scan; 506 507 res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); 508 if (res != DI_OK) return res; 509 510 scan = map_dik_to_scan(DIDFT_GETINSTANCE(pdidoi->dwType), This->subtype); 511 if (!GetKeyNameTextW((scan & 0x80) << 17 | (scan & 0x7f) << 16, 512 pdidoi->tszName, ARRAY_SIZE(pdidoi->tszName))) 513 return DIERR_OBJECTNOTFOUND; 514 515 _dump_OBJECTINSTANCEW(pdidoi); 516 return res; 517 } 518 519 /****************************************************************************** 520 * GetDeviceInfo : get information about a device's identity 521 */ 522 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( 523 LPDIRECTINPUTDEVICE8A iface, 524 LPDIDEVICEINSTANCEA pdidi) 525 { 526 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 527 TRACE("(this=%p,%p)\n", This, pdidi); 528 529 fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion, This->subtype); 530 531 return DI_OK; 532 } 533 534 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) 535 { 536 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 537 TRACE("(this=%p,%p)\n", This, pdidi); 538 539 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) { 540 WARN(" dinput3 not supported yet...\n"); 541 return DI_OK; 542 } 543 544 fill_keyboard_dideviceinstanceW(pdidi, This->base.dinput->dwVersion, This->subtype); 545 546 return DI_OK; 547 } 548 549 /****************************************************************************** 550 * GetProperty : Retrieves information about the input device. 551 */ 552 static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, 553 REFGUID rguid, LPDIPROPHEADER pdiph) 554 { 555 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 556 557 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph); 558 _dump_DIPROPHEADER(pdiph); 559 560 if (!IS_DIPROP(rguid)) return DI_OK; 561 562 switch (LOWORD(rguid)) 563 { 564 case (DWORD_PTR)DIPROP_KEYNAME: 565 { 566 HRESULT hr; 567 LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph; 568 DIDEVICEOBJECTINSTANCEW didoi; 569 570 if (pdiph->dwSize != sizeof(DIPROPSTRING)) 571 return DIERR_INVALIDPARAM; 572 573 didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW); 574 575 hr = SysKeyboardWImpl_GetObjectInfo(iface, &didoi, ps->diph.dwObj, ps->diph.dwHow); 576 if (hr == DI_OK) 577 memcpy(ps->wsz, didoi.tszName, sizeof(ps->wsz)); 578 return hr; 579 } 580 case (DWORD_PTR) DIPROP_RANGE: 581 return DIERR_UNSUPPORTED; 582 default: 583 return IDirectInputDevice2AImpl_GetProperty( IDirectInputDevice8A_from_impl(This), rguid, pdiph ); 584 } 585 return DI_OK; 586 } 587 588 static HRESULT WINAPI SysKeyboardAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, 589 REFGUID rguid, LPDIPROPHEADER pdiph) 590 { 591 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 592 return SysKeyboardWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); 593 } 594 595 static HRESULT WINAPI SysKeyboardWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) 596 { 597 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 598 HRESULT res; 599 600 TRACE("(%p)\n", This); 601 602 res = IDirectInputDevice2WImpl_Acquire(iface); 603 if (res == DI_OK) 604 { 605 TRACE("clearing keystate\n"); 606 memset(This->DInputKeyState, 0, sizeof(This->DInputKeyState)); 607 } 608 609 return res; 610 } 611 612 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) 613 { 614 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 615 return SysKeyboardWImpl_Acquire(IDirectInputDevice8W_from_impl(This)); 616 } 617 618 static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, 619 LPDIACTIONFORMATW lpdiaf, 620 LPCWSTR lpszUserName, 621 DWORD dwFlags) 622 { 623 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 624 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags); 625 626 return _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard); 627 } 628 629 static HRESULT WINAPI SysKeyboardAImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, 630 LPDIACTIONFORMATA lpdiaf, 631 LPCSTR lpszUserName, 632 DWORD dwFlags) 633 { 634 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 635 DIACTIONFORMATW diafW; 636 HRESULT hr; 637 WCHAR *lpszUserNameW = NULL; 638 int username_size; 639 640 diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions); 641 _copy_diactionformatAtoW(&diafW, lpdiaf); 642 643 if (lpszUserName != NULL) 644 { 645 username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0); 646 lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size); 647 MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size); 648 } 649 650 hr = SysKeyboardWImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags); 651 652 _copy_diactionformatWtoA(lpdiaf, &diafW); 653 HeapFree(GetProcessHeap(), 0, diafW.rgoAction); 654 HeapFree(GetProcessHeap(), 0, lpszUserNameW); 655 656 return hr; 657 } 658 659 static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, 660 LPDIACTIONFORMATW lpdiaf, 661 LPCWSTR lpszUserName, 662 DWORD dwFlags) 663 { 664 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 665 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags); 666 667 return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard); 668 } 669 670 static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface, 671 LPDIACTIONFORMATA lpdiaf, 672 LPCSTR lpszUserName, 673 DWORD dwFlags) 674 { 675 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 676 DIACTIONFORMATW diafW; 677 HRESULT hr; 678 WCHAR *lpszUserNameW = NULL; 679 int username_size; 680 681 diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions); 682 _copy_diactionformatAtoW(&diafW, lpdiaf); 683 684 if (lpszUserName != NULL) 685 { 686 username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0); 687 lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size); 688 MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size); 689 } 690 691 hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags); 692 693 lpdiaf->dwCRC = diafW.dwCRC; 694 695 HeapFree(GetProcessHeap(), 0, diafW.rgoAction); 696 HeapFree(GetProcessHeap(), 0, lpszUserNameW); 697 698 return hr; 699 } 700 701 static const IDirectInputDevice8AVtbl SysKeyboardAvt = 702 { 703 IDirectInputDevice2AImpl_QueryInterface, 704 IDirectInputDevice2AImpl_AddRef, 705 IDirectInputDevice2AImpl_Release, 706 SysKeyboardAImpl_GetCapabilities, 707 IDirectInputDevice2AImpl_EnumObjects, 708 SysKeyboardAImpl_GetProperty, 709 IDirectInputDevice2AImpl_SetProperty, 710 SysKeyboardAImpl_Acquire, 711 IDirectInputDevice2AImpl_Unacquire, 712 SysKeyboardAImpl_GetDeviceState, 713 IDirectInputDevice2AImpl_GetDeviceData, 714 IDirectInputDevice2AImpl_SetDataFormat, 715 IDirectInputDevice2AImpl_SetEventNotification, 716 IDirectInputDevice2AImpl_SetCooperativeLevel, 717 SysKeyboardAImpl_GetObjectInfo, 718 SysKeyboardAImpl_GetDeviceInfo, 719 IDirectInputDevice2AImpl_RunControlPanel, 720 IDirectInputDevice2AImpl_Initialize, 721 IDirectInputDevice2AImpl_CreateEffect, 722 IDirectInputDevice2AImpl_EnumEffects, 723 IDirectInputDevice2AImpl_GetEffectInfo, 724 IDirectInputDevice2AImpl_GetForceFeedbackState, 725 IDirectInputDevice2AImpl_SendForceFeedbackCommand, 726 IDirectInputDevice2AImpl_EnumCreatedEffectObjects, 727 IDirectInputDevice2AImpl_Escape, 728 IDirectInputDevice2AImpl_Poll, 729 IDirectInputDevice2AImpl_SendDeviceData, 730 IDirectInputDevice7AImpl_EnumEffectsInFile, 731 IDirectInputDevice7AImpl_WriteEffectToFile, 732 SysKeyboardAImpl_BuildActionMap, 733 SysKeyboardAImpl_SetActionMap, 734 IDirectInputDevice8AImpl_GetImageInfo 735 }; 736 737 static const IDirectInputDevice8WVtbl SysKeyboardWvt = 738 { 739 IDirectInputDevice2WImpl_QueryInterface, 740 IDirectInputDevice2WImpl_AddRef, 741 IDirectInputDevice2WImpl_Release, 742 SysKeyboardWImpl_GetCapabilities, 743 IDirectInputDevice2WImpl_EnumObjects, 744 SysKeyboardWImpl_GetProperty, 745 IDirectInputDevice2WImpl_SetProperty, 746 SysKeyboardWImpl_Acquire, 747 IDirectInputDevice2WImpl_Unacquire, 748 SysKeyboardWImpl_GetDeviceState, 749 IDirectInputDevice2WImpl_GetDeviceData, 750 IDirectInputDevice2WImpl_SetDataFormat, 751 IDirectInputDevice2WImpl_SetEventNotification, 752 IDirectInputDevice2WImpl_SetCooperativeLevel, 753 SysKeyboardWImpl_GetObjectInfo, 754 SysKeyboardWImpl_GetDeviceInfo, 755 IDirectInputDevice2WImpl_RunControlPanel, 756 IDirectInputDevice2WImpl_Initialize, 757 IDirectInputDevice2WImpl_CreateEffect, 758 IDirectInputDevice2WImpl_EnumEffects, 759 IDirectInputDevice2WImpl_GetEffectInfo, 760 IDirectInputDevice2WImpl_GetForceFeedbackState, 761 IDirectInputDevice2WImpl_SendForceFeedbackCommand, 762 IDirectInputDevice2WImpl_EnumCreatedEffectObjects, 763 IDirectInputDevice2WImpl_Escape, 764 IDirectInputDevice2WImpl_Poll, 765 IDirectInputDevice2WImpl_SendDeviceData, 766 IDirectInputDevice7WImpl_EnumEffectsInFile, 767 IDirectInputDevice7WImpl_WriteEffectToFile, 768 SysKeyboardWImpl_BuildActionMap, 769 SysKeyboardWImpl_SetActionMap, 770 IDirectInputDevice8WImpl_GetImageInfo 771 }; 772