device.c 38.6 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 "winuser.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
36 37 38
#include "winerror.h"
#include "dinput.h"
#include "device_private.h"
39
#include "dinput_private.h"
Lionel Ulmer's avatar
Lionel Ulmer committed
40

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

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

void _dump_EnumObjects_flags(DWORD dwFlags) {
69
    if (TRACE_ON(dinput)) {
70
	unsigned int   i;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
	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),
86 87 88 89
	    FE(DIDFT_OUTPUT),
	    FE(DIDFT_VENDORDEFINED),
	    FE(DIDFT_ALIAS),
	    FE(DIDFT_OPTIONAL)
Lionel Ulmer's avatar
Lionel Ulmer committed
90
#undef FE
91 92 93 94 95 96 97 98 99 100 101 102 103 104
	};
	type = (dwFlags & 0xFF0000FF);
	instance = ((dwFlags >> 8) & 0xFFFF);
	DPRINTF("Type:");
	if (type == DIDFT_ALL) {
	    DPRINTF(" DIDFT_ALL");
	} else {
	    for (i = 0; i < (sizeof(flags) / sizeof(flags[0])); i++) {
		if (flags[i].mask & type) {
		    type &= ~flags[i].mask;
		    DPRINTF(" %s",flags[i].name);
		}
	    }
	    if (type) {
105
                DPRINTF(" (unhandled: %08x)", type);
106 107 108 109 110 111
	    }
	}
	DPRINTF(" / Instance: ");
	if (instance == ((DIDFT_ANYINSTANCE >> 8) & 0xFFFF)) {
	    DPRINTF("DIDFT_ANYINSTANCE");
	} else {
112
            DPRINTF("%3d", instance);
113 114
	}
    }
Lionel Ulmer's avatar
Lionel Ulmer committed
115 116
}

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

void _dump_OBJECTINSTANCEA(DIDEVICEOBJECTINSTANCEA *ddoi) {
128
    if (TRACE_ON(dinput)) {
129
        DPRINTF("    - enumerating : %s ('%s') - %2d - 0x%08x - %s\n",
130 131
		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(DIDEVICEOBJECTINSTANCEW *ddoi) {
135
    if (TRACE_ON(dinput)) {
136
        DPRINTF("    - enumerating : %s ('%s'), - %2d - 0x%08x - %s\n",
137 138
		debugstr_guid(&ddoi->guidType), _dump_dinput_GUID(&ddoi->guidType), ddoi->dwOfs, ddoi->dwType, debugstr_w(ddoi->tszName));
    }
139 140
}

141 142
/* This function is a helper to convert a GUID into any possible DInput GUID out there */
const char *_dump_dinput_GUID(const GUID *guid) {
143
    unsigned int i;
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 180 181
    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
182 183
	}
    }
184
    return "Unknown GUID";
Lionel Ulmer's avatar
Lionel Ulmer committed
185 186
}

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

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

219
/* Conversion between internal data buffer and external data buffer */
220
void fill_DataFormat(void *out, const void *in, DataFormat *df) {
221
    int i;
222
    const char *in_c = in;
223
    char *out_c = (char *) out;
224

225 226 227 228 229 230 231 232 233
    if (df->dt == NULL) {
	/* This means that the app uses Wine's internal data format */
	memcpy(out, in, df->internal_format_size);
    } 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",
234 235
                              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);
236
			break;
237

238 239
		    case 2:
			TRACE("Copying (s) to %d from %d (value %d)\n",
240 241
			      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));
242
			break;
243

244 245
		    case 4:
			TRACE("Copying (i) to %d from %d (value %d)\n",
246 247
                              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));
248
			break;
249

250 251 252 253 254 255 256 257 258
		    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);
259
			*(out_c + df->dt[i].offset_out) = (char) df->dt[i].value;
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
			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);
			*((int *) (out_c + df->dt[i].offset_out)) = (int) df->dt[i].value;
			break;
			
		    default:
275
			memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size);
276 277 278 279 280 281
			break;
		}
	    }
	}
    }
}
282

283 284
void release_DataFormat(DataFormat * format)
{
285
    TRACE("Deleting DataFormat: %p\n", format);
286 287

    HeapFree(GetProcessHeap(), 0, format->dt);
288 289 290
    format->dt = NULL;
    HeapFree(GetProcessHeap(), 0, format->offsets);
    format->offsets = NULL;
291 292
    HeapFree(GetProcessHeap(), 0, format->user_df);
    format->user_df = NULL;
293 294
}

