keyboard.c 23.6 KB
Newer Older
Lionel Ulmer's avatar
Lionel Ulmer committed
1 2 3 4
/*		DirectInput Keyboard device
 *
 * Copyright 1998 Marcus Meissner
 * Copyright 1998,1999 Lionel Ulmer
5
 * Copyright 2000-2001 TransGaming Technologies Inc.
6
 * Copyright 2005 Raphael Junqueira
Lionel Ulmer's avatar
Lionel Ulmer committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Lionel Ulmer's avatar
Lionel Ulmer committed
21 22 23
 */

#include "config.h"
24 25
#include "wine/port.h"

26
#include <stdarg.h>
Lionel Ulmer's avatar
Lionel Ulmer committed
27
#include <string.h>
28
#include "windef.h"
29 30
#include "winbase.h"
#include "winuser.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
31 32 33 34 35
#include "winerror.h"
#include "dinput.h"

#include "dinput_private.h"
#include "device_private.h"
36
#include "wine/debug.h"
37
#include "wine/unicode.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
38

39
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
Lionel Ulmer's avatar
Lionel Ulmer committed
40

41 42
#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256

43 44
static const IDirectInputDevice8AVtbl SysKeyboardAvt;
static const IDirectInputDevice8WVtbl SysKeyboardWvt;
45

46 47
typedef struct SysKeyboardImpl SysKeyboardImpl;
struct SysKeyboardImpl
Lionel Ulmer's avatar
Lionel Ulmer committed
48
{
49
    struct IDirectInputDeviceImpl base;
50
    BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS];
Lionel Ulmer's avatar
Lionel Ulmer committed
51 52
};

53 54
static inline SysKeyboardImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
{
55
    return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), SysKeyboardImpl, base);
56 57 58
}
static inline SysKeyboardImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
{
59
    return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), SysKeyboardImpl, base);
60
}
61 62
static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(SysKeyboardImpl *This)
{
63
    return &This->base.IDirectInputDevice8A_iface;
64 65 66
}
static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysKeyboardImpl *This)
{
67
    return &This->base.IDirectInputDevice8W_iface;
68
}
69

70 71 72
static BYTE map_dik_code(DWORD scanCode, DWORD vkCode)
{
    static const BYTE asciiCodes[] =
73 74 75 76 77 78 79
     {/*32*/  DIK_SPACE,0,0,0,0,0,0,DIK_APOSTROPHE,
      /*40*/  0,0,0,0,DIK_COMMA,DIK_MINUS,DIK_PERIOD,DIK_SLASH,
      /*48*/  DIK_0,DIK_1,DIK_2,DIK_3,DIK_4,DIK_5,DIK_6,DIK_7,
      /*56*/  DIK_8,DIK_9,DIK_COLON,DIK_SEMICOLON,0,DIK_EQUALS,0,0,
      /*64*/  DIK_AT,DIK_A,DIK_B,DIK_C,DIK_D,DIK_E,DIK_F,DIK_G,
      /*72*/  DIK_H,DIK_I,DIK_J,DIK_K,DIK_L,DIK_M,DIK_N,DIK_O,
      /*80*/  DIK_P,DIK_Q,DIK_R,DIK_S,DIK_T,DIK_U,DIK_V,DIK_W,
80 81 82 83 84 85 86 87 88 89 90 91 92 93
      /*88*/  DIK_X,DIK_Y,DIK_Z,DIK_LBRACKET,0,DIK_RBRACKET,DIK_CIRCUMFLEX,DIK_UNDERLINE}      /*95*/ ;

    BYTE out_code = 0;
    WCHAR c = MapVirtualKeyW(vkCode,MAPVK_VK_TO_CHAR);

    if (c > 31 && c < 96)
        out_code = asciiCodes[c - 32];

    if (out_code == 0)
        out_code = scanCode;

    return out_code;
}

