device.c 39.9 KB
Newer Older
Lionel Ulmer's avatar
Lionel Ulmer committed
1 2 3 4 5
/*		DirectInput Device
 *
 * Copyright 1998 Marcus Meissner
 * Copyright 1998,1999 Lionel Ulmer
 *
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Lionel Ulmer's avatar
Lionel Ulmer committed
20 21 22 23 24 25 26 27 28
 */

/* This file contains all the Device specific functions that can be used as stubs
   by real device implementations.

   It also contains all the helper functions.
*/
#include "config.h"

29
#include <stdarg.h>
30
#include <string.h>
31
#include "wine/debug.h"
32
#include "wine/unicode.h"
33
#include "windef.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
34
#include "winbase.h"
35
#include "winreg.h"
36
#include "winuser.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
37 38 39
#include "winerror.h"
#include "dinput.h"
#include "device_private.h"
40
#include "dinput_private.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
41

42
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
Lionel Ulmer's avatar
Lionel Ulmer committed
43 44 45 46

/******************************************************************************
 *	Various debugging tools
 */
47
static void _dump_cooperativelevel_DI(DWORD dwFlags) {
48
    if (TRACE_ON(dinput)) {
49
	unsigned int   i;
50 51 52 53 54 55 56 57
	static const struct {
	    DWORD       mask;
	    const char  *name;
	} flags[] = {
#define FE(x) { x, #x}
	    FE(DISCL_BACKGROUND),
	    FE(DISCL_EXCLUSIVE),
	    FE(DISCL_FOREGROUND),
58 59
	    FE(DISCL_NONEXCLUSIVE),
	    FE(DISCL_NOWINKEY)
Lionel Ulmer's avatar
Lionel Ulmer committed
60
#undef FE
61
	};
62
	TRACE(" cooperative level : ");
63 64
	for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++)
	    if (flags[i].mask & dwFlags)
Andrew Riedi's avatar
Andrew Riedi committed
65 66
		TRACE("%s ",flags[i].name);
	TRACE("\n");
67
    }
Lionel Ulmer's avatar
Lionel Ulmer committed
68 69
}

70
static void _dump_EnumObjects_flags(DWORD dwFlags) {
71
    if (TRACE_ON(dinput)) {
72
	unsigned int   i;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	DWORD type, instance;
	static const struct {
	    DWORD       mask;
	    const char  *name;
	} flags[] = {
#define FE(x) { x, #x}
	    FE(DIDFT_RELAXIS),
	    FE(DIDFT_ABSAXIS),
	    FE(DIDFT_PSHBUTTON),
	    FE(DIDFT_TGLBUTTON),
	    FE(DIDFT_POV),
	    FE(DIDFT_COLLECTION),
	    FE(DIDFT_NODATA),	    
	    FE(DIDFT_FFACTUATOR),
	    FE(DIDFT_FFEFFECTTRIGGER),
88 89 90 91
	    FE(DIDFT_OUTPUT),
	    FE(DIDFT_VENDORDEFINED),
	    FE(DIDFT_ALIAS),
	    FE(DIDFT_OPTIONAL)
Lionel Ulmer's avatar
Lionel Ulmer committed
92
#undef FE
93 94 95
	};
	type = (dwFlags & 0xFF0000FF);
	instance = ((dwFlags >> 8) & 0xFFFF);
Andrew Riedi's avatar
Andrew Riedi committed
96
	TRACE("Type:");
97
	if (type == DIDFT_ALL) {
Andrew Riedi's avatar
Andrew Riedi committed
98
	    TRACE(" DIDFT_ALL");
99 100 101 102
	} else {
	    for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) {
		if (flags[i].mask & type) {
		    type &= ~flags[i].mask;
Andrew Riedi's avatar
Andrew Riedi committed
103
		    TRACE(" %s",flags[i].name);
104 105 106
		}
	    }
	    if (type) {
Andrew Riedi's avatar
Andrew Riedi committed
107
                TRACE(" (unhandled: %08x)", type);
108 109
	    }
	}
Andrew Riedi's avatar
Andrew Riedi committed
110
	TRACE(" / Instance: ");
111
	if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
Andrew Riedi's avatar
Andrew Riedi committed
112
	    TRACE("DIDFT_ANYINSTANCE");
113
	} else {
Andrew Riedi's avatar
Andrew Riedi committed
114
            TRACE("%3d", instance);
115 116
	}
    }
Lionel Ulmer's avatar
Lionel Ulmer committed
117 118
}

119
void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) {
120
    if (TRACE_ON(dinput)) {
Andrew Riedi's avatar
Andrew Riedi committed
121 122 123 124 125
        TRACE("  - dwObj = 0x%08x\n", diph->dwObj);
        TRACE("  - dwHow = %s\n",
            ((diph->dwHow == DIPH_DEVICE) ? "DIPH_DEVICE" :
            ((diph->dwHow == DIPH_BYOFFSET) ? "DIPH_BYOFFSET" :
            ((diph->dwHow == DIPH_BYID)) ? "DIPH_BYID" : "unknown")));
126
    }
Lionel Ulmer's avatar
Lionel Ulmer committed
127 128
}

129
void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) {
Andrew Riedi's avatar
Andrew Riedi committed
130 131
    TRACE("    - enumerating : %s ('%s') - %2d - 0x%08x - %s\n",
        debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, ddoi->tszName);
Lionel Ulmer's avatar
Lionel Ulmer committed
132 133
}

134
void _dump_OBJECTINSTANCEW(const DIDEVICEOBJECTINSTANCEW *ddoi) {
Andrew Riedi's avatar
Andrew Riedi committed
135 136
    TRACE("    - enumerating : %s ('%s'), - %2d - 0x%08x - %s\n",
        debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName));