295 296 297 298 299 300
inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
{
    if (idx < 0 || idx >= df->dwNumObjs) return NULL;
    return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize);
}

301
HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format)
302
{
303
    DataTransform *dt;
304
    unsigned int i, j;
305 306 307
    int same = 1;
    int *done;
    int index = 0;
308
    DWORD next = 0;
309 310

    if (!format->wine_df) return DIERR_INVALIDPARAM;
311
    done = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, asked_format->dwNumObjs * sizeof(int));
312
    dt = HeapAlloc(GetProcessHeap(), 0, asked_format->dwNumObjs * sizeof(DataTransform));
313 314
    if (!dt || !done) goto failed;

315
    if (!(format->offsets = HeapAlloc(GetProcessHeap(), 0, format->wine_df->dwNumObjs * sizeof(int))))
316 317
        goto failed;

318 319 320 321
    if (!(format->user_df = HeapAlloc(GetProcessHeap(), 0, asked_format->dwSize)))
        goto failed;
    memcpy(format->user_df, asked_format, asked_format->dwSize);

322
    TRACE("Creating DataTransform :\n");
323
    
324 325
    for (i = 0; i < format->wine_df->dwNumObjs; i++)
    {
326 327
        format->offsets[i] = -1;

328 329 330 331 332 333 334 335
	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) ||
336 337
		 (format->wine_df->rgodf[i].pguid == NULL) ||
		 (IsEqualGUID(format->wine_df->rgodf[i].pguid, asked_format->rgodf[j].pguid)))
338 339 340 341
		&&
		(/* Then check if it accepts any instance id, and if not, if it matches Wine's
		  * instance id.
		  */
342
		 ((asked_format->rgodf[j].dwType & DIDFT_INSTANCEMASK) == DIDFT_ANYINSTANCE) ||
343
		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == 0x00FF) || /* This is mentionned in no DX docs, but it works fine - tested on WinXP */
344
		 (DIDFT_GETINSTANCE(asked_format->rgodf[j].dwType) == DIDFT_GETINSTANCE(format->wine_df->rgodf[i].dwType)))
345 346
		&&
		( /* Then if the asked type matches the one Wine provides */
347
                 DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
348
            {
349 350
		done[j] = 1;
		
351
		TRACE("Matching :\n");
352 353 354 355
		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));
356 357
                TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
                TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
358 359
		TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
		
360
		TRACE("   - Wine  (%d) :\n", i);
361
		TRACE("       * GUID: %s ('%s')\n",
362 363 364 365 366
                      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");
367
		
368
                if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON)
369 370 371
		    dt[index].size = sizeof(BYTE);
		else
		    dt[index].size = sizeof(DWORD);
372
                dt[index].offset_in = format->wine_df->rgodf[i].dwOfs;
373
                dt[index].offset_out = asked_format->rgodf[j].dwOfs;
374
                format->offsets[i]   = asked_format->rgodf[j].dwOfs;
375
		dt[index].value = 0;
376
                next = next + dt[index].size;
377
		
378
                if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out)
379 380
		    same = 0;
		
381
		index++;
382 383 384 385 386 387 388 389 390
		break;
	    }
	}
	
	if (j == asked_format->dwNumObjs)
	    same = 0;
    }
    
    TRACE("Setting to default value :\n");
Lionel Ulmer's avatar
Lionel Ulmer committed
391
    for (j = 0; j < asked_format->dwNumObjs; j++) {
392 393 394 395 396
	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));
397 398
            TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
            TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
399 400 401 402 403 404 405 406 407 408 409 410 411
	    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;
	    dt[index].value = 0;
	    index++;
	    
	    same = 0;
	}
Lionel Ulmer's avatar
Lionel Ulmer committed
412
    }
413
    
414
    format->internal_format_size = format->wine_df->dwDataSize;
415
    format->size = index;
416 417
    if (same) {
	HeapFree(GetProcessHeap(), 0, dt);
418
        dt = NULL;
Lionel Ulmer's avatar
Lionel Ulmer committed
419
    }
420 421
    format->dt = dt;

422
    HeapFree(GetProcessHeap(), 0, done);
423

424 425 426 427 428 429 430 431
    return DI_OK;

failed:
    HeapFree(GetProcessHeap(), 0, done);
    HeapFree(GetProcessHeap(), 0, dt);
    format->dt = NULL;
    HeapFree(GetProcessHeap(), 0, format->offsets);
    format->offsets = NULL;