94
static int KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
95
{
96
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
97
    int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE;
98 99
    KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
    BYTE new_diks;
100

101 102
    if (wparam != WM_KEYDOWN && wparam != WM_KEYUP &&
        wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP)
103
        return 0;
104 105

    TRACE("(%p) %ld,%ld\n", iface, wparam, lparam);
106

107 108 109 110 111 112 113 114 115 116 117
    switch (hook->vkCode)
    {
        /* R-Shift is special - it is an extended key with separate scan code */
        case VK_RSHIFT  : dik_code = DIK_RSHIFT; break;
        case VK_PAUSE   : dik_code = DIK_PAUSE; break;
        case VK_NUMLOCK : dik_code = DIK_NUMLOCK; break;
        case VK_SUBTRACT: dik_code = DIK_SUBTRACT; break;
        default:
            dik_code = map_dik_code(hook->scanCode & 0xff, hook->vkCode);
            if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
    }
118 119 120
    new_diks = hook->flags & LLKHF_UP ? 0 : 0x80;

    /* returns now if key event already known */
121
    if (new_diks == This->DInputKeyState[dik_code])
122
        return ret;
123

124 125
    This->DInputKeyState[dik_code] = new_diks;
    TRACE(" setting %02X to %02X\n", dik_code, This->DInputKeyState[dik_code]);
126

127
    EnterCriticalSection(&This->base.crit);
128
    queue_event(iface, DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON,
129
                new_diks, hook->time, This->base.dinput->evsequence++);
130
    LeaveCriticalSection(&This->base.crit);
131 132

    return ret;
133
}
134

135 136
const GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
    0x0ab8648a, 0x7735, 0x11d2, {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41}
Lionel Ulmer's avatar
Lionel Ulmer committed
137 138
};

139
static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
140 141 142 143 144
    DWORD dwSize;
    DIDEVICEINSTANCEA ddi;
    
    dwSize = lpddi->dwSize;

145
    TRACE("%d %p\n", dwSize, lpddi);
146 147 148 149 150 151 152
    
    memset(lpddi, 0, dwSize);
    memset(&ddi, 0, sizeof(ddi));

    ddi.dwSize = dwSize;
    ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
    ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
153
    if (version >= 0x0800)
154 155 156
        ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
    else
        ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
157 158 159 160 161 162
    strcpy(ddi.tszInstanceName, "Keyboard");
    strcpy(ddi.tszProductName, "Wine Keyboard");

    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
}

163
static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
164 165 166 167 168
    DWORD dwSize;
    DIDEVICEINSTANCEW ddi;
    
    dwSize = lpddi->dwSize;

169
    TRACE("%d %p\n", dwSize, lpddi);
170 171 172 173 174 175 176
    
    memset(lpddi, 0, dwSize);
    memset(&ddi, 0, sizeof(ddi));
 
    ddi.dwSize = dwSize;
    ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
    ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
177
    if (version >= 0x0800)
178 179 180 181 182 183 184 185 186
        ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8);
    else
        ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
    MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH);
    MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH);

    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
}
 
187
static BOOL keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
188
{
189 190 191
  if (id != 0)
    return FALSE;

192
  if ((dwDevType == 0) ||
193 194
      ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
      (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
195 196 197 198 199 200 201 202 203 204
    TRACE("Enumerating the Keyboard device\n");
 
    fill_keyboard_dideviceinstanceA(lpddi, version);
    
    return TRUE;
  }

  return FALSE;
}

205
static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
Lionel Ulmer's avatar
Lionel Ulmer committed
206
{
207 208 209
  if (id != 0)
    return FALSE;

210
  if ((dwDevType == 0) ||
211 212
      ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
      (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
Lionel Ulmer's avatar
Lionel Ulmer committed
213
    TRACE("Enumerating the Keyboard device\n");
214

215
    fill_keyboard_dideviceinstanceW(lpddi, version);
216
    
Lionel Ulmer's avatar
Lionel Ulmer committed
217 218 219 220 221 222
    return TRUE;
  }

  return FALSE;
}

223
static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
Lionel Ulmer's avatar
Lionel Ulmer committed
224
{
225
    SysKeyboardImpl* newDevice;
226 227
    LPDIDATAFORMAT df = NULL;
    int i, idx = 0;
228

229
    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
230 231
    newDevice->base.IDirectInputDevice8A_iface.lpVtbl = &SysKeyboardAvt;
    newDevice->base.IDirectInputDevice8W_iface.lpVtbl = &SysKeyboardWvt;
232 233
    newDevice->base.ref = 1;
    memcpy(&newDevice->base.guid, rguid, sizeof(*rguid));
234
    newDevice->base.dinput = dinput;
235
    newDevice->base.event_proc = KeyboardCallback;
236
    InitializeCriticalSection(&newDevice->base.crit);
237
    newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
Lionel Ulmer's avatar
Lionel Ulmer committed
238

239 240 241 242 243 244
    /* Create copy of default data format */
    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIKeyboard.dwSize))) goto failed;
    memcpy(df, &c_dfDIKeyboard, c_dfDIKeyboard.dwSize);
    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;

    for (i = 0; i < df->dwNumObjs; i++)