137 138
}

139 140
/* This function is a helper to convert a GUID into any possible DInput GUID out there */
const char *_dump_dinput_GUID(const GUID *guid) {
141
    unsigned int i;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
    static const struct {
	const GUID *guid;
	const char *name;
    } guids[] = {
#define FE(x) { &x, #x}
	FE(GUID_XAxis),
	FE(GUID_YAxis),
	FE(GUID_ZAxis),
	FE(GUID_RxAxis),
	FE(GUID_RyAxis),
	FE(GUID_RzAxis),
	FE(GUID_Slider),
	FE(GUID_Button),
	FE(GUID_Key),
	FE(GUID_POV),
	FE(GUID_Unknown),
	FE(GUID_SysMouse),
	FE(GUID_SysKeyboard),
	FE(GUID_Joystick),
	FE(GUID_ConstantForce),
	FE(GUID_RampForce),
	FE(GUID_Square),
	FE(GUID_Sine),
	FE(GUID_Triangle),
	FE(GUID_SawtoothUp),
	FE(GUID_SawtoothDown),
	FE(GUID_Spring),
	FE(GUID_Damper),
	FE(GUID_Inertia),
	FE(GUID_Friction),
	FE(GUID_CustomForce)
#undef FE
    };
    if (guid == NULL)
	return "null GUID";
    for (i = 0; i < (sizeof(guids) / sizeof(guids[0])); i++) {
	if (IsEqualGUID(guids[i].guid, guid)) {
	    return guids[i].name;
Lionel Ulmer's avatar
Lionel Ulmer committed
180 181
	}
    }
182
    return debugstr_guid(guid);
Lionel Ulmer's avatar
Lionel Ulmer committed
183 184
}

185
void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
186
    unsigned int i;
Lionel Ulmer's avatar
Lionel Ulmer committed
187

188
    TRACE("Dumping DIDATAFORMAT structure:\n");
189
    TRACE("  - dwSize: %d\n", df->dwSize);
190
    if (df->dwSize != sizeof(DIDATAFORMAT)) {
191
        WARN("Non-standard DIDATAFORMAT structure size %d\n", df->dwSize);
192
    }
193
    TRACE("  - dwObjsize: %d\n", df->dwObjSize);
194
    if (df->dwObjSize != sizeof(DIOBJECTDATAFORMAT)) {
195
        WARN("Non-standard DIOBJECTDATAFORMAT structure size %d\n", df->dwObjSize);
196
    }
197
    TRACE("  - dwFlags: 0x%08x (", df->dwFlags);
198 199 200 201 202 203
    switch (df->dwFlags) {
        case DIDF_ABSAXIS: TRACE("DIDF_ABSAXIS"); break;
	case DIDF_RELAXIS: TRACE("DIDF_RELAXIS"); break;
	default: TRACE("unknown"); break;
    }
    TRACE(")\n");
204 205
    TRACE("  - dwDataSize: %d\n", df->dwDataSize);
    TRACE("  - dwNumObjs: %d\n", df->dwNumObjs);
206 207 208 209
    
    for (i = 0; i < df->dwNumObjs; i++) {
	TRACE("  - Object %d:\n", i);
	TRACE("      * GUID: %s ('%s')\n", debugstr_guid(df->rgodf[i].pguid), _dump_dinput_GUID(df->rgodf[i].pguid));
210 211
        TRACE("      * dwOfs: %d\n", df->rgodf[i].dwOfs);
        TRACE("      * dwType: 0x%08x\n", df->rgodf[i].dwType);
212
	TRACE("        "); _dump_EnumObjects_flags(df->rgodf[i].dwType); TRACE("\n");
213
        TRACE("      * dwFlags: 0x%08x\n", df->rgodf[i].dwFlags);
214 215
    }
}
216

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
/******************************************************************************
 * Get the default and the app-specific config keys.
 */
BOOL get_app_key(HKEY *defkey, HKEY *appkey)
{
    char buffer[MAX_PATH+16];
    DWORD len;

    *appkey = 0;

    /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */
    if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", defkey))
        *defkey = 0;

    len = GetModuleFileNameA(0, buffer, MAX_PATH);
    if (len && len < MAX_PATH)
    {
        HKEY tmpkey;

        /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */
        if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey))
        {
            char *p, *appname = buffer;
            if ((p = strrchr(appname, '/'))) appname = p + 1;
            if ((p = strrchr(appname, '\\'))) appname = p + 1;
            strcat(appname, "\\DirectInput");

Vitaliy Margolen's avatar
Vitaliy Margolen committed
244
            if (RegOpenKeyA(tmpkey, appname, appkey)) *appkey = 0;
245 246 247 248 249 250 251
            RegCloseKey(tmpkey);
        }
    }

    return *defkey || *appkey;
}

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
/******************************************************************************
 * Get a config key from either the app-specific or the default config
 */
DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
                             char *buffer, DWORD size )
{
    if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size ))
        return 0;

    if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size ))
        return 0;

    return ERROR_FILE_NOT_FOUND;
}

