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 const GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */ 149 0x0ab8648a, 0x7735, 0x11d2, {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41} 150 }; 151 152 static DWORD get_keyboard_subtype(void) 153 { 154 DWORD kbd_type, kbd_subtype, dev_subtype; 155 kbd_type = GetKeyboardType(0); 156 kbd_subtype = GetKeyboardType(1); 157 158 if (kbd_type == 4 || (kbd_type == 7 && kbd_subtype == 0)) 159 dev_subtype = DIDEVTYPEKEYBOARD_PCENH; 160 else if (kbd_type == 7 && kbd_subtype == 2) 161 dev_subtype = DIDEVTYPEKEYBOARD_JAPAN106; 162 else { 163 FIXME("Unknown keyboard type=%u, subtype=%u\n", kbd_type, kbd_subtype); 164 dev_subtype = DIDEVTYPEKEYBOARD_PCENH; 165 } 166 return dev_subtype; 167 } 168 169 static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, DWORD subtype) { 170 DWORD dwSize; 171 DIDEVICEINSTANCEA ddi; 172 173 dwSize = lpddi->dwSize; 174 175 TRACE("%d %p\n", dwSize, lpddi); 176 177 memset(lpddi, 0, dwSize); 178 memset(&ddi, 0, sizeof(ddi)); 179 180 ddi.dwSize = dwSize; 181 ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ 182 ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ 183 if (version >= 0x0800) 184 ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (subtype << 8); 185 else 186 ddi.dwDevType = DIDEVTYPE_KEYBOARD | (subtype << 8); 187 strcpy(ddi.tszInstanceName, "Keyboard"); 188 strcpy(ddi.tszProductName, "Wine Keyboard"); 189 190 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); 191 } 192 193 static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, DWORD subtype) { 194 DWORD dwSize; 195 DIDEVICEINSTANCEW ddi; 196 197 dwSize = lpddi->dwSize; 198 199 TRACE("%d %p\n", dwSize, lpddi); 200 201 memset(lpddi, 0, dwSize); 202 memset(&ddi, 0, sizeof(ddi)); 203 204 ddi.dwSize = dwSize; 205 ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ 206 ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ 207 if (version >= 0x0800) 208 ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (subtype << 8); 209 else 210 ddi.dwDevType = DIDEVTYPE_KEYBOARD | (subtype << 8); 211 MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH); 212 MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH); 213 214 memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); 215 } 216 217 static HRESULT keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) 218 { 219 if (id != 0) 220 return E_FAIL; 221 222 if ((dwDevType == 0) || 223 ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || 224 (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { 225 TRACE("Enumerating the Keyboard device\n"); 226 227 fill_keyboard_dideviceinstanceA(lpddi, version, get_keyboard_subtype()); 228 229 return S_OK; 230 } 231 232 return S_FALSE; 233 } 234 235 static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) 236 { 237 if (id != 0) 238 return E_FAIL; 239 240 if ((dwDevType == 0) || 241 ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) || 242 (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) { 243 TRACE("Enumerating the Keyboard device\n"); 244 245 fill_keyboard_dideviceinstanceW(lpddi, version, get_keyboard_subtype()); 246 247 return S_OK; 248 } 249 250 return S_FALSE; 251 } 252 253 static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput) 254 { 255 SysKeyboardImpl* newDevice; 256 LPDIDATAFORMAT df = NULL; 257 int i, idx = 0; 258 259 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl)); 260 newDevice->base.IDirectInputDevice8A_iface.lpVtbl = &SysKeyboardAvt; 261 newDevice->base.IDirectInputDevice8W_iface.lpVtbl = &SysKeyboardWvt; 262 newDevice->base.ref = 1; 263 memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); 264 newDevice->base.dinput = dinput; 265 newDevice->base.event_proc = KeyboardCallback; 266 InitializeCriticalSection(&newDevice->base.crit); 267 newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit"); 268 newDevice->subtype = get_keyboard_subtype(); 269 270 /* Create copy of default data format */ 271 if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIKeyboard.dwSize))) goto failed; 272 memcpy(df, &c_dfDIKeyboard, c_dfDIKeyboard.dwSize); 273 if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed; 274 275 for (i = 0; i < df->dwNumObjs; i++) 276 { 277 char buf[MAX_PATH]; 278 BYTE dik_code; 279 280 if (!GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), buf, sizeof(buf))) 281 continue; 282 283 dik_code = map_dik_code(i, 0, newDevice->subtype); 284 memcpy(&df->rgodf[idx], &c_dfDIKeyboard.rgodf[dik_code], df->dwObjSize); 285 df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON; 286 } 287 df->dwNumObjs = idx; 288 289 newDevice->base.data_format.wine_df = df; 290 IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface); 291 292 EnterCriticalSection(&dinput->crit); 293 list_add_tail(&dinput->devices_list, &newDevice->base.entry); 294 LeaveCriticalSection(&dinput->crit); 295 296 return newDevice; 297 298 failed: 299 if (df) HeapFree(GetProcessHeap(), 0, df->rgodf); 300 HeapFree(GetProcessHeap(), 0, df); 301 HeapFree(GetProcessHeap(), 0, newDevice); 302 return NULL; 303 } 304 305 306 static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode) 307 { 308 TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode); 309 *pdev = NULL; 310 311 if (IsEqualGUID(&GUID_SysKeyboard, rguid) || /* Generic Keyboard */ 312 IsEqualGUID(&DInput_Wine_Keyboard_GUID, rguid)) /* Wine Keyboard */ 313 { 314 SysKeyboardImpl *This; 315 316 if (riid == NULL) 317 ;/* nothing */ 318 else if (IsEqualGUID(&IID_IDirectInputDeviceA, riid) || 319 IsEqualGUID(&IID_IDirectInputDevice2A, riid) || 320 IsEqualGUID(&IID_IDirectInputDevice7A, riid) || 321 IsEqualGUID(&IID_IDirectInputDevice8A, riid)) 322 { 323 unicode = 0; 324 } 325 else if (IsEqualGUID(&IID_IDirectInputDeviceW, riid) || 326 IsEqualGUID(&IID_IDirectInputDevice2W, riid) || 327 IsEqualGUID(&IID_IDirectInputDevice7W, riid) || 328 IsEqualGUID(&IID_IDirectInputDevice8W, riid)) 329 { 330 unicode = 1; 331 } 332 else 333 { 334 WARN("no interface\n"); 335 return DIERR_NOINTERFACE; 336 } 337 338 This = alloc_device(rguid, dinput); 339 TRACE("Created a Keyboard device (%p)\n", This); 340 341 if (!This) return DIERR_OUTOFMEMORY; 342 343 if (unicode) 344 *pdev = &This->base.IDirectInputDevice8W_iface; 345 else 346 *pdev = &This->base.IDirectInputDevice8A_iface; 347 348 return DI_OK; 349 } 350 351 return DIERR_DEVICENOTREG; 352 } 353 354 const struct dinput_device keyboard_device = { 355 "Wine keyboard driver", 356 keyboarddev_enum_deviceA, 357 keyboarddev_enum_deviceW, 358 keyboarddev_create_device 359 }; 360 361 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) 362 { 363 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 364 TRACE("(%p)->(%d,%p)\n", This, len, ptr); 365 366 if (!This->base.acquired) return DIERR_NOTACQUIRED; 367 368 if (len != This->base.data_format.user_df->dwDataSize ) 369 return DIERR_INVALIDPARAM; 370 371 check_dinput_events(); 372 373 EnterCriticalSection(&This->base.crit); 374 375 if (TRACE_ON(dinput)) { 376 int i; 377 for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { 378 if (This->DInputKeyState[i] != 0x00) 379 TRACE(" - %02X: %02x\n", i, This->DInputKeyState[i]); 380 } 381 } 382 383 fill_DataFormat(ptr, len, This->DInputKeyState, &This->base.data_format); 384 LeaveCriticalSection(&This->base.crit); 385 386 return DI_OK; 387 } 388 389 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr) 390 { 391 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 392 return SysKeyboardWImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr); 393 } 394 395 /****************************************************************************** 396 * GetCapabilities : get the device capabilities 397 */ 398 static HRESULT WINAPI SysKeyboardWImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) 399 { 400 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 401 DIDEVCAPS devcaps; 402 403 TRACE("(this=%p,%p)\n",This,lpDIDevCaps); 404 405 if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) { 406 WARN("invalid parameter\n"); 407 return DIERR_INVALIDPARAM; 408 } 409 410 devcaps.dwSize = lpDIDevCaps->dwSize; 411 devcaps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED; 412 if (This->base.dinput->dwVersion >= 0x0800) 413 devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (This->subtype << 8); 414 else 415 devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (This->subtype << 8); 416 devcaps.dwAxes = 0; 417 devcaps.dwButtons = This->base.data_format.wine_df->dwNumObjs; 418 devcaps.dwPOVs = 0; 419 devcaps.dwFFSamplePeriod = 0; 420 devcaps.dwFFMinTimeResolution = 0; 421 devcaps.dwFirmwareRevision = 100; 422 devcaps.dwHardwareRevision = 100; 423 devcaps.dwFFDriverVersion = 0; 424 425 memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize); 426 427 return DI_OK; 428 } 429 430 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps) 431 { 432 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 433 return SysKeyboardWImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps); 434 } 435 436 static DWORD map_dik_to_scan(DWORD dik_code, DWORD subtype) 437 { 438 if (dik_code == DIK_PAUSE || dik_code == DIK_NUMLOCK) dik_code ^= 0x80; 439 if (subtype == DIDEVTYPEKEYBOARD_JAPAN106) 440 { 441 switch (dik_code) 442 { 443 case DIK_CIRCUMFLEX: 444 dik_code = 0x0d; 445 break; 446 case DIK_AT: 447 dik_code = 0x1a; 448 break; 449 case DIK_LBRACKET: 450 dik_code = 0x1b; 451 break; 452 case DIK_COLON: 453 dik_code = 0x28; 454 break; 455 case DIK_KANJI: 456 dik_code = 0x29; 457 break; 458 case DIK_RBRACKET: 459 dik_code = 0x2b; 460 break; 461 case DIK_BACKSLASH: 462 dik_code = 0x73; 463 break; 464 } 465 } 466 467 return dik_code; 468 } 469 470 /****************************************************************************** 471 * GetObjectInfo : get information about a device object such as a button 472 * or axis 473 */ 474 static HRESULT WINAPI 475 SysKeyboardAImpl_GetObjectInfo( 476 LPDIRECTINPUTDEVICE8A iface, 477 LPDIDEVICEOBJECTINSTANCEA pdidoi, 478 DWORD dwObj, 479 DWORD dwHow) 480 { 481 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 482 HRESULT res; 483 LONG scan; 484 485 res = IDirectInputDevice2AImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); 486 if (res != DI_OK) return res; 487 488 scan = map_dik_to_scan(DIDFT_GETINSTANCE(pdidoi->dwType), This->subtype); 489 if (!GetKeyNameTextA((scan & 0x80) << 17 | (scan & 0x7f) << 16, 490 pdidoi->tszName, sizeof(pdidoi->tszName))) 491 return DIERR_OBJECTNOTFOUND; 492 493 _dump_OBJECTINSTANCEA(pdidoi); 494 return res; 495 } 496 497 static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 498 LPDIDEVICEOBJECTINSTANCEW pdidoi, 499 DWORD dwObj, 500 DWORD dwHow) 501 { 502 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 503 HRESULT res; 504 LONG scan; 505 506 res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow); 507 if (res != DI_OK) return res; 508 509 scan = map_dik_to_scan(DIDFT_GETINSTANCE(pdidoi->dwType), This->subtype); 510 if (!GetKeyNameTextW((scan & 0x80) << 17 | (scan & 0x7f) << 16, 511 pdidoi->tszName, sizeof(pdidoi->tszName)/sizeof(pdidoi->tszName[0]))) 512 return DIERR_OBJECTNOTFOUND; 513 514 _dump_OBJECTINSTANCEW(pdidoi); 515 return res; 516 } 517 518 /****************************************************************************** 519 * GetDeviceInfo : get information about a device's identity 520 */ 521 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( 522 LPDIRECTINPUTDEVICE8A iface, 523 LPDIDEVICEINSTANCEA pdidi) 524 { 525 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 526 TRACE("(this=%p,%p)\n", This, pdidi); 527 528 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { 529 WARN(" dinput3 not supported yet...\n"); 530 return DI_OK; 531 } 532 533 fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion, This->subtype); 534 535 return DI_OK; 536 } 537 538 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) 539 { 540 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 541 TRACE("(this=%p,%p)\n", This, pdidi); 542 543 if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) { 544 WARN(" dinput3 not supported yet...\n"); 545 return DI_OK; 546 } 547 548 fill_keyboard_dideviceinstanceW(pdidi, This->base.dinput->dwVersion, This->subtype); 549 550 return DI_OK; 551 } 552 553 /****************************************************************************** 554 * GetProperty : Retrieves information about the input device. 555 */ 556 static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, 557 REFGUID rguid, LPDIPROPHEADER pdiph) 558 { 559 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 560 561 TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph); 562 _dump_DIPROPHEADER(pdiph); 563 564 if (!IS_DIPROP(rguid)) return DI_OK; 565 566 switch (LOWORD(rguid)) 567 { 568 case (DWORD_PTR)DIPROP_KEYNAME: 569 { 570 HRESULT hr; 571 LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph; 572 DIDEVICEOBJECTINSTANCEW didoi; 573 574 if (pdiph->dwSize != sizeof(DIPROPSTRING)) 575 return DIERR_INVALIDPARAM; 576 577 didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW); 578 579 hr = SysKeyboardWImpl_GetObjectInfo(iface, &didoi, ps->diph.dwObj, ps->diph.dwHow); 580 if (hr == DI_OK) 581 memcpy(ps->wsz, didoi.tszName, sizeof(ps->wsz)); 582 return hr; 583 } 584 case (DWORD_PTR) DIPROP_RANGE: 585 return DIERR_UNSUPPORTED; 586 default: 587 return IDirectInputDevice2AImpl_GetProperty( IDirectInputDevice8A_from_impl(This), rguid, pdiph ); 588 } 589 return DI_OK; 590 } 591 592 static HRESULT WINAPI SysKeyboardAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, 593 REFGUID rguid, LPDIPROPHEADER pdiph) 594 { 595 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 596 return SysKeyboardWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph); 597 } 598 599 static HRESULT WINAPI SysKeyboardWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) 600 { 601 SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface); 602 HRESULT res; 603 604 TRACE("(%p)\n", This); 605 606 res = IDirectInputDevice2WImpl_Acquire(iface); 607 if (res == DI_OK) 608 { 609 TRACE("clearing keystate\n"); 610 memset(This->DInputKeyState, 0, sizeof(This->DInputKeyState)); 611 } 612 613 return res; 614 } 615 616 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) 617 { 618 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 619 return SysKeyboardWImpl_Acquire(IDirectInputDevice8W_from_impl(This)); 620 } 621 622 static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, 623 LPDIACTIONFORMATW lpdiaf, 624 LPCWSTR lpszUserName, 625 DWORD dwFlags) 626 { 627 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); 628 629 return _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard); 630 } 631 632 static HRESULT WINAPI SysKeyboardAImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, 633 LPDIACTIONFORMATA lpdiaf, 634 LPCSTR lpszUserName, 635 DWORD dwFlags) 636 { 637 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 638 DIACTIONFORMATW diafW; 639 HRESULT hr; 640 WCHAR *lpszUserNameW = NULL; 641 int username_size; 642 643 diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions); 644 _copy_diactionformatAtoW(&diafW, lpdiaf); 645 646 if (lpszUserName != NULL) 647 { 648 username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0); 649 lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size); 650 MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size); 651 } 652 653 hr = SysKeyboardWImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags); 654 655 _copy_diactionformatWtoA(lpdiaf, &diafW); 656 HeapFree(GetProcessHeap(), 0, diafW.rgoAction); 657 HeapFree(GetProcessHeap(), 0, lpszUserNameW); 658 659 return hr; 660 } 661 662 static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, 663 LPDIACTIONFORMATW lpdiaf, 664 LPCWSTR lpszUserName, 665 DWORD dwFlags) 666 { 667 FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags); 668 669 return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard); 670 } 671 672 static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface, 673 LPDIACTIONFORMATA lpdiaf, 674 LPCSTR lpszUserName, 675 DWORD dwFlags) 676 { 677 SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface); 678 DIACTIONFORMATW diafW; 679 HRESULT hr; 680 WCHAR *lpszUserNameW = NULL; 681 int username_size; 682 683 diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions); 684 _copy_diactionformatAtoW(&diafW, lpdiaf); 685 686 if (lpszUserName != NULL) 687 { 688 username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0); 689 lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size); 690 MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size); 691 } 692 693 hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags); 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