245
    {
246 247 248 249 250 251 252
        char buf[MAX_PATH];

        if (!GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), buf, sizeof(buf)))
            continue;

        memcpy(&df->rgodf[idx], &c_dfDIKeyboard.rgodf[i], df->dwObjSize);
        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
253
    }
254
    df->dwNumObjs = idx;
255

256
    newDevice->base.data_format.wine_df = df;
257
    IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface);
258 259 260 261 262

    EnterCriticalSection(&dinput->crit);
    list_add_tail(&dinput->devices_list, &newDevice->base.entry);
    LeaveCriticalSection(&dinput->crit);

263 264 265 266 267
    return newDevice;

failed:
    if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
    HeapFree(GetProcessHeap(), 0, df);
268
    HeapFree(GetProcessHeap(), 0, newDevice);
269
    return NULL;
Lionel Ulmer's avatar
Lionel Ulmer committed
270 271 272
}


273
static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
Lionel Ulmer's avatar
Lionel Ulmer committed
274
{
275 276
    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
    *pdev = NULL;
Lionel Ulmer's avatar
Lionel Ulmer committed
277

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    if (IsEqualGUID(&GUID_SysKeyboard, rguid) ||        /* Generic Keyboard */
        IsEqualGUID(&DInput_Wine_Keyboard_GUID, rguid)) /* Wine Keyboard */
    {
        SysKeyboardImpl *This;

        if (riid == NULL)
            ;/* nothing */
        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
        {
            unicode = 0;
        }
        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
        {
            unicode = 1;
        }
        else
        {
            WARN("no interface\n");
            return DIERR_NOINTERFACE;
        }

        This = alloc_device(rguid, dinput);
        TRACE("Created a Keyboard device (%p)\n", This);

        if (!This) return DIERR_OUTOFMEMORY;

        if (unicode)
            *pdev = &This->base.IDirectInputDevice8W_iface;
        else
            *pdev = &This->base.IDirectInputDevice8A_iface;

        return DI_OK;
    }

    return DIERR_DEVICENOTREG;
Lionel Ulmer's avatar
Lionel Ulmer committed
319 320
}

321
const struct dinput_device keyboard_device = {
322
  "Wine keyboard driver",
323 324
  keyboarddev_enum_deviceA,
  keyboarddev_enum_deviceW,
325
  keyboarddev_create_device
Lionel Ulmer's avatar
Lionel Ulmer committed
326 327
};

328
static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
Lionel Ulmer's avatar
Lionel Ulmer committed
329
{
330
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
331
    TRACE("(%p)->(%d,%p)\n", This, len, ptr);
332

333
    if (!This->base.acquired) return DIERR_NOTACQUIRED;
334

335
    if (len != This->base.data_format.user_df->dwDataSize )
336
        return DIERR_INVALIDPARAM;
337

338
    EnterCriticalSection(&This->base.crit);
339

340 341
    if (TRACE_ON(dinput)) {
	int i;
342
	for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
343 344
	    if (This->DInputKeyState[i] != 0x00)
		TRACE(" - %02X: %02x\n", i, This->DInputKeyState[i]);
345 346
	}
    }
347

348
    fill_DataFormat(ptr, len, This->DInputKeyState, &This->base.data_format);
349
    LeaveCriticalSection(&This->base.crit);
350

351
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
352 353
}