267
/* Conversion between internal data buffer and external data buffer */
268 269
void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df)
{
270
    int i;
271
    const char *in_c = in;
272
    char *out_c = out;
273

274
    memset(out, 0, size);
275 276
    if (df->dt == NULL) {
	/* This means that the app uses Wine's internal data format */
277
        memcpy(out, in, min(size, df->internal_format_size));
278 279 280 281 282 283
    } else {
	for (i = 0; i < df->size; i++) {
	    if (df->dt[i].offset_in >= 0) {
		switch (df->dt[i].size) {
		    case 1:
		        TRACE("Copying (c) to %d from %d (value %d)\n",
284 285
                              df->dt[i].offset_out, df->dt[i].offset_in, *(in_c + df->dt[i].offset_in));
			*(out_c + df->dt[i].offset_out) = *(in_c + df->dt[i].offset_in);
286
			break;
287

288 289
		    case 2:
			TRACE("Copying (s) to %d from %d (value %d)\n",
290 291
			      df->dt[i].offset_out, df->dt[i].offset_in, *((const short *)(in_c + df->dt[i].offset_in)));
			*((short *)(out_c + df->dt[i].offset_out)) = *((const short *)(in_c + df->dt[i].offset_in));
292
			break;
293

294 295
		    case 4:
			TRACE("Copying (i) to %d from %d (value %d)\n",
296 297
                              df->dt[i].offset_out, df->dt[i].offset_in, *((const int *)(in_c + df->dt[i].offset_in)));
                        *((int *)(out_c + df->dt[i].offset_out)) = *((const int *)(in_c + df->dt[i].offset_in));
298
			break;
299

300 301 302 303 304 305 306 307 308
		    default:
			memcpy((out_c + df->dt[i].offset_out), (in_c + df->dt[i].offset_in), df->dt[i].size);
			break;
		}
	    } else {
		switch (df->dt[i].size) {
		    case 1:
		        TRACE("Copying (c) to %d default value %d\n",
			      df->dt[i].offset_out, df->dt[i].value);
309
			*(out_c + df->dt[i].offset_out) = (char) df->dt[i].value;
310 311 312 313 314 315 316 317 318 319 320
			break;
			
		    case 2:
			TRACE("Copying (s) to %d default value %d\n",
			      df->dt[i].offset_out, df->dt[i].value);
			*((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
			break;
			
		    case 4:
			TRACE("Copying (i) to %d default value %d\n",
			      df->dt[i].offset_out, df->dt[i].value);
321
			*((int *) (out_c + df->dt[i].offset_out)) = df->dt[i].value;
322 323 324
			break;
			
		    default:
325
			memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size);
326 327 328 329 330 331
			break;
		}
	    }
	}
    }
}
332

333 334
void release_DataFormat(DataFormat * format)
{
335
    TRACE("Deleting DataFormat: %p\n", format);
336 337

    HeapFree(GetProcessHeap(), 0, format->dt);
338 339 340
    format->dt = NULL;
    HeapFree(GetProcessHeap(), 0, format->offsets);
    format->offsets = NULL;
341 342
    HeapFree(GetProcessHeap(), 0, format->user_df);
    format->user_df = NULL;
343 344
}

345
static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
346 347 348 349 350
{
    if (idx < 0 || idx >= df->dwNumObjs) return NULL;
    return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize);
}

351
static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format)
352
{
353
    DataTransform *dt;
354
    unsigned int i, j;
355 356 357
    int same = 1;
    int *done;
    int index = 0;
358
    DWORD next = 0;
359 360

    if (!format->wine_df) return DIERR_INVALIDPARAM;
361
    done = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, asked_format->dwNumObjs * sizeof(int));
362
    dt = HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
363 364
    if (!dt || !done) goto failed;

365
    if (!(format->offsets = HeapAlloc(GetProcessHeap(), 0, format->wine_df->dwNumObjs * sizeof(int))))
366 367
        goto failed;

368 369 370 371
    if (!(format->user_df = HeapAlloc(GetProcessHeap(), 0, asked_format->dwSize)))
        goto failed;
    memcpy(format->user_df, asked_format, asked_format->dwSize);

372
    TRACE("Creating DataTransform :\n");
373
    