432 433
    HeapFree(GetProcessHeap(), 0, format->user_df);
    format->user_df = NULL;
434 435

    return DIERR_OUTOFMEMORY;
Lionel Ulmer's avatar
Lionel Ulmer committed
436 437
}

438
/* find an object by it's offset in a data format */
439
static int offset_to_object(DataFormat *df, int offset)
440 441 442
{
    int i;

443 444 445 446
    if (!df->offsets) return -1;

    for (i = 0; i < df->wine_df->dwNumObjs; i++)
        if (df->offsets[i] == offset) return i;
447 448 449 450 451 452 453 454

    return -1;
}

static int id_to_object(LPCDIDATAFORMAT df, int id)
{
    int i;

455
    id &= 0x00ffffff;
456
    for (i = 0; i < df->dwNumObjs; i++)
457
        if ((dataformat_to_odf(df, i)->dwType & 0x00ffffff) == id)
458 459 460 461 462
            return i;

    return -1;
}

463 464 465 466 467 468 469
int id_to_offset(DataFormat *df, int id)
{
    int obj = id_to_object(df->wine_df, id);

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

470
int find_property(DataFormat *df, LPCDIPROPHEADER ph)
471 472 473
{
    switch (ph->dwHow)
    {
474 475
        case DIPH_BYID:     return id_to_object(df->wine_df, ph->dwObj);
        case DIPH_BYOFFSET: return offset_to_object(df, ph->dwObj);
476 477 478 479 480 481 482
    }
    FIXME("Unhandled ph->dwHow=='%04X'\n", (unsigned int)ph->dwHow);

    return -1;
}


483
BOOL DIEnumDevicesCallbackAtoW(LPCDIDEVICEOBJECTINSTANCEA lpddi, LPVOID lpvRef) {
484 485 486 487 488
    DIDEVICEOBJECTINSTANCEW ddtmp;
    device_enumobjects_AtoWcb_data* data;

    data = (device_enumobjects_AtoWcb_data*) lpvRef;
    
489
    memset(&ddtmp, 0, sizeof(ddtmp));
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    
    ddtmp.dwSize = sizeof(DIDEVICEINSTANCEW);
    ddtmp.guidType     = lpddi->guidType;
    ddtmp.dwOfs        = lpddi->dwOfs;
    ddtmp.dwType       = lpddi->dwType;
    ddtmp.dwFlags      = lpddi->dwFlags;
    MultiByteToWideChar(CP_ACP, 0, lpddi->tszName, -1, ddtmp.tszName, MAX_PATH);
    
    if (lpddi->dwSize == sizeof(DIDEVICEINSTANCEA)) {
	/**
	 * if dwSize < sizeof(DIDEVICEINSTANCEA of DInput version >= 5)
	 *  force feedback and other newer datas aren't available
	 */
	ddtmp.dwFFMaxForce        = lpddi->dwFFMaxForce;
	ddtmp.dwFFForceResolution = lpddi->dwFFForceResolution;
	ddtmp.wCollectionNumber   = lpddi->wCollectionNumber;
	ddtmp.wDesignatorIndex    = lpddi->wDesignatorIndex;
	ddtmp.wUsagePage          = lpddi->wUsagePage;
	ddtmp.wUsage              = lpddi->wUsage;
	ddtmp.dwDimension         = lpddi->dwDimension;
	ddtmp.wExponent           = lpddi->wExponent;
	ddtmp.wReserved           = lpddi->wReserved;
    }
    return data->lpCallBack(&ddtmp, data->lpvRef);
514 515
}

516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
/******************************************************************************
 *	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;

    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;
543 544
    /* Send event if asked */
    if (This->hEvent) SetEvent(This->hEvent);
545 546
}

547 548 549 550 551 552 553
/******************************************************************************
 *	Acquire
 */

HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
554
    HRESULT res;
555

556 557
    if (!This->data_format.user_df) return DIERR_INVALIDPARAM;

558 559
    EnterCriticalSection(&This->crit);
    res = This->acquired ? S_FALSE : DI_OK;
560
    This->acquired = 1;
561 562
    if (res == DI_OK)
        This->queue_head = This->queue_tail = This->overflow = 0;
563
    LeaveCriticalSection(&This->crit);
564

565
    return res;
566 567 568 569 570 571 572 573 574
}

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

HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
{
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
575
    HRESULT res;
576

577 578
    EnterCriticalSection(&This->crit);
    res = !This->acquired ? DI_NOEFFECT : DI_OK;
579
    This->acquired = 0;
580
    LeaveCriticalSection(&This->crit);
581

582
    return res;
583 584
}

Lionel Ulmer's avatar
Lionel Ulmer committed
585 586 587 588 589
/******************************************************************************
 *	IDirectInputDeviceA
 */

HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(
590 591
        LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
{
592
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
593 594 595 596
    HRESULT res = DI_OK;

    if (!df) return E_POINTER;
    TRACE("(%p) %p\n", This, df);
597
    _dump_DIDATAFORMAT(df);
598 599 600 601 602 603 604

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

    EnterCriticalSection(&This->crit);

    release_DataFormat(&This->data_format);
605
    res = create_DataFormat(df, &This->data_format);
606 607 608

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

611 612 613 614 615
/******************************************************************************
  *     SetCooperativeLevel
  *
  *  Set cooperative level and the source window for the events.
  */
Lionel Ulmer's avatar
Lionel Ulmer committed
616
HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(
617 618
        LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
{
619
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643

    TRACE("(%p) %p,0x%08x\n", This, hwnd, dwflags);
    TRACE(" cooperative level : ");
    _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 */
644
    EnterCriticalSection(&This->crit);
645 646
    This->win = hwnd;
    This->dwCoopLevel = dwflags;
647
    LeaveCriticalSection(&This->crit);
648

649
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
650 651
}

652 653 654
/******************************************************************************
  *     SetEventNotification : specifies event to be sent on state change
  */
Lionel Ulmer's avatar
Lionel Ulmer committed
655
HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(
656 657
	LPDIRECTINPUTDEVICE8A iface, HANDLE event)
{
658
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
659 660 661

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

662
    EnterCriticalSection(&This->crit);
663
    This->hEvent = event;
664
    LeaveCriticalSection(&This->crit);
665
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
666 667
}

668
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
669
{
670
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
671
    ULONG ref;
672

673
    ref = InterlockedDecrement(&(This->ref));
674 675 676 677 678 679 680
    if (ref) return ref;

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

    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
681 682 683
}

HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(
684
	LPDIRECTINPUTDEVICE8A iface,REFIID riid,LPVOID *ppobj
Lionel Ulmer's avatar
Lionel Ulmer committed
685 686
)
{
687
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    
    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;
    }
710 711 712 713 714
    if (IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
	IDirectInputDevice8_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
715 716
    TRACE("Unsupported interface !\n");
    return E_FAIL;
Lionel Ulmer's avatar
Lionel Ulmer committed
717 718
}

719 720 721 722
HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(
	LPDIRECTINPUTDEVICE8W iface,REFIID riid,LPVOID *ppobj
)
{
723
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
    
    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;
    }
746 747 748 749 750
    if (IsEqualGUID(&IID_IDirectInputDevice8W,riid)) {
	IDirectInputDevice8_AddRef(iface);
	*ppobj = This;
	return DI_OK;
    }
751 752
    TRACE("Unsupported interface !\n");
    return E_FAIL;
753 754
}

Lionel Ulmer's avatar
Lionel Ulmer committed
755
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(
756
	LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
757
{
758
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
759
    return InterlockedIncrement(&(This->ref));
Lionel Ulmer's avatar
Lionel Ulmer committed
760 761
}

762 763
HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
        LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
Lionel Ulmer's avatar
Lionel Ulmer committed
764
{
765 766
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    DIDEVICEOBJECTINSTANCEA ddoi;
767
    int i;
768 769 770 771 772 773 774 775 776 777 778 779

    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++)
    {
780
        LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
781

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

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

789
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
790
}
791

792 793
HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
        LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
794
{
795 796 797
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
    DIDEVICEOBJECTINSTANCEW ddoi;
    int i;
798

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

804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
    /* 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;
820 821
}

822 823 824 825
/******************************************************************************
 *	GetProperty
 */

Lionel Ulmer's avatar
Lionel Ulmer committed
826
HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(
827
	LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
Lionel Ulmer's avatar
Lionel Ulmer committed
828
{
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
    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))
    {
        case (DWORD) DIPROP_BUFFERSIZE:
        {
            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))
    {
872 873 874 875 876 877 878 879
        case (DWORD) DIPROP_AXISMODE:
        {
            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;
880
            if (!This->data_format.user_df) return DI_OK;
881 882 883 884 885 886 887 888 889 890 891

            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;
        }
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916
        case (DWORD) DIPROP_BUFFERSIZE:
        {
            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;
    }

917
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
918 919 920
}

HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
921
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
922 923 924 925
	LPDIDEVICEOBJECTINSTANCEA pdidoi,
	DWORD dwObj,
	DWORD dwHow)
{
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
    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
949
}
950

951 952 953 954 955 956
HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIDEVICEOBJECTINSTANCEW pdidoi,
	DWORD dwObj,
	DWORD dwHow)
{
957
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;
958
    DWORD dwSize;
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
    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);
993
    dwSize = pdidoi->dwSize; /* save due to memset below */
994 995
    memset(pdidoi, 0, pdidoi->dwSize);
    pdidoi->dwSize   = dwSize;
996
    if (odf->pguid) pdidoi->guidType = *odf->pguid;
997 998 999 1000
    pdidoi->dwOfs    = This->data_format.offsets ? This->data_format.offsets[idx] : odf->dwOfs;
    pdidoi->dwType   = odf->dwType;
    pdidoi->dwFlags  = odf->dwFlags;

1001
    return DI_OK;
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 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
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
1057
HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceInfo(
1058
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1059 1060
	LPDIDEVICEINSTANCEA pdidi)
{
1061 1062 1063 1064
    FIXME("(this=%p,%p): stub!\n",
	  iface, pdidi);
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1065
}
1066

1067 1068 1069 1070
HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceInfo(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIDEVICEINSTANCEW pdidi)
{
1071 1072 1073 1074
    FIXME("(this=%p,%p): stub!\n",
	  iface, pdidi);
    
    return DI_OK;
1075
}
1076

Lionel Ulmer's avatar
Lionel Ulmer committed
1077
HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(
1078
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1079 1080 1081
	HWND hwndOwner,
	DWORD dwFlags)
{
1082
    FIXME("(this=%p,%p,0x%08x): stub!\n",
1083
	  iface, hwndOwner, dwFlags);
1084

1085
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1086
}
1087

Lionel Ulmer's avatar
Lionel Ulmer committed
1088
HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(
1089
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1090 1091 1092 1093
	HINSTANCE hinst,
	DWORD dwVersion,
	REFGUID rguid)
{
1094
    FIXME("(this=%p,%p,%d,%s): stub!\n",
1095 1096
	  iface, hinst, dwVersion, debugstr_guid(rguid));
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1097
}
1098

Lionel Ulmer's avatar
Lionel Ulmer committed
1099 1100 1101 1102 1103
/******************************************************************************
 *	IDirectInputDevice2A
 */

HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(
1104
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1105 1106 1107 1108 1109
	REFGUID rguid,
	LPCDIEFFECT lpeff,
	LPDIRECTINPUTEFFECT *ppdef,
	LPUNKNOWN pUnkOuter)
{
1110 1111 1112
    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
1113 1114 1115
}

HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
1116
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1117 1118 1119 1120
	LPDIENUMEFFECTSCALLBACKA lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1121
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1122 1123 1124
	  iface, lpCallback, lpvRef, dwFlags);
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1125 1126
}