354 355 356 357 358 359
static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
{
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
    return SysKeyboardWImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr);
}

360
/******************************************************************************
Austin English's avatar
Austin English committed
361
  *     GetCapabilities : get the device capabilities
362
  */
363
static HRESULT WINAPI SysKeyboardWImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps)
Lionel Ulmer's avatar
Lionel Ulmer committed
364
{
365
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
366
    DIDEVCAPS devcaps;
Lionel Ulmer's avatar
Lionel Ulmer committed
367

368
    TRACE("(this=%p,%p)\n",This,lpDIDevCaps);
Lionel Ulmer's avatar
Lionel Ulmer committed
369

370 371 372 373
    if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) {
        WARN("invalid parameter\n");
        return DIERR_INVALIDPARAM;
    }
374

375
    devcaps.dwSize = lpDIDevCaps->dwSize;
376
    devcaps.dwFlags = DIDC_ATTACHED | DIDC_EMULATED;
377
    if (This->base.dinput->dwVersion >= 0x0800)
378
        devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_PCENH << 8);
379
    else
380
        devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_PCENH << 8);
381
    devcaps.dwAxes = 0;
382
    devcaps.dwButtons = This->base.data_format.wine_df->dwNumObjs;
383 384 385 386 387 388 389 390
    devcaps.dwPOVs = 0;
    devcaps.dwFFSamplePeriod = 0;
    devcaps.dwFFMinTimeResolution = 0;
    devcaps.dwFirmwareRevision = 100;
    devcaps.dwHardwareRevision = 100;
    devcaps.dwFFDriverVersion = 0;

    memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize);
391

392
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
393 394
}

395 396 397 398 399 400
static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
{
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
    return SysKeyboardWImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps);
}

401 402 403 404 405 406 407 408 409 410 411
/******************************************************************************
  *     GetObjectInfo : get information about a device object such as a button
  *                     or axis
  */
static HRESULT WINAPI
SysKeyboardAImpl_GetObjectInfo(
	LPDIRECTINPUTDEVICE8A iface,
	LPDIDEVICEOBJECTINSTANCEA pdidoi,
	DWORD dwObj,
	DWORD dwHow)
{
412
    HRESULT res;
413
    LONG scan;
414

415 416
    res = IDirectInputDevice2AImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
    if (res != DI_OK) return res;
417

418 419 420
    scan = DIDFT_GETINSTANCE(pdidoi->dwType);
    if (scan == DIK_PAUSE || scan == DIK_NUMLOCK) scan ^= 0x80;
    if (!GetKeyNameTextA((scan & 0x80) << 17 | (scan & 0x7f) << 16,
421
                         pdidoi->tszName, sizeof(pdidoi->tszName)))
422
        return DIERR_OBJECTNOTFOUND;
423 424

    _dump_OBJECTINSTANCEA(pdidoi);
425
    return res;
426 427
}

428 429 430 431 432
static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
						     LPDIDEVICEOBJECTINSTANCEW pdidoi,
						     DWORD dwObj,
						     DWORD dwHow)
{
433
    HRESULT res;
434
    LONG scan;
435

436 437
    res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
    if (res != DI_OK) return res;
438

439 440 441 442
    scan = DIDFT_GETINSTANCE(pdidoi->dwType);
    if (scan == DIK_PAUSE || scan == DIK_NUMLOCK) scan ^= 0x80;
    if (!GetKeyNameTextW((scan & 0x80) << 17 | (scan & 0x7f) << 16,
                         pdidoi->tszName, sizeof(pdidoi->tszName)))
443
        return DIERR_OBJECTNOTFOUND;
444 445

    _dump_OBJECTINSTANCEW(pdidoi);
446
    return res;
447 448
}

449 450 451 452 453 454 455
/******************************************************************************
  *     GetDeviceInfo : get information about a device's identity
  */
static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
	LPDIRECTINPUTDEVICE8A iface,
	LPDIDEVICEINSTANCEA pdidi)
{
456
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
457 458 459
    TRACE("(this=%p,%p)\n", This, pdidi);

    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
460
        WARN(" dinput3 not supported yet...\n");
461 462 463
	return DI_OK;
    }