374 375
    for (i = 0; i < format->wine_df->dwNumObjs; i++)
    {
376 377
        format->offsets[i] = -1;

378 379 380 381 382 383 384 385
	for (j = 0; j < asked_format->dwNumObjs; j++) {
	    if (done[j] == 1)
		continue;
	    
	    if (/* Check if the application either requests any GUID and if not, it if matches
		 * the GUID of the Wine object.
		 */
		((asked_format->rgodf[j].pguid == NULL) ||
386 387
		 (format->wine_df->rgodf[i].pguid == NULL) ||
		 (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
388 389 390 391
		&&
		(/* Then check if it accepts any instance id, and if not, if it matches Wine's
		  * instance id.
		  */
392
		 ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) ||
393
		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentionned in no DX docs, but it works fine - tested on WinXP */
394
		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType)))
395 396
		&&
		( /* Then if the asked type matches the one Wine provides */
397
                 DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
398
            {
399 400
		done[j] = 1;
		
401
		TRACE("Matching :\n");
402 403 404 405
		TRACE("   - Asked (%d) :\n", j);
		TRACE("       * GUID: %s ('%s')\n",
		      debugstr_guid(asked_format->rgodf[j].pguid),
		      _dump_dinput_GUID(asked_format->rgodf[j].pguid));
406 407
                TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
                TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
408 409
		TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
		
410
		TRACE("   - Wine  (%d) :\n", i);
411
		TRACE("       * GUID: %s ('%s')\n",
412 413 414 415 416
                      debugstr_guid(format->wine_df->rgodf[i].pguid),
                      _dump_dinput_GUID(format->wine_df->rgodf[i].pguid));
                TRACE("       * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs);
                TRACE("       * dwType: %08x\n", format->wine_df->rgodf[i].dwType);
                TRACE("         "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n");
417
		
418
                if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON)
419 420 421
		    dt[index].size = sizeof(BYTE);
		else
		    dt[index].size = sizeof(DWORD);
422
                dt[index].offset_in = format->wine_df->rgodf[i].dwOfs;
423
                dt[index].offset_out = asked_format->rgodf[j].dwOfs;
424
                format->offsets[i]   = asked_format->rgodf[j].dwOfs;
425
		dt[index].value = 0;
426
                next = next + dt[index].size;
427
		
428
                if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out)
429 430
		    same = 0;
		
431
		index++;
432 433 434 435
		break;
	    }
	}
    }
436

437
    TRACE("Setting to default value :\n");
Lionel Ulmer's avatar
Lionel Ulmer committed
438
    for (j = 0; j < asked_format->dwNumObjs; j++) {
439 440 441 442 443
	if (done[j] == 0) {
	    TRACE("   - Asked (%d) :\n", j);
	    TRACE("       * GUID: %s ('%s')\n",
		  debugstr_guid(asked_format->rgodf[j].pguid),
		  _dump_dinput_GUID(asked_format->rgodf[j].pguid));
444 445
            TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
            TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
446 447 448 449 450 451 452 453
	    TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
	    
	    if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
		dt[index].size = sizeof(BYTE);
	    else
		dt[index].size = sizeof(DWORD);
	    dt[index].offset_in  = -1;
	    dt[index].offset_out = asked_format->rgodf[j].dwOfs;
454 455 456 457
            if (asked_format->rgodf[j].dwType & DIDFT_POV)
                dt[index].value = -1;
            else
                dt[index].value = 0;
458
	    index++;
459

460 461
	    same = 0;
	}
Lionel Ulmer's avatar
Lionel Ulmer committed
462
    }
463
    
464
    format->internal_format_size = format->wine_df->dwDataSize;
465
    format->size = index;
466 467
    if (same) {
	HeapFree(GetProcessHeap(), 0, dt);
468
        dt = NULL;
Lionel Ulmer's avatar
Lionel Ulmer committed
469
    }
470 471
    format->dt = dt;

472
    HeapFree(GetProcessHeap(), 0, done);
473

474 475 476 477 478 479 480 481
    return DI_OK;

failed:
    HeapFree(GetProcessHeap(), 0, done);
    HeapFree(GetProcessHeap(), 0, dt);
    format->dt = NULL;
    HeapFree(GetProcessHeap(), 0, format->offsets);
    format->offsets = NULL;
482 483
    HeapFree(GetProcessHeap(), 0, format->user_df);
    format->user_df = NULL;
484 485

    return DIERR_OUTOFMEMORY;
Lionel Ulmer's avatar
Lionel Ulmer committed
486 487
}

488
/* find an object by it's offset in a data format */
489
static int offset_to_object(const DataFormat *df, int offset)
490 491 492
{
    int i;

493 494 495 496
    if (!df->offsets) return -1;

    for (i = 0; i < df->wine_df->dwNumObjs; i++)
        if (df->offsets[i] == offset) return i;
497 498 499 500

    return -1;
}

501
int id_to_object(LPCDIDATAFORMAT df, int id)
502 503 504
{
    int i;

505
    id &= 0x00ffffff;
506
    for (i = 0; i < df->dwNumObjs; i++)
507
        if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id)
508 509 510 511 512
            return i;

    return -1;
}

513
int id_to_offset(const DataFormat *df, int id)
514 515 516 517 518 519
{
    int obj = id_to_object(df->wine_df, id);

    return obj >= 0 && df->offsets ? df->offsets[obj] : -1;
}

520
int find_property(const DataFormat *df, LPCDIPROPHEADER ph)
521 522 523
{
    switch (ph->dwHow)
    {
524 525
        case DIPH_BYID:     return id_to_object(df->wine_df, ph->dwObj);
        case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj);
526 527 528 529 530 531
    }
    FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow);

    return -1;
}

532 533 534 535 536 537 538 539 540
/******************************************************************************
 *	queue_event - add new event to the ring queue
 */

void queue_event(LPDIRECTINPUTDEVICE8A iface, int ofs, DWORD data, DWORD time, DWORD seq)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    int next_pos;

541 542 543
    /* Event is being set regardless of the queue state */
    if (This->hEvent) SetEvent(This->hEvent);

544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
    if (!This->queue_len || This->overflow || ofs < 0) return;

    next_pos = (This->queue_head + 1) % This->queue_len;
    if (next_pos == This->queue_tail)
    {
        TRACE(" queue overflowed\n");
        This->overflow = TRUE;
        return;
    }

    TRACE(" queueing %d at offset %d (queue head %d / size %d)\n",
          data, ofs, This->queue_head, This->queue_len);

    This->data_queue[This->queue_head].dwOfs       = ofs;
    This->data_queue[This->queue_head].dwData      = data;
    This->data_queue[This->queue_head].dwTimeStamp = time;
    This->data_queue[This->queue_head].dwSequence  = seq;
    This->queue_head = next_pos;
562
    /* Send event if asked */
563 564
}

565 566 567 568 569 570 571
/******************************************************************************
 *	Acquire
 */

HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
572
    HRESULT res;
573

574
    if (!This->data_format.user_df) return DIERR_INVALIDPARAM;
575 576
    if (This->dwCoopLevel & DISCL_FOREGROUND && This->win != GetForegroundWindow())
        return DIERR_OTHERAPPHASPRIO;
577

578 579
    EnterCriticalSection(&This->crit);
    res = This->acquired ? S_FALSE : DI_OK;
580
    This->acquired = 1;
581
    if (res == DI_OK)