1127 1128 1129 1130 1131 1132
HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIENUMEFFECTSCALLBACKW lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1133
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1134 1135 1136
	  iface, lpCallback, lpvRef, dwFlags);
    
    return DI_OK;
1137 1138
}

Lionel Ulmer's avatar
Lionel Ulmer committed
1139
HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
1140
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1141 1142 1143
	LPDIEFFECTINFOA lpdei,
	REFGUID rguid)
{
1144 1145 1146
    FIXME("(this=%p,%p,%s): stub!\n",
	  iface, lpdei, debugstr_guid(rguid));
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1147 1148
}

1149 1150 1151 1152 1153
HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
	LPDIRECTINPUTDEVICE8W iface,
	LPDIEFFECTINFOW lpdei,
	REFGUID rguid)
{
1154 1155 1156
    FIXME("(this=%p,%p,%s): stub!\n",
	  iface, lpdei, debugstr_guid(rguid));
    return DI_OK;
1157 1158
}

Lionel Ulmer's avatar
Lionel Ulmer committed
1159
HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(
1160
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1161 1162
	LPDWORD pdwOut)
{
1163 1164 1165
    FIXME("(this=%p,%p): stub!\n",
	  iface, pdwOut);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1166 1167 1168
}

HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(
1169
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1170 1171
	DWORD dwFlags)
{
1172
    FIXME("(this=%p,0x%08x): stub!\n",
1173 1174
	  iface, dwFlags);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1175 1176 1177
}

HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(
1178
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1179 1180 1181 1182
	LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
	LPVOID lpvRef,
	DWORD dwFlags)
{
1183
    FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
1184 1185
	  iface, lpCallback, lpvRef, dwFlags);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1186 1187 1188
}

HRESULT WINAPI IDirectInputDevice2AImpl_Escape(
1189
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1190 1191
	LPDIEFFESCAPE lpDIEEsc)
{
1192 1193 1194
    FIXME("(this=%p,%p): stub!\n",
	  iface, lpDIEEsc);
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1195 1196 1197
}

HRESULT WINAPI IDirectInputDevice2AImpl_Poll(
1198
	LPDIRECTINPUTDEVICE8A iface)
Lionel Ulmer's avatar
Lionel Ulmer committed
1199
{
1200 1201 1202
    IDirectInputDevice2AImpl *This = (IDirectInputDevice2AImpl *)iface;

    if (!This->acquired) return DIERR_NOTACQUIRED;
1203 1204
    /* Because wine devices do not need to be polled, just return DI_NOEFFECT */
    return DI_NOEFFECT;
Lionel Ulmer's avatar
Lionel Ulmer committed
1205 1206 1207
}

HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(
1208
	LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1209
	DWORD cbObjectData,
1210
	LPCDIDEVICEOBJECTDATA rgdod,
Lionel Ulmer's avatar
Lionel Ulmer committed
1211 1212 1213
	LPDWORD pdwInOut,
	DWORD dwFlags)
{
1214
    FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n",
1215 1216 1217
	  iface, cbObjectData, rgdod, pdwInOut, dwFlags);
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1218 1219
}

1220
HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1221 1222 1223 1224 1225
							  LPCSTR lpszFileName,
							  LPDIENUMEFFECTSINFILECALLBACK pec,
							  LPVOID pvRef,
							  DWORD dwFlags)
{
1226
    FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
1227 1228
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1229 1230
}

1231 1232 1233 1234 1235 1236
HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
							  LPCWSTR lpszFileName,
							  LPDIENUMEFFECTSINFILECALLBACK pec,
							  LPVOID pvRef,
							  DWORD dwFlags)
{
1237
    FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
1238 1239
    
    return DI_OK;
1240 1241
}

1242
HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
Lionel Ulmer's avatar
Lionel Ulmer committed
1243 1244 1245 1246 1247
							  LPCSTR lpszFileName,
							  DWORD dwEntries,
							  LPDIFILEEFFECT rgDiFileEft,
							  DWORD dwFlags)
{
1248
    FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
1249 1250
    
    return DI_OK;
Lionel Ulmer's avatar
Lionel Ulmer committed
1251
}
1252

1253 1254 1255 1256 1257 1258
HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
							  LPCWSTR lpszFileName,
							  DWORD dwEntries,
							  LPDIFILEEFFECT rgDiFileEft,
							  DWORD dwFlags)
{
1259
    FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
1260 1261
    
    return DI_OK;
1262 1263
}

1264 1265 1266 1267 1268
HRESULT WINAPI IDirectInputDevice8AImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
						       LPDIACTIONFORMATA lpdiaf,
						       LPCSTR lpszUserName,
						       DWORD dwFlags)
{
1269
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
1270 1271
    
    return DI_OK;
1272 1273
}

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

1284 1285 1286 1287 1288
HRESULT WINAPI IDirectInputDevice8AImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
						     LPDIACTIONFORMATA lpdiaf,
						     LPCSTR lpszUserName,
						     DWORD dwFlags)
{
1289
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
1290 1291
    
    return DI_OK;
1292 1293
}

1294 1295 1296 1297 1298
HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
						     LPDIACTIONFORMATW lpdiaf,
						     LPCWSTR lpszUserName,
						     DWORD dwFlags)
{
1299
    FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
1300 1301
    
    return DI_OK;
1302 1303
}

1304 1305 1306
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
						     LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
{
1307 1308 1309
    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
    
    return DI_OK;
1310
}
1311 1312 1313 1314

HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
						     LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
{
1315 1316 1317
    FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
    
    return DI_OK;
1318
}