464
    fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
465 466 467 468
    
    return DI_OK;
}

469
static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
470
{
471
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
472 473 474
    TRACE("(this=%p,%p)\n", This, pdidi);

    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
475
        WARN(" dinput3 not supported yet...\n");
476 477 478
	return DI_OK;
    }

479
    fill_keyboard_dideviceinstanceW(pdidi, This->base.dinput->dwVersion);
480 481 482
    
    return DI_OK;
}
483

484 485 486
/******************************************************************************
 *      GetProperty : Retrieves information about the input device.
 */
487 488
static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
                                                   REFGUID rguid, LPDIPROPHEADER pdiph)
489
{
490 491
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);

492 493 494
    TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
    _dump_DIPROPHEADER(pdiph);

495
    if (!IS_DIPROP(rguid)) return DI_OK;
496 497 498

    switch (LOWORD(rguid))
    {
499
        case (DWORD_PTR)DIPROP_KEYNAME:
500 501 502 503 504 505 506 507 508 509
        {
            HRESULT hr;
            LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph;
            DIDEVICEOBJECTINSTANCEW didoi;

            if (pdiph->dwSize != sizeof(DIPROPSTRING))
                return DIERR_INVALIDPARAM;

            didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW);

510
            hr = SysKeyboardWImpl_GetObjectInfo(iface, &didoi, ps->diph.dwObj, ps->diph.dwHow);
511 512 513 514
            if (hr == DI_OK)
                memcpy(ps->wsz, didoi.tszName, sizeof(ps->wsz));
            return hr;
        }
515 516
        case (DWORD_PTR) DIPROP_RANGE:
            return DIERR_UNSUPPORTED;
517
        default:
518
            return IDirectInputDevice2AImpl_GetProperty( IDirectInputDevice8A_from_impl(This), rguid, pdiph );
519 520 521 522
    }
    return DI_OK;
}

523 524 525 526 527 528 529
static HRESULT WINAPI SysKeyboardAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
                                                   REFGUID rguid, LPDIPROPHEADER pdiph)
{
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
    return SysKeyboardWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
}

530 531 532 533 534 535 536
static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                      LPDIACTIONFORMATW lpdiaf,
                                                      LPCWSTR lpszUserName,
                                                      DWORD dwFlags)
{
    FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);

537
    return  _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard);
538 539 540 541 542 543 544 545 546 547
}

static HRESULT WINAPI SysKeyboardAImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
                                                      LPDIACTIONFORMATA lpdiaf,
                                                      LPCSTR lpszUserName,
                                                      DWORD dwFlags)
{
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
    DIACTIONFORMATW diafW;
    HRESULT hr;
548 549
    WCHAR *lpszUserNameW = NULL;
    int username_size;
550 551 552 553

    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
    _copy_diactionformatAtoW(&diafW, lpdiaf);

554 555 556 557 558 559 560 561
    if (lpszUserName != NULL)
    {
        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
    }

    hr = SysKeyboardWImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
562 563 564

    _copy_diactionformatWtoA(lpdiaf, &diafW);
    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
565
    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
566 567 568 569

    return hr;
}

570 571 572 573 574
static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                    LPDIACTIONFORMATW lpdiaf,
                                                    LPCWSTR lpszUserName,
                                                    DWORD dwFlags)
{
575
    FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
576

577
    return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard);
578 579 580 581 582 583 584 585 586 587
}

static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
                                                    LPDIACTIONFORMATA lpdiaf,
                                                    LPCSTR lpszUserName,
                                                    DWORD dwFlags)
{
    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
    DIACTIONFORMATW diafW;
    HRESULT hr;
588 589
    WCHAR *lpszUserNameW = NULL;
    int username_size;
590 591 592 593

    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
    _copy_diactionformatAtoW(&diafW, lpdiaf);

594 595 596 597 598 599 600 601
    if (lpszUserName != NULL)
    {
        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
    }

    hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
602 603

    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
604
    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
605 606 607 608

    return hr;
}

609
static const IDirectInputDevice8AVtbl SysKeyboardAvt =
Lionel Ulmer's avatar
Lionel Ulmer committed
610
{
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
    IDirectInputDevice2AImpl_QueryInterface,
    IDirectInputDevice2AImpl_AddRef,
    IDirectInputDevice2AImpl_Release,
    SysKeyboardAImpl_GetCapabilities,
    IDirectInputDevice2AImpl_EnumObjects,
    SysKeyboardAImpl_GetProperty,
    IDirectInputDevice2AImpl_SetProperty,
    IDirectInputDevice2AImpl_Acquire,
    IDirectInputDevice2AImpl_Unacquire,
    SysKeyboardAImpl_GetDeviceState,
    IDirectInputDevice2AImpl_GetDeviceData,
    IDirectInputDevice2AImpl_SetDataFormat,
    IDirectInputDevice2AImpl_SetEventNotification,
    IDirectInputDevice2AImpl_SetCooperativeLevel,
    SysKeyboardAImpl_GetObjectInfo,
    SysKeyboardAImpl_GetDeviceInfo,
    IDirectInputDevice2AImpl_RunControlPanel,
    IDirectInputDevice2AImpl_Initialize,
    IDirectInputDevice2AImpl_CreateEffect,
    IDirectInputDevice2AImpl_EnumEffects,
    IDirectInputDevice2AImpl_GetEffectInfo,
    IDirectInputDevice2AImpl_GetForceFeedbackState,
    IDirectInputDevice2AImpl_SendForceFeedbackCommand,
    IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
    IDirectInputDevice2AImpl_Escape,
    IDirectInputDevice2AImpl_Poll,
    IDirectInputDevice2AImpl_SendDeviceData,
    IDirectInputDevice7AImpl_EnumEffectsInFile,
    IDirectInputDevice7AImpl_WriteEffectToFile,
640
    SysKeyboardAImpl_BuildActionMap,
641
    SysKeyboardAImpl_SetActionMap,
642
    IDirectInputDevice8AImpl_GetImageInfo
Lionel Ulmer's avatar
Lionel Ulmer committed
643
};
644

645
static const IDirectInputDevice8WVtbl SysKeyboardWvt =
646
{
647 648 649
    IDirectInputDevice2WImpl_QueryInterface,
    IDirectInputDevice2WImpl_AddRef,
    IDirectInputDevice2WImpl_Release,
650
    SysKeyboardWImpl_GetCapabilities,
651
    IDirectInputDevice2WImpl_EnumObjects,
652
    SysKeyboardWImpl_GetProperty,
653 654 655
    IDirectInputDevice2WImpl_SetProperty,
    IDirectInputDevice2WImpl_Acquire,
    IDirectInputDevice2WImpl_Unacquire,
656
    SysKeyboardWImpl_GetDeviceState,
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
    IDirectInputDevice2WImpl_GetDeviceData,
    IDirectInputDevice2WImpl_SetDataFormat,
    IDirectInputDevice2WImpl_SetEventNotification,
    IDirectInputDevice2WImpl_SetCooperativeLevel,
    SysKeyboardWImpl_GetObjectInfo,
    SysKeyboardWImpl_GetDeviceInfo,
    IDirectInputDevice2WImpl_RunControlPanel,
    IDirectInputDevice2WImpl_Initialize,
    IDirectInputDevice2WImpl_CreateEffect,
    IDirectInputDevice2WImpl_EnumEffects,
    IDirectInputDevice2WImpl_GetEffectInfo,
    IDirectInputDevice2WImpl_GetForceFeedbackState,
    IDirectInputDevice2WImpl_SendForceFeedbackCommand,
    IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
    IDirectInputDevice2WImpl_Escape,
    IDirectInputDevice2WImpl_Poll,
    IDirectInputDevice2WImpl_SendDeviceData,
    IDirectInputDevice7WImpl_EnumEffectsInFile,
    IDirectInputDevice7WImpl_WriteEffectToFile,
676
    SysKeyboardWImpl_BuildActionMap,
677
    SysKeyboardWImpl_SetActionMap,
678
    IDirectInputDevice8WImpl_GetImageInfo
679
};