582
    {
583
        This->queue_head = This->queue_tail = This->overflow = 0;
584 585
        check_dinput_hooks(iface);
    }
586
    LeaveCriticalSection(&This->crit);
587

588
    return res;
589 590 591 592 593 594 595 596 597
}

/******************************************************************************
 *	Unacquire
 */

HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
598
    HRESULT res;
599

600 601
    EnterCriticalSection(&This->crit);
    res = !This->acquired ? DI_NOEFFECT : DI_OK;
602
    This->acquired = 0;
603 604
    if (res == DI_OK)
        check_dinput_hooks(iface);
605
    LeaveCriticalSection(&This->crit);
606

607
    return res;
608 609
}

Lionel Ulmer's avatar
Lionel Ulmer committed
610 611 612 613 614
/******************************************************************************
 *	IDirectInputDeviceA
 */

HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
615 616
        LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
{
617
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
618 619 620 621
    HRESULT res = DI_OK;

    if (!df) return E_POINTER;
    TRACE("(%p) %p\n", This, df);
622
    _dump_DIDATAFORMAT(df);
623 624 625 626 627 628 629

    if (df->dwSize != sizeof(DIDATAFORMAT)) return DIERR_INVALIDPARAM;
    if (This->acquired) return DIERR_ACQUIRED;

    EnterCriticalSection(&This->crit);

    release_DataFormat(&This->data_format);
630
    res = create_DataFormat(df, &This->data_format);
631 632 633

    LeaveCriticalSection(&This->crit);
    return res;
Lionel Ulmer's avatar
Lionel Ulmer committed
634 635
}

636 637 638 639 640
/******************************************************************************
  *     SetCooperativeLevel
  *
  *  Set cooperative level and the source window for the events.
  */
Lionel Ulmer's avatar
Lionel Ulmer committed
641
HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
642 643
        LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
{
644
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667

    TRACE("(%p) %p,0x%08x\n", This, hwnd, dwflags);
    _dump_cooperativelevel_DI(dwflags);

    if ((dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == 0 ||
        (dwflags & (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE)) == (DISCL_EXCLUSIVE | DISCL_NONEXCLUSIVE) ||
        (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == 0 ||
        (dwflags & (DISCL_FOREGROUND | DISCL_BACKGROUND)) == (DISCL_FOREGROUND | DISCL_BACKGROUND))
        return DIERR_INVALIDPARAM;

    if (dwflags == (DISCL_NONEXCLUSIVE | DISCL_BACKGROUND))
        hwnd = GetDesktopWindow();

    if (!hwnd) return E_HANDLE;

    /* For security reasons native does not allow exclusive background level
       for mouse and keyboard only */
    if (dwflags & DISCL_EXCLUSIVE && dwflags & DISCL_BACKGROUND &&
        (IsEqualGUID(&This->guid, &GUID_SysMouse) ||
         IsEqualGUID(&This->guid, &GUID_SysKeyboard)))
        return DIERR_UNSUPPORTED;

    /* Store the window which asks for the mouse */
668
    EnterCriticalSection(&This->crit);
669 670
    This->win = hwnd;
    This->dwCoopLevel = dwflags;
671
    LeaveCriticalSection(&This->crit);
672

673
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
674 675
}

676 677 678
/******************************************************************************
  *     SetEventNotification : specifies event to be sent on state change
  */
Lionel Ulmer's avatar
Lionel Ulmer committed
679
HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
680 681
	LPDIRECTINPUTDEVICE8A iface, HANDLE event)
{
682
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
683 684 685

    TRACE("(%p) %p\n", This, event);

686
    EnterCriticalSection(&This->crit);
687
    This->hEvent = event;
688
    LeaveCriticalSection(&This->crit);
689
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
690 691
}

692
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
693
{
694
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
695
    ULONG ref;
696

697
    ref = InterlockedDecrement(&(This->ref));
698 699
    if (ref) return ref;

700 701 702 703
    IDirectInputDevice_Unacquire(iface);
    /* Reset the FF state, free all effects, etc */
    IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET);

704
    HeapFree(GetProcessHeap(), 0, This->data_queue);
705 706 707 708 709 710

    /* Free data format */
    HeapFree(GetProcessHeap(), 0, This->data_format.wine_df->rgodf);
    HeapFree(GetProcessHeap(), 0, This->data_format.wine_df);
    release_DataFormat(&This->data_format);

711 712 713 714
    EnterCriticalSection( &This->dinput->crit );
    list_remove( &This->entry );
    LeaveCriticalSection( &This->dinput->crit );

715 716 717 718
    IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput);
    This->crit.DebugInfo->Spare[0] = 0;
    DeleteCriticalSection(&This->crit);

719 720 721
    HeapFree(GetProcessHeap(), 0, This);

    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
722 723 724
}

HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
725
	LPDIRECTINPUTDEVICE8A iface,REFIID riid,LPVOID *ppobj
Lionel Ulmer's avatar
Lionel Ulmer committed
726 727
)
{
728
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
    
    TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
    if (IsEqualGUID(&IID_IUnknown,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDeviceA,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) {
	IDirectInputDevice7_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
751 752 753 754 755
    if (IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
	IDirectInputDevice8_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
756 757
    TRACE("Unsupported interface !\n");
    return E_FAIL;
Lionel Ulmer's avatar
Lionel Ulmer committed
758 759
}

760 761 762 763
HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(
	LPDIRECTINPUTDEVICE8W iface,REFIID riid,LPVOID *ppobj
)
{
764
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
    
    TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
    if (IsEqualGUID(&IID_IUnknown,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDeviceW,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDevice2W,riid)) {
	IDirectInputDevice2_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
    if (IsEqualGUID(&IID_IDirectInputDevice7W,riid)) {
	IDirectInputDevice7_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
787 788 789 790 791
    if (IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
	IDirectInputDevice8_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
792 793
    TRACE("Unsupported interface !\n");
    return E_FAIL;
794 795
}

Lionel Ulmer's avatar
Lionel Ulmer committed
796
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
797
	LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
798
{
799
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
800
    return InterlockedIncrement(&(This->ref));
Lionel Ulmer's avatar
Lionel Ulmer committed
801 802
}

803 804
HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
        LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Lionel Ulmer's avatar
Lionel Ulmer committed
805
{
806 807
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    DIDEVICEOBJECTINSTANCEA ddoi;
808
    int i;
809 810 811 812 813 814 815 816 817 818 819 820

    TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
    TRACE("  - flags = ");
    _dump_EnumObjects_flags(dwFlags);
    TRACE("\n");

    /* Only the fields till dwFFMaxForce are relevant */
    memset(&ddoi, 0, sizeof(ddoi));
    ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);

    for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
    {
821
        LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
822

823 824 825
        if (dwFlags != DIDFT_ALL && !(dwFlags & DIEFT_GETTYPE(odf->dwType))) continue;
        if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
            continue;
826 827

	if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
828
    }
829

830
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
831
}
832

833 834
HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
        LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
835
{
836 837 838
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    DIDEVICEOBJECTINSTANCEW ddoi;
    int i;
839

840 841 842 843
    TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
    TRACE("  - flags = ");
    _dump_EnumObjects_flags(dwFlags);
    TRACE("\n");
844

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
    /* Only the fields till dwFFMaxForce are relevant */
    memset(&ddoi, 0, sizeof(ddoi));
    ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, dwFFMaxForce);

    for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
    {
        LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);

        if (dwFlags != DIDFT_ALL && !(dwFlags & DIEFT_GETTYPE(odf->dwType))) continue;
        if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
            continue;

	if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
    }

    return DI_OK;
861 862
}

863 864 865 866
/******************************************************************************
 *	GetProperty
 */

Lionel Ulmer's avatar
Lionel Ulmer committed
867
HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
868
	LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
Lionel Ulmer's avatar
Lionel Ulmer committed
869
{
870 871 872 873 874 875 876 877 878
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;

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

    if (HIWORD(rguid)) return DI_OK;

    switch (LOWORD(rguid))
    {
879
        case (DWORD_PTR) DIPROP_BUFFERSIZE:
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
        {
            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;

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

            pd->dwData = This->queue_len;
            TRACE("buffersize = %d\n", pd->dwData);
            break;
        }
        default:
            WARN("Unknown property %s\n", debugstr_guid(rguid));
            break;
    }

    return DI_OK;
}

/******************************************************************************
 *	SetProperty
 */

HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty(
        LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;

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

    if (HIWORD(rguid)) return DI_OK;

    switch (LOWORD(rguid))
    {
913
        case (DWORD_PTR) DIPROP_AXISMODE:
914 915 916 917 918 919 920
        {
            LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;

            if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
            if (pdiph->dwHow == DIPH_DEVICE && pdiph->dwObj) return DIERR_INVALIDPARAM;
            if (This->acquired) return DIERR_ACQUIRED;
            if (pdiph->dwHow != DIPH_DEVICE) return DIERR_UNSUPPORTED;
921
            if (!This->data_format.user_df) return DI_OK;
922 923 924 925 926 927 928 929 930 931 932

            TRACE("Axis mode: %s\n", pd->dwData == DIPROPAXISMODE_ABS ? "absolute" :
                                                                        "relative");

            EnterCriticalSection(&This->crit);
            This->data_format.user_df->dwFlags &= ~DIDFT_AXIS;
            This->data_format.user_df->dwFlags |= pd->dwData == DIPROPAXISMODE_ABS ?
                                                  DIDF_ABSAXIS : DIDF_RELAXIS;
            LeaveCriticalSection(&This->crit);
            break;
        }
933
        case (DWORD_PTR) DIPROP_BUFFERSIZE:
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
        {
            LPCDIPROPDWORD pd = (LPCDIPROPDWORD)pdiph;

            if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
            if (This->acquired) return DIERR_ACQUIRED;

            TRACE("buffersize = %d\n", pd->dwData);

            EnterCriticalSection(&This->crit);
            HeapFree(GetProcessHeap(), 0, This->data_queue);

            This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0,
                                pd->dwData * sizeof(DIDEVICEOBJECTDATA));
            This->queue_head = This->queue_tail = This->overflow = 0;
            This->queue_len  = pd->dwData;

            LeaveCriticalSection(&This->crit);
            break;
        }
        default:
            WARN("Unknown property %s\n", debugstr_guid(rguid));
            return DIERR_UNSUPPORTED;
    }

958
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
959 960 961
}

HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
962
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
963 964 965 966
	LPDIDEVICEOBJECTINSTANCEA pdidoi,
	DWORD dwObj,
	DWORD dwHow)
{
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
    DIDEVICEOBJECTINSTANCEW didoiW;
    HRESULT res;

    if (!pdidoi ||
        (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) &&
         pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A)))
        return DIERR_INVALIDPARAM;

    didoiW.dwSize = sizeof(didoiW);
    res = IDirectInputDevice2WImpl_GetObjectInfo((LPDIRECTINPUTDEVICE8W)iface, &didoiW, dwObj, dwHow);
    if (res == DI_OK)
    {
        DWORD dwSize = pdidoi->dwSize;

        memset(pdidoi, 0, pdidoi->dwSize);
        pdidoi->dwSize   = dwSize;
        pdidoi->guidType = didoiW.guidType;
        pdidoi->dwOfs    = didoiW.dwOfs;
        pdidoi->dwType   = didoiW.dwType;
        pdidoi->dwFlags  = didoiW.dwFlags;
    }

    return res;
Lionel Ulmer's avatar
Lionel Ulmer committed
990
}
991

992 993 994 995 996 997
HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIDEVICEOBJECTINSTANCEW pdidoi,
	DWORD dwObj,
	DWORD dwHow)
{
998
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
999
    DWORD dwSize;
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
    LPDIOBJECTDATAFORMAT odf;
    int idx = -1;

    TRACE("(%p) %d(0x%08x) -> %p\n", This, dwHow, dwObj, pdidoi);

    if (!pdidoi ||
        (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW) &&
         pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W)))
        return DIERR_INVALIDPARAM;

    switch (dwHow)
    {
    case DIPH_BYOFFSET:
        if (!This->data_format.offsets) break;
        for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
            if (This->data_format.offsets[idx] == dwObj) break;
        break;
    case DIPH_BYID:
        dwObj &= 0x00ffffff;
        for (idx = This->data_format.wine_df->dwNumObjs - 1; idx >= 0; idx--)
            if ((dataformat_to_odf(This->data_format.wine_df, idx)->dwType & 0x00ffffff) == dwObj)
                break;
        break;

    case DIPH_BYUSAGE:
        FIXME("dwHow = DIPH_BYUSAGE not implemented\n");
        break;
    default:
        WARN("invalid parameter: dwHow = %08x\n", dwHow);
        return DIERR_INVALIDPARAM;
    }
    if (idx < 0) return DIERR_OBJECTNOTFOUND;

    odf = dataformat_to_odf(This->data_format.wine_df, idx);
1034
    dwSize = pdidoi->dwSize; /* save due to memset below */
1035 1036
    memset(pdidoi, 0, pdidoi->dwSize);
    pdidoi->dwSize   = dwSize;
1037
    if (odf->pguid) pdidoi->guidType = *odf->pguid;
1038 1039 1040 1041
    pdidoi->dwOfs    = This->data_format.offsets ? This->data_format.offsets[idx] : odf->dwOfs;
    pdidoi->dwType   = odf->dwType;
    pdidoi->dwFlags  = odf->dwFlags;

1042
    return DI_OK;
1043 1044
}

1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(
        LPDIRECTINPUTDEVICE8A iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
        LPDWORD entries, DWORD flags)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    HRESULT ret = DI_OK;
    int len;

    TRACE("(%p) %p -> %p(%d) x%d, 0x%08x\n",
          This, dod, entries, entries ? *entries : 0, dodsize, flags);

    if (!This->acquired)
        return DIERR_NOTACQUIRED;
    if (!This->queue_len)
        return DIERR_NOTBUFFERED;
    if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
        return DIERR_INVALIDPARAM;

    IDirectInputDevice2_Poll(iface);
    EnterCriticalSection(&This->crit);

    len = This->queue_head - This->queue_tail;
    if (len < 0) len += This->queue_len;

    if ((*entries != INFINITE) && (len > *entries)) len = *entries;

    if (dod)
    {
        int i;
        for (i = 0; i < len; i++)
        {
            int n = (This->queue_tail + i) % This->queue_len;
            memcpy((char *)dod + dodsize * i, This->data_queue + n, dodsize);
        }
    }
    *entries = len;

    if (This->overflow)
        ret = DI_BUFFEROVERFLOW;

    if (!(flags & DIGDD_PEEK))
    {
        /* Advance reading position */
        This->queue_tail = (This->queue_tail + len) % This->queue_len;
        This->overflow = FALSE;
    }

    LeaveCriticalSection(&This->crit);

    TRACE("Returning %d events queued\n", *entries);
    return ret;
}

Lionel Ulmer's avatar
Lionel Ulmer committed
1098
HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
1099
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1100 1101 1102
	HWND hwndOwner,
	DWORD dwFlags)
{
1103
    FIXME("(this=%p,%p,0x%08x): stub!\n",
1104
	  iface, hwndOwner, dwFlags);
1105

1106
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1107
}
1108

Lionel Ulmer's avatar
Lionel Ulmer committed
1109
HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
1110
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1111 1112 1113 1114
	HINSTANCE hinst,
	DWORD dwVersion,
	REFGUID rguid)
{
1115
    FIXME("(this=%p,%p,%d,%s): stub!\n",
1116 1117
	  iface, hinst, dwVersion, debugstr_guid(rguid));
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1118
}
1119

Lionel Ulmer's avatar
Lionel Ulmer committed
1120 1121 1122 1123 1124
/******************************************************************************
 *	IDirectInputDevice2A
 */

HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
1125
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1126 1127 1128 1129 1130
	REFGUID rguid,
	LPCDIEFFECT lpeff,
	LPDIRECTINPUTEFFECT *ppdef,
	LPUNKNOWN pUnkOuter)
{
1131 1132 1133
    FIXME("(this=%p,%s,%p,%p,%p): stub!\n",
	  iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1134 1135 1136
}

HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1137
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1138 1139 1140 1141
	LPDIENUMEFFECTSCALLBACKA lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1142
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1143 1144 1145
	  iface, lpCallback, lpvRef, dwFlags);
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1146 1147
}

1148 1149 1150 1151 1152 1153
HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIENUMEFFECTSCALLBACKW lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1154
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1155 1156 1157
	  iface, lpCallback, lpvRef, dwFlags);
    
    return DI_OK;
1158 1159
}

Lionel Ulmer's avatar
Lionel Ulmer committed
1160
HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1161
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1162 1163 1164
	LPDIEFFECTINFOA lpdei,
	REFGUID rguid)
{
1165 1166 1167
    FIXME("(this=%p,%p,%s): stub!\n",
	  iface, lpdei, debugstr_guid(rguid));
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1168 1169
}

1170 1171 1172 1173 1174
HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIEFFECTINFOW lpdei,
	REFGUID rguid)
{
1175 1176 1177
    FIXME("(this=%p,%p,%s): stub!\n",
	  iface, lpdei, debugstr_guid(rguid));
    return DI_OK;
1178 1179
}

Lionel Ulmer's avatar
Lionel Ulmer committed
1180
HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
1181
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1182 1183
	LPDWORD pdwOut)
{
1184 1185 1186
    FIXME("(this=%p,%p): stub!\n",
	  iface, pdwOut);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1187 1188 1189
}

HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
1190
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1191 1192
	DWORD dwFlags)
{
1193 1194
    TRACE("(%p) 0x%08x:\n", iface, dwFlags);
    return DI_NOEFFECT;
Lionel Ulmer's avatar
Lionel Ulmer committed
1195 1196 1197
}

HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
1198
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1199 1200 1201 1202
	LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1203
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1204 1205
	  iface, lpCallback, lpvRef, dwFlags);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1206 1207 1208
}

HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
1209
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1210 1211
	LPDIEFFESCAPE lpDIEEsc)
{
1212 1213 1214
    FIXME("(this=%p,%p): stub!\n",
	  iface, lpDIEEsc);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1215 1216 1217
}

HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
1218
	LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
1219
{
1220 1221 1222
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;

    if (!This->acquired) return DIERR_NOTACQUIRED;
1223 1224
    /* Because wine devices do not need to be polled, just return DI_NOEFFECT */
    return DI_NOEFFECT;
Lionel Ulmer's avatar
Lionel Ulmer committed
1225 1226 1227
}

HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
1228
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1229
	DWORD cbObjectData,
1230
	LPCDIDEVICEOBJECTDATA rgdod,
Lionel Ulmer's avatar
Lionel Ulmer committed
1231 1232 1233
	LPDWORD pdwInOut,
	DWORD dwFlags)
{
1234
    FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n",
1235 1236 1237
	  iface, cbObjectData, rgdod, pdwInOut, dwFlags);
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1238 1239
}

1240
HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1241 1242 1243 1244 1245
							  LPCSTR lpszFileName,
							  LPDIENUMEFFECTSINFILECALLBACK pec,
							  LPVOID pvRef,
							  DWORD dwFlags)
{
1246
    FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
1247 1248
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1249 1250
}

1251 1252 1253 1254 1255 1256
HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
							  LPCWSTR lpszFileName,
							  LPDIENUMEFFECTSINFILECALLBACK pec,
							  LPVOID pvRef,
							  DWORD dwFlags)
{
1257
    FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
1258 1259
    
    return DI_OK;
1260 1261
}

1262
HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1263 1264 1265 1266 1267
							  LPCSTR lpszFileName,
							  DWORD dwEntries,
							  LPDIFILEEFFECT rgDiFileEft,
							  DWORD dwFlags)
{
1268
    FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
1269 1270
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1271
}
1272

1273 1274 1275 1276 1277 1278
HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
							  LPCWSTR lpszFileName,
							  DWORD dwEntries,
							  LPDIFILEEFFECT rgDiFileEft,
							  DWORD dwFlags)
{
1279
    FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
1280 1281
    
    return DI_OK;
1282 1283
}

1284 1285 1286 1287 1288
HRESULT WINAPI IDirectInputDevice8AImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
						       LPDIACTIONFORMATA lpdiaf,
						       LPCSTR lpszUserName,
						       DWORD dwFlags)
{
1289
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
1290 1291 1292 1293 1294 1295
#define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
	X(DIDBAM_DEFAULT)
	X(DIDBAM_PRESERVE)
	X(DIDBAM_INITIALIZE)
	X(DIDBAM_HWDEFAULTS)
#undef X
1296
    _dump_diactionformatA(lpdiaf);
1297
    return DI_OK;
1298 1299
}

1300 1301 1302 1303 1304
HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
						       LPDIACTIONFORMATW lpdiaf,
						       LPCWSTR lpszUserName,
						       DWORD dwFlags)
{
1305
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
1306 1307 1308 1309 1310 1311
#define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
	X(DIDBAM_DEFAULT)
	X(DIDBAM_PRESERVE)
	X(DIDBAM_INITIALIZE)
	X(DIDBAM_HWDEFAULTS)
#undef X
1312 1313
  
    return DI_OK;
1314 1315
}

1316 1317 1318 1319 1320
HRESULT WINAPI IDirectInputDevice8AImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
						     LPDIACTIONFORMATA lpdiaf,
						     LPCSTR lpszUserName,
						     DWORD dwFlags)
{
1321
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
1322 1323
    
    return DI_OK;
1324 1325
}

1326 1327 1328 1329 1330
HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
						     LPDIACTIONFORMATW lpdiaf,
						     LPCWSTR lpszUserName,
						     DWORD dwFlags)
{
1331
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
1332 1333
    
    return DI_OK;
1334 1335
}

1336 1337 1338
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
						     LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
{
1339 1340 1341
    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
    
    return DI_OK;
1342
}
1343 1344 1345 1346

HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
						     LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
{
1347 1348 1349
    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
    
    return DI_OK;
1350
}