dinput/tests: Avoid leaking a IDirectInput reference (Valgrind).
[wine.git] / dlls / dinput / tests / joystick8.c
blob60bee06479a7d8f9d56879429635375c16ecff60
1 /*
2 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define DIRECTINPUT_VERSION 0x0800
21 #include <stdarg.h>
22 #include <stddef.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
29 #define COBJMACROS
30 #include "dinput.h"
31 #include "dinputd.h"
32 #include "devguid.h"
33 #include "mmsystem.h"
34 #include "roapi.h"
35 #include "unknwn.h"
36 #include "winstring.h"
38 #include "wine/hid.h"
40 #include "dinput_test.h"
42 #define WIDL_using_Windows_Foundation
43 #define WIDL_using_Windows_Foundation_Collections
44 #include "windows.foundation.h"
45 #define WIDL_using_Windows_Devices_Haptics
46 #define WIDL_using_Windows_Gaming_Input
47 #include "windows.gaming.input.h"
48 #undef Size
50 #include "initguid.h"
52 DEFINE_GUID(GUID_action_mapping_1,0x00000001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b);
53 DEFINE_GUID(GUID_action_mapping_2,0x00010001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b);
54 DEFINE_GUID(GUID_map_other_device,0x00020001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b);
56 static HRESULT (WINAPI *pRoGetActivationFactory)( HSTRING, REFIID, void** );
57 static HRESULT (WINAPI *pRoInitialize)( RO_INIT_TYPE );
58 static HRESULT (WINAPI *pWindowsCreateString)( const WCHAR*, UINT32, HSTRING* );
59 static HRESULT (WINAPI *pWindowsDeleteString)( HSTRING str );
60 static const WCHAR* (WINAPI *pWindowsGetStringRawBuffer)( HSTRING, UINT32* );
62 static BOOL load_combase_functions(void)
64 HMODULE combase = GetModuleHandleW( L"combase.dll" );
66 #define LOAD_FUNC(m, f) if (!(p ## f = (void *)GetProcAddress( m, #f ))) goto failed;
67 LOAD_FUNC( combase, RoGetActivationFactory );
68 LOAD_FUNC( combase, RoInitialize );
69 LOAD_FUNC( combase, WindowsCreateString );
70 LOAD_FUNC( combase, WindowsDeleteString );
71 LOAD_FUNC( combase, WindowsGetStringRawBuffer );
72 #undef LOAD_FUNC
74 return TRUE;
76 failed:
77 win_skip("Failed to load combase.dll functions, skipping tests\n");
78 return FALSE;
81 struct check_object_todo
83 BOOL type;
84 BOOL ofs;
85 BOOL guid;
86 BOOL flags;
87 BOOL usage;
88 BOOL usage_page;
89 BOOL name;
92 struct check_objects_params
94 DWORD version;
95 UINT index;
96 UINT expect_count;
97 const DIDEVICEOBJECTINSTANCEW *expect_objs;
98 const struct check_object_todo *todo_objs;
99 BOOL todo_extra;
102 #define check_object( a, b, c ) check_object_( __LINE__, a, b, c )
103 static void check_object_( int line, const DIDEVICEOBJECTINSTANCEW *actual,
104 const DIDEVICEOBJECTINSTANCEW *expected,
105 const struct check_object_todo *todo )
107 static const struct check_object_todo todo_none = {0};
108 if (!todo) todo = &todo_none;
110 check_member_( __FILE__, line, *actual, *expected, "%lu", dwSize );
111 todo_wine_if( todo->guid )
112 check_member_guid_( __FILE__, line, *actual, *expected, guidType );
113 todo_wine_if( todo->ofs )
114 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwOfs );
115 todo_wine_if( todo->type )
116 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwType );
117 todo_wine_if( todo->flags )
118 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwFlags );
119 if (!localized) todo_wine_if( todo->name ) check_member_wstr_( __FILE__, line, *actual, *expected, tszName );
120 check_member_( __FILE__, line, *actual, *expected, "%lu", dwFFMaxForce );
121 check_member_( __FILE__, line, *actual, *expected, "%lu", dwFFForceResolution );
122 check_member_( __FILE__, line, *actual, *expected, "%u", wCollectionNumber );
123 check_member_( __FILE__, line, *actual, *expected, "%u", wDesignatorIndex );
124 todo_wine_if( todo->usage_page )
125 check_member_( __FILE__, line, *actual, *expected, "%#04x", wUsagePage );
126 todo_wine_if( todo->usage )
127 check_member_( __FILE__, line, *actual, *expected, "%#04x", wUsage );
128 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwDimension );
129 check_member_( __FILE__, line, *actual, *expected, "%#04x", wExponent );
130 check_member_( __FILE__, line, *actual, *expected, "%u", wReportId );
133 static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
135 static const DIDEVICEOBJECTINSTANCEW unexpected_obj = {0};
136 static const struct check_object_todo todo_none = {0};
137 struct check_objects_params *params = args;
138 const DIDEVICEOBJECTINSTANCEW *exp = params->expect_objs + params->index;
139 const struct check_object_todo *todo;
141 if (!params->todo_objs) todo = &todo_none;
142 else todo = params->todo_objs + params->index;
144 todo_wine_if( params->todo_extra && params->index >= params->expect_count )
145 ok( params->index < params->expect_count, "unexpected extra object\n" );
146 if (params->index >= params->expect_count) return DIENUM_STOP;
148 winetest_push_context( "obj[%d]", params->index );
150 ok( params->index < params->expect_count, "unexpected extra object\n" );
151 if (params->index >= params->expect_count) exp = &unexpected_obj;
153 check_object( obj, exp, todo );
155 winetest_pop_context();
157 params->index++;
158 return DIENUM_CONTINUE;
161 static BOOL CALLBACK check_object_count( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
163 DWORD *count = args;
164 *count = *count + 1;
165 return DIENUM_CONTINUE;
168 struct check_effects_params
170 UINT index;
171 UINT expect_count;
172 const DIEFFECTINFOW *expect_effects;
175 static BOOL CALLBACK check_effects( const DIEFFECTINFOW *effect, void *args )
177 static const DIEFFECTINFOW unexpected_effect = {0};
178 struct check_effects_params *params = args;
179 const DIEFFECTINFOW *exp = params->expect_effects + params->index;
181 winetest_push_context( "effect[%d]", params->index );
183 ok( params->index < params->expect_count, "unexpected extra object\n" );
184 if (params->index >= params->expect_count) exp = &unexpected_effect;
186 check_member( *effect, *exp, "%lu", dwSize );
187 check_member_guid( *effect, *exp, guid );
188 check_member( *effect, *exp, "%#lx", dwEffType );
189 check_member( *effect, *exp, "%#lx", dwStaticParams );
190 check_member( *effect, *exp, "%#lx", dwDynamicParams );
191 check_member_wstr( *effect, *exp, tszName );
193 winetest_pop_context();
194 params->index++;
196 return DIENUM_CONTINUE;
199 static BOOL CALLBACK check_effect_count( const DIEFFECTINFOW *effect, void *args )
201 DWORD *count = args;
202 *count = *count + 1;
203 return DIENUM_CONTINUE;
206 static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect, void *context )
208 ok( 0, "unexpected effect %p\n", effect );
209 return DIENUM_CONTINUE;
212 #define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b )
213 static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected )
215 check_member_( __FILE__, line, *actual, *expected, "%#Ix", uAppData );
216 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSemantic );
217 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwFlags );
218 if (actual->lptszActionName && expected->lptszActionName)
219 check_member_wstr_( __FILE__, line, *actual, *expected, lptszActionName );
220 else
221 check_member_( __FILE__, line, *actual, *expected, "%p", lptszActionName );
222 check_member_guid_( __FILE__, line, *actual, *expected, guidInstance );
223 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwObjID );
224 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwHow );
227 #define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b )
228 static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected )
230 DWORD i;
231 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSize );
232 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwActionSize );
233 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwDataSize );
234 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwNumActions );
235 for (i = 0; i < min( actual->dwNumActions, expected->dwNumActions ); ++i)
237 winetest_push_context( "action[%lu]", i );
238 check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i );
239 winetest_pop_context();
240 if (expected->dwActionSize != sizeof(DIACTIONW)) break;
241 if (actual->dwActionSize != sizeof(DIACTIONW)) break;
243 check_member_guid_( __FILE__, line, *actual, *expected, guidActionMap );
244 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwGenre );
245 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwBufferSize );
246 check_member_( __FILE__, line, *actual, *expected, "%+ld", lAxisMin );
247 check_member_( __FILE__, line, *actual, *expected, "%+ld", lAxisMax );
248 check_member_( __FILE__, line, *actual, *expected, "%p", hInstString );
249 check_member_( __FILE__, line, *actual, *expected, "%ld", ftTimeStamp.dwLowDateTime );
250 check_member_( __FILE__, line, *actual, *expected, "%ld", ftTimeStamp.dwHighDateTime );
251 todo_wine
252 check_member_( __FILE__, line, *actual, *expected, "%#lx", dwCRC );
253 check_member_wstr_( __FILE__, line, *actual, *expected, tszActionMap );
256 static BOOL CALLBACK enum_device_count( const DIDEVICEINSTANCEW *devinst, void *context )
258 DWORD *count = context;
259 *count = *count + 1;
260 return DIENUM_CONTINUE;
263 static void check_dinput_devices( DWORD version, DIDEVICEINSTANCEW *devinst )
265 DIPROPDWORD prop_dword =
267 .diph =
269 .dwSize = sizeof(DIPROPDWORD),
270 .dwHeaderSize = sizeof(DIPROPHEADER),
271 .dwHow = DIPH_DEVICE,
274 IDirectInputDevice8W *device;
275 IDirectInput8W *di8;
276 IDirectInputW *di;
277 ULONG ref, count;
278 HRESULT hr;
280 if (version >= 0x800)
282 hr = DirectInput8Create( instance, version, &IID_IDirectInput8W, (void **)&di8, NULL );
283 ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr );
285 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, NULL, NULL, DIEDFL_ALLDEVICES );
286 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
287 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, 0xdeadbeef );
288 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
289 hr = IDirectInput8_EnumDevices( di8, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
290 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
292 count = 0;
293 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, DIEDFL_ALLDEVICES );
294 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
295 ok( count == 3, "got count %lu, expected 0\n", count );
296 count = 0;
297 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
298 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
299 ok( count == 0, "got count %lu, expected 0\n", count );
300 count = 0;
301 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_POINTER, enum_device_count, &count,
302 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
303 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
304 todo_wine
305 ok( count == 3, "got count %lu, expected 3\n", count );
306 count = 0;
307 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_KEYBOARD, enum_device_count, &count,
308 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
309 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
310 todo_wine
311 ok( count == 3, "got count %lu, expected 3\n", count );
312 count = 0;
313 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_GAMECTRL, enum_device_count, &count,
314 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
315 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
316 ok( count == 1, "got count %lu, expected 1\n", count );
318 count = 0;
319 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
320 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
321 ok( count == 1, "got count %lu, expected 1\n", count );
323 count = 0;
324 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
325 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
326 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %lu, expected 0\n", count );
327 else ok( count == 1, "got count %lu, expected 1\n", count );
329 count = 0;
330 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff) + 1, enum_device_count, &count, DIEDFL_ALLDEVICES );
331 if ((devinst->dwDevType & 0xff) != DI8DEVTYPE_SUPPLEMENTAL) ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
332 else ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
333 ok( count == 0, "got count %lu, expected 0\n", count );
335 hr = IDirectInput8_CreateDevice( di8, &devinst->guidInstance, NULL, NULL );
336 ok( hr == E_POINTER, "CreateDevice returned %#lx\n", hr );
337 hr = IDirectInput8_CreateDevice( di8, NULL, &device, NULL );
338 ok( hr == E_POINTER, "CreateDevice returned %#lx\n", hr );
339 hr = IDirectInput8_CreateDevice( di8, &GUID_NULL, &device, NULL );
340 ok( hr == DIERR_DEVICENOTREG, "CreateDevice returned %#lx\n", hr );
342 hr = IDirectInput8_CreateDevice( di8, &devinst->guidInstance, &device, NULL );
343 ok( hr == DI_OK, "CreateDevice returned %#lx\n", hr );
345 prop_dword.dwData = 0xdeadbeef;
346 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
347 ok( hr == DI_OK, "GetProperty DIPROP_VIDPID returned %#lx\n", hr );
348 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#lx expected %#lx\n", prop_dword.dwData, EXPECT_VIDPID );
350 ref = IDirectInputDevice8_Release( device );
351 ok( ref == 0, "Release returned %ld\n", ref );
352 ref = IDirectInput8_Release( di8 );
353 ok( ref == 0, "Release returned %ld\n", ref );
355 else
357 hr = DirectInputCreateEx( instance, version, &IID_IDirectInput2W, (void **)&di, NULL );
358 ok( hr == DI_OK, "DirectInputCreateEx returned %#lx\n", hr );
360 hr = IDirectInput_EnumDevices( di, 0, NULL, NULL, DIEDFL_ALLDEVICES );
361 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
362 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, 0xdeadbeef );
363 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
364 hr = IDirectInput_EnumDevices( di, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
365 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
366 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_INCLUDEHIDDEN );
367 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
369 count = 0;
370 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_ALLDEVICES );
371 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
372 ok( count == 3, "got count %lu, expected 0\n", count );
373 count = 0;
374 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
375 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
376 ok( count == 0, "got count %lu, expected 0\n", count );
377 count = 0;
378 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_MOUSE, enum_device_count, &count,
379 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
380 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
381 todo_wine
382 ok( count == 3, "got count %lu, expected 3\n", count );
383 count = 0;
384 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_KEYBOARD, enum_device_count, &count,
385 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
386 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
387 todo_wine
388 ok( count == 3, "got count %lu, expected 3\n", count );
389 count = 0;
390 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_JOYSTICK, enum_device_count, &count,
391 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
392 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
393 ok( count == 1, "got count %lu, expected 1\n", count );
395 count = 0;
396 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
397 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
398 ok( count == 1, "got count %lu, expected 1\n", count );
400 count = 0;
401 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
402 ok( hr == DI_OK, "EnumDevices returned: %#lx\n", hr );
403 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %lu, expected 0\n", count );
404 else ok( count == 1, "got count %lu, expected 1\n", count );
406 hr = IDirectInput_EnumDevices( di, 0x14, enum_device_count, &count, DIEDFL_ALLDEVICES );
407 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#lx\n", hr );
408 ref = IDirectInput_Release( di );
409 ok( ref == 0, "Release returned %ld\n", ref );
413 static BOOL CALLBACK enum_devices_by_semantic( const DIDEVICEINSTANCEW *instance, IDirectInputDevice8W *device,
414 DWORD flags, DWORD remaining, void *context )
416 const DIDEVICEINSTANCEW expect_joystick =
418 .dwSize = sizeof(DIDEVICEINSTANCEW),
419 .guidInstance = expect_guid_product,
420 .guidProduct = expect_guid_product,
421 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK,
422 .tszInstanceName = L"Wine Test",
423 .tszProductName = L"Wine Test",
424 .wUsagePage = HID_USAGE_PAGE_GENERIC,
425 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
427 const DIDEVICEINSTANCEW expect_keyboard =
429 .dwSize = sizeof(DIDEVICEINSTANCEW),
430 .guidInstance = GUID_SysKeyboard,
431 .guidProduct = GUID_SysKeyboard,
432 .dwDevType = (DI8DEVTYPEKEYBOARD_PCENH << 8) | DI8DEVTYPE_KEYBOARD,
433 .tszInstanceName = L"Keyboard",
434 .tszProductName = L"Keyboard",
436 const DIDEVICEINSTANCEW expect_mouse =
438 .dwSize = sizeof(DIDEVICEINSTANCEW),
439 .guidInstance = GUID_SysMouse,
440 .guidProduct = GUID_SysMouse,
441 .dwDevType = (DI8DEVTYPEMOUSE_UNKNOWN << 8) | DI8DEVTYPE_MOUSE,
442 .tszInstanceName = L"Mouse",
443 .tszProductName = L"Mouse",
445 const DIDEVICEINSTANCEW *expect_instance = NULL;
447 ok( remaining <= 2, "got remaining %lu\n", remaining );
449 if (remaining == 2)
451 expect_instance = &expect_joystick;
452 ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags );
454 else if (remaining == 1)
456 expect_instance = &expect_keyboard;
457 ok( flags == 1, "got flags %#lx\n", flags );
459 else if (remaining == 0)
461 expect_instance = &expect_mouse;
462 ok( flags == 1, "got flags %#lx\n", flags );
465 check_member( *instance, *expect_instance, "%#lx", dwSize );
466 if (expect_instance != &expect_joystick) check_member_guid( *instance, *expect_instance, guidInstance );
467 check_member_guid( *instance, *expect_instance, guidProduct );
468 todo_wine_if( expect_instance == &expect_mouse )
469 check_member( *instance, *expect_instance, "%#lx", dwDevType );
470 if (!localized)
472 check_member_wstr( *instance, *expect_instance, tszInstanceName );
473 todo_wine_if( expect_instance != &expect_joystick )
474 check_member_wstr( *instance, *expect_instance, tszProductName );
476 check_member_guid( *instance, *expect_instance, guidFFDriver );
477 check_member( *instance, *expect_instance, "%#x", wUsagePage );
478 check_member( *instance, *expect_instance, "%#x", wUsage );
480 return DIENUM_CONTINUE;
483 static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE event )
485 const DIACTIONW expect_actions[] =
488 .dwSemantic = DIBUTTON_ANY( 1 ),
489 .guidInstance = expect_guid_product,
490 .dwHow = DIAH_DEFAULT,
491 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ),
494 .dwSemantic = DIBUTTON_ANY( 2 ),
495 .guidInstance = expect_guid_product,
496 .dwHow = DIAH_DEFAULT,
497 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 ),
500 .dwSemantic = DIAXIS_ANY_X_1,
503 .dwSemantic = DIPOV_ANY_1,
504 .guidInstance = expect_guid_product,
505 .dwHow = DIAH_DEFAULT,
506 .dwObjID = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ),
509 .dwSemantic = DIAXIS_DRIVINGR_ACCELERATE,
512 .dwSemantic = DIAXIS_ANY_Z_2,
513 .guidInstance = expect_guid_product,
514 .dwHow = DIAH_DEFAULT,
515 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ),
518 .dwSemantic = DIAXIS_ANY_4,
519 .guidInstance = expect_guid_product,
520 .dwHow = DIAH_DEFAULT,
521 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 ),
524 .dwSemantic = DIAXIS_DRIVINGR_STEER,
525 .guidInstance = expect_guid_product,
526 .dwHow = DIAH_DEFAULT,
527 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ),
530 .dwSemantic = DIAXIS_ANY_Y_1,
531 .guidInstance = expect_guid_product,
532 .dwHow = DIAH_DEFAULT,
533 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
536 .dwSemantic = DIMOUSE_WHEEL,
539 .dwSemantic = 0x81000410,
542 const DIACTIONW expect_actions_3[] =
545 .dwSemantic = DIAXIS_DRIVINGR_STEER,
546 .guidInstance = expect_guid_product,
547 .dwHow = DIAH_DEFAULT,
548 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ),
551 .dwSemantic = DIAXIS_ANY_Y_1,
552 .guidInstance = expect_guid_product,
553 .dwHow = DIAH_DEFAULT,
554 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
557 .dwSemantic = DIMOUSE_WHEEL,
558 .dwObjID = DIDFT_RELAXIS | DIDFT_MAKEINSTANCE( 2 ),
561 .dwSemantic = 0x81000410,
562 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0x10 ),
565 const DIACTIONW expect_actions_4[] =
568 .dwSemantic = DIAXIS_DRIVINGR_STEER,
569 .guidInstance = expect_guid_product,
570 .dwHow = DIAH_DEFAULT,
571 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ),
574 .dwSemantic = DIAXIS_ANY_Y_1,
575 .guidInstance = expect_guid_product,
576 .dwHow = DIAH_DEFAULT,
577 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
580 .dwSemantic = DIMOUSE_WHEEL,
581 .guidInstance = GUID_SysMouse,
582 .dwObjID = DIDFT_RELAXIS | DIDFT_MAKEINSTANCE( 2 ),
583 .dwHow = DIAH_DEFAULT,
586 .dwSemantic = 0x81000410,
587 .guidInstance = GUID_SysKeyboard,
588 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0x10 ),
589 .dwHow = DIAH_DEFAULT,
592 const DIACTIONW expect_filled_actions[ARRAY_SIZE(expect_actions)] =
595 .dwSemantic = DIBUTTON_ANY( 1 ),
596 .guidInstance = expect_guid_product,
597 .dwHow = DIAH_APPREQUESTED,
598 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 ),
599 .dwFlags = DIA_APPMAPPED,
600 .lptszActionName = L"Button 1",
601 .uAppData = 1,
604 .dwSemantic = DIBUTTON_ANY( 2 ),
605 .guidInstance = expect_guid_product,
606 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ),
607 .dwFlags = DIA_APPNOMAP,
608 .lptszActionName = L"Button 2",
609 .uAppData = 2,
612 .dwSemantic = DIAXIS_ANY_X_1,
613 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
614 .dwFlags = DIA_FORCEFEEDBACK,
615 .lptszActionName = L"Wheel",
616 .uAppData = 3,
619 .dwSemantic = DIPOV_ANY_1,
620 .guidInstance = expect_guid_product,
621 .dwHow = DIAH_APPREQUESTED,
622 .dwObjID = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ),
623 .dwFlags = DIA_APPMAPPED | DIA_APPFIXED,
624 .lptszActionName = L"POV",
625 .uAppData = 4,
628 .dwSemantic = DIAXIS_DRIVINGR_ACCELERATE,
629 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
630 .dwFlags = DIA_NORANGE,
631 .lptszActionName = L"Accelerate",
632 .uAppData = 5,
635 .dwSemantic = DIAXIS_ANY_Z_2,
636 .guidInstance = expect_guid_product,
637 .dwHow = DIAH_DEFAULT,
638 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ),
639 .dwFlags = DIA_APPFIXED,
640 .lptszActionName = L"Z",
641 .uAppData = 6,
644 .dwSemantic = DIAXIS_ANY_4,
645 .guidInstance = expect_guid_product,
646 .dwHow = DIAH_DEFAULT,
647 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 6 ),
648 .dwFlags = DIA_APPFIXED,
649 .lptszActionName = L"Axis 4",
650 .uAppData = 7,
653 .dwSemantic = DIAXIS_DRIVINGR_STEER,
654 .guidInstance = expect_guid_product,
655 .dwHow = DIAH_DEFAULT,
656 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ),
657 .lptszActionName = L"Steer",
658 .uAppData = 8,
661 .dwSemantic = DIAXIS_ANY_Y_1,
662 .guidInstance = expect_guid_product,
663 .dwHow = DIAH_DEFAULT,
664 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
665 .lptszActionName = L"Y Axis",
666 .uAppData = 9,
669 .dwSemantic = DIMOUSE_WHEEL,
670 .lptszActionName = L"Wheel",
671 .uAppData = 10,
674 .dwSemantic = 0x81000410,
675 .lptszActionName = L"Key",
676 .dwFlags = DIA_APPFIXED,
677 .uAppData = 11,
680 const DIACTIONFORMATW expect_action_format_1 =
682 .dwSize = sizeof(DIACTIONFORMATW),
683 .dwActionSize = sizeof(DIACTIONW),
684 .dwNumActions = 1,
685 .dwDataSize = 4,
686 .rgoAction = (DIACTIONW *)expect_actions,
687 .dwGenre = DIVIRTUAL_DRIVING_RACE,
688 .guidActionMap = GUID_action_mapping_1,
689 .dwCRC = 0x6cd1f698,
691 const DIACTIONFORMATW expect_action_format_2 =
693 .dwSize = sizeof(DIACTIONFORMATW),
694 .dwActionSize = sizeof(DIACTIONW),
695 .dwNumActions = ARRAY_SIZE(expect_actions),
696 .dwDataSize = 4 * ARRAY_SIZE(expect_actions),
697 .rgoAction = (DIACTIONW *)expect_actions,
698 .dwGenre = DIVIRTUAL_DRIVING_RACE,
699 .guidActionMap = GUID_action_mapping_2,
700 .dwCRC = 0x6981e1f7,
702 const DIACTIONFORMATW expect_action_format_3 =
704 .dwSize = sizeof(DIACTIONFORMATW),
705 .dwActionSize = sizeof(DIACTIONW),
706 .dwNumActions = ARRAY_SIZE(expect_actions_3),
707 .dwDataSize = 4 * ARRAY_SIZE(expect_actions_3),
708 .rgoAction = (DIACTIONW *)expect_actions_3,
709 .dwGenre = DIVIRTUAL_DRIVING_RACE,
710 .guidActionMap = GUID_action_mapping_2,
711 .dwCRC = 0xf8748d65,
713 const DIACTIONFORMATW expect_action_format_4 =
715 .dwSize = sizeof(DIACTIONFORMATW),
716 .dwActionSize = sizeof(DIACTIONW),
717 .dwNumActions = ARRAY_SIZE(expect_actions_4),
718 .dwDataSize = 4 * ARRAY_SIZE(expect_actions_4),
719 .rgoAction = (DIACTIONW *)expect_actions_4,
720 .dwGenre = DIVIRTUAL_DRIVING_RACE,
721 .guidActionMap = GUID_action_mapping_2,
722 .dwCRC = 0xf8748d65,
724 const DIACTIONFORMATW expect_action_format_2_filled =
726 .dwSize = sizeof(DIACTIONFORMATW),
727 .dwActionSize = sizeof(DIACTIONW),
728 .dwNumActions = ARRAY_SIZE(expect_actions),
729 .dwDataSize = 4 * ARRAY_SIZE(expect_actions),
730 .rgoAction = (DIACTIONW *)expect_filled_actions,
731 .dwGenre = DIVIRTUAL_DRIVING_RACE,
732 .guidActionMap = GUID_action_mapping_2,
733 .dwBufferSize = 32,
734 .lAxisMin = -128,
735 .lAxisMax = +128,
736 .tszActionMap = L"Action Map Filled",
737 .dwCRC = 0x5ebf86a6,
739 struct hid_expect injected_input[] =
742 .code = IOCTL_HID_READ_REPORT,
743 .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0},
746 .code = IOCTL_HID_READ_REPORT,
747 .report_buf = {1,0x10,0x10,0x38,0x38,0x10,0x10,0x10,0xf8},
750 .code = IOCTL_HID_READ_REPORT,
751 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
754 .code = IOCTL_HID_READ_REPORT,
755 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
758 .code = IOCTL_HID_READ_REPORT,
759 .report_buf = {1,0x10,0x10,0x80,0x80,0x10,0x10,0x10,0xff},
762 .code = IOCTL_HID_READ_REPORT,
763 .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54},
766 const DWORD expect_state[ARRAY_SIZE(injected_input)][ARRAY_SIZE(expect_actions)] =
768 { 0, 0, 0, -1, 0, 0, 0, 0},
769 { 0, 0, 0, -1, 0, 0, 0, 0},
770 {+128, 0, 0, +31500, 0, 0, 0, +128},
771 { 0, 0, 0, -1, 0, 0, 0, -43},
772 { 0, 0, 0, -1, 0, 0, 0, -43},
773 {+128, 0, 0, -1, 0, 0, 0, -128},
775 const DIDEVICEOBJECTDATA expect_objdata[11] =
777 {.dwOfs = 0x20, .dwData = +128, .uAppData = 9},
778 {.dwOfs = 0x1c, .dwData = +128, .uAppData = 8},
779 {.dwOfs = 0xc, .dwData = +31500, .uAppData = 4},
780 {.dwOfs = 0, .dwData = +128, .uAppData = 1},
781 {.dwOfs = 0x20, .dwData = -67, .uAppData = 9},
782 {.dwOfs = 0x1c, .dwData = -43, .uAppData = 8},
783 {.dwOfs = 0xc, .dwData = -1, .uAppData = 4},
784 {.dwOfs = 0, .dwData = 0, .uAppData = 1},
785 {.dwOfs = 0x20, .dwData = -128, .uAppData = 9},
786 {.dwOfs = 0x1c, .dwData = -128, .uAppData = 8},
787 {.dwOfs = 0, .dwData = +128, .uAppData = 1},
789 DIACTIONW voice_actions[] =
791 {.dwSemantic = DIVOICE_CHANNEL1},
793 DIACTIONFORMATW voice_action_format =
795 .dwSize = sizeof(DIACTIONFORMATW),
796 .dwActionSize = sizeof(*voice_actions),
797 .dwNumActions = 1,
798 .dwDataSize = 4,
799 .rgoAction = voice_actions,
800 .dwGenre = DIVIRTUAL_DRIVING_RACE,
801 .guidActionMap = GUID_action_mapping_1,
803 DIACTIONW default_actions[ARRAY_SIZE(expect_actions)] =
805 {.dwSemantic = DIBUTTON_ANY( 1 )},
806 {.dwSemantic = DIBUTTON_ANY( 2 )},
807 {.dwSemantic = DIAXIS_ANY_X_1},
808 {.dwSemantic = DIPOV_ANY_1},
809 {.dwSemantic = DIAXIS_DRIVINGR_ACCELERATE},
810 {.dwSemantic = DIAXIS_ANY_Z_2},
811 {.dwSemantic = DIAXIS_ANY_4},
812 {.dwSemantic = DIAXIS_DRIVINGR_STEER},
813 {.dwSemantic = DIAXIS_ANY_Y_1},
814 {.dwSemantic = DIMOUSE_WHEEL},
815 {.dwSemantic = 0x81000410},
817 DIACTIONFORMATW action_format_1 =
819 .dwSize = sizeof(DIACTIONFORMATW),
820 .dwActionSize = sizeof(*default_actions),
821 .dwNumActions = 1,
822 .dwDataSize = 4,
823 .rgoAction = default_actions,
824 .dwGenre = DIVIRTUAL_DRIVING_RACE,
825 .guidActionMap = GUID_action_mapping_1,
827 DIACTIONFORMATW action_format_2 =
829 .dwSize = sizeof(DIACTIONFORMATW),
830 .dwActionSize = sizeof(*default_actions),
831 .dwNumActions = ARRAY_SIZE(expect_actions),
832 .dwDataSize = 4 * ARRAY_SIZE(expect_actions),
833 .rgoAction = default_actions,
834 .dwGenre = DIVIRTUAL_DRIVING_RACE,
835 .guidActionMap = GUID_action_mapping_2,
837 DIACTIONFORMATW action_format_3 =
839 .dwSize = sizeof(DIACTIONFORMATW),
840 .dwActionSize = sizeof(*default_actions),
841 .dwNumActions = ARRAY_SIZE(expect_actions_3),
842 .dwDataSize = 4 * ARRAY_SIZE(expect_actions_3),
843 .rgoAction = default_actions,
844 .dwGenre = DIVIRTUAL_DRIVING_RACE,
845 .guidActionMap = GUID_action_mapping_2,
847 DIACTIONW filled_actions[ARRAY_SIZE(expect_actions)] =
850 .dwSemantic = DIBUTTON_ANY( 1 ),
851 .guidInstance = expect_guid_product,
852 .dwHow = DIAH_USERCONFIG,
853 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 ),
854 .dwFlags = DIA_APPMAPPED,
855 .lptszActionName = L"Button 1",
856 .uAppData = 1,
859 .dwSemantic = DIBUTTON_ANY( 2 ),
860 .guidInstance = expect_guid_product,
861 .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ),
862 .dwFlags = DIA_APPNOMAP,
863 .lptszActionName = L"Button 2",
864 .uAppData = 2,
867 .dwSemantic = DIAXIS_ANY_X_1,
868 .guidInstance = expect_guid_product,
869 .dwHow = DIAH_HWDEFAULT,
870 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
871 .dwFlags = DIA_FORCEFEEDBACK,
872 .lptszActionName = L"Wheel",
873 .uAppData = 3,
876 .dwSemantic = DIPOV_ANY_1,
877 .guidInstance = expect_guid_product,
878 .dwHow = DIAH_HWAPP,
879 .dwObjID = DIDFT_POV | DIDFT_MAKEINSTANCE( 0 ),
880 .dwFlags = DIA_APPMAPPED | DIA_APPFIXED,
881 .lptszActionName = L"POV",
882 .uAppData = 4,
885 .dwSemantic = DIAXIS_DRIVINGR_ACCELERATE,
886 .guidInstance = expect_guid_product,
887 .dwHow = DIAH_USERCONFIG,
888 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
889 .dwFlags = DIA_NORANGE,
890 .lptszActionName = L"Accelerate",
891 .uAppData = 5,
894 .dwSemantic = DIAXIS_ANY_Z_2,
895 .guidInstance = expect_guid_product,
896 .dwHow = DIAH_UNMAPPED,
897 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 ),
898 .dwFlags = DIA_APPFIXED,
899 .lptszActionName = L"Z",
900 .uAppData = 6,
903 .dwSemantic = DIAXIS_ANY_4,
904 .guidInstance = expect_guid_product,
905 .dwHow = DIAH_DEFAULT,
906 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 5 ),
907 .dwFlags = DIA_APPFIXED,
908 .lptszActionName = L"Axis 4",
909 .uAppData = 7,
912 .dwSemantic = DIAXIS_DRIVINGR_STEER,
913 .guidInstance = expect_guid_product,
914 .dwHow = DIAH_USERCONFIG,
915 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 4 ),
916 .lptszActionName = L"Steer",
917 .uAppData = 8,
920 .dwSemantic = DIAXIS_ANY_Y_1,
921 .guidInstance = expect_guid_product,
922 .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ),
923 .lptszActionName = L"Y Axis",
924 .uAppData = 9,
927 .dwSemantic = DIMOUSE_WHEEL,
928 .guidInstance = expect_guid_product,
929 .lptszActionName = L"Wheel",
930 .uAppData = 10,
933 .dwSemantic = 0x81000410,
934 .guidInstance = expect_guid_product,
935 .lptszActionName = L"Key",
936 .dwFlags = DIA_APPFIXED,
937 .uAppData = 11,
940 DIACTIONFORMATW action_format_2_filled =
942 .dwSize = sizeof(DIACTIONFORMATW),
943 .dwActionSize = sizeof(*default_actions),
944 .dwNumActions = ARRAY_SIZE(expect_actions),
945 .dwDataSize = 4 * ARRAY_SIZE(expect_actions),
946 .rgoAction = filled_actions,
947 .dwGenre = DIVIRTUAL_DRIVING_RACE,
948 .guidActionMap = GUID_action_mapping_2,
949 .dwBufferSize = 32,
950 .lAxisMin = -128,
951 .lAxisMax = +128,
952 .tszActionMap = L"Action Map Filled",
954 DIPROPRANGE prop_range =
956 .diph =
958 .dwHeaderSize = sizeof(DIPROPHEADER),
959 .dwSize = sizeof(DIPROPRANGE),
960 .dwHow = DIPH_DEVICE,
963 DIPROPDWORD prop_dword =
965 .diph =
967 .dwHeaderSize = sizeof(DIPROPHEADER),
968 .dwSize = sizeof(DIPROPDWORD),
969 .dwHow = DIPH_DEVICE,
972 DIPROPSTRING prop_username =
974 .diph =
976 .dwHeaderSize = sizeof(DIPROPHEADER),
977 .dwSize = sizeof(DIPROPSTRING),
978 .dwHow = DIPH_DEVICE,
981 DIPROPPOINTER prop_pointer =
983 .diph =
985 .dwHeaderSize = sizeof(DIPROPHEADER),
986 .dwSize = sizeof(DIPROPPOINTER),
989 DIDEVICEOBJECTDATA objdata[ARRAY_SIZE(expect_objdata)];
990 DIACTIONW actions[ARRAY_SIZE(expect_actions)];
991 DWORD state[ARRAY_SIZE(expect_actions)];
992 IDirectInputDevice8W *mouse, *keyboard;
993 DIACTIONFORMATW action_format;
994 IDirectInput8W *dinput;
995 WCHAR username[256];
996 DWORD i, res, flags;
997 HRESULT hr;
999 res = ARRAY_SIZE(username);
1000 GetUserNameW( username, &res );
1002 memset( prop_username.wsz, 0, sizeof(prop_username.wsz) );
1003 hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph );
1004 ok( hr == DI_NOEFFECT, "GetProperty returned %#lx\n", hr );
1005 ok( !wcscmp( prop_username.wsz, L"" ), "got username %s\n", debugstr_w(prop_username.wsz) );
1008 hr = IDirectInputDevice8_BuildActionMap( device, NULL, L"username", DIDBAM_DEFAULT );
1009 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1010 hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", 0xdeadbeef );
1011 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1012 flags = DIDBAM_HWDEFAULTS | DIDBAM_INITIALIZE;
1013 hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags );
1014 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1015 flags = DIDBAM_HWDEFAULTS | DIDBAM_PRESERVE;
1016 hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags );
1017 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1018 flags = DIDBAM_INITIALIZE | DIDBAM_PRESERVE;
1019 hr = IDirectInputDevice8_BuildActionMap( device, &action_format_1, L"username", flags );
1020 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1022 hr = IDirectInputDevice8_SetActionMap( device, NULL, NULL, DIDSAM_DEFAULT );
1023 ok( hr == DIERR_INVALIDPARAM, "SetActionMap returned %#lx\n", hr );
1024 flags = DIDSAM_FORCESAVE | DIDSAM_NOUSER;
1025 hr = IDirectInputDevice8_SetActionMap( device, &action_format_1, NULL, flags );
1026 ok( hr == DIERR_INVALIDPARAM, "SetActionMap returned %#lx\n", hr );
1029 /* action format with no suitable actions */
1031 hr = IDirectInputDevice8_BuildActionMap( device, &voice_action_format, NULL, DIDBAM_DEFAULT );
1032 ok( hr == DI_NOEFFECT, "BuildActionMap returned %#lx\n", hr );
1034 /* first SetActionMap call for a user always return DI_SETTINGSNOTSAVED */
1036 hr = IDirectInputDevice8_SetActionMap( device, &voice_action_format, NULL, DIDSAM_FORCESAVE );
1037 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1039 memset( prop_username.wsz, 0, sizeof(prop_username.wsz) );
1040 hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph );
1041 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1042 ok( !wcscmp( prop_username.wsz, username ), "got username %s\n", debugstr_w(prop_username.wsz) );
1044 hr = IDirectInputDevice8_SetActionMap( device, &voice_action_format, NULL, DIDSAM_DEFAULT );
1045 ok( hr == DI_NOEFFECT, "SetActionMap returned %#lx\n", hr );
1046 hr = IDirectInputDevice8_SetActionMap( device, &voice_action_format, NULL, DIDSAM_FORCESAVE );
1047 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1049 memset( prop_username.wsz, 0, sizeof(prop_username.wsz) );
1050 hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph );
1051 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1052 ok( !wcscmp( prop_username.wsz, username ), "got username %s\n", debugstr_w(prop_username.wsz) );
1055 action_format = action_format_1;
1056 action_format.rgoAction = actions;
1057 memset( actions, 0, sizeof(actions) );
1058 actions[0] = default_actions[0];
1059 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, NULL, DIDBAM_DEFAULT );
1060 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1061 check_diactionformatw( &action_format, &expect_action_format_1 );
1062 hr = IDirectInputDevice8_SetActionMap( device, &action_format, NULL, DIDSAM_DEFAULT );
1063 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1064 check_diactionformatw( &action_format, &expect_action_format_1 );
1067 action_format = action_format_1;
1068 action_format.rgoAction = actions;
1069 memset( actions, 0, sizeof(actions) );
1070 actions[0] = default_actions[0];
1071 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1072 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1073 check_diactionformatw( &action_format, &expect_action_format_1 );
1075 /* first SetActionMap call for a user always return DI_SETTINGSNOTSAVED */
1077 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1078 todo_wine
1079 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1080 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1081 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1083 /* same SetActionMap call returns DI_OK */
1085 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1086 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1088 /* DIDSAM_FORCESAVE always returns DI_SETTINGSNOTSAVED */
1090 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_FORCESAVE );
1091 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1092 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_FORCESAVE );
1093 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1094 check_diactionformatw( &action_format, &expect_action_format_1 );
1097 /* action format dwDataSize and dwNumActions have to match, actions require a dwSemantic */
1099 action_format = action_format_2;
1100 action_format.rgoAction = actions;
1101 memset( actions, 0, sizeof(actions) );
1102 actions[0] = default_actions[0];
1103 action_format.dwDataSize = 8;
1104 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1105 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1106 action_format.dwNumActions = 2;
1107 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1108 ok( hr == DIERR_INVALIDPARAM, "BuildActionMap returned %#lx\n", hr );
1109 action_format.dwNumActions = 1;
1110 action_format.dwDataSize = 4;
1113 action_format = action_format_2;
1114 action_format.rgoAction = actions;
1115 memcpy( actions, default_actions, sizeof(default_actions) );
1116 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1117 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1118 check_diactionformatw( &action_format, &expect_action_format_2 );
1120 action_format = action_format_2;
1121 action_format.rgoAction = actions;
1122 memcpy( actions, default_actions, sizeof(default_actions) );
1123 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE );
1124 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1125 check_diactionformatw( &action_format, &expect_action_format_2 );
1127 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1128 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1131 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
1132 prop_pointer.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1133 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1134 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1135 ok( prop_pointer.uData == 0, "got uData %#Ix\n", prop_pointer.uData );
1137 prop_range.diph.dwHow = DIPH_BYID;
1138 prop_range.diph.dwObj = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
1139 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1140 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1141 ok( prop_range.lMin == +1000, "got lMin %+ld\n", prop_range.lMin );
1142 ok( prop_range.lMax == +51000, "got lMax %+ld\n", prop_range.lMax );
1144 prop_range.diph.dwHow = DIPH_BYUSAGE;
1145 prop_range.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1146 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1147 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1148 ok( prop_range.lMin == -14000, "got lMin %+ld\n", prop_range.lMin );
1149 ok( prop_range.lMax == -4000, "got lMax %+ld\n", prop_range.lMax );
1151 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
1152 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1153 ok( prop_dword.dwData == 0, "got dwData %#lx\n", prop_dword.dwData );
1156 /* saving action map actually does nothing */
1158 action_format = action_format_2_filled;
1159 action_format.rgoAction = actions;
1160 memcpy( actions, filled_actions, sizeof(filled_actions) );
1161 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1162 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1163 check_diactionformatw( &action_format, &expect_action_format_2_filled );
1164 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1165 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1166 check_diactionformatw( &action_format, &expect_action_format_2_filled );
1167 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_FORCESAVE );
1168 ok( hr == DI_SETTINGSNOTSAVED, "SetActionMap returned %#lx\n", hr );
1169 check_diactionformatw( &action_format, &expect_action_format_2_filled );
1172 prop_pointer.diph.dwHow = DIPH_DEVICE;
1173 prop_pointer.diph.dwObj = 0;
1174 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1175 ok( hr == DIERR_UNSUPPORTED, "GetProperty returned %#lx\n", hr );
1177 prop_pointer.diph.dwHow = DIPH_BYID;
1178 prop_pointer.diph.dwObj = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 3 );
1179 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1180 ok( hr == DIERR_NOTFOUND, "GetProperty returned %#lx\n", hr );
1182 prop_pointer.diph.dwHow = DIPH_BYID;
1183 prop_pointer.diph.dwObj = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
1184 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1185 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1186 ok( prop_pointer.uData == 6, "got uData %#Ix\n", prop_pointer.uData );
1188 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
1189 prop_pointer.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1190 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1191 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1192 ok( prop_pointer.uData == 8, "got uData %#Ix\n", prop_pointer.uData );
1194 prop_range.diph.dwHow = DIPH_BYID;
1195 prop_range.diph.dwObj = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
1196 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1197 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1198 ok( prop_range.lMin == -128, "got lMin %+ld\n", prop_range.lMin );
1199 ok( prop_range.lMax == +128, "got lMax %+ld\n", prop_range.lMax );
1201 prop_range.diph.dwHow = DIPH_BYUSAGE;
1202 prop_range.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1203 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1204 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1205 ok( prop_range.lMin == -128, "got lMin %+ld\n", prop_range.lMin );
1206 ok( prop_range.lMax == +128, "got lMax %+ld\n", prop_range.lMax );
1208 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
1209 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1210 ok( prop_dword.dwData == 32, "got dwData %#lx\n", prop_dword.dwData );
1213 action_format = action_format_2;
1214 action_format.rgoAction = actions;
1215 memcpy( actions, default_actions, sizeof(default_actions) );
1216 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_HWDEFAULTS );
1217 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1218 check_diactionformatw( &action_format, &expect_action_format_2 );
1220 action_format = action_format_2;
1221 action_format.rgoAction = actions;
1222 memcpy( actions, default_actions, sizeof(default_actions) );
1223 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_INITIALIZE );
1224 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1225 check_diactionformatw( &action_format, &expect_action_format_2 );
1227 action_format = action_format_2;
1228 action_format.rgoAction = actions;
1229 memcpy( actions, default_actions, sizeof(default_actions) );
1230 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE );
1231 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1232 check_diactionformatw( &action_format, &expect_action_format_2 );
1235 hr = IDirectInputDevice8_Acquire( device );
1236 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
1238 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT );
1239 ok( hr == DIERR_ACQUIRED, "SetActionMap returned %#lx\n", hr );
1241 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
1242 res = WaitForSingleObject( event, 100 );
1243 if (res == WAIT_TIMEOUT) /* Acquire is asynchronous */
1245 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
1246 res = WaitForSingleObject( event, 100 );
1248 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
1250 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
1252 winetest_push_context( "state[%ld]", i );
1254 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), state );
1255 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
1256 ok( state[0] == expect_state[i][0], "got state[0] %+ld\n", state[0] );
1257 ok( state[1] == expect_state[i][1], "got state[1] %+ld\n", state[1] );
1258 ok( state[2] == expect_state[i][2], "got state[2] %+ld\n", state[2] );
1259 ok( state[3] == expect_state[i][3], "got state[3] %+ld\n", state[3] );
1260 ok( state[4] == expect_state[i][4], "got state[4] %+ld\n", state[4] );
1261 ok( state[5] == expect_state[i][5], "got state[5] %+ld\n", state[5] );
1262 ok( state[6] == expect_state[i][6], "got state[6] %+ld\n", state[6] );
1263 ok( state[7] == expect_state[i][7] ||
1264 broken(state[7] == -45 && expect_state[i][7] == -43) /* 32-bit rounding */,
1265 "got state[7] %+ld\n", state[7] );
1267 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
1269 res = WaitForSingleObject( event, 100 );
1270 if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
1271 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
1272 ResetEvent( event );
1273 winetest_pop_context();
1276 res = ARRAY_SIZE(objdata);
1277 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(*objdata), objdata, &res, DIGDD_PEEK );
1278 todo_wine
1279 ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#lx\n", hr );
1280 ok( res == ARRAY_SIZE(objdata), "got %lu expected %u\n", res, 8 );
1281 while (res--)
1283 winetest_push_context( "%lu", res );
1284 check_member( objdata[res], expect_objdata[res], "%#lx", dwOfs );
1285 ok( objdata[res].dwData == expect_objdata[res].dwData ||
1286 broken(objdata[res].dwData == -45 && expect_objdata[res].dwData == -43) /* 32-bit rounding */ ||
1287 broken(objdata[res].dwData == -71 && expect_objdata[res].dwData == -67) /* 32-bit rounding */,
1288 "got dwData %+ld\n", objdata[res].dwData );
1289 check_member( objdata[res], expect_objdata[res], "%#Ix", uAppData );
1290 winetest_pop_context();
1293 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1294 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1296 hr = IDirectInputDevice8_Unacquire( device );
1297 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
1300 /* setting the data format resets action map */
1302 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
1303 prop_pointer.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1304 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1305 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1306 ok( prop_pointer.uData == 8, "got uData %#Ix\n", prop_pointer.uData );
1308 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
1309 ok( hr == DI_OK, "SetDataFormat returned %#lx\n", hr );
1311 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
1312 prop_pointer.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1313 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
1314 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1315 ok( prop_pointer.uData == -1, "got uData %#Ix\n", prop_pointer.uData );
1317 prop_range.diph.dwHow = DIPH_BYID;
1318 prop_range.diph.dwObj = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 );
1319 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1320 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1321 ok( prop_range.lMin == -128, "got lMin %+ld\n", prop_range.lMin );
1322 ok( prop_range.lMax == +128, "got lMax %+ld\n", prop_range.lMax );
1324 prop_range.diph.dwHow = DIPH_BYUSAGE;
1325 prop_range.diph.dwObj = MAKELONG(HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC);
1326 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
1327 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1328 ok( prop_range.lMin == -128, "got lMin %+ld\n", prop_range.lMin );
1329 ok( prop_range.lMax == +128, "got lMax %+ld\n", prop_range.lMax );
1331 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
1332 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1333 ok( prop_dword.dwData == 32, "got dwData %#lx\n", prop_dword.dwData );
1336 /* DIDSAM_NOUSER flag clears the device user property */
1338 memset( prop_username.wsz, 0, sizeof(prop_username.wsz) );
1339 hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph );
1340 ok( hr == DI_OK, "GetProperty returned %#lx\n", hr );
1341 ok( !wcscmp( prop_username.wsz, L"username" ), "got username %s\n", debugstr_w(prop_username.wsz) );
1343 hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_NOUSER );
1344 ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
1346 memset( prop_username.wsz, 0, sizeof(prop_username.wsz) );
1347 hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph );
1348 ok( hr == DI_NOEFFECT, "GetProperty returned %#lx\n", hr );
1349 ok( !wcscmp( prop_username.wsz, L"" ), "got username %s\n", debugstr_w(prop_username.wsz) );
1352 /* test BuildActionMap with multiple devices and EnumDevicesBySemantics */
1354 hr = DirectInput8Create( instance, 0x800, &IID_IDirectInput8W, (void **)&dinput, NULL );
1355 ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr );
1357 hr = IDirectInput8_CreateDevice( dinput, &GUID_SysMouse, &mouse, NULL );
1358 ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr );
1359 hr = IDirectInput8_CreateDevice( dinput, &GUID_SysKeyboard, &keyboard, NULL );
1360 ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr );
1362 action_format = action_format_3;
1363 action_format.rgoAction = actions;
1364 memcpy( actions, default_actions + 7, sizeof(expect_actions_3) );
1365 hr = IDirectInputDevice8_BuildActionMap( mouse, &action_format, L"username", DIDBAM_DEFAULT );
1366 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1367 hr = IDirectInputDevice8_BuildActionMap( keyboard, &action_format, L"username", DIDBAM_DEFAULT );
1368 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1369 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT );
1370 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1371 check_diactionformatw( &action_format, &expect_action_format_3 );
1373 action_format = action_format_3;
1374 action_format.rgoAction = actions;
1375 memcpy( actions, default_actions + 7, sizeof(expect_actions_4) );
1376 hr = IDirectInputDevice8_BuildActionMap( mouse, &action_format, L"username", DIDBAM_PRESERVE );
1377 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1378 hr = IDirectInputDevice8_BuildActionMap( keyboard, &action_format, L"username", DIDBAM_PRESERVE );
1379 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1380 hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE );
1381 ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr );
1382 check_diactionformatw( &action_format, &expect_action_format_4 );
1384 IDirectInputDevice8_Release( keyboard );
1385 IDirectInputDevice8_Release( mouse );
1387 action_format = action_format_2;
1388 action_format.rgoAction = actions;
1389 memcpy( actions, default_actions, sizeof(default_actions) );
1390 hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, (void *)0xdeadbeef, 0 );
1391 ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr );
1393 action_format = action_format_3;
1394 action_format.rgoAction = actions;
1395 memcpy( actions, default_actions + 7, sizeof(expect_actions_4) );
1396 hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, (void *)0xdeadbeef, 0 );
1397 ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr );
1399 action_format = action_format_3;
1400 action_format.rgoAction = actions;
1401 memcpy( actions, default_actions + 9, 2 * sizeof(DIACTIONW) );
1402 action_format.dwNumActions = 2;
1403 action_format.dwDataSize = 8;
1404 hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, NULL, 0 );
1405 ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr );
1407 IDirectInput8_Release( dinput );
1410 static void test_simple_joystick( DWORD version )
1412 #include "psh_hid_macros.h"
1413 static const unsigned char report_desc[] =
1415 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
1416 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
1417 COLLECTION(1, Application),
1418 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
1419 COLLECTION(1, Report),
1420 REPORT_ID(1, 1),
1422 USAGE(1, HID_USAGE_GENERIC_WHEEL),
1423 USAGE(4, (0xff01u<<16)|(0x1234)),
1424 USAGE(1, HID_USAGE_GENERIC_X),
1425 USAGE(1, HID_USAGE_GENERIC_Y),
1426 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_RUDDER),
1427 USAGE(4, (HID_USAGE_PAGE_DIGITIZER<<16)|HID_USAGE_DIGITIZER_TIP_PRESSURE),
1428 USAGE(4, (HID_USAGE_PAGE_CONSUMER<<16)|HID_USAGE_CONSUMER_VOLUME),
1429 LOGICAL_MINIMUM(1, 0xe7),
1430 LOGICAL_MAXIMUM(1, 0x38),
1431 PHYSICAL_MINIMUM(1, 0xe7),
1432 PHYSICAL_MAXIMUM(1, 0x38),
1433 REPORT_SIZE(1, 8),
1434 REPORT_COUNT(1, 7),
1435 INPUT(1, Data|Var|Abs),
1437 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
1438 LOGICAL_MINIMUM(1, 1),
1439 LOGICAL_MAXIMUM(1, 8),
1440 PHYSICAL_MINIMUM(1, 0),
1441 PHYSICAL_MAXIMUM(1, 8),
1442 REPORT_SIZE(1, 4),
1443 REPORT_COUNT(1, 1),
1444 INPUT(1, Data|Var|Abs|Null),
1446 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
1447 USAGE_MINIMUM(1, 1),
1448 USAGE_MAXIMUM(1, 2),
1449 LOGICAL_MINIMUM(1, 0),
1450 LOGICAL_MAXIMUM(1, 1),
1451 PHYSICAL_MINIMUM(1, 0),
1452 PHYSICAL_MAXIMUM(1, 1),
1453 REPORT_SIZE(1, 1),
1454 REPORT_COUNT(1, 4),
1455 INPUT(1, Data|Var|Abs),
1456 END_COLLECTION,
1458 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
1459 USAGE(1, HID_USAGE_GENERIC_RZ),
1460 COLLECTION(1, Physical),
1461 END_COLLECTION,
1462 END_COLLECTION,
1464 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
1465 #include "pop_hid_macros.h"
1467 struct hid_device_desc desc =
1469 .use_report_id = TRUE,
1470 .caps = { .InputReportByteLength = 9 },
1471 .attributes = default_attributes,
1473 const DIDEVCAPS expect_caps =
1475 .dwSize = sizeof(DIDEVCAPS),
1476 .dwFlags = DIDC_ATTACHED | DIDC_EMULATED,
1477 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
1478 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_RUDDER << 8) | DIDEVTYPE_JOYSTICK,
1479 .dwAxes = 6,
1480 .dwPOVs = 1,
1481 .dwButtons = 2,
1483 struct hid_expect injected_input[] =
1486 .code = IOCTL_HID_READ_REPORT,
1487 .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0},
1490 .code = IOCTL_HID_READ_REPORT,
1491 .report_buf = {1,0x10,0x10,0x38,0x38,0x10,0x10,0x10,0xf8},
1494 .code = IOCTL_HID_READ_REPORT,
1495 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
1498 .code = IOCTL_HID_READ_REPORT,
1499 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
1502 .code = IOCTL_HID_READ_REPORT,
1503 .report_buf = {1,0x10,0x10,0x80,0x80,0x10,0x10,0x10,0xff},
1506 .code = IOCTL_HID_READ_REPORT,
1507 .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54},
1510 static const struct DIJOYSTATE2 expect_state[] =
1512 {.lX = 32767, .lY = 32767, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1513 {.lX = 32767, .lY = 32767, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1514 {.lX = 65535, .lY = 65535, .lZ = 32767, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1515 {.lX = 20779, .lY = 20779, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1516 {.lX = 20779, .lY = 20779, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1517 {.lX = 0, .lY = 0, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1518 {.lX = 32767, .lY = 5594, .lZ = 32767, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
1520 static const struct DIJOYSTATE2 expect_state_abs[] =
1522 {.lX = -9000, .lY = 26000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1523 {.lX = -9000, .lY = 26000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1524 {.lX = -4000, .lY = 51000, .lZ = 26000, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1525 {.lX = -10667, .lY = 12905, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1526 {.lX = -10667, .lY = 12905, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1527 {.lX = -14000, .lY = 1000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1528 {.lX = -9000, .lY = 1000, .lZ = 26000, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
1530 static const struct DIJOYSTATE2 expect_state_rel[] =
1532 {.lX = 0, .lY = 0, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80, 0}},
1533 {.lX = 9016, .lY = -984, .lZ = -25984, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1534 {.lX = 40, .lY = 40, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1535 {.lX = -55, .lY = -55, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1536 {.lX = 0, .lY = 0, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
1537 {.lX = -129, .lY = -129, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
1538 {.lX = 144, .lY = 110, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
1540 static const DIDEVICEOBJECTDATA expect_objdata[] =
1542 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
1543 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
1544 {.dwOfs = 0, .dwData = 0xffff, .dwSequence = 0xa},
1545 {.dwOfs = 0x20, .dwData = 31500, .dwSequence = 0xa},
1546 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xa},
1547 {.dwOfs = 0x4, .dwData = 0x512b, .dwSequence = 0xd},
1548 {.dwOfs = 0, .dwData = 0x512b, .dwSequence = 0xd},
1549 {.dwOfs = 0x20, .dwData = -1, .dwSequence = 0xd},
1550 {.dwOfs = 0x30, .dwData = 0, .dwSequence = 0xd},
1551 {.dwOfs = 0x31, .dwData = 0, .dwSequence = 0xd},
1552 {.dwOfs = 0x4, .dwData = 0, .dwSequence = 0xf},
1553 {.dwOfs = 0, .dwData = 0, .dwSequence = 0xf},
1554 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xf},
1555 {.dwOfs = 0x31, .dwData = 0x80, .dwSequence = 0xf},
1558 const DIDEVICEINSTANCEW expect_devinst =
1560 .dwSize = sizeof(DIDEVICEINSTANCEW),
1561 .guidInstance = expect_guid_product,
1562 .guidProduct = expect_guid_product,
1563 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
1564 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_RUDDER << 8) | DIDEVTYPE_JOYSTICK,
1565 .tszInstanceName = L"Wine Test",
1566 .tszProductName = L"Wine Test",
1567 .guidFFDriver = GUID_NULL,
1568 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1569 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
1571 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
1574 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1575 .guidType = GUID_Unknown,
1576 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(6),
1577 .tszName = L"Volume",
1578 .wCollectionNumber = 1,
1579 .wUsagePage = HID_USAGE_PAGE_CONSUMER,
1580 .wUsage = HID_USAGE_CONSUMER_VOLUME,
1581 .wReportId = 1,
1584 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1585 .guidType = GUID_Unknown,
1586 .dwOfs = 0x4,
1587 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(7),
1588 .tszName = L"Tip Pressure",
1589 .wCollectionNumber = 1,
1590 .wUsagePage = HID_USAGE_PAGE_DIGITIZER,
1591 .wUsage = HID_USAGE_DIGITIZER_TIP_PRESSURE,
1592 .wReportId = 1,
1595 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1596 .guidType = GUID_RzAxis,
1597 .dwOfs = 0x8,
1598 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5),
1599 .dwFlags = DIDOI_ASPECTPOSITION,
1600 .tszName = L"Rudder",
1601 .wCollectionNumber = 1,
1602 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
1603 .wUsage = HID_USAGE_SIMULATION_RUDDER,
1604 .wReportId = 1,
1607 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1608 .guidType = GUID_YAxis,
1609 .dwOfs = 0xc,
1610 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
1611 .dwFlags = DIDOI_ASPECTPOSITION,
1612 .tszName = L"Y Axis",
1613 .wCollectionNumber = 1,
1614 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1615 .wUsage = HID_USAGE_GENERIC_Y,
1616 .wReportId = 1,
1619 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1620 .guidType = GUID_XAxis,
1621 .dwOfs = 0x10,
1622 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
1623 .dwFlags = DIDOI_ASPECTPOSITION,
1624 .tszName = L"X Axis",
1625 .wCollectionNumber = 1,
1626 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1627 .wUsage = HID_USAGE_GENERIC_X,
1628 .wReportId = 1,
1631 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1632 .guidType = GUID_ZAxis,
1633 .dwOfs = 0x18,
1634 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2),
1635 .dwFlags = DIDOI_ASPECTPOSITION,
1636 .tszName = L"Wheel",
1637 .wCollectionNumber = 1,
1638 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1639 .wUsage = HID_USAGE_GENERIC_WHEEL,
1640 .wReportId = 1,
1643 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1644 .guidType = GUID_POV,
1645 .dwOfs = 0x1c,
1646 .dwType = DIDFT_POV|DIDFT_MAKEINSTANCE(0),
1647 .tszName = L"Hat Switch",
1648 .wCollectionNumber = 1,
1649 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1650 .wUsage = HID_USAGE_GENERIC_HATSWITCH,
1651 .wReportId = 1,
1654 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1655 .guidType = GUID_Button,
1656 .dwOfs = 0x20,
1657 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0),
1658 .tszName = L"Button 0",
1659 .wCollectionNumber = 1,
1660 .wUsagePage = HID_USAGE_PAGE_BUTTON,
1661 .wUsage = 0x1,
1662 .wReportId = 1,
1665 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1666 .guidType = GUID_Button,
1667 .dwOfs = 0x21,
1668 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1),
1669 .tszName = L"Button 1",
1670 .wCollectionNumber = 1,
1671 .wUsagePage = HID_USAGE_PAGE_BUTTON,
1672 .wUsage = 0x2,
1673 .wReportId = 1,
1676 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1677 .guidType = GUID_Unknown,
1678 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
1679 .tszName = L"Collection 0 - Joystick",
1680 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1681 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
1684 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1685 .guidType = GUID_Unknown,
1686 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
1687 .tszName = L"Collection 1 - Joystick",
1688 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1689 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
1692 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1693 .guidType = GUID_Unknown,
1694 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(2),
1695 .tszName = L"Collection 2 - Z Rotation",
1696 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1697 .wUsage = HID_USAGE_GENERIC_RZ,
1700 const DIDEVICEOBJECTINSTANCEW expect_objects_5[] =
1703 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1704 .guidType = GUID_XAxis,
1705 .dwOfs = DIJOFS_X,
1706 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
1707 .dwFlags = DIDOI_ASPECTPOSITION,
1708 .tszName = L"X Axis",
1709 .wCollectionNumber = 1,
1710 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1711 .wUsage = HID_USAGE_GENERIC_X,
1712 .wReportId = 1,
1715 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1716 .guidType = GUID_YAxis,
1717 .dwOfs = DIJOFS_Y,
1718 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
1719 .dwFlags = DIDOI_ASPECTPOSITION,
1720 .tszName = L"Y Axis",
1721 .wCollectionNumber = 1,
1722 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1723 .wUsage = HID_USAGE_GENERIC_Y,
1724 .wReportId = 1,
1727 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1728 .guidType = GUID_ZAxis,
1729 .dwOfs = DIJOFS_Z,
1730 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2),
1731 .dwFlags = DIDOI_ASPECTPOSITION,
1732 .tszName = L"Wheel",
1733 .wCollectionNumber = 1,
1734 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1735 .wUsage = HID_USAGE_GENERIC_WHEEL,
1736 .wReportId = 1,
1739 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1740 .guidType = GUID_RzAxis,
1741 .dwOfs = DIJOFS_RZ,
1742 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5),
1743 .dwFlags = DIDOI_ASPECTPOSITION,
1744 .tszName = L"Rudder",
1745 .wCollectionNumber = 1,
1746 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
1747 .wUsage = HID_USAGE_SIMULATION_RUDDER,
1748 .wReportId = 1,
1751 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1752 .guidType = GUID_POV,
1753 .dwOfs = DIJOFS_POV(0),
1754 .dwType = DIDFT_POV|DIDFT_MAKEINSTANCE(0),
1755 .tszName = L"Hat Switch",
1756 .wCollectionNumber = 1,
1757 .wUsagePage = HID_USAGE_PAGE_GENERIC,
1758 .wUsage = HID_USAGE_GENERIC_HATSWITCH,
1759 .wReportId = 1,
1762 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1763 .guidType = GUID_Button,
1764 .dwOfs = DIJOFS_BUTTON(0),
1765 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0),
1766 .tszName = L"Button 0",
1767 .wCollectionNumber = 1,
1768 .wUsagePage = HID_USAGE_PAGE_BUTTON,
1769 .wUsage = 0x1,
1770 .wReportId = 1,
1773 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
1774 .guidType = GUID_Button,
1775 .dwOfs = DIJOFS_BUTTON(1),
1776 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1),
1777 .tszName = L"Button 1",
1778 .wCollectionNumber = 1,
1779 .wUsagePage = HID_USAGE_PAGE_BUTTON,
1780 .wUsage = 0x2,
1781 .wReportId = 1,
1784 struct check_object_todo todo_objects_5[ARRAY_SIZE(expect_objects_5)] =
1786 {.guid = TRUE, .type = TRUE, .flags = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1787 {.guid = TRUE, .type = TRUE, .flags = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1788 {.guid = TRUE, .type = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1789 {.guid = TRUE, .ofs = TRUE, .type = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1790 {.guid = TRUE, .ofs = TRUE, .type = TRUE, .flags = TRUE, .usage = TRUE, .name = TRUE},
1791 {.guid = TRUE, .ofs = TRUE, .type = TRUE, .flags = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1792 {.guid = TRUE, .ofs = TRUE, .type = TRUE, .usage = TRUE, .usage_page = TRUE, .name = TRUE},
1794 struct check_object_todo todo_ofs = {.ofs = TRUE};
1795 struct check_objects_params check_objects_params =
1797 .version = version,
1798 .expect_count = version < 0x700 ? ARRAY_SIZE(expect_objects_5) : ARRAY_SIZE(expect_objects),
1799 .expect_objs = version < 0x700 ? expect_objects_5 : expect_objects,
1800 .todo_objs = version < 0x700 ? todo_objects_5 : NULL,
1801 .todo_extra = version < 0x700,
1804 const DIEFFECTINFOW expect_effects[] = {};
1805 struct check_effects_params check_effects_params =
1807 .expect_count = ARRAY_SIZE(expect_effects),
1808 .expect_effects = expect_effects,
1810 DIPROPGUIDANDPATH prop_guid_path =
1812 .diph =
1814 .dwSize = sizeof(DIPROPGUIDANDPATH),
1815 .dwHeaderSize = sizeof(DIPROPHEADER),
1816 .dwHow = DIPH_DEVICE,
1819 DIPROPSTRING prop_string =
1821 .diph =
1823 .dwSize = sizeof(DIPROPSTRING),
1824 .dwHeaderSize = sizeof(DIPROPHEADER),
1825 .dwHow = DIPH_DEVICE,
1828 DIPROPDWORD prop_dword =
1830 .diph =
1832 .dwSize = sizeof(DIPROPDWORD),
1833 .dwHeaderSize = sizeof(DIPROPHEADER),
1834 .dwHow = DIPH_DEVICE,
1837 DIPROPRANGE prop_range =
1839 .diph =
1841 .dwSize = sizeof(DIPROPRANGE),
1842 .dwHeaderSize = sizeof(DIPROPHEADER),
1843 .dwHow = DIPH_DEVICE,
1846 DIPROPPOINTER prop_pointer =
1848 .diph =
1850 .dwSize = sizeof(DIPROPPOINTER),
1851 .dwHeaderSize = sizeof(DIPROPHEADER),
1854 DIOBJECTDATAFORMAT objdataformat[32] = {{0}};
1855 DIDEVICEOBJECTDATA objdata[32] = {{0}};
1856 DIDEVICEOBJECTINSTANCEW objinst = {0};
1857 DIDEVICEOBJECTINSTANCEW expect_obj;
1858 DIDEVICEINSTANCEW devinst = {0};
1859 DIEFFECTINFOW effectinfo = {0};
1860 DIDATAFORMAT dataformat = {0};
1861 IDirectInputDevice8W *device;
1862 IDirectInputEffect *effect;
1863 DIEFFESCAPE escape = {0};
1864 ULONG i, size, res, ref;
1865 DIDEVCAPS caps = {0};
1866 HANDLE event, file;
1867 char buffer[1024];
1868 DIJOYSTATE2 state;
1869 HRESULT hr;
1870 GUID guid;
1871 HWND hwnd;
1873 winetest_push_context( "%#lx", version );
1875 cleanup_registry_keys();
1877 desc.report_descriptor_len = sizeof(report_desc);
1878 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
1879 fill_context( desc.context, ARRAY_SIZE(desc.context) );
1881 if (!hid_device_start( &desc, 1 )) goto done;
1882 if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done;
1884 check_dinput_devices( version, &devinst );
1886 hr = IDirectInputDevice8_Initialize( device, instance, 0x800 - (version - 0x700), &GUID_NULL );
1887 if (version == 0x800)
1889 todo_wine
1890 ok( hr == DIERR_BETADIRECTINPUTVERSION, "Initialize returned %#lx\n", hr );
1892 else
1894 todo_wine
1895 ok( hr == DIERR_OLDDIRECTINPUTVERSION, "Initialize returned %#lx\n", hr );
1897 hr = IDirectInputDevice8_Initialize( device, instance, version, NULL );
1898 todo_wine
1899 ok( hr == E_POINTER, "Initialize returned %#lx\n", hr );
1900 hr = IDirectInputDevice8_Initialize( device, NULL, version, &GUID_NULL );
1901 todo_wine
1902 ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#lx\n", hr );
1903 hr = IDirectInputDevice8_Initialize( device, instance, version, &GUID_NULL );
1904 todo_wine
1905 ok( hr == REGDB_E_CLASSNOTREG, "Initialize returned %#lx\n", hr );
1907 hr = IDirectInputDevice8_Initialize( device, instance, version, &devinst.guidInstance );
1908 ok( hr == DI_OK, "Initialize returned %#lx\n", hr );
1909 guid = devinst.guidInstance;
1910 memset( &devinst, 0, sizeof(devinst) );
1911 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
1912 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
1913 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
1914 ok( IsEqualGUID( &guid, &devinst.guidInstance ), "got %s expected %s\n", debugstr_guid( &guid ),
1915 debugstr_guid( &devinst.guidInstance ) );
1916 hr = IDirectInputDevice8_Initialize( device, instance, version, &devinst.guidProduct );
1917 ok( hr == DI_OK, "Initialize returned %#lx\n", hr );
1919 hr = IDirectInputDevice8_GetDeviceInfo( device, NULL );
1920 ok( hr == E_POINTER, "GetDeviceInfo returned %#lx\n", hr );
1921 devinst.dwSize = sizeof(DIDEVICEINSTANCEW) + 1;
1922 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
1923 ok( hr == DIERR_INVALIDPARAM, "GetDeviceInfo returned %#lx\n", hr );
1925 devinst.dwSize = sizeof(DIDEVICEINSTANCE_DX3W);
1926 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
1927 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
1928 todo_wine
1929 check_member_guid( devinst, expect_devinst, guidInstance );
1930 check_member_guid( devinst, expect_devinst, guidProduct );
1931 todo_wine_if( version < 0x0800 )
1932 check_member( devinst, expect_devinst, "%#lx", dwDevType );
1933 check_member_wstr( devinst, expect_devinst, tszInstanceName );
1934 check_member_wstr( devinst, expect_devinst, tszProductName );
1936 memset( &devinst, 0, sizeof(devinst) );
1937 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
1938 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
1939 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
1940 check_member( devinst, expect_devinst, "%lu", dwSize );
1941 todo_wine
1942 check_member_guid( devinst, expect_devinst, guidInstance );
1943 check_member_guid( devinst, expect_devinst, guidProduct );
1944 todo_wine_if( version < 0x0800 )
1945 check_member( devinst, expect_devinst, "%#lx", dwDevType );
1946 check_member_wstr( devinst, expect_devinst, tszInstanceName );
1947 check_member_wstr( devinst, expect_devinst, tszProductName );
1948 check_member_guid( devinst, expect_devinst, guidFFDriver );
1949 check_member( devinst, expect_devinst, "%04x", wUsagePage );
1950 check_member( devinst, expect_devinst, "%04x", wUsage );
1952 hr = IDirectInputDevice8_GetCapabilities( device, NULL );
1953 ok( hr == E_POINTER, "GetCapabilities returned %#lx\n", hr );
1954 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
1955 ok( hr == DIERR_INVALIDPARAM, "GetCapabilities returned %#lx\n", hr );
1956 caps.dwSize = sizeof(DIDEVCAPS);
1957 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
1958 ok( hr == DI_OK, "GetCapabilities returned %#lx\n", hr );
1959 check_member( caps, expect_caps, "%lu", dwSize );
1960 check_member( caps, expect_caps, "%#lx", dwFlags );
1961 todo_wine_if( version < 0x0800 )
1962 check_member( caps, expect_caps, "%#lx", dwDevType );
1963 check_member( caps, expect_caps, "%lu", dwAxes );
1964 check_member( caps, expect_caps, "%lu", dwButtons );
1965 check_member( caps, expect_caps, "%lu", dwPOVs );
1966 check_member( caps, expect_caps, "%lu", dwFFSamplePeriod );
1967 check_member( caps, expect_caps, "%lu", dwFFMinTimeResolution );
1968 check_member( caps, expect_caps, "%lu", dwFirmwareRevision );
1969 check_member( caps, expect_caps, "%lu", dwHardwareRevision );
1970 check_member( caps, expect_caps, "%lu", dwFFDriverVersion );
1972 hr = IDirectInputDevice8_GetProperty( device, NULL, NULL );
1973 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#lx\n", hr );
1974 hr = IDirectInputDevice8_GetProperty( device, &GUID_NULL, NULL );
1975 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#lx\n", hr );
1976 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, NULL );
1977 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#lx\n", hr );
1978 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_string.diph );
1979 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_INVALIDPARAM),
1980 "GetProperty DIPROP_VIDPID returned %#lx\n", hr );
1981 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER) - 1;
1982 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
1983 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#lx\n", hr );
1984 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
1986 prop_dword.dwData = 0xdeadbeef;
1987 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
1988 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
1989 "GetProperty DIPROP_VIDPID returned %#lx\n", hr );
1990 if (hr == DI_OK)
1992 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#lx expected %#lx\n",
1993 prop_dword.dwData, EXPECT_VIDPID );
1996 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
1997 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
1998 ok( IsEqualGUID( &prop_guid_path.guidClass, &GUID_DEVCLASS_HIDCLASS ), "got guid %s\n",
1999 debugstr_guid( &prop_guid_path.guidClass ) );
2000 todo_wine
2001 ok( !wcsncmp( prop_guid_path.wszPath, expect_path, wcslen( expect_path ) ), "got path %s\n",
2002 debugstr_w(prop_guid_path.wszPath) );
2003 todo_wine
2004 ok( !wcscmp( wcsrchr( prop_guid_path.wszPath, '&' ), expect_path_end ), "got path %s\n",
2005 debugstr_w(prop_guid_path.wszPath) );
2007 hr = IDirectInputDevice8_GetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
2008 ok( hr == DI_OK, "GetProperty DIPROP_INSTANCENAME returned %#lx\n", hr );
2009 ok( !wcscmp( prop_string.wsz, expect_devinst.tszInstanceName ), "got instance %s\n",
2010 debugstr_w(prop_string.wsz) );
2011 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
2012 ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
2013 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
2014 debugstr_w(prop_string.wsz) );
2015 hr = IDirectInputDevice8_GetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
2016 todo_wine_if( version >= 0x0800 )
2017 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2018 "GetProperty DIPROP_TYPENAME returned %#lx\n", hr );
2019 if (hr == DI_OK)
2021 todo_wine
2022 ok( !wcscmp( prop_string.wsz, expect_vidpid_str ), "got type %s\n", debugstr_w(prop_string.wsz) );
2024 hr = IDirectInputDevice8_GetProperty( device, DIPROP_USERNAME, &prop_string.diph );
2025 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_NOEFFECT),
2026 "GetProperty DIPROP_USERNAME returned %#lx\n", hr );
2027 if (hr == DI_NOEFFECT)
2029 todo_wine
2030 ok( !wcscmp( prop_string.wsz, L"" ), "got user %s\n", debugstr_w(prop_string.wsz) );
2033 prop_dword.dwData = 0xdeadbeef;
2034 hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
2035 ok( hr == DI_OK, "GetProperty DIPROP_JOYSTICKID returned %#lx\n", hr );
2036 todo_wine
2037 ok( prop_dword.dwData == 0, "got %#lx expected 0\n", prop_dword.dwData );
2039 prop_dword.dwData = 0xdeadbeef;
2040 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
2041 todo_wine
2042 ok( hr == DI_OK, "GetProperty DIPROP_AXISMODE returned %#lx\n", hr );
2043 todo_wine
2044 ok( prop_dword.dwData == DIPROPAXISMODE_ABS, "got %lu expected %u\n", prop_dword.dwData, DIPROPAXISMODE_ABS );
2045 prop_dword.dwData = 0xdeadbeef;
2046 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2047 ok( hr == DI_OK, "GetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2048 ok( prop_dword.dwData == 0, "got %#lx expected %#x\n", prop_dword.dwData, 0 );
2049 prop_dword.dwData = 0xdeadbeef;
2050 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2051 ok( hr == DI_OK, "GetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2052 ok( prop_dword.dwData == 10000, "got %lu expected %u\n", prop_dword.dwData, 10000 );
2054 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
2055 ok( hr == DIERR_INVALIDPARAM, "GetProperty DIPROP_CALIBRATION returned %#lx\n", hr );
2056 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2057 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2058 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2059 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2060 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2061 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_FFLOAD returned %#lx\n", hr );
2062 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
2063 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_GRANULARITY returned %#lx\n", hr );
2064 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2065 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_SATURATION returned %#lx\n", hr );
2066 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2067 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2068 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2069 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2070 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
2071 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_INVALIDPARAM),
2072 "GetProperty DIPROP_KEYNAME returned %#lx\n", hr );
2073 hr = IDirectInputDevice8_GetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
2074 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_LOGICALRANGE returned %#lx\n", hr );
2075 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
2076 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_PHYSICALRANGE returned %#lx\n", hr );
2078 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2079 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2080 prop_dword.dwData = 0xdeadbeef;
2081 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2082 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2083 ok( prop_dword.dwData == 0, "got %lu expected %u\n", prop_dword.dwData, 0 );
2084 prop_dword.dwData = 0xdeadbeef;
2085 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
2086 ok( hr == DI_OK, "GetProperty DIPROP_GRANULARITY returned %#lx\n", hr );
2087 ok( prop_dword.dwData == 1, "got %lu expected %u\n", prop_dword.dwData, 1 );
2088 prop_dword.dwData = 0xdeadbeef;
2089 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2090 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#lx\n", hr );
2091 ok( prop_dword.dwData == 10000, "got %lu expected %u\n", prop_dword.dwData, 10000 );
2092 prop_dword.dwData = 0xdeadbeef;
2093 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2094 ok( hr == DI_OK, "GetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2095 ok( prop_dword.dwData == DIPROPCALIBRATIONMODE_COOKED, "got %lu expected %u\n",
2096 prop_dword.dwData, DIPROPCALIBRATIONMODE_COOKED );
2098 prop_string.diph.dwHow = DIPH_BYUSAGE;
2099 prop_string.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2100 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
2101 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2102 "GetProperty DIPROP_KEYNAME returned %#lx\n", hr );
2103 if (hr == DI_OK)
2105 ok( !wcscmp( prop_string.wsz, expect_objects[4].tszName ), "got DIPROP_KEYNAME %s\n",
2106 debugstr_w(prop_string.wsz) );
2108 prop_string.diph.dwObj = MAKELONG( 0x1, HID_USAGE_PAGE_BUTTON );
2109 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
2110 todo_wine
2111 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_KEYNAME returned %#lx\n", hr );
2112 prop_string.diph.dwHow = DIPH_BYUSAGE;
2113 prop_string.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2114 hr = IDirectInputDevice8_SetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
2115 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_KEYNAME returned %#lx\n", hr );
2117 prop_range.diph.dwHow = DIPH_BYUSAGE;
2118 prop_range.diph.dwObj = MAKELONG( 0, 0 );
2119 prop_range.lMin = 0xdeadbeef;
2120 prop_range.lMax = 0xdeadbeef;
2121 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2122 todo_wine_if( version < 0x0800 )
2123 ok( hr == (version < 0x0800 ? DI_OK : DIERR_NOTFOUND),
2124 "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2125 prop_range.diph.dwObj = MAKELONG( 0, HID_USAGE_PAGE_GENERIC );
2126 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2127 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2128 prop_range.diph.dwObj = MAKELONG( HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X );
2129 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2130 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2131 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2132 prop_range.lMin = 0xdeadbeef;
2133 prop_range.lMax = 0xdeadbeef;
2134 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2135 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2136 ok( prop_range.lMin == 0, "got %ld expected %d\n", prop_range.lMin, 0 );
2137 ok( prop_range.lMax == 65535, "got %ld expected %d\n", prop_range.lMax, 65535 );
2138 hr = IDirectInputDevice8_GetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
2139 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2140 "GetProperty DIPROP_LOGICALRANGE returned %#lx\n", hr );
2141 if (hr == DI_OK)
2143 ok( prop_range.lMin == -25, "got %ld expected %d\n", prop_range.lMin, -25 );
2144 ok( prop_range.lMax == 56, "got %ld expected %d\n", prop_range.lMax, 56 );
2146 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
2147 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2148 "GetProperty DIPROP_PHYSICALRANGE returned %#lx\n", hr );
2149 if (hr == DI_OK)
2151 ok( prop_range.lMin == -25, "got %ld expected %d\n", prop_range.lMin, -25 );
2152 ok( prop_range.lMax == 56, "got %ld expected %d\n", prop_range.lMax, 56 );
2155 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
2156 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2157 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
2158 todo_wine_if( version >= 0x0800 )
2159 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_NOTINITIALIZED),
2160 "GetProperty DIPROP_APPDATA returned %#lx\n", hr );
2162 hr = IDirectInputDevice8_EnumObjects( device, NULL, NULL, DIDFT_ALL );
2163 ok( hr == DIERR_INVALIDPARAM, "EnumObjects returned %#lx\n", hr );
2164 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, 0x20 );
2165 ok( hr == DIERR_INVALIDPARAM, "EnumObjects returned %#lx\n", hr );
2166 res = 0;
2167 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
2168 ok( hr == DI_OK, "EnumObjects returned %#lx\n", hr );
2169 todo_wine_if( version < 0x0700 )
2170 ok( res == (version < 0x0700 ? 6 : 8), "got %lu objects\n", res );
2171 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
2172 ok( hr == DI_OK, "EnumObjects returned %#lx\n", hr );
2173 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
2174 check_objects_params.expect_count - check_objects_params.index );
2176 hr = IDirectInputDevice8_GetObjectInfo( device, NULL, 0, DIPH_DEVICE );
2177 ok( hr == E_POINTER, "GetObjectInfo returned: %#lx\n", hr );
2178 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_DEVICE );
2179 ok( hr == DIERR_INVALIDPARAM, "GetObjectInfo returned: %#lx\n", hr );
2180 objinst.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW);
2181 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_DEVICE );
2182 ok( hr == DIERR_INVALIDPARAM, "GetObjectInfo returned: %#lx\n", hr );
2184 res = MAKELONG( HID_USAGE_GENERIC_Z, HID_USAGE_PAGE_GENERIC );
2185 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE );
2186 todo_wine_if( version < 0x0800 )
2187 ok( hr == (version < 0x0800 ? DI_OK : DIERR_NOTFOUND), "GetObjectInfo returned: %#lx\n", hr );
2188 res = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2189 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE );
2190 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
2192 if (version < 0x0700) expect_obj = expect_objects_5[0];
2193 else expect_obj = expect_objects[4];
2194 check_object( &objinst, &expect_obj, version < 0x0700 ? &todo_ofs : NULL );
2196 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0x14, DIPH_BYOFFSET );
2197 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#lx\n", hr );
2198 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_BYOFFSET );
2199 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#lx\n", hr );
2200 res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 3 );
2201 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
2202 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#lx\n", hr );
2203 res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 );
2204 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
2205 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
2207 if (version < 0x0700) expect_obj = expect_objects_5[6];
2208 else expect_obj = expect_objects[8];
2209 check_object( &objinst, &expect_obj, version < 0x0700 ? &todo_ofs : NULL );
2211 hr = IDirectInputDevice8_EnumEffects( device, NULL, NULL, DIEFT_ALL );
2212 ok( hr == DIERR_INVALIDPARAM, "EnumEffects returned %#lx\n", hr );
2213 res = 0;
2214 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, 0xfe );
2215 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2216 ok( res == 0, "got %lu expected %u\n", res, 0 );
2217 res = 0;
2218 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, DIEFT_PERIODIC );
2219 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2220 ok( res == 0, "got %lu expected %u\n", res, 0 );
2221 hr = IDirectInputDevice8_EnumEffects( device, check_effects, &check_effects_params, DIEFT_ALL );
2222 ok( hr == DI_OK, "EnumEffects returned %#lx\n", hr );
2223 ok( check_effects_params.index >= check_effects_params.expect_count, "missing %u effects\n",
2224 check_effects_params.expect_count - check_effects_params.index );
2226 hr = IDirectInputDevice8_GetEffectInfo( device, NULL, &GUID_Sine );
2227 ok( hr == E_POINTER, "GetEffectInfo returned %#lx\n", hr );
2228 effectinfo.dwSize = sizeof(DIEFFECTINFOW) + 1;
2229 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
2230 ok( hr == DIERR_INVALIDPARAM, "GetEffectInfo returned %#lx\n", hr );
2231 effectinfo.dwSize = sizeof(DIEFFECTINFOW);
2232 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_NULL );
2233 ok( hr == DIERR_DEVICENOTREG, "GetEffectInfo returned %#lx\n", hr );
2234 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
2235 ok( hr == DIERR_DEVICENOTREG, "GetEffectInfo returned %#lx\n", hr );
2237 hr = IDirectInputDevice8_SetDataFormat( device, NULL );
2238 ok( hr == E_POINTER, "SetDataFormat returned: %#lx\n", hr );
2239 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2240 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2241 dataformat.dwSize = sizeof(DIDATAFORMAT);
2242 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2243 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2244 dataformat.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
2245 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2246 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2247 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
2248 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2250 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, DIJOFS_Y, DIPH_BYOFFSET );
2251 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
2253 if (version < 0x0700) expect_obj = expect_objects_5[1];
2254 else expect_obj = expect_objects[3];
2255 if (version < 0x0800) expect_obj.dwOfs = DIJOFS_Y;
2256 check_object( &objinst, &expect_obj, version < 0x0800 ? &todo_ofs : NULL );
2258 hr = IDirectInputDevice8_SetEventNotification( device, (HANDLE)0xdeadbeef );
2259 todo_wine
2260 ok( hr == E_HANDLE, "SetEventNotification returned: %#lx\n", hr );
2261 event = CreateEventW( NULL, FALSE, FALSE, NULL );
2262 ok( event != NULL, "CreateEventW failed, last error %lu\n", GetLastError() );
2263 hr = IDirectInputDevice8_SetEventNotification( device, event );
2264 ok( hr == DI_OK, "SetEventNotification returned: %#lx\n", hr );
2266 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2267 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
2268 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
2269 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
2271 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, 0 );
2272 ok( hr == DIERR_INVALIDPARAM, "SetCooperativeLevel returned: %#lx\n", hr );
2273 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND );
2274 ok( hr == DIERR_INVALIDPARAM, "SetCooperativeLevel returned: %#lx\n", hr );
2275 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
2276 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#lx\n", hr );
2277 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
2278 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#lx\n", hr );
2279 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
2280 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#lx\n", hr );
2282 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
2283 NULL, NULL, NULL, NULL );
2285 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
2286 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2287 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
2288 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2289 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
2290 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2292 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
2293 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2294 hr = IDirectInputDevice8_Unacquire( device );
2295 ok( hr == DI_NOEFFECT, "Unacquire returned: %#lx\n", hr );
2296 hr = IDirectInputDevice8_Acquire( device );
2297 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
2298 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
2299 ok( hr == DIERR_ACQUIRED, "SetCooperativeLevel returned: %#lx\n", hr );
2300 hr = IDirectInputDevice8_Unacquire( device );
2301 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2303 DestroyWindow( hwnd );
2305 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
2306 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
2308 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2309 ok( hr == DIERR_NOTACQUIRED, "GetDeviceState returned: %#lx\n", hr );
2311 hr = IDirectInputDevice8_Poll( device );
2312 ok( hr == DIERR_NOTACQUIRED, "Poll returned: %#lx\n", hr );
2314 hr = IDirectInputDevice8_Acquire( device );
2315 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
2317 hr = IDirectInputDevice8_Poll( device );
2318 todo_wine_if( version < 0x0700 )
2319 ok( hr == (version < 0x0700 ? DI_OK : DI_NOEFFECT), "Poll returned: %#lx\n", hr );
2321 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2) + 1, &state );
2322 ok( hr == DIERR_INVALIDPARAM, "GetDeviceState returned: %#lx\n", hr );
2324 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
2326 winetest_push_context( "state[%ld]", i );
2327 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2328 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2329 check_member( state, expect_state[i], "%ld", lX );
2330 check_member( state, expect_state[i], "%ld", lY );
2331 check_member( state, expect_state[i], "%ld", lZ );
2332 check_member( state, expect_state[i], "%ld", lRx );
2333 check_member( state, expect_state[i], "%#lx", rgdwPOV[0] );
2334 check_member( state, expect_state[i], "%#lx", rgdwPOV[1] );
2335 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
2336 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
2337 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
2339 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
2341 res = WaitForSingleObject( event, 100 );
2342 if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
2343 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2344 ResetEvent( event );
2345 winetest_pop_context();
2348 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2349 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2350 winetest_push_context( "state[%ld]", i );
2351 check_member( state, expect_state[i], "%ld", lX );
2352 check_member( state, expect_state[i], "%ld", lY );
2353 check_member( state, expect_state[i], "%ld", lZ );
2354 check_member( state, expect_state[i], "%ld", lRx );
2355 check_member( state, expect_state[i], "%#lx", rgdwPOV[0] );
2356 check_member( state, expect_state[i], "%#lx", rgdwPOV[1] );
2357 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
2358 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
2359 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
2360 winetest_pop_context();
2362 res = 1;
2363 size = version < 0x0800 ? sizeof(DIDEVICEOBJECTDATA_DX3) : sizeof(DIDEVICEOBJECTDATA);
2364 hr = IDirectInputDevice8_GetDeviceData( device, size - 1, objdata, &res, DIGDD_PEEK );
2365 todo_wine_if( version >= 0x0800 )
2366 ok( hr == (version < 0x0800 ? DI_OK : DIERR_INVALIDPARAM), "GetDeviceData returned %#lx\n", hr );
2367 res = 1;
2368 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, DIGDD_PEEK );
2369 ok( hr == DIERR_NOTBUFFERED, "GetDeviceData returned %#lx\n", hr );
2371 hr = IDirectInputDevice8_Unacquire( device );
2372 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2373 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2374 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2375 prop_dword.dwData = 1;
2376 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2377 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2378 prop_dword.diph.dwHow = DIPH_DEVICE;
2379 prop_dword.diph.dwObj = 0;
2380 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2381 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2382 hr = IDirectInputDevice8_Acquire( device );
2383 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2385 res = 1;
2386 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, DIGDD_PEEK );
2387 ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
2388 ok( res == 0, "got %lu expected %u\n", res, 0 );
2390 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
2391 res = WaitForSingleObject( event, 100 );
2392 if (res == WAIT_TIMEOUT) /* Acquire is asynchronous */
2394 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
2395 res = WaitForSingleObject( event, 5000 );
2397 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2398 ResetEvent( event );
2400 res = 1;
2401 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, DIGDD_PEEK );
2402 todo_wine_if( version < 0x0800 )
2403 ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#lx\n", hr );
2404 ok( res == 0, "got %lu expected %u\n", res, 0 );
2405 res = 1;
2406 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, 0 );
2407 todo_wine_if( version >= 0x0800 )
2408 ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
2409 ok( res == 0, "got %lu expected %u\n", res, 0 );
2411 hr = IDirectInputDevice8_Unacquire( device );
2412 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2413 prop_dword.diph.dwHow = DIPH_DEVICE;
2414 prop_dword.diph.dwObj = 0;
2415 prop_dword.dwData = 10;
2416 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2417 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2418 hr = IDirectInputDevice8_Acquire( device );
2419 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2421 send_hid_input( file, &injected_input[1], sizeof(*injected_input) );
2422 res = WaitForSingleObject( event, 100 );
2423 if (res == WAIT_TIMEOUT) /* Acquire is asynchronous */
2425 send_hid_input( file, &injected_input[1], sizeof(*injected_input) );
2426 res = WaitForSingleObject( event, 5000 );
2428 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2429 ResetEvent( event );
2431 res = 1;
2432 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, DIGDD_PEEK );
2433 ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
2434 ok( res == 1, "got %lu expected %u\n", res, 1 );
2435 check_member( objdata[0], expect_objdata[0], "%#lx", dwOfs );
2436 check_member( objdata[0], expect_objdata[0], "%#lx", dwData );
2437 if (version >= 0x0800) ok( objdata[0].uAppData == -1, "got %p\n", (void *)objdata[0].uAppData );
2438 res = 4;
2439 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, 0 );
2440 ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
2441 ok( res == 4, "got %lu expected %u\n", res, 4 );
2442 for (i = 0; i < 4; ++i)
2444 DIDEVICEOBJECTDATA *ptr = (DIDEVICEOBJECTDATA *)((char *)objdata + size * i);
2445 winetest_push_context( "objdata[%ld]", i );
2446 check_member( *ptr, expect_objdata[1 + i], "%#lx", dwOfs );
2447 check_member( *ptr, expect_objdata[1 + i], "%#lx", dwData );
2448 if (version >= 0x0800) ok( ptr->uAppData == -1, "got %p\n", (void *)ptr->uAppData );
2449 winetest_pop_context();
2452 send_hid_input( file, &injected_input[2], sizeof(*injected_input) );
2453 res = WaitForSingleObject( event, 5000 );
2454 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2455 ResetEvent( event );
2456 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2457 res = WaitForSingleObject( event, 5000 );
2458 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2459 ResetEvent( event );
2461 res = 1;
2462 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, 0 );
2463 todo_wine_if( version < 0x0800 )
2464 ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#lx\n", hr );
2465 ok( res == 1, "got %lu expected %u\n", res, 1 );
2466 todo_wine
2467 check_member( objdata[0], expect_objdata[5], "%#lx", dwOfs );
2468 todo_wine
2469 check_member( objdata[0], expect_objdata[5], "%#lx", dwData );
2470 if (version >= 0x0800) ok( objdata[0].uAppData == -1, "got %p\n", (void *)objdata[0].uAppData );
2471 res = ARRAY_SIZE(objdata);
2472 hr = IDirectInputDevice8_GetDeviceData( device, size, objdata, &res, 0 );
2473 ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
2474 ok( res == 8, "got %lu expected %u\n", res, 8 );
2475 for (i = 0; i < 8; ++i)
2477 DIDEVICEOBJECTDATA *ptr = (DIDEVICEOBJECTDATA *)((char *)objdata + size * i);
2478 winetest_push_context( "objdata[%ld]", i );
2479 todo_wine
2480 check_member( *ptr, expect_objdata[6 + i], "%#lx", dwOfs );
2481 todo_wine_if( i == 1 || i == 2 || i == 6 )
2482 check_member( *ptr, expect_objdata[6 + i], "%#lx", dwData );
2483 if (version >= 0x0800) ok( ptr->uAppData == -1, "got %p\n", (void *)ptr->uAppData );
2484 winetest_pop_context();
2487 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
2488 res = WaitForSingleObject( event, 5000 );
2489 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2490 ResetEvent( event );
2492 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2493 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2494 check_member( state, expect_state[3], "%ld", lX );
2495 check_member( state, expect_state[3], "%ld", lY );
2496 check_member( state, expect_state[3], "%ld", lZ );
2497 check_member( state, expect_state[3], "%ld", lRx );
2498 check_member( state, expect_state[3], "%ld", rgdwPOV[0] );
2499 check_member( state, expect_state[3], "%ld", rgdwPOV[1] );
2500 check_member( state, expect_state[3], "%#x", rgbButtons[0] );
2501 check_member( state, expect_state[3], "%#x", rgbButtons[1] );
2502 check_member( state, expect_state[3], "%#x", rgbButtons[2] );
2504 hr = IDirectInputDevice8_Unacquire( device );
2505 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2507 dataformat.dwSize = sizeof(DIDATAFORMAT);
2508 dataformat.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
2509 dataformat.dwFlags = DIDF_ABSAXIS;
2510 dataformat.dwDataSize = sizeof(buffer);
2511 dataformat.dwNumObjs = 0;
2512 dataformat.rgodf = objdataformat;
2513 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2514 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2516 dataformat.dwNumObjs = 1;
2517 dataformat.dwDataSize = 8;
2518 objdataformat[0].pguid = NULL;
2519 objdataformat[0].dwOfs = 2;
2520 objdataformat[0].dwType = DIDFT_AXIS | DIDFT_ANYINSTANCE;
2521 objdataformat[0].dwFlags = 0;
2522 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2523 todo_wine
2524 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2525 objdataformat[0].dwOfs = 4;
2526 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2527 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2528 dataformat.dwDataSize = 10;
2529 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2530 todo_wine
2531 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2532 dataformat.dwDataSize = 8;
2533 objdataformat[0].dwOfs = 2;
2534 objdataformat[0].dwType = DIDFT_OPTIONAL | 0xff | DIDFT_ANYINSTANCE;
2535 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2536 todo_wine
2537 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2539 dataformat.dwNumObjs = 2;
2540 dataformat.dwDataSize = 5;
2541 objdataformat[0].pguid = NULL;
2542 objdataformat[0].dwOfs = 4;
2543 objdataformat[0].dwType = DIDFT_BUTTON | DIDFT_ANYINSTANCE;
2544 objdataformat[0].dwFlags = 0;
2545 objdataformat[1].pguid = NULL;
2546 objdataformat[1].dwOfs = 0;
2547 objdataformat[1].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 0 );
2548 objdataformat[1].dwFlags = 0;
2549 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2550 todo_wine
2551 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2552 dataformat.dwDataSize = 8;
2553 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2554 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2556 dataformat.dwNumObjs = 4;
2557 dataformat.dwDataSize = 12;
2558 objdataformat[0].pguid = NULL;
2559 objdataformat[0].dwOfs = 0;
2560 objdataformat[0].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 0 );
2561 objdataformat[0].dwFlags = 0;
2562 objdataformat[1].pguid = NULL;
2563 objdataformat[1].dwOfs = 0;
2564 objdataformat[1].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 0 );
2565 objdataformat[1].dwFlags = 0;
2566 objdataformat[2].pguid = &GUID_ZAxis;
2567 objdataformat[2].dwOfs = 8;
2568 objdataformat[2].dwType = 0xff | DIDFT_ANYINSTANCE;
2569 objdataformat[2].dwFlags = 0;
2570 objdataformat[3].pguid = &GUID_POV;
2571 objdataformat[3].dwOfs = 0;
2572 objdataformat[3].dwType = 0xff | DIDFT_ANYINSTANCE;
2573 objdataformat[3].dwFlags = 0;
2574 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2575 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2576 objdataformat[1].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 12 );
2577 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2578 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2579 objdataformat[1].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 0xff );
2580 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2581 ok( hr == (version < 0x0700 ? DI_OK : DIERR_INVALIDPARAM),
2582 "SetDataFormat returned: %#lx\n", hr );
2583 objdataformat[1].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE( 1 );
2584 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2585 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2586 objdataformat[1].pguid = &GUID_RzAxis;
2587 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2588 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2589 objdataformat[1].pguid = &GUID_Unknown;
2590 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2591 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#lx\n", hr );
2592 objdataformat[1].pguid = &GUID_YAxis;
2593 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2594 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2595 objdataformat[1].pguid = NULL;
2596 objdataformat[1].dwType = DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_MAKEINSTANCE( 0 );
2597 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2598 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2600 dataformat.dwNumObjs = 0;
2601 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2602 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2603 hr = IDirectInputDevice8_Acquire( device );
2604 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2606 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2607 res = WaitForSingleObject( event, 100 );
2608 todo_wine
2609 ok( res == WAIT_TIMEOUT, "WaitForSingleObject failed\n" );
2610 ResetEvent( event );
2612 hr = IDirectInputDevice8_GetDeviceState( device, dataformat.dwDataSize, buffer );
2613 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2614 hr = IDirectInputDevice8_Unacquire( device );
2615 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2617 dataformat.dwNumObjs = 4;
2618 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
2619 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2620 hr = IDirectInputDevice8_Acquire( device );
2621 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2623 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2624 res = WaitForSingleObject( event, 100 );
2625 if (res == WAIT_TIMEOUT) /* Acquire is asynchronous */
2627 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2628 res = WaitForSingleObject( event, 100 );
2630 todo_wine
2631 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2632 ResetEvent( event );
2634 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
2635 res = WaitForSingleObject( event, 5000 );
2636 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2637 ResetEvent( event );
2639 hr = IDirectInputDevice8_GetDeviceState( device, dataformat.dwDataSize, buffer );
2640 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2641 ok( ((ULONG *)buffer)[0] == 0x512b, "got %#lx, expected %#x\n", ((ULONG *)buffer)[0], 0x512b );
2642 ok( ((ULONG *)buffer)[1] == 0, "got %#lx, expected %#x\n", ((ULONG *)buffer)[1], 0 );
2643 ok( ((ULONG *)buffer)[2] == 0x7fff, "got %#lx, expected %#x\n", ((ULONG *)buffer)[2], 0x7fff );
2644 hr = IDirectInputDevice8_Unacquire( device );
2645 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2646 hr = IDirectInputDevice8_SetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
2647 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_LOGICALRANGE returned %#lx\n", hr );
2648 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
2649 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_PHYSICALRANGE returned %#lx\n", hr );
2651 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
2652 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
2653 hr = IDirectInputDevice8_Acquire( device );
2654 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2656 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2657 res = WaitForSingleObject( event, 100 );
2658 if (res == WAIT_TIMEOUT) /* Acquire is asynchronous */
2660 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
2661 res = WaitForSingleObject( event, 5000 );
2663 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2664 ResetEvent( event );
2666 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
2667 res = WaitForSingleObject( event, 5000 );
2668 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2669 ResetEvent( event );
2671 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2672 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2673 check_member( state, expect_state[3], "%ld", lX );
2674 check_member( state, expect_state[3], "%ld", lY );
2675 check_member( state, expect_state[3], "%ld", lZ );
2676 check_member( state, expect_state[3], "%ld", lRx );
2677 check_member( state, expect_state[3], "%ld", rgdwPOV[0] );
2678 check_member( state, expect_state[3], "%ld", rgdwPOV[1] );
2679 check_member( state, expect_state[3], "%#x", rgbButtons[0] );
2680 check_member( state, expect_state[3], "%#x", rgbButtons[1] );
2681 check_member( state, expect_state[3], "%#x", rgbButtons[2] );
2683 prop_range.diph.dwHow = DIPH_DEVICE;
2684 prop_range.diph.dwObj = 0;
2685 prop_range.lMin = 1000;
2686 prop_range.lMax = 51000;
2687 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
2688 ok( hr == DI_OK, "SetProperty DIPROP_RANGE returned %#lx\n", hr );
2689 prop_range.diph.dwHow = DIPH_BYUSAGE;
2690 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2691 prop_range.lMin = -4000;
2692 prop_range.lMax = -14000;
2693 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
2694 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_RANGE returned %#lx\n", hr );
2695 prop_range.lMin = -14000;
2696 prop_range.lMax = -4000;
2697 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
2698 ok( hr == DI_OK, "SetProperty DIPROP_RANGE returned %#lx\n", hr );
2699 hr = IDirectInputDevice8_SetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
2700 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_ACQUIRED),
2701 "SetProperty DIPROP_LOGICALRANGE returned %#lx\n", hr );
2702 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
2703 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_ACQUIRED),
2704 "SetProperty DIPROP_PHYSICALRANGE returned %#lx\n", hr );
2706 prop_range.diph.dwHow = DIPH_DEVICE;
2707 prop_range.diph.dwObj = 0;
2708 prop_range.lMin = 0xdeadbeef;
2709 prop_range.lMax = 0xdeadbeef;
2710 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2711 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2712 prop_range.diph.dwHow = DIPH_BYUSAGE;
2713 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2714 prop_range.lMin = 0xdeadbeef;
2715 prop_range.lMax = 0xdeadbeef;
2716 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2717 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2718 ok( prop_range.lMin == -14000, "got %ld expected %d\n", prop_range.lMin, -14000 );
2719 ok( prop_range.lMax == -4000, "got %ld expected %d\n", prop_range.lMax, -4000 );
2720 prop_range.diph.dwHow = DIPH_BYUSAGE;
2721 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
2722 prop_range.lMin = 0xdeadbeef;
2723 prop_range.lMax = 0xdeadbeef;
2724 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
2725 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#lx\n", hr );
2726 ok( prop_range.lMin == 1000, "got %ld expected %d\n", prop_range.lMin, 1000 );
2727 ok( prop_range.lMax == 51000, "got %ld expected %d\n", prop_range.lMax, 51000 );
2729 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2730 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2731 ok( state.lX == expect_state_abs[1].lX || broken( state.lX == 16853 ) /* w8 */, "got lX %ld\n", state.lX );
2732 ok( state.lY == expect_state_abs[1].lY || broken( state.lY == 16853 ) /* w8 */, "got lY %ld\n", state.lY );
2733 check_member( state, expect_state_abs[1], "%ld", lZ );
2734 check_member( state, expect_state_abs[1], "%ld", lRx );
2735 check_member( state, expect_state_abs[1], "%ld", rgdwPOV[0] );
2736 check_member( state, expect_state_abs[1], "%ld", rgdwPOV[1] );
2737 check_member( state, expect_state_abs[1], "%#x", rgbButtons[0] );
2738 check_member( state, expect_state_abs[1], "%#x", rgbButtons[1] );
2739 check_member( state, expect_state_abs[1], "%#x", rgbButtons[2] );
2741 hr = IDirectInputDevice8_SetProperty( device, NULL, NULL );
2742 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#lx\n", hr );
2743 hr = IDirectInputDevice8_SetProperty( device, &GUID_NULL, NULL );
2744 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#lx\n", hr );
2745 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, NULL );
2746 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#lx\n", hr );
2747 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_string.diph );
2748 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_INVALIDPARAM),
2749 "SetProperty DIPROP_VIDPID returned %#lx\n", hr );
2751 prop_dword.diph.dwHow = DIPH_DEVICE;
2752 prop_dword.diph.dwObj = 0;
2753 prop_dword.dwData = 0xdeadbeef;
2754 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
2755 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_READONLY),
2756 "SetProperty DIPROP_VIDPID returned %#lx\n", hr );
2757 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
2758 ok( hr == DIERR_READONLY, "SetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
2760 prop_string.diph.dwHow = DIPH_DEVICE;
2761 prop_string.diph.dwObj = 0;
2762 wcscpy( prop_string.wsz, L"instance name" );
2763 hr = IDirectInputDevice8_SetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
2764 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_INSTANCENAME returned %#lx\n", hr );
2766 wcscpy( prop_string.wsz, L"product name" );
2767 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
2768 todo_wine
2769 ok( hr == DI_OK, "SetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
2770 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
2771 ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
2772 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
2773 debugstr_w(prop_string.wsz) );
2775 hr = IDirectInputDevice8_SetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
2776 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_READONLY),
2777 "SetProperty DIPROP_TYPENAME returned %#lx\n", hr );
2778 hr = IDirectInputDevice8_SetProperty( device, DIPROP_USERNAME, &prop_string.diph );
2779 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_READONLY),
2780 "SetProperty DIPROP_USERNAME returned %#lx\n", hr );
2781 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
2782 ok( hr == DIERR_READONLY, "SetProperty DIPROP_FFLOAD returned %#lx\n", hr );
2783 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
2784 ok( hr == DIERR_READONLY, "SetProperty DIPROP_GRANULARITY returned %#lx\n", hr );
2786 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
2787 todo_wine
2788 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_JOYSTICKID returned %#lx\n", hr );
2789 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
2790 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_AXISMODE returned %#lx\n", hr );
2791 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2792 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2793 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2794 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2795 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
2796 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2797 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
2798 todo_wine_if( version >= 0x0800 )
2799 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DIERR_ACQUIRED),
2800 "SetProperty DIPROP_APPDATA returned %#lx\n", hr );
2802 prop_dword.diph.dwHow = DIPH_DEVICE;
2803 prop_dword.diph.dwObj = 0;
2804 prop_dword.dwData = 10001;
2805 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2806 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2807 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2808 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_SATURATION returned %#lx\n", hr );
2809 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2810 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2811 prop_dword.dwData = 1000;
2812 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2813 ok( hr == DI_OK, "SetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2814 prop_dword.dwData = 6000;
2815 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2816 ok( hr == DI_OK, "SetProperty DIPROP_SATURATION returned %#lx\n", hr );
2817 prop_dword.dwData = DIPROPCALIBRATIONMODE_COOKED;
2818 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2819 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2821 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2822 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2823 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2824 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_SATURATION returned %#lx\n", hr );
2825 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2826 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2828 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2829 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2830 prop_dword.dwData = 2000;
2831 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2832 ok( hr == DI_OK, "SetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2833 ok( prop_dword.dwData == 2000, "got %lu expected %u\n", prop_dword.dwData, 2000 );
2834 prop_dword.dwData = 7000;
2835 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2836 ok( hr == DI_OK, "SetProperty DIPROP_SATURATION returned %#lx\n", hr );
2838 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2839 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2840 prop_dword.dwData = 0xdeadbeef;
2841 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2842 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2843 ok( prop_dword.dwData == 2000, "got %lu expected %u\n", prop_dword.dwData, 2000 );
2844 prop_dword.dwData = 0xdeadbeef;
2845 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2846 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#lx\n", hr );
2847 ok( prop_dword.dwData == 7000, "got %lu expected %u\n", prop_dword.dwData, 7000 );
2849 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2850 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
2851 prop_dword.dwData = 0xdeadbeef;
2852 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
2853 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#lx\n", hr );
2854 ok( prop_dword.dwData == 1000, "got %lu expected %u\n", prop_dword.dwData, 1000 );
2855 prop_dword.dwData = 0xdeadbeef;
2856 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
2857 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#lx\n", hr );
2858 ok( prop_dword.dwData == 6000, "got %lu expected %u\n", prop_dword.dwData, 6000 );
2860 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
2862 winetest_push_context( "state[%ld]", i );
2863 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2864 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2865 if (broken( state.lX == -10750 )) win_skip( "Ignoring 32-bit rounding\n" );
2866 else
2868 check_member( state, expect_state_abs[i], "%ld", lX );
2869 check_member( state, expect_state_abs[i], "%ld", lY );
2871 check_member( state, expect_state_abs[i], "%ld", lZ );
2872 check_member( state, expect_state_abs[i], "%ld", lRx );
2873 check_member( state, expect_state_abs[i], "%ld", rgdwPOV[0] );
2874 check_member( state, expect_state_abs[i], "%ld", rgdwPOV[1] );
2875 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
2876 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
2877 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
2879 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
2881 res = WaitForSingleObject( event, 100 );
2882 if (i == 0) ok( res == WAIT_TIMEOUT || broken( res == WAIT_OBJECT_0 ) /* w8 */, "WaitForSingleObject succeeded\n" );
2883 else if (i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
2884 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2885 ResetEvent( event );
2886 winetest_pop_context();
2889 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2890 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2891 winetest_push_context( "state[%ld]", i );
2892 check_member( state, expect_state_abs[i], "%ld", lX );
2893 check_member( state, expect_state_abs[i], "%ld", lY );
2894 check_member( state, expect_state_abs[i], "%ld", lZ );
2895 check_member( state, expect_state_abs[i], "%ld", lRx );
2896 check_member( state, expect_state_abs[i], "%ld", rgdwPOV[0] );
2897 check_member( state, expect_state_abs[i], "%ld", rgdwPOV[1] );
2898 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
2899 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
2900 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
2901 winetest_pop_context();
2903 prop_dword.diph.dwHow = DIPH_BYUSAGE;
2904 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2905 prop_dword.dwData = DIPROPCALIBRATIONMODE_RAW;
2906 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2907 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2908 prop_dword.dwData = 0xdeadbeef;
2909 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2910 ok( hr == DI_OK, "GetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2911 ok( prop_dword.dwData == DIPROPCALIBRATIONMODE_RAW, "got %lu expected %u\n", prop_dword.dwData,
2912 DIPROPCALIBRATIONMODE_RAW );
2914 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
2915 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
2916 winetest_push_context( "state[%ld]", i );
2917 todo_wine_if( version >= 0x0700 )
2918 ok( state.lX == (version < 0x0700 ? -9000 : 15), "got lX %ld\n", state.lX );
2919 check_member( state, expect_state_abs[0], "%ld", lY );
2920 check_member( state, expect_state_abs[0], "%ld", lZ );
2921 check_member( state, expect_state_abs[0], "%ld", lRx );
2922 check_member( state, expect_state_abs[0], "%ld", rgdwPOV[0] );
2923 check_member( state, expect_state_abs[0], "%ld", rgdwPOV[1] );
2924 winetest_pop_context();
2926 prop_dword.dwData = DIPROPCALIBRATIONMODE_COOKED;
2927 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
2928 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#lx\n", hr );
2930 send_hid_input( file, &injected_input[ARRAY_SIZE(injected_input) - 1], sizeof(*injected_input) );
2931 res = WaitForSingleObject( event, 5000 );
2932 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
2934 hr = IDirectInputDevice8_Unacquire( device );
2935 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2937 prop_dword.diph.dwHow = DIPH_DEVICE;
2938 prop_dword.diph.dwObj = 0;
2939 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
2940 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_JOYSTICKID returned %#lx\n", hr );
2941 prop_dword.dwData = 0x1000;
2942 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2943 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2944 prop_dword.dwData = 0xdeadbeef;
2945 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2946 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2947 prop_dword.dwData = DIPROPAUTOCENTER_ON;
2948 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
2949 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_AUTOCENTER returned %#lx\n", hr );
2950 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
2951 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2952 prop_pointer.uData = 0xfeedcafe;
2953 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
2954 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2955 "SetProperty DIPROP_APPDATA returned %#lx\n", hr );
2957 prop_dword.dwData = 0xdeadbeef;
2958 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
2959 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_AXISMODE returned %#lx\n", hr );
2960 prop_dword.dwData = DIPROPAXISMODE_REL;
2961 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
2962 ok( hr == DI_OK, "SetProperty DIPROP_AXISMODE returned %#lx\n", hr );
2964 hr = IDirectInputDevice8_Acquire( device );
2965 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
2967 prop_dword.dwData = 0xdeadbeef;
2968 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
2969 todo_wine
2970 ok( hr == DI_OK, "GetProperty DIPROP_AXISMODE returned %#lx\n", hr );
2971 todo_wine
2972 ok( prop_dword.dwData == DIPROPAXISMODE_REL, "got %lu expected %u\n", prop_dword.dwData, DIPROPAXISMODE_REL );
2974 prop_dword.dwData = 0xdeadbeef;
2975 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
2976 ok( hr == DI_OK, "GetProperty DIPROP_BUFFERSIZE returned %#lx\n", hr );
2977 ok( prop_dword.dwData == 0x1000, "got %#lx expected %#x\n", prop_dword.dwData, 0x1000 );
2979 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
2980 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
2981 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
2982 ok( hr == (version < 0x0800 ? DIERR_UNSUPPORTED : DI_OK),
2983 "GetProperty DIPROP_APPDATA returned %#lx\n", hr );
2984 if (hr == DI_OK) ok( prop_pointer.uData == 0xfeedcafe, "got %p\n", (void *)prop_pointer.uData );
2986 prop_dword.diph.dwHow = DIPH_DEVICE;
2987 prop_dword.diph.dwObj = 0;
2988 prop_dword.dwData = 0xdeadbeef;
2989 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2990 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2991 prop_dword.dwData = 1000;
2992 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
2993 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#lx\n", hr );
2995 prop_dword.dwData = 0xdeadbeef;
2996 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
2997 todo_wine
2998 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_CALIBRATION returned %#lx\n", hr );
2999 prop_dword.dwData = 0xdeadbeef;
3000 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
3001 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_DEADZONE returned %#lx\n", hr );
3002 prop_dword.dwData = 0xdeadbeef;
3003 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
3004 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_SATURATION returned %#lx\n", hr );
3006 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
3008 winetest_push_context( "state[%ld]", i );
3009 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
3010 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
3011 todo_wine
3012 check_member( state, expect_state_rel[i], "%ld", lX );
3013 todo_wine
3014 check_member( state, expect_state_rel[i], "%ld", lY );
3015 todo_wine
3016 check_member( state, expect_state_rel[i], "%ld", lZ );
3017 check_member( state, expect_state_rel[i], "%ld", lRx );
3018 check_member( state, expect_state_rel[i], "%ld", rgdwPOV[0] );
3019 check_member( state, expect_state_rel[i], "%ld", rgdwPOV[1] );
3020 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
3021 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
3022 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
3024 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
3026 res = WaitForSingleObject( event, 100 );
3027 if (i == 0 && res == WAIT_TIMEOUT) /* Acquire is asynchronous */
3029 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
3030 res = WaitForSingleObject( event, 100 );
3032 if (i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
3033 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
3034 ResetEvent( event );
3035 winetest_pop_context();
3038 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
3039 ok( hr == DI_OK, "GetDeviceState returned: %#lx\n", hr );
3040 winetest_push_context( "state[%ld]", i );
3041 todo_wine
3042 check_member( state, expect_state_rel[i], "%ld", lX );
3043 todo_wine
3044 check_member( state, expect_state_rel[i], "%ld", lY );
3045 todo_wine
3046 check_member( state, expect_state_rel[i], "%ld", lZ );
3047 check_member( state, expect_state_rel[i], "%ld", lRx );
3048 check_member( state, expect_state_rel[i], "%ld", rgdwPOV[0] );
3049 check_member( state, expect_state_rel[i], "%ld", rgdwPOV[1] );
3050 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
3051 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
3052 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
3053 winetest_pop_context();
3055 hr = IDirectInputDevice8_GetForceFeedbackState( device, NULL );
3056 ok( hr == E_POINTER, "GetForceFeedbackState returned %#lx\n", hr );
3057 res = 0xdeadbeef;
3058 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
3059 ok( hr == DIERR_UNSUPPORTED, "GetForceFeedbackState returned %#lx\n", hr );
3061 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
3062 ok( hr == DIERR_INVALIDPARAM, "SendForceFeedbackCommand returned %#lx\n", hr );
3063 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
3064 ok( hr == DIERR_UNSUPPORTED, "SendForceFeedbackCommand returned %#lx\n", hr );
3066 objdata[0].dwOfs = 0xd;
3067 objdata[0].dwData = 0x80;
3068 res = 1;
3069 hr = IDirectInputDevice8_SendDeviceData( device, size, objdata, &res, 0xdeadbeef );
3070 todo_wine
3071 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#lx\n", hr );
3072 res = 1;
3073 hr = IDirectInputDevice8_SendDeviceData( device, size, objdata, &res, 1 /*DISDD_CONTINUE*/ );
3074 todo_wine
3075 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#lx\n", hr );
3076 res = 1;
3077 hr = IDirectInputDevice8_SendDeviceData( device, size, objdata, &res, 0 );
3078 todo_wine
3079 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#lx\n", hr );
3081 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, NULL, NULL );
3082 ok( hr == E_POINTER, "CreateEffect returned %#lx\n", hr );
3083 hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL );
3084 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#lx\n", hr );
3085 hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL );
3086 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#lx\n", hr );
3087 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
3088 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#lx\n", hr );
3090 hr = IDirectInputDevice8_Unacquire( device );
3091 ok( hr == DI_OK, "Unacquire returned: %#lx\n", hr );
3093 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
3094 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#lx\n", hr );
3096 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, NULL, effect, 0 );
3097 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#lx\n", hr );
3098 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef );
3099 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#lx\n", hr );
3100 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, (void *)0xdeadbeef, 0 );
3101 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#lx\n", hr );
3103 hr = IDirectInputDevice8_Escape( device, NULL );
3104 todo_wine
3105 ok( hr == E_POINTER, "Escape returned: %#lx\n", hr );
3106 hr = IDirectInputDevice8_Escape( device, &escape );
3107 todo_wine
3108 ok( hr == DIERR_INVALIDPARAM, "Escape returned: %#lx\n", hr );
3109 escape.dwSize = sizeof(DIEFFESCAPE) + 1;
3110 hr = IDirectInputDevice8_Escape( device, &escape );
3111 todo_wine
3112 ok( hr == DIERR_INVALIDPARAM, "Escape returned: %#lx\n", hr );
3113 escape.dwSize = sizeof(DIEFFESCAPE);
3114 escape.dwCommand = 0;
3115 escape.lpvInBuffer = buffer;
3116 escape.cbInBuffer = 10;
3117 escape.lpvOutBuffer = buffer + 10;
3118 escape.cbOutBuffer = 10;
3119 hr = IDirectInputDevice8_Escape( device, &escape );
3120 todo_wine
3121 ok( hr == DIERR_UNSUPPORTED, "Escape returned: %#lx\n", hr );
3123 if (version == 0x800) test_action_map( device, file, event );
3125 ref = IDirectInputDevice8_Release( device );
3126 ok( ref == 0, "Release returned %ld\n", ref );
3128 CloseHandle( event );
3129 CloseHandle( file );
3131 done:
3132 hid_device_stop( &desc, 1 );
3133 cleanup_registry_keys();
3134 winetest_pop_context();
3137 struct device_desc
3139 const BYTE *report_desc_buf;
3140 ULONG report_desc_len;
3141 HIDP_CAPS hid_caps;
3144 static BOOL test_device_types( DWORD version )
3146 #include "psh_hid_macros.h"
3147 static const unsigned char unknown_desc[] =
3149 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3150 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3151 COLLECTION(1, Application),
3152 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3153 COLLECTION(1, Physical),
3154 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3155 USAGE_MINIMUM(1, 1),
3156 USAGE_MAXIMUM(1, 6),
3157 LOGICAL_MINIMUM(1, 0),
3158 LOGICAL_MAXIMUM(1, 1),
3159 PHYSICAL_MINIMUM(1, 0),
3160 PHYSICAL_MAXIMUM(1, 1),
3161 REPORT_SIZE(1, 1),
3162 REPORT_COUNT(1, 8),
3163 INPUT(1, Data|Var|Abs),
3164 END_COLLECTION,
3165 END_COLLECTION,
3167 C_ASSERT(sizeof(unknown_desc) < MAX_HID_DESCRIPTOR_LEN);
3168 static const unsigned char limited_desc[] =
3170 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3171 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3172 COLLECTION(1, Application),
3173 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3174 COLLECTION(1, Physical),
3175 USAGE(1, HID_USAGE_GENERIC_X),
3176 USAGE(1, HID_USAGE_GENERIC_Y),
3177 LOGICAL_MINIMUM(1, 0),
3178 LOGICAL_MAXIMUM(1, 127),
3179 PHYSICAL_MINIMUM(1, 0),
3180 PHYSICAL_MAXIMUM(1, 127),
3181 REPORT_SIZE(1, 8),
3182 REPORT_COUNT(1, 2),
3183 INPUT(1, Data|Var|Abs),
3185 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3186 USAGE_MINIMUM(1, 1),
3187 USAGE_MAXIMUM(1, 6),
3188 LOGICAL_MINIMUM(1, 0),
3189 LOGICAL_MAXIMUM(1, 1),
3190 PHYSICAL_MINIMUM(1, 0),
3191 PHYSICAL_MAXIMUM(1, 1),
3192 REPORT_SIZE(1, 1),
3193 REPORT_COUNT(1, 8),
3194 INPUT(1, Data|Var|Abs),
3195 END_COLLECTION,
3196 END_COLLECTION,
3198 C_ASSERT(sizeof(limited_desc) < MAX_HID_DESCRIPTOR_LEN);
3199 static const unsigned char gamepad_desc[] =
3201 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3202 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
3203 COLLECTION(1, Application),
3204 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
3205 COLLECTION(1, Physical),
3206 USAGE(1, HID_USAGE_GENERIC_X),
3207 USAGE(1, HID_USAGE_GENERIC_Y),
3208 LOGICAL_MINIMUM(1, 0),
3209 LOGICAL_MAXIMUM(1, 127),
3210 PHYSICAL_MINIMUM(1, 0),
3211 PHYSICAL_MAXIMUM(1, 127),
3212 REPORT_SIZE(1, 8),
3213 REPORT_COUNT(1, 2),
3214 INPUT(1, Data|Var|Abs),
3216 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3217 USAGE_MINIMUM(1, 1),
3218 USAGE_MAXIMUM(1, 6),
3219 LOGICAL_MINIMUM(1, 0),
3220 LOGICAL_MAXIMUM(1, 1),
3221 PHYSICAL_MINIMUM(1, 0),
3222 PHYSICAL_MAXIMUM(1, 1),
3223 REPORT_SIZE(1, 1),
3224 REPORT_COUNT(1, 8),
3225 INPUT(1, Data|Var|Abs),
3226 END_COLLECTION,
3227 END_COLLECTION,
3229 C_ASSERT(sizeof(gamepad_desc) < MAX_HID_DESCRIPTOR_LEN);
3230 static const unsigned char joystick_desc[] =
3232 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3233 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3234 COLLECTION(1, Application),
3235 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3236 COLLECTION(1, Physical),
3237 USAGE(1, HID_USAGE_GENERIC_X),
3238 USAGE(1, HID_USAGE_GENERIC_Y),
3239 USAGE(1, HID_USAGE_GENERIC_Z),
3240 LOGICAL_MINIMUM(1, 0),
3241 LOGICAL_MAXIMUM(1, 127),
3242 PHYSICAL_MINIMUM(1, 0),
3243 PHYSICAL_MAXIMUM(1, 127),
3244 REPORT_SIZE(1, 8),
3245 REPORT_COUNT(1, 3),
3246 INPUT(1, Data|Var|Abs),
3248 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3249 LOGICAL_MINIMUM(1, 1),
3250 LOGICAL_MAXIMUM(1, 8),
3251 PHYSICAL_MINIMUM(1, 0),
3252 PHYSICAL_MAXIMUM(1, 8),
3253 REPORT_SIZE(1, 8),
3254 REPORT_COUNT(1, 1),
3255 INPUT(1, Data|Var|Abs|Null),
3257 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3258 USAGE_MINIMUM(1, 1),
3259 USAGE_MAXIMUM(1, 5),
3260 LOGICAL_MINIMUM(1, 0),
3261 LOGICAL_MAXIMUM(1, 1),
3262 PHYSICAL_MINIMUM(1, 0),
3263 PHYSICAL_MAXIMUM(1, 1),
3264 REPORT_SIZE(1, 1),
3265 REPORT_COUNT(1, 8),
3266 INPUT(1, Data|Var|Abs),
3267 END_COLLECTION,
3268 END_COLLECTION,
3270 C_ASSERT(sizeof(joystick_desc) < MAX_HID_DESCRIPTOR_LEN);
3271 static const unsigned char wheel_steering_only_desc[] =
3273 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3274 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3275 COLLECTION(1, Application),
3276 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3277 COLLECTION(1, Physical),
3278 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_STEERING),
3279 LOGICAL_MINIMUM(1, 0),
3280 LOGICAL_MAXIMUM(1, 127),
3281 PHYSICAL_MINIMUM(1, 0),
3282 PHYSICAL_MAXIMUM(1, 127),
3283 REPORT_SIZE(1, 8),
3284 REPORT_COUNT(1, 1),
3285 INPUT(1, Data|Var|Abs),
3287 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3288 LOGICAL_MINIMUM(1, 1),
3289 LOGICAL_MAXIMUM(1, 8),
3290 PHYSICAL_MINIMUM(1, 0),
3291 PHYSICAL_MAXIMUM(1, 8),
3292 REPORT_SIZE(1, 8),
3293 REPORT_COUNT(1, 1),
3294 INPUT(1, Data|Var|Abs|Null),
3296 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3297 USAGE_MINIMUM(1, 1),
3298 USAGE_MAXIMUM(1, 5),
3299 LOGICAL_MINIMUM(1, 0),
3300 LOGICAL_MAXIMUM(1, 1),
3301 PHYSICAL_MINIMUM(1, 0),
3302 PHYSICAL_MAXIMUM(1, 1),
3303 REPORT_SIZE(1, 1),
3304 REPORT_COUNT(1, 8),
3305 INPUT(1, Data|Var|Abs),
3306 END_COLLECTION,
3307 END_COLLECTION,
3309 C_ASSERT(sizeof(wheel_steering_only_desc) < MAX_HID_DESCRIPTOR_LEN);
3310 static const unsigned char wheel_dualpedals_desc[] =
3312 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3313 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3314 COLLECTION(1, Application),
3315 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3316 COLLECTION(1, Physical),
3317 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_STEERING),
3318 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_ACCELERATOR),
3319 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_BRAKE),
3320 USAGE(1, HID_USAGE_GENERIC_X),
3321 LOGICAL_MINIMUM(1, 0),
3322 LOGICAL_MAXIMUM(1, 127),
3323 PHYSICAL_MINIMUM(1, 0),
3324 PHYSICAL_MAXIMUM(1, 127),
3325 REPORT_SIZE(1, 8),
3326 REPORT_COUNT(1, 4),
3327 INPUT(1, Data|Var|Abs),
3329 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3330 LOGICAL_MINIMUM(1, 1),
3331 LOGICAL_MAXIMUM(1, 8),
3332 PHYSICAL_MINIMUM(1, 0),
3333 PHYSICAL_MAXIMUM(1, 8),
3334 REPORT_SIZE(1, 8),
3335 REPORT_COUNT(1, 1),
3336 INPUT(1, Data|Var|Abs|Null),
3338 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3339 USAGE_MINIMUM(1, 1),
3340 USAGE_MAXIMUM(1, 5),
3341 LOGICAL_MINIMUM(1, 0),
3342 LOGICAL_MAXIMUM(1, 1),
3343 PHYSICAL_MINIMUM(1, 0),
3344 PHYSICAL_MAXIMUM(1, 1),
3345 REPORT_SIZE(1, 1),
3346 REPORT_COUNT(1, 8),
3347 INPUT(1, Data|Var|Abs),
3348 END_COLLECTION,
3349 END_COLLECTION,
3351 C_ASSERT(sizeof(wheel_dualpedals_desc) < MAX_HID_DESCRIPTOR_LEN);
3352 static const unsigned char wheel_threepedals_desc[] =
3354 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3355 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3356 COLLECTION(1, Application),
3357 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3358 COLLECTION(1, Physical),
3359 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_STEERING),
3360 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_ACCELERATOR),
3361 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_BRAKE),
3362 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_CLUTCH),
3363 USAGE(1, HID_USAGE_GENERIC_Y),
3364 LOGICAL_MINIMUM(1, 0),
3365 LOGICAL_MAXIMUM(1, 127),
3366 PHYSICAL_MINIMUM(1, 0),
3367 PHYSICAL_MAXIMUM(1, 127),
3368 REPORT_SIZE(1, 8),
3369 REPORT_COUNT(1, 5),
3370 INPUT(1, Data|Var|Abs),
3372 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3373 LOGICAL_MINIMUM(1, 1),
3374 LOGICAL_MAXIMUM(1, 8),
3375 PHYSICAL_MINIMUM(1, 0),
3376 PHYSICAL_MAXIMUM(1, 8),
3377 REPORT_SIZE(1, 8),
3378 REPORT_COUNT(1, 1),
3379 INPUT(1, Data|Var|Abs|Null),
3381 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3382 USAGE_MINIMUM(1, 1),
3383 USAGE_MAXIMUM(1, 5),
3384 LOGICAL_MINIMUM(1, 0),
3385 LOGICAL_MAXIMUM(1, 1),
3386 PHYSICAL_MINIMUM(1, 0),
3387 PHYSICAL_MAXIMUM(1, 1),
3388 REPORT_SIZE(1, 1),
3389 REPORT_COUNT(1, 8),
3390 INPUT(1, Data|Var|Abs),
3391 END_COLLECTION,
3392 END_COLLECTION,
3394 C_ASSERT(sizeof(wheel_threepedals_desc) < MAX_HID_DESCRIPTOR_LEN);
3395 #include "pop_hid_macros.h"
3397 static struct device_desc device_desc[] =
3400 .report_desc_buf = unknown_desc,
3401 .report_desc_len = sizeof(unknown_desc),
3402 .hid_caps =
3404 .InputReportByteLength = 1,
3408 .report_desc_buf = limited_desc,
3409 .report_desc_len = sizeof(limited_desc),
3410 .hid_caps =
3412 .InputReportByteLength = 3,
3416 .report_desc_buf = gamepad_desc,
3417 .report_desc_len = sizeof(gamepad_desc),
3418 .hid_caps =
3420 .InputReportByteLength = 3,
3424 .report_desc_buf = joystick_desc,
3425 .report_desc_len = sizeof(joystick_desc),
3426 .hid_caps =
3428 .InputReportByteLength = 5,
3432 .report_desc_buf = wheel_steering_only_desc,
3433 .report_desc_len = sizeof(wheel_steering_only_desc),
3434 .hid_caps =
3436 .InputReportByteLength = 3,
3440 .report_desc_buf = wheel_dualpedals_desc,
3441 .report_desc_len = sizeof(wheel_dualpedals_desc),
3442 .hid_caps =
3444 .InputReportByteLength = 6,
3448 .report_desc_buf = wheel_threepedals_desc,
3449 .report_desc_len = sizeof(wheel_threepedals_desc),
3450 .hid_caps =
3452 .InputReportByteLength = 7,
3456 const DIDEVCAPS expect_caps[] =
3459 .dwSize = sizeof(DIDEVCAPS),
3460 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3461 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPESUPPLEMENTAL_UNKNOWN << 8)|DI8DEVTYPE_SUPPLEMENTAL
3462 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3463 .dwButtons = 6,
3466 .dwSize = sizeof(DIDEVCAPS),
3467 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3468 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_LIMITED << 8)|DI8DEVTYPE_JOYSTICK
3469 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3470 .dwAxes = 2,
3471 .dwButtons = 6,
3474 .dwSize = sizeof(DIDEVCAPS),
3475 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3476 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEGAMEPAD_STANDARD << 8)|DI8DEVTYPE_GAMEPAD
3477 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_GAMEPAD << 8)|DIDEVTYPE_JOYSTICK,
3478 .dwAxes = 2,
3479 .dwButtons = 6,
3482 .dwSize = sizeof(DIDEVCAPS),
3483 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3484 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_STANDARD << 8)|DI8DEVTYPE_JOYSTICK
3485 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3486 .dwAxes = 3,
3487 .dwPOVs = 1,
3488 .dwButtons = 5,
3491 .dwSize = sizeof(DIDEVCAPS),
3492 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3493 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_LIMITED << 8)|DI8DEVTYPE_DRIVING
3494 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3495 .dwAxes = 1,
3496 .dwPOVs = 1,
3497 .dwButtons = 5,
3500 .dwSize = sizeof(DIDEVCAPS),
3501 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3502 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_DUALPEDALS << 8)|DI8DEVTYPE_DRIVING
3503 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3504 .dwAxes = 4,
3505 .dwPOVs = 1,
3506 .dwButtons = 5,
3509 .dwSize = sizeof(DIDEVCAPS),
3510 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
3511 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_THREEPEDALS << 8)|DI8DEVTYPE_DRIVING
3512 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3513 .dwAxes = 5,
3514 .dwPOVs = 1,
3515 .dwButtons = 5,
3519 const DIDEVICEINSTANCEW expect_devinst[] =
3522 .dwSize = sizeof(DIDEVICEINSTANCEW),
3523 .guidInstance = expect_guid_product,
3524 .guidProduct = expect_guid_product,
3525 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPESUPPLEMENTAL_UNKNOWN << 8)|DI8DEVTYPE_SUPPLEMENTAL
3526 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3527 .tszInstanceName = L"Wine Test",
3528 .tszProductName = L"Wine Test",
3529 .guidFFDriver = GUID_NULL,
3530 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3531 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3534 .dwSize = sizeof(DIDEVICEINSTANCEW),
3535 .guidInstance = expect_guid_product,
3536 .guidProduct = expect_guid_product,
3537 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_LIMITED << 8)|DI8DEVTYPE_JOYSTICK
3538 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3539 .tszInstanceName = L"Wine Test",
3540 .tszProductName = L"Wine Test",
3541 .guidFFDriver = GUID_NULL,
3542 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3543 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3546 .dwSize = sizeof(DIDEVICEINSTANCEW),
3547 .guidInstance = expect_guid_product,
3548 .guidProduct = expect_guid_product,
3549 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEGAMEPAD_STANDARD << 8)|DI8DEVTYPE_GAMEPAD
3550 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_GAMEPAD << 8)|DIDEVTYPE_JOYSTICK,
3551 .tszInstanceName = L"Wine Test",
3552 .tszProductName = L"Wine Test",
3553 .guidFFDriver = GUID_NULL,
3554 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3555 .wUsage = HID_USAGE_GENERIC_GAMEPAD,
3558 .dwSize = sizeof(DIDEVICEINSTANCEW),
3559 .guidInstance = expect_guid_product,
3560 .guidProduct = expect_guid_product,
3561 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_STANDARD << 8)|DI8DEVTYPE_JOYSTICK
3562 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
3563 .tszInstanceName = L"Wine Test",
3564 .tszProductName = L"Wine Test",
3565 .guidFFDriver = GUID_NULL,
3566 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3567 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3570 .dwSize = sizeof(DIDEVICEINSTANCEW),
3571 .guidInstance = expect_guid_product,
3572 .guidProduct = expect_guid_product,
3573 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_LIMITED << 8)|DI8DEVTYPE_DRIVING
3574 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3575 .tszInstanceName = L"Wine Test",
3576 .tszProductName = L"Wine Test",
3577 .guidFFDriver = GUID_NULL,
3578 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3579 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3582 .dwSize = sizeof(DIDEVICEINSTANCEW),
3583 .guidInstance = expect_guid_product,
3584 .guidProduct = expect_guid_product,
3585 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_DUALPEDALS << 8)|DI8DEVTYPE_DRIVING
3586 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3587 .tszInstanceName = L"Wine Test",
3588 .tszProductName = L"Wine Test",
3589 .guidFFDriver = GUID_NULL,
3590 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3591 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3594 .dwSize = sizeof(DIDEVICEINSTANCEW),
3595 .guidInstance = expect_guid_product,
3596 .guidProduct = expect_guid_product,
3597 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_THREEPEDALS << 8)|DI8DEVTYPE_DRIVING
3598 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
3599 .tszInstanceName = L"Wine Test",
3600 .tszProductName = L"Wine Test",
3601 .guidFFDriver = GUID_NULL,
3602 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3603 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3606 struct hid_device_desc desc =
3608 .use_report_id = TRUE,
3609 .attributes = default_attributes,
3612 C_ASSERT(ARRAY_SIZE(expect_caps) == ARRAY_SIZE(device_desc));
3613 C_ASSERT(ARRAY_SIZE(expect_devinst) == ARRAY_SIZE(device_desc));
3615 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
3616 DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)};
3617 IDirectInputDevice8W *device;
3618 BOOL success = TRUE;
3619 ULONG i, ref;
3620 HRESULT hr;
3622 winetest_push_context( "%#lx", version );
3624 for (i = 0; i < ARRAY_SIZE(device_desc) && success; ++i)
3626 winetest_push_context( "desc[%ld]", i );
3627 cleanup_registry_keys();
3629 desc.caps = device_desc[i].hid_caps;
3630 desc.report_descriptor_len = device_desc[i].report_desc_len;
3631 memcpy( desc.report_descriptor_buf, device_desc[i].report_desc_buf, device_desc[i].report_desc_len );
3632 fill_context( desc.context, ARRAY_SIZE(desc.context) );
3634 if (!hid_device_start( &desc, 1 ))
3636 success = FALSE;
3637 goto done;
3640 if (FAILED(hr = dinput_test_create_device( version, &devinst, &device )))
3642 success = FALSE;
3643 goto done;
3646 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
3647 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
3648 check_member( devinst, expect_devinst[i], "%lu", dwSize );
3649 check_member_guid( devinst, expect_devinst[i], guidProduct );
3650 todo_wine_if( version <= 0x700 && i == 3 )
3651 check_member( devinst, expect_devinst[i], "%#lx", dwDevType );
3652 check_member_guid( devinst, expect_devinst[i], guidFFDriver );
3653 check_member( devinst, expect_devinst[i], "%04x", wUsagePage );
3654 check_member( devinst, expect_devinst[i], "%04x", wUsage );
3656 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
3657 ok( hr == DI_OK, "GetCapabilities returned %#lx\n", hr );
3658 check_member( caps, expect_caps[i], "%lu", dwSize );
3659 check_member( caps, expect_caps[i], "%#lx", dwFlags );
3660 todo_wine_if( version <= 0x700 && i == 3 )
3661 check_member( caps, expect_caps[i], "%#lx", dwDevType );
3662 check_member( caps, expect_caps[i], "%lu", dwAxes );
3663 check_member( caps, expect_caps[i], "%lu", dwButtons );
3664 check_member( caps, expect_caps[i], "%lu", dwPOVs );
3665 check_member( caps, expect_caps[i], "%lu", dwFFSamplePeriod );
3666 check_member( caps, expect_caps[i], "%lu", dwFFMinTimeResolution );
3667 check_member( caps, expect_caps[i], "%lu", dwFirmwareRevision );
3668 check_member( caps, expect_caps[i], "%lu", dwHardwareRevision );
3669 check_member( caps, expect_caps[i], "%lu", dwFFDriverVersion );
3671 ref = IDirectInputDevice8_Release( device );
3672 ok( ref == 0, "Release returned %ld\n", ref );
3674 done:
3675 hid_device_stop( &desc, 1 );
3676 cleanup_registry_keys();
3677 winetest_pop_context();
3680 winetest_pop_context();
3682 return success;
3685 struct three_sliders_state
3687 LONG slider[3];
3690 static const DIOBJECTDATAFORMAT df_three_sliders[] =
3692 {&GUID_Slider, FIELD_OFFSET(struct three_sliders_state, slider[0]), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION},
3693 {&GUID_Slider, FIELD_OFFSET(struct three_sliders_state, slider[1]), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION},
3694 {&GUID_Slider, FIELD_OFFSET(struct three_sliders_state, slider[2]), DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE, DIDOI_ASPECTPOSITION},
3697 static const DIDATAFORMAT c_df_three_sliders =
3699 sizeof(DIDATAFORMAT),
3700 sizeof(DIOBJECTDATAFORMAT),
3701 DIDF_ABSAXIS,
3702 sizeof(struct three_sliders_state),
3703 ARRAY_SIZE(df_three_sliders),
3704 (DIOBJECTDATAFORMAT *)df_three_sliders,
3707 static void test_many_axes_joystick(void)
3709 #include "psh_hid_macros.h"
3710 static const unsigned char report_desc[] =
3712 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3713 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3714 COLLECTION(1, Application),
3715 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3716 COLLECTION(1, Report),
3717 REPORT_ID(1, 1),
3719 USAGE(1, HID_USAGE_GENERIC_DIAL),
3720 USAGE(1, HID_USAGE_GENERIC_SLIDER),
3721 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_RUDDER),
3722 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_THROTTLE),
3723 USAGE(1, HID_USAGE_GENERIC_RZ),
3724 USAGE(1, HID_USAGE_GENERIC_RY),
3725 USAGE(1, HID_USAGE_GENERIC_RX),
3726 USAGE(1, HID_USAGE_GENERIC_Z),
3727 USAGE(1, HID_USAGE_GENERIC_Y),
3728 USAGE(1, HID_USAGE_GENERIC_X),
3729 LOGICAL_MINIMUM(1, 0),
3730 LOGICAL_MAXIMUM(1, 0x7f),
3731 PHYSICAL_MINIMUM(1, 0),
3732 PHYSICAL_MAXIMUM(1, 0x7f),
3733 REPORT_SIZE(1, 8),
3734 REPORT_COUNT(1, 10),
3735 INPUT(1, Data|Var|Abs),
3737 USAGE(1, HID_USAGE_GENERIC_Z),
3738 USAGE(1, HID_USAGE_GENERIC_Y),
3739 USAGE(1, HID_USAGE_GENERIC_X),
3740 LOGICAL_MINIMUM(1, 0),
3741 LOGICAL_MAXIMUM(1, 0x7f),
3742 PHYSICAL_MINIMUM(1, 0),
3743 PHYSICAL_MAXIMUM(1, 0x7f),
3744 UNIT(4, 0xf011), /* cm * s^-1 */
3745 REPORT_SIZE(1, 8),
3746 REPORT_COUNT(1, 3),
3747 INPUT(1, Data|Var|Abs),
3749 USAGE(1, HID_USAGE_GENERIC_Z),
3750 USAGE(1, HID_USAGE_GENERIC_Y),
3751 USAGE(1, HID_USAGE_GENERIC_X),
3752 LOGICAL_MINIMUM(1, 0),
3753 LOGICAL_MAXIMUM(1, 0x7f),
3754 PHYSICAL_MINIMUM(1, 0),
3755 PHYSICAL_MAXIMUM(1, 0x7f),
3756 UNIT(4, 0xe011), /* cm * s^-2 */
3757 REPORT_SIZE(1, 8),
3758 REPORT_COUNT(1, 3),
3759 INPUT(1, Data|Var|Abs),
3761 USAGE(1, HID_USAGE_GENERIC_Z),
3762 USAGE(1, HID_USAGE_GENERIC_Y),
3763 USAGE(1, HID_USAGE_GENERIC_X),
3764 LOGICAL_MINIMUM(1, 0),
3765 LOGICAL_MAXIMUM(1, 0x7f),
3766 PHYSICAL_MINIMUM(1, 0),
3767 PHYSICAL_MAXIMUM(1, 0x7f),
3768 UNIT(4, 0xe111), /* g * cm * s^-2 */
3769 REPORT_SIZE(1, 8),
3770 REPORT_COUNT(1, 3),
3771 INPUT(1, Data|Var|Abs),
3772 UNIT(1, 0), /* None */
3773 END_COLLECTION,
3774 END_COLLECTION,
3776 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
3777 #include "pop_hid_macros.h"
3779 struct hid_device_desc desc =
3781 .use_report_id = TRUE,
3782 .caps = { .InputReportByteLength = 20 },
3783 .attributes = default_attributes,
3785 const DIDEVCAPS expect_caps =
3787 .dwSize = sizeof(DIDEVCAPS),
3788 .dwFlags = DIDC_ATTACHED | DIDC_EMULATED,
3789 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPE1STPERSON_LIMITED << 8) | DI8DEVTYPE_1STPERSON,
3790 .dwAxes = 19,
3792 const DIDEVICEINSTANCEW expect_devinst =
3794 .dwSize = sizeof(DIDEVICEINSTANCEW),
3795 .guidInstance = expect_guid_product,
3796 .guidProduct = expect_guid_product,
3797 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPE1STPERSON_LIMITED << 8) | DI8DEVTYPE_1STPERSON,
3798 .tszInstanceName = L"Wine Test",
3799 .tszProductName = L"Wine Test",
3800 .guidFFDriver = GUID_NULL,
3801 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3802 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3804 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
3807 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3808 .guidType = GUID_XAxis,
3809 .dwOfs = 0,
3810 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
3811 .dwFlags = DIDOI_ASPECTPOSITION,
3812 .tszName = L"X Axis",
3813 .wCollectionNumber = 1,
3814 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3815 .wUsage = HID_USAGE_GENERIC_X,
3816 .wReportId = 1,
3819 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3820 .guidType = GUID_YAxis,
3821 .dwOfs = 0x4,
3822 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
3823 .dwFlags = DIDOI_ASPECTPOSITION,
3824 .tszName = L"Y Axis",
3825 .wCollectionNumber = 1,
3826 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3827 .wUsage = HID_USAGE_GENERIC_Y,
3828 .wReportId = 1,
3831 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3832 .guidType = GUID_ZAxis,
3833 .dwOfs = 0x8,
3834 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2),
3835 .dwFlags = DIDOI_ASPECTPOSITION,
3836 .tszName = L"Z Axis",
3837 .wCollectionNumber = 1,
3838 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3839 .wUsage = HID_USAGE_GENERIC_Z,
3840 .wReportId = 1,
3843 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3844 .guidType = GUID_RxAxis,
3845 .dwOfs = 0xc,
3846 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(3),
3847 .dwFlags = DIDOI_ASPECTPOSITION,
3848 .tszName = L"X Rotation",
3849 .wCollectionNumber = 1,
3850 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3851 .wUsage = HID_USAGE_GENERIC_RX,
3852 .wReportId = 1,
3855 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3856 .guidType = GUID_RyAxis,
3857 .dwOfs = 0x10,
3858 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(4),
3859 .dwFlags = DIDOI_ASPECTPOSITION,
3860 .tszName = L"Y Rotation",
3861 .wCollectionNumber = 1,
3862 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3863 .wUsage = HID_USAGE_GENERIC_RY,
3864 .wReportId = 1,
3867 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3868 .guidType = GUID_RzAxis,
3869 .dwOfs = 0x14,
3870 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5),
3871 .dwFlags = DIDOI_ASPECTPOSITION,
3872 .tszName = L"Z Rotation",
3873 .wCollectionNumber = 1,
3874 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3875 .wUsage = HID_USAGE_GENERIC_RZ,
3876 .wReportId = 1,
3879 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3880 .guidType = GUID_Slider,
3881 .dwOfs = 0x18,
3882 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(6),
3883 .dwFlags = DIDOI_ASPECTPOSITION,
3884 .tszName = L"Throttle",
3885 .wCollectionNumber = 1,
3886 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
3887 .wUsage = HID_USAGE_SIMULATION_THROTTLE,
3888 .wReportId = 1,
3891 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3892 .guidType = GUID_RzAxis,
3893 .dwOfs = 0x1c,
3894 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(7),
3895 .dwFlags = DIDOI_ASPECTPOSITION,
3896 .tszName = L"Rudder",
3897 .wCollectionNumber = 1,
3898 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
3899 .wUsage = HID_USAGE_SIMULATION_RUDDER,
3900 .wReportId = 1,
3903 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3904 .guidType = GUID_Slider,
3905 .dwOfs = 0x20,
3906 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(8),
3907 .dwFlags = DIDOI_ASPECTPOSITION,
3908 .tszName = L"Slider",
3909 .wCollectionNumber = 1,
3910 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3911 .wUsage = HID_USAGE_GENERIC_SLIDER,
3912 .wReportId = 1,
3915 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3916 .guidType = GUID_Slider,
3917 .dwOfs = 0x24,
3918 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(9),
3919 .dwFlags = DIDOI_ASPECTPOSITION,
3920 .tszName = L"Dial",
3921 .wCollectionNumber = 1,
3922 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3923 .wUsage = HID_USAGE_GENERIC_DIAL,
3924 .wReportId = 1,
3927 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3928 .guidType = GUID_XAxis,
3929 .dwOfs = 0x28,
3930 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(10),
3931 .dwFlags = DIDOI_ASPECTVELOCITY,
3932 .tszName = L"X Axis",
3933 .wCollectionNumber = 1,
3934 .dwDimension = 0xf011,
3935 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3936 .wUsage = HID_USAGE_GENERIC_X,
3937 .wReportId = 1,
3940 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3941 .guidType = GUID_YAxis,
3942 .dwOfs = 0x2c,
3943 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(11),
3944 .dwFlags = DIDOI_ASPECTVELOCITY,
3945 .tszName = L"Y Axis",
3946 .wCollectionNumber = 1,
3947 .dwDimension = 0xf011,
3948 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3949 .wUsage = HID_USAGE_GENERIC_Y,
3950 .wReportId = 1,
3953 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3954 .guidType = GUID_ZAxis,
3955 .dwOfs = 0x30,
3956 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(12),
3957 .dwFlags = DIDOI_ASPECTVELOCITY,
3958 .tszName = L"Z Axis",
3959 .wCollectionNumber = 1,
3960 .dwDimension = 0xf011,
3961 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3962 .wUsage = HID_USAGE_GENERIC_Z,
3963 .wReportId = 1,
3966 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3967 .guidType = GUID_XAxis,
3968 .dwOfs = 0x34,
3969 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(13),
3970 .dwFlags = DIDOI_ASPECTACCEL,
3971 .tszName = L"X Axis",
3972 .wCollectionNumber = 1,
3973 .dwDimension = 0xe011,
3974 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3975 .wUsage = HID_USAGE_GENERIC_X,
3976 .wReportId = 1,
3979 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3980 .guidType = GUID_YAxis,
3981 .dwOfs = 0x38,
3982 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(14),
3983 .dwFlags = DIDOI_ASPECTACCEL,
3984 .tszName = L"Y Axis",
3985 .wCollectionNumber = 1,
3986 .dwDimension = 0xe011,
3987 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3988 .wUsage = HID_USAGE_GENERIC_Y,
3989 .wReportId = 1,
3992 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3993 .guidType = GUID_ZAxis,
3994 .dwOfs = 0x3c,
3995 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(15),
3996 .dwFlags = DIDOI_ASPECTACCEL,
3997 .tszName = L"Z Axis",
3998 .wCollectionNumber = 1,
3999 .dwDimension = 0xe011,
4000 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4001 .wUsage = HID_USAGE_GENERIC_Z,
4002 .wReportId = 1,
4005 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4006 .guidType = GUID_XAxis,
4007 .dwOfs = 0x40,
4008 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(16),
4009 .dwFlags = DIDOI_ASPECTFORCE,
4010 .tszName = L"X Axis",
4011 .wCollectionNumber = 1,
4012 .dwDimension = 0xe111,
4013 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4014 .wUsage = HID_USAGE_GENERIC_X,
4015 .wReportId = 1,
4018 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4019 .guidType = GUID_YAxis,
4020 .dwOfs = 0x44,
4021 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(17),
4022 .dwFlags = DIDOI_ASPECTFORCE,
4023 .tszName = L"Y Axis",
4024 .wCollectionNumber = 1,
4025 .dwDimension = 0xe111,
4026 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4027 .wUsage = HID_USAGE_GENERIC_Y,
4028 .wReportId = 1,
4031 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4032 .guidType = GUID_ZAxis,
4033 .dwOfs = 0x48,
4034 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(18),
4035 .dwFlags = DIDOI_ASPECTFORCE,
4036 .tszName = L"Z Axis",
4037 .wCollectionNumber = 1,
4038 .dwDimension = 0xe111,
4039 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4040 .wUsage = HID_USAGE_GENERIC_Z,
4041 .wReportId = 1,
4044 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4045 .guidType = GUID_Unknown,
4046 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
4047 .tszName = L"Collection 0 - Joystick",
4048 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4049 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
4052 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4053 .guidType = GUID_Unknown,
4054 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
4055 .tszName = L"Collection 1 - Joystick",
4056 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4057 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
4060 struct check_object_todo todo_objects[ARRAY_SIZE(expect_objects)] =
4062 {0},
4063 {0},
4064 {0},
4065 {0},
4066 {0},
4067 {0},
4068 {0},
4069 {0},
4070 {0},
4071 {0},
4072 {.flags = TRUE},
4073 {.flags = TRUE},
4074 {.flags = TRUE},
4075 {.flags = TRUE},
4076 {.flags = TRUE},
4077 {.flags = TRUE},
4078 {.flags = TRUE},
4079 {.flags = TRUE},
4080 {.flags = TRUE},
4082 struct check_objects_params check_objects_params =
4084 .version = DIRECTINPUT_VERSION,
4085 .expect_count = ARRAY_SIZE(expect_objects),
4086 .expect_objs = expect_objects,
4087 .todo_objs = todo_objects,
4090 DIDEVICEOBJECTINSTANCEW objinst = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)};
4091 struct check_object_todo todo_flags = {.flags = TRUE};
4092 DIDEVICEINSTANCEW devinst = {0};
4093 IDirectInputDevice8W *device;
4094 DIDEVCAPS caps = {0};
4095 HRESULT hr;
4096 ULONG ref;
4098 cleanup_registry_keys();
4100 desc.report_descriptor_len = sizeof(report_desc);
4101 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
4102 fill_context( desc.context, ARRAY_SIZE(desc.context) );
4104 if (!hid_device_start( &desc, 1 )) goto done;
4105 if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
4107 check_dinput_devices( DIRECTINPUT_VERSION, &devinst );
4109 memset( &devinst, 0, sizeof(devinst) );
4110 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
4111 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4112 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
4113 check_member( devinst, expect_devinst, "%lu", dwSize );
4114 todo_wine
4115 check_member_guid( devinst, expect_devinst, guidInstance );
4116 check_member_guid( devinst, expect_devinst, guidProduct );
4117 todo_wine
4118 check_member( devinst, expect_devinst, "%#lx", dwDevType );
4119 check_member_wstr( devinst, expect_devinst, tszInstanceName );
4120 check_member_wstr( devinst, expect_devinst, tszProductName );
4121 check_member_guid( devinst, expect_devinst, guidFFDriver );
4122 check_member( devinst, expect_devinst, "%04x", wUsagePage );
4123 check_member( devinst, expect_devinst, "%04x", wUsage );
4125 hr = IDirectInputDevice8_GetCapabilities( device, NULL );
4126 ok( hr == E_POINTER, "GetCapabilities returned %#lx\n", hr );
4127 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4128 ok( hr == DIERR_INVALIDPARAM, "GetCapabilities returned %#lx\n", hr );
4129 caps.dwSize = sizeof(DIDEVCAPS);
4130 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4131 ok( hr == DI_OK, "GetCapabilities returned %#lx\n", hr );
4132 check_member( caps, expect_caps, "%lu", dwSize );
4133 check_member( caps, expect_caps, "%#lx", dwFlags );
4134 todo_wine
4135 check_member( caps, expect_caps, "%#lx", dwDevType );
4136 check_member( caps, expect_caps, "%lu", dwAxes );
4137 check_member( caps, expect_caps, "%lu", dwButtons );
4138 check_member( caps, expect_caps, "%lu", dwPOVs );
4139 check_member( caps, expect_caps, "%lu", dwFFSamplePeriod );
4140 check_member( caps, expect_caps, "%lu", dwFFMinTimeResolution );
4141 check_member( caps, expect_caps, "%lu", dwFirmwareRevision );
4142 check_member( caps, expect_caps, "%lu", dwHardwareRevision );
4143 check_member( caps, expect_caps, "%lu", dwFFDriverVersion );
4145 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
4146 ok( hr == DI_OK, "EnumObjects returned %#lx\n", hr );
4147 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
4148 check_objects_params.expect_count - check_objects_params.index );
4150 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
4151 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
4153 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, DIJOFS_RZ, DIPH_BYOFFSET );
4154 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4155 check_object( &objinst, &expect_objects[5], NULL );
4157 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, rglSlider[0]), DIPH_BYOFFSET );
4158 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4159 check_object( &objinst, &expect_objects[6], NULL );
4161 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, rglSlider[1]), DIPH_BYOFFSET );
4162 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4163 check_object( &objinst, &expect_objects[8], NULL );
4165 /* c_dfDIJoystick2 is broken when it comes to more than two sliders */
4166 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, rglVSlider[0]), DIPH_BYOFFSET );
4167 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#lx\n", hr );
4169 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, lVX), DIPH_BYOFFSET );
4170 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4171 check_object( &objinst, &expect_objects[10], &todo_flags );
4173 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, lAX), DIPH_BYOFFSET );
4174 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4175 check_object( &objinst, &expect_objects[13], &todo_flags );
4177 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(DIJOYSTATE2, lFX), DIPH_BYOFFSET );
4178 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4179 check_object( &objinst, &expect_objects[16], &todo_flags );
4181 /* make sure that we handle three sliders correctly when the format allows */
4182 hr = IDirectInputDevice8_SetDataFormat( device, &c_df_three_sliders );
4183 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
4185 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(struct three_sliders_state, slider[0]), DIPH_BYOFFSET );
4186 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4187 check_object( &objinst, &expect_objects[6], NULL );
4189 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(struct three_sliders_state, slider[1]), DIPH_BYOFFSET );
4190 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4191 check_object( &objinst, &expect_objects[8], NULL );
4193 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, offsetof(struct three_sliders_state, slider[2]), DIPH_BYOFFSET );
4194 ok( hr == DI_OK, "GetObjectInfo returned: %#lx\n", hr );
4195 check_object( &objinst, &expect_objects[9], NULL );
4197 ref = IDirectInputDevice8_Release( device );
4198 ok( ref == 0, "Release returned %ld\n", ref );
4200 done:
4201 hid_device_stop( &desc, 1 );
4202 cleanup_registry_keys();
4205 static void test_driving_wheel_axes(void)
4207 #include "psh_hid_macros.h"
4208 static const unsigned char report_desc[] =
4210 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
4211 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4212 COLLECTION(1, Application),
4213 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4214 COLLECTION(1, Report),
4215 REPORT_ID(1, 1),
4217 USAGE_PAGE(1, HID_USAGE_PAGE_SIMULATION),
4218 USAGE(1, HID_USAGE_SIMULATION_RUDDER),
4219 USAGE(1, HID_USAGE_SIMULATION_THROTTLE),
4220 USAGE(1, HID_USAGE_SIMULATION_ACCELERATOR),
4221 USAGE(1, HID_USAGE_SIMULATION_BRAKE),
4222 USAGE(1, HID_USAGE_SIMULATION_CLUTCH),
4223 USAGE(1, HID_USAGE_SIMULATION_STEERING),
4224 LOGICAL_MINIMUM(1, 0),
4225 LOGICAL_MAXIMUM(1, 0x7f),
4226 PHYSICAL_MINIMUM(1, 0),
4227 PHYSICAL_MAXIMUM(1, 0x7f),
4228 REPORT_SIZE(1, 8),
4229 REPORT_COUNT(1, 6),
4230 INPUT(1, Data|Var|Abs),
4231 END_COLLECTION,
4232 END_COLLECTION,
4234 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
4235 #include "pop_hid_macros.h"
4237 struct hid_device_desc desc =
4239 .use_report_id = TRUE,
4240 .caps = { .InputReportByteLength = 7 },
4241 .attributes = default_attributes,
4243 const DIDEVCAPS expect_caps =
4245 .dwSize = sizeof(DIDEVCAPS),
4246 .dwFlags = DIDC_ATTACHED | DIDC_EMULATED,
4247 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEDRIVING_LIMITED << 8) | DI8DEVTYPE_DRIVING,
4248 .dwAxes = 6,
4250 const DIDEVICEINSTANCEW expect_devinst =
4252 .dwSize = sizeof(DIDEVICEINSTANCEW),
4253 .guidInstance = expect_guid_product,
4254 .guidProduct = expect_guid_product,
4255 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEDRIVING_LIMITED << 8) | DI8DEVTYPE_DRIVING,
4256 .tszInstanceName = L"Wine Test",
4257 .tszProductName = L"Wine Test",
4258 .guidFFDriver = GUID_NULL,
4259 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4260 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
4262 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
4265 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4266 .guidType = GUID_XAxis,
4267 .dwOfs = 0,
4268 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
4269 .dwFlags = DIDOI_ASPECTPOSITION,
4270 .tszName = L"Steering",
4271 .wCollectionNumber = 1,
4272 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4273 .wUsage = HID_USAGE_SIMULATION_STEERING,
4274 .wReportId = 1,
4277 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4278 .guidType = GUID_Unknown,
4279 .dwOfs = 0x4,
4280 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(6),
4281 .dwFlags = 0,
4282 .tszName = L"Clutch",
4283 .wCollectionNumber = 1,
4284 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4285 .wUsage = HID_USAGE_SIMULATION_CLUTCH,
4286 .wReportId = 1,
4289 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4290 .guidType = GUID_RzAxis,
4291 .dwOfs = 0x8,
4292 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5),
4293 .dwFlags = DIDOI_ASPECTPOSITION,
4294 .tszName = L"Brake",
4295 .wCollectionNumber = 1,
4296 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4297 .wUsage = HID_USAGE_SIMULATION_BRAKE,
4298 .wReportId = 1,
4301 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4302 .guidType = GUID_YAxis,
4303 .dwOfs = 0xc,
4304 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
4305 .dwFlags = DIDOI_ASPECTPOSITION,
4306 .tszName = L"Accelerator",
4307 .wCollectionNumber = 1,
4308 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4309 .wUsage = HID_USAGE_SIMULATION_ACCELERATOR,
4310 .wReportId = 1,
4313 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4314 .guidType = GUID_Slider,
4315 .dwOfs = 0x10,
4316 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2),
4317 .dwFlags = DIDOI_ASPECTPOSITION,
4318 .tszName = L"Throttle",
4319 .wCollectionNumber = 1,
4320 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4321 .wUsage = HID_USAGE_SIMULATION_THROTTLE,
4322 .wReportId = 1,
4325 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4326 .guidType = GUID_RzAxis,
4327 .dwOfs = 0x14,
4328 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(7),
4329 .dwFlags = DIDOI_ASPECTPOSITION,
4330 .tszName = L"Rudder",
4331 .wCollectionNumber = 1,
4332 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
4333 .wUsage = HID_USAGE_SIMULATION_RUDDER,
4334 .wReportId = 1,
4337 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4338 .guidType = GUID_Unknown,
4339 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
4340 .tszName = L"Collection 0 - Joystick",
4341 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4342 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
4345 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
4346 .guidType = GUID_Unknown,
4347 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
4348 .tszName = L"Collection 1 - Joystick",
4349 .wUsagePage = HID_USAGE_PAGE_GENERIC,
4350 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
4353 struct check_objects_params check_objects_params =
4355 .version = DIRECTINPUT_VERSION,
4356 .expect_count = ARRAY_SIZE(expect_objects),
4357 .expect_objs = expect_objects,
4360 DIDEVICEINSTANCEW devinst = {0};
4361 IDirectInputDevice8W *device;
4362 DIDEVCAPS caps = {0};
4363 HRESULT hr;
4364 ULONG ref;
4366 cleanup_registry_keys();
4368 desc.report_descriptor_len = sizeof(report_desc);
4369 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
4370 fill_context( desc.context, ARRAY_SIZE(desc.context) );
4372 if (!hid_device_start( &desc, 1 )) goto done;
4373 if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
4375 check_dinput_devices( DIRECTINPUT_VERSION, &devinst );
4377 memset( &devinst, 0, sizeof(devinst) );
4378 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
4379 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4380 ok( hr == DI_OK, "GetDeviceInfo returned %#lx\n", hr );
4381 check_member( devinst, expect_devinst, "%lu", dwSize );
4382 todo_wine
4383 check_member_guid( devinst, expect_devinst, guidInstance );
4384 check_member_guid( devinst, expect_devinst, guidProduct );
4385 check_member( devinst, expect_devinst, "%#lx", dwDevType );
4386 check_member_wstr( devinst, expect_devinst, tszInstanceName );
4387 check_member_wstr( devinst, expect_devinst, tszProductName );
4388 check_member_guid( devinst, expect_devinst, guidFFDriver );
4389 check_member( devinst, expect_devinst, "%04x", wUsagePage );
4390 check_member( devinst, expect_devinst, "%04x", wUsage );
4392 hr = IDirectInputDevice8_GetCapabilities( device, NULL );
4393 ok( hr == E_POINTER, "GetCapabilities returned %#lx\n", hr );
4394 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4395 ok( hr == DIERR_INVALIDPARAM, "GetCapabilities returned %#lx\n", hr );
4396 caps.dwSize = sizeof(DIDEVCAPS);
4397 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4398 ok( hr == DI_OK, "GetCapabilities returned %#lx\n", hr );
4399 check_member( caps, expect_caps, "%lu", dwSize );
4400 check_member( caps, expect_caps, "%#lx", dwFlags );
4401 check_member( caps, expect_caps, "%#lx", dwDevType );
4402 check_member( caps, expect_caps, "%lu", dwAxes );
4403 check_member( caps, expect_caps, "%lu", dwButtons );
4404 check_member( caps, expect_caps, "%lu", dwPOVs );
4405 check_member( caps, expect_caps, "%lu", dwFFSamplePeriod );
4406 check_member( caps, expect_caps, "%lu", dwFFMinTimeResolution );
4407 check_member( caps, expect_caps, "%lu", dwFirmwareRevision );
4408 check_member( caps, expect_caps, "%lu", dwHardwareRevision );
4409 check_member( caps, expect_caps, "%lu", dwFFDriverVersion );
4411 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
4412 ok( hr == DI_OK, "EnumObjects returned %#lx\n", hr );
4413 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
4414 check_objects_params.expect_count - check_objects_params.index );
4416 ref = IDirectInputDevice8_Release( device );
4417 ok( ref == 0, "Release returned %ld\n", ref );
4419 done:
4420 hid_device_stop( &desc, 1 );
4421 cleanup_registry_keys();
4424 static BOOL test_winmm_joystick(void)
4426 #include "psh_hid_macros.h"
4427 const unsigned char report_desc[] =
4429 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
4430 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4431 COLLECTION(1, Application),
4432 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4433 COLLECTION(1, Report),
4434 REPORT_ID(1, 1),
4436 USAGE(1, HID_USAGE_GENERIC_X),
4437 USAGE(1, HID_USAGE_GENERIC_Y),
4438 USAGE(1, HID_USAGE_GENERIC_Z),
4439 USAGE(1, HID_USAGE_GENERIC_WHEEL),
4440 USAGE(1, HID_USAGE_GENERIC_SLIDER),
4441 USAGE(1, HID_USAGE_GENERIC_RX),
4442 USAGE(1, HID_USAGE_GENERIC_RY),
4443 USAGE(1, HID_USAGE_GENERIC_RZ),
4444 LOGICAL_MINIMUM(1, 1),
4445 LOGICAL_MAXIMUM(4, 0xffff),
4446 PHYSICAL_MINIMUM(1, 1),
4447 PHYSICAL_MAXIMUM(4, 0xffff),
4448 REPORT_SIZE(1, 16),
4449 REPORT_COUNT(1, 8),
4450 INPUT(1, Data|Var|Abs),
4452 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
4453 LOGICAL_MINIMUM(1, 1),
4454 LOGICAL_MAXIMUM(1, 8),
4455 PHYSICAL_MINIMUM(1, 0),
4456 PHYSICAL_MAXIMUM(1, 8),
4457 REPORT_SIZE(1, 4),
4458 REPORT_COUNT(1, 1),
4459 INPUT(1, Data|Var|Abs|Null),
4461 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
4462 USAGE_MINIMUM(1, 1),
4463 USAGE_MAXIMUM(1, 4),
4464 LOGICAL_MINIMUM(1, 0),
4465 LOGICAL_MAXIMUM(1, 1),
4466 PHYSICAL_MINIMUM(1, 0),
4467 PHYSICAL_MAXIMUM(1, 1),
4468 REPORT_SIZE(1, 1),
4469 REPORT_COUNT(1, 4),
4470 INPUT(1, Data|Var|Abs),
4471 END_COLLECTION,
4472 END_COLLECTION,
4474 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
4475 #include "pop_hid_macros.h"
4477 struct hid_device_desc desc =
4479 .use_report_id = TRUE,
4480 .caps = { .InputReportByteLength = 18 },
4481 .attributes = default_attributes,
4483 static const JOYCAPS2W expect_regcaps =
4485 .szRegKey = L"DINPUT.DLL",
4487 static const JOYCAPS2W expect_caps =
4489 .wMid = 0x1209,
4490 .wPid = 0x0001,
4491 .szPname = L"Microsoft PC-joystick driver",
4492 .wXmax = 0xffff,
4493 .wYmax = 0xffff,
4494 .wZmax = 0xffff,
4495 .wNumButtons = 4,
4496 .wPeriodMin = 10,
4497 .wPeriodMax = 1000,
4498 .wRmax = 0xffff,
4499 .wUmax = 0xffff,
4500 .wVmax = 0xffff,
4501 .wCaps = JOYCAPS_HASZ | JOYCAPS_HASR | JOYCAPS_HASU | JOYCAPS_HASV | JOYCAPS_HASPOV | JOYCAPS_POV4DIR,
4502 .wMaxAxes = 6,
4503 .wNumAxes = 6,
4504 .wMaxButtons = 32,
4505 .szRegKey = L"DINPUT.DLL",
4507 struct hid_expect injected_input[] =
4510 .code = IOCTL_HID_READ_REPORT,
4511 .report_buf = {1,0x00,0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x38,0xf1},
4514 .code = IOCTL_HID_READ_REPORT,
4515 .report_buf = {1,0x00,0x38,0x00,0x30,0x00,0x28,0x00,0x20,0x00,0x18,0x00,0x10,0x00,0x08,0x00,0x00,0x63},
4518 static const JOYINFOEX expect_infoex[] =
4521 .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff,
4522 .dwXpos = 0x7fff, .dwYpos = 0x7fff, .dwZpos = 0x7fff, .dwRpos = 0x7fff, .dwUpos = 0x7fff, .dwVpos = 0x7fff,
4523 .dwButtons = 0, .dwButtonNumber = 0, .dwPOV = 0xffff,
4524 .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd,
4527 .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff,
4528 .dwXpos = 0, .dwYpos = 0x07ff, .dwZpos = 0x17ff, .dwRpos = 0x37ff, .dwUpos = 0x1fff, .dwVpos = 0x27ff,
4529 .dwButtons = 0xf, .dwButtonNumber = 0x4, .dwPOV = 0,
4530 .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd,
4533 .dwSize = sizeof(JOYINFOEX), .dwFlags = 0xff,
4534 .dwXpos = 0x37ff, .dwYpos = 0x2fff, .dwZpos = 0x1fff, .dwRpos = 0, .dwUpos = 0x17ff, .dwVpos = 0x0fff,
4535 .dwButtons = 0x6, .dwButtonNumber = 0x2, .dwPOV = 0x2328,
4536 .dwReserved1 = 0xcdcdcdcd, .dwReserved2 = 0xcdcdcdcd,
4539 static const JOYINFO expect_info =
4541 .wXpos = 0x7fff,
4542 .wYpos = 0x7fff,
4543 .wZpos = 0x7fff,
4544 .wButtons = 0,
4546 JOYINFOEX infoex = {.dwSize = sizeof(JOYINFOEX)};
4547 DIPROPGUIDANDPATH prop_guid_path =
4549 .diph =
4551 .dwSize = sizeof(DIPROPGUIDANDPATH),
4552 .dwHeaderSize = sizeof(DIPROPHEADER),
4553 .dwHow = DIPH_DEVICE,
4556 IDirectInputDevice8W *device = NULL;
4557 DIDEVICEINSTANCEW devinst = {0};
4558 JOYCAPS2W caps = {0};
4559 JOYINFO info = {0};
4560 HANDLE event, file;
4561 HRESULT hr;
4562 UINT ret;
4564 cleanup_registry_keys();
4566 ret = joyGetNumDevs();
4567 ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
4569 ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
4570 ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
4572 memset( &caps, 0xcd, sizeof(caps) );
4573 ret = joyGetDevCapsW( -1, (JOYCAPSW *)&caps, sizeof(caps) );
4574 ok( ret == 0, "joyGetDevCapsW returned %u\n", ret );
4575 check_member( caps, expect_regcaps, "%#x", wMid );
4576 check_member( caps, expect_regcaps, "%#x", wPid );
4577 check_member_wstr( caps, expect_regcaps, szPname );
4578 check_member( caps, expect_regcaps, "%#x", wXmin );
4579 check_member( caps, expect_regcaps, "%#x", wXmax );
4580 check_member( caps, expect_regcaps, "%#x", wYmin );
4581 check_member( caps, expect_regcaps, "%#x", wYmax );
4582 check_member( caps, expect_regcaps, "%#x", wZmin );
4583 check_member( caps, expect_regcaps, "%#x", wZmax );
4584 check_member( caps, expect_regcaps, "%#x", wNumButtons );
4585 check_member( caps, expect_regcaps, "%#x", wPeriodMin );
4586 check_member( caps, expect_regcaps, "%#x", wPeriodMax );
4587 check_member( caps, expect_regcaps, "%#x", wRmin );
4588 check_member( caps, expect_regcaps, "%#x", wRmax );
4589 check_member( caps, expect_regcaps, "%#x", wUmin );
4590 check_member( caps, expect_regcaps, "%#x", wUmax );
4591 check_member( caps, expect_regcaps, "%#x", wVmin );
4592 check_member( caps, expect_regcaps, "%#x", wVmax );
4593 check_member( caps, expect_regcaps, "%#x", wCaps );
4594 check_member( caps, expect_regcaps, "%#x", wMaxAxes );
4595 check_member( caps, expect_regcaps, "%#x", wNumAxes );
4596 check_member( caps, expect_regcaps, "%#x", wMaxButtons );
4597 check_member_wstr( caps, expect_regcaps, szRegKey );
4598 check_member_wstr( caps, expect_regcaps, szOEMVxD );
4599 check_member_guid( caps, expect_regcaps, ManufacturerGuid );
4600 check_member_guid( caps, expect_regcaps, ProductGuid );
4601 check_member_guid( caps, expect_regcaps, NameGuid );
4603 desc.report_descriptor_len = sizeof(report_desc);
4604 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
4605 fill_context( desc.context, ARRAY_SIZE(desc.context) );
4607 if (!hid_device_start( &desc, 1 )) goto done;
4609 ret = joyGetNumDevs();
4610 ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
4612 ret = joyGetPosEx( 1, &infoex );
4613 ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret );
4614 ret = joyGetPosEx( 0, &infoex );
4615 /* first call for an index sometimes fail */
4616 if (ret == JOYERR_PARMS) ret = joyGetPosEx( 0, &infoex );
4617 ok( ret == 0, "joyGetPosEx returned %u\n", ret );
4619 ret = joyGetDevCapsW( 1, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
4620 ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
4622 memset( &caps, 0xcd, sizeof(caps) );
4623 ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(caps) );
4624 ok( ret == 0, "joyGetDevCapsW returned %u\n", ret );
4625 check_member( caps, expect_caps, "%#x", wMid );
4626 check_member( caps, expect_caps, "%#x", wPid );
4627 todo_wine
4628 check_member_wstr( caps, expect_caps, szPname );
4629 check_member( caps, expect_caps, "%#x", wXmin );
4630 check_member( caps, expect_caps, "%#x", wXmax );
4631 check_member( caps, expect_caps, "%#x", wYmin );
4632 check_member( caps, expect_caps, "%#x", wYmax );
4633 check_member( caps, expect_caps, "%#x", wZmin );
4634 check_member( caps, expect_caps, "%#x", wZmax );
4635 check_member( caps, expect_caps, "%#x", wNumButtons );
4636 check_member( caps, expect_caps, "%#x", wPeriodMin );
4637 check_member( caps, expect_caps, "%#x", wPeriodMax );
4638 check_member( caps, expect_caps, "%#x", wRmin );
4639 check_member( caps, expect_caps, "%#x", wRmax );
4640 check_member( caps, expect_caps, "%#x", wUmin );
4641 check_member( caps, expect_caps, "%#x", wUmax );
4642 check_member( caps, expect_caps, "%#x", wVmin );
4643 check_member( caps, expect_caps, "%#x", wVmax );
4644 check_member( caps, expect_caps, "%#x", wCaps );
4645 check_member( caps, expect_caps, "%#x", wMaxAxes );
4646 check_member( caps, expect_caps, "%#x", wNumAxes );
4647 check_member( caps, expect_caps, "%#x", wMaxButtons );
4648 check_member_wstr( caps, expect_caps, szRegKey );
4649 check_member_wstr( caps, expect_caps, szOEMVxD );
4650 check_member_guid( caps, expect_caps, ManufacturerGuid );
4651 check_member_guid( caps, expect_caps, ProductGuid );
4652 check_member_guid( caps, expect_caps, NameGuid );
4654 ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) );
4655 ok( ret == 0, "joyGetDevCapsW returned %u\n", ret );
4656 ret = joyGetDevCapsW( 0, NULL, sizeof(JOYCAPSW) );
4657 ok( ret == MMSYSERR_INVALPARAM, "joyGetDevCapsW returned %u\n", ret );
4658 ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) + 4 );
4659 ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
4660 ret = joyGetDevCapsW( 0, (JOYCAPSW *)&caps, sizeof(JOYCAPSW) - 4 );
4661 ok( ret == JOYERR_PARMS, "joyGetDevCapsW returned %u\n", ret );
4663 infoex.dwSize = sizeof(JOYINFOEX);
4664 infoex.dwFlags = JOY_RETURNALL;
4665 ret = joyGetPosEx( -1, &infoex );
4666 ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret );
4667 ret = joyGetPosEx( 1, &infoex );
4668 ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret );
4669 ret = joyGetPosEx( 16, &infoex );
4670 ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret );
4672 memset( &infoex, 0xcd, sizeof(infoex) );
4673 infoex.dwSize = sizeof(JOYINFOEX);
4674 infoex.dwFlags = JOY_RETURNALL;
4675 ret = joyGetPosEx( 0, &infoex );
4676 ok( ret == 0, "joyGetPosEx returned %u\n", ret );
4677 check_member( infoex, expect_infoex[0], "%#lx", dwSize );
4678 check_member( infoex, expect_infoex[0], "%#lx", dwFlags );
4679 check_member( infoex, expect_infoex[0], "%#lx", dwXpos );
4680 check_member( infoex, expect_infoex[0], "%#lx", dwYpos );
4681 check_member( infoex, expect_infoex[0], "%#lx", dwZpos );
4682 check_member( infoex, expect_infoex[0], "%#lx", dwRpos );
4683 check_member( infoex, expect_infoex[0], "%#lx", dwUpos );
4684 check_member( infoex, expect_infoex[0], "%#lx", dwVpos );
4685 check_member( infoex, expect_infoex[0], "%#lx", dwButtons );
4686 check_member( infoex, expect_infoex[0], "%#lx", dwButtonNumber );
4687 check_member( infoex, expect_infoex[0], "%#lx", dwPOV );
4688 check_member( infoex, expect_infoex[0], "%#lx", dwReserved1 );
4689 check_member( infoex, expect_infoex[0], "%#lx", dwReserved2 );
4691 infoex.dwSize = sizeof(JOYINFOEX) - 4;
4692 ret = joyGetPosEx( 0, &infoex );
4693 ok( ret == JOYERR_PARMS, "joyGetPosEx returned %u\n", ret );
4695 ret = joyGetPos( -1, &info );
4696 ok( ret == JOYERR_PARMS, "joyGetPos returned %u\n", ret );
4697 ret = joyGetPos( 1, &info );
4698 ok( ret == JOYERR_PARMS, "joyGetPos returned %u\n", ret );
4699 memset( &info, 0xcd, sizeof(info) );
4700 ret = joyGetPos( 0, &info );
4701 ok( ret == 0, "joyGetPos returned %u\n", ret );
4702 check_member( info, expect_info, "%#x", wXpos );
4703 check_member( info, expect_info, "%#x", wYpos );
4704 check_member( info, expect_info, "%#x", wZpos );
4705 check_member( info, expect_info, "%#x", wButtons );
4707 if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
4709 event = CreateEventW( NULL, FALSE, FALSE, NULL );
4710 ok( event != NULL, "CreateEventW failed, last error %lu\n", GetLastError() );
4711 hr = IDirectInputDevice8_SetEventNotification( device, event );
4712 ok( hr == DI_OK, "SetEventNotification returned: %#lx\n", hr );
4714 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
4715 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#lx\n", hr );
4716 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
4717 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
4718 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
4719 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
4721 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
4722 ok( hr == DI_OK, "SetDataFormat returned: %#lx\n", hr );
4723 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
4724 ok( hr == DI_OK, "SetCooperativeLevel returned: %#lx\n", hr );
4725 hr = IDirectInputDevice8_Acquire( device );
4726 ok( hr == DI_OK, "Acquire returned: %#lx\n", hr );
4728 send_hid_input( file, &injected_input[0], sizeof(struct hid_expect) );
4729 ret = WaitForSingleObject( event, 5000 );
4730 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", ret );
4731 Sleep( 50 ); /* leave some time for winmm to keep up */
4733 memset( &infoex, 0xcd, sizeof(infoex) );
4734 infoex.dwSize = sizeof(JOYINFOEX);
4735 infoex.dwFlags = JOY_RETURNALL;
4736 ret = joyGetPosEx( 0, &infoex );
4737 ok( ret == 0, "joyGetPosEx returned %u\n", ret );
4738 check_member( infoex, expect_infoex[1], "%#lx", dwSize );
4739 check_member( infoex, expect_infoex[1], "%#lx", dwFlags );
4740 check_member( infoex, expect_infoex[1], "%#lx", dwXpos );
4741 check_member( infoex, expect_infoex[1], "%#lx", dwYpos );
4742 check_member( infoex, expect_infoex[1], "%#lx", dwZpos );
4743 check_member( infoex, expect_infoex[1], "%#lx", dwRpos );
4744 check_member( infoex, expect_infoex[1], "%#lx", dwUpos );
4745 check_member( infoex, expect_infoex[1], "%#lx", dwVpos );
4746 check_member( infoex, expect_infoex[1], "%#lx", dwButtons );
4747 check_member( infoex, expect_infoex[1], "%#lx", dwButtonNumber );
4748 check_member( infoex, expect_infoex[1], "%#lx", dwPOV );
4750 send_hid_input( file, &injected_input[1], sizeof(struct hid_expect) );
4751 ret = WaitForSingleObject( event, 5000 );
4752 ok( ret == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", ret );
4753 Sleep( 50 ); /* leave some time for winmm to keep up */
4755 memset( &infoex, 0xcd, sizeof(infoex) );
4756 infoex.dwSize = sizeof(JOYINFOEX);
4757 infoex.dwFlags = JOY_RETURNALL;
4758 ret = joyGetPosEx( 0, &infoex );
4759 ok( ret == 0, "joyGetPosEx returned %u\n", ret );
4760 check_member( infoex, expect_infoex[2], "%#lx", dwSize );
4761 check_member( infoex, expect_infoex[2], "%#lx", dwFlags );
4762 check_member( infoex, expect_infoex[2], "%#lx", dwXpos );
4763 check_member( infoex, expect_infoex[2], "%#lx", dwYpos );
4764 check_member( infoex, expect_infoex[2], "%#lx", dwZpos );
4765 check_member( infoex, expect_infoex[2], "%#lx", dwRpos );
4766 check_member( infoex, expect_infoex[2], "%#lx", dwUpos );
4767 check_member( infoex, expect_infoex[2], "%#lx", dwVpos );
4768 check_member( infoex, expect_infoex[2], "%#lx", dwButtons );
4769 check_member( infoex, expect_infoex[2], "%#lx", dwButtonNumber );
4770 check_member( infoex, expect_infoex[2], "%#lx", dwPOV );
4772 ret = IDirectInputDevice8_Release( device );
4773 ok( ret == 0, "Release returned %d\n", ret );
4775 CloseHandle( event );
4776 CloseHandle( file );
4778 done:
4779 hid_device_stop( &desc, 1 );
4780 cleanup_registry_keys();
4782 return device != NULL;
4785 #define check_interface( a, b, c ) check_interface_( __LINE__, a, b, c )
4786 static void check_interface_( unsigned int line, void *iface_ptr, REFIID iid, BOOL supported )
4788 IUnknown *iface = iface_ptr;
4789 HRESULT hr, expected;
4790 IUnknown *unk;
4792 expected = supported ? S_OK : E_NOINTERFACE;
4793 hr = IUnknown_QueryInterface( iface, iid, (void **)&unk );
4794 ok_ (__FILE__, line)( hr == expected, "got hr %#lx, expected %#lx.\n", hr, expected );
4795 if (SUCCEEDED(hr)) IUnknown_Release( unk );
4798 #define check_runtimeclass( a, b ) check_runtimeclass_( __LINE__, (IInspectable *)a, b )
4799 static void check_runtimeclass_( int line, IInspectable *inspectable, const WCHAR *class_name )
4801 const WCHAR *buffer;
4802 UINT32 length;
4803 HSTRING str;
4804 HRESULT hr;
4806 hr = IInspectable_GetRuntimeClassName( inspectable, &str );
4807 ok_ (__FILE__, line)( hr == S_OK, "GetRuntimeClassName returned %#lx\n", hr );
4808 buffer = pWindowsGetStringRawBuffer( str, &length );
4809 ok_ (__FILE__, line)( !wcscmp( buffer, class_name ), "got class name %s\n", debugstr_w(buffer) );
4810 pWindowsDeleteString( str );
4813 struct controller_handler
4815 IEventHandler_RawGameController IEventHandler_RawGameController_iface;
4816 HANDLE event;
4817 BOOL invoked;
4820 static inline struct controller_handler *impl_from_IEventHandler_RawGameController( IEventHandler_RawGameController *iface )
4822 return CONTAINING_RECORD( iface, struct controller_handler, IEventHandler_RawGameController_iface );
4825 static HRESULT WINAPI controller_handler_QueryInterface( IEventHandler_RawGameController *iface, REFIID iid, void **out )
4827 if (IsEqualGUID( iid, &IID_IUnknown ) ||
4828 IsEqualGUID( iid, &IID_IAgileObject ) ||
4829 IsEqualGUID( iid, &IID_IEventHandler_RawGameController ))
4831 IUnknown_AddRef( iface );
4832 *out = iface;
4833 return S_OK;
4836 if (winetest_debug > 1) trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
4837 *out = NULL;
4838 return E_NOINTERFACE;
4841 static ULONG WINAPI controller_handler_AddRef( IEventHandler_RawGameController *iface )
4843 return 2;
4846 static ULONG WINAPI controller_handler_Release( IEventHandler_RawGameController *iface )
4848 return 1;
4851 static HRESULT WINAPI controller_handler_Invoke( IEventHandler_RawGameController *iface,
4852 IInspectable *sender, IRawGameController *controller )
4854 struct controller_handler *impl = impl_from_IEventHandler_RawGameController( iface );
4856 if (winetest_debug > 1) trace( "iface %p, sender %p, controller %p\n", iface, sender, controller );
4858 ok( sender == NULL, "got sender %p\n", sender );
4859 impl->invoked = TRUE;
4860 SetEvent( impl->event );
4862 return S_OK;
4865 static const IEventHandler_RawGameControllerVtbl controller_handler_vtbl =
4867 controller_handler_QueryInterface,
4868 controller_handler_AddRef,
4869 controller_handler_Release,
4870 controller_handler_Invoke,
4873 static struct controller_handler controller_added = {{&controller_handler_vtbl}};
4875 static void test_windows_gaming_input(void)
4877 #include "psh_hid_macros.h"
4878 const unsigned char report_desc[] =
4880 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
4881 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
4882 COLLECTION(1, Application),
4883 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
4884 COLLECTION(1, Physical),
4885 USAGE(1, HID_USAGE_GENERIC_X),
4886 USAGE(1, HID_USAGE_GENERIC_Y),
4887 USAGE(1, HID_USAGE_GENERIC_RX),
4888 USAGE(1, HID_USAGE_GENERIC_RY),
4889 USAGE(1, HID_USAGE_GENERIC_Z),
4890 USAGE(1, HID_USAGE_GENERIC_RZ),
4891 LOGICAL_MINIMUM(1, 0),
4892 LOGICAL_MAXIMUM(1, 127),
4893 PHYSICAL_MINIMUM(1, 0),
4894 PHYSICAL_MAXIMUM(1, 127),
4895 REPORT_SIZE(1, 8),
4896 REPORT_COUNT(1, 6),
4897 INPUT(1, Data|Var|Abs),
4899 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
4900 LOGICAL_MINIMUM(1, 1),
4901 LOGICAL_MAXIMUM(1, 8),
4902 PHYSICAL_MINIMUM(1, 0),
4903 PHYSICAL_MAXIMUM(1, 8),
4904 REPORT_SIZE(1, 4),
4905 REPORT_COUNT(1, 1),
4906 INPUT(1, Data|Var|Abs|Null),
4908 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
4909 USAGE_MINIMUM(1, 1),
4910 USAGE_MAXIMUM(1, 12),
4911 LOGICAL_MINIMUM(1, 0),
4912 LOGICAL_MAXIMUM(1, 1),
4913 PHYSICAL_MINIMUM(1, 0),
4914 PHYSICAL_MAXIMUM(1, 1),
4915 REPORT_SIZE(1, 1),
4916 REPORT_COUNT(1, 12),
4917 INPUT(1, Data|Var|Abs),
4918 END_COLLECTION,
4919 END_COLLECTION,
4921 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
4922 static const unsigned char wheel_threepedals_desc[] =
4924 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
4925 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4926 COLLECTION(1, Application),
4927 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
4928 COLLECTION(1, Physical),
4929 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_STEERING),
4930 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_ACCELERATOR),
4931 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_BRAKE),
4932 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_CLUTCH),
4933 USAGE(1, HID_USAGE_GENERIC_Y),
4934 LOGICAL_MINIMUM(1, 0),
4935 LOGICAL_MAXIMUM(1, 127),
4936 PHYSICAL_MINIMUM(1, 0),
4937 PHYSICAL_MAXIMUM(1, 127),
4938 REPORT_SIZE(1, 8),
4939 REPORT_COUNT(1, 5),
4940 INPUT(1, Data|Var|Abs),
4942 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
4943 LOGICAL_MINIMUM(1, 1),
4944 LOGICAL_MAXIMUM(1, 8),
4945 PHYSICAL_MINIMUM(1, 0),
4946 PHYSICAL_MAXIMUM(1, 8),
4947 REPORT_SIZE(1, 8),
4948 REPORT_COUNT(1, 1),
4949 INPUT(1, Data|Var|Abs|Null),
4951 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
4952 USAGE_MINIMUM(1, 1),
4953 USAGE_MAXIMUM(1, 5),
4954 LOGICAL_MINIMUM(1, 0),
4955 LOGICAL_MAXIMUM(1, 1),
4956 PHYSICAL_MINIMUM(1, 0),
4957 PHYSICAL_MAXIMUM(1, 1),
4958 REPORT_SIZE(1, 1),
4959 REPORT_COUNT(1, 16),
4960 INPUT(1, Data|Var|Abs),
4961 END_COLLECTION,
4962 END_COLLECTION,
4964 C_ASSERT(sizeof(wheel_threepedals_desc) < MAX_HID_DESCRIPTOR_LEN);
4965 #include "pop_hid_macros.h"
4967 struct hid_device_desc desc =
4969 .use_report_id = TRUE,
4970 .caps = { .InputReportByteLength = 8 },
4971 .attributes = default_attributes,
4973 static const WCHAR *controller_class_name = RuntimeClass_Windows_Gaming_Input_RawGameController;
4974 static const WCHAR *racing_wheel_class_name = RuntimeClass_Windows_Gaming_Input_RacingWheel;
4975 static const WCHAR *gamepad_class_name = RuntimeClass_Windows_Gaming_Input_Gamepad;
4977 IRawGameController *raw_controller, *tmp_raw_controller;
4978 IVectorView_RawGameController *controllers_view;
4979 IRawGameControllerStatics *controller_statics;
4980 EventRegistrationToken controller_added_token;
4981 IVectorView_RacingWheel *racing_wheels_view;
4982 IRacingWheelStatics2 *racing_wheel_statics2;
4983 IRacingWheelStatics *racing_wheel_statics;
4984 IVectorView_Gamepad *gamepads_view;
4985 IGamepadStatics *gamepad_statics;
4986 IGameController *game_controller;
4987 IRacingWheel *racing_wheel;
4988 UINT32 size;
4989 HSTRING str;
4990 HRESULT hr;
4991 DWORD res;
4993 if (!load_combase_functions()) return;
4995 cleanup_registry_keys();
4997 hr = pRoInitialize( RO_INIT_MULTITHREADED );
4998 ok( hr == RPC_E_CHANGED_MODE, "RoInitialize returned %#lx\n", hr );
5000 hr = pWindowsCreateString( controller_class_name, wcslen( controller_class_name ), &str );
5001 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5002 hr = pRoGetActivationFactory( str, &IID_IRawGameControllerStatics, (void **)&controller_statics );
5003 ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "RoGetActivationFactory returned %#lx\n", hr );
5004 pWindowsDeleteString( str );
5006 if (hr == REGDB_E_CLASSNOTREG)
5008 win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( controller_class_name ) );
5009 goto done;
5012 hr = IRawGameControllerStatics_get_RawGameControllers( controller_statics, &controllers_view );
5013 ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
5014 hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
5015 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5016 ok( size == 0, "got size %u\n", size );
5018 controller_added.event = CreateEventW( NULL, FALSE, FALSE, NULL );
5019 ok( !!controller_added.event, "CreateEventW failed, error %lu\n", GetLastError() );
5021 hr = IRawGameControllerStatics_add_RawGameControllerAdded( controller_statics, &controller_added.IEventHandler_RawGameController_iface,
5022 &controller_added_token );
5023 ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
5024 ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
5026 desc.report_descriptor_len = sizeof(report_desc);
5027 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
5028 fill_context( desc.context, ARRAY_SIZE(desc.context) );
5030 if (!hid_device_start( &desc, 1 )) goto done;
5031 res = WaitForSingleObject( controller_added.event, 5000 );
5032 ok( !res, "WaitForSingleObject returned %#lx\n", res );
5033 CloseHandle( controller_added.event );
5035 hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
5036 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5037 ok( size == 0, "got size %u\n", size );
5038 IVectorView_RawGameController_Release( controllers_view );
5040 hr = IRawGameControllerStatics_get_RawGameControllers( controller_statics, &controllers_view );
5041 ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
5042 hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
5043 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5044 ok( size == 1, "got size %u\n", size );
5045 hr = IVectorView_RawGameController_GetAt( controllers_view, 0, &raw_controller );
5046 ok( hr == S_OK, "GetAt returned %#lx\n", hr );
5047 IVectorView_RawGameController_Release( controllers_view );
5049 /* HID gamepads aren't exposed as WGI gamepads on Windows */
5051 hr = pWindowsCreateString( gamepad_class_name, wcslen( gamepad_class_name ), &str );
5052 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5053 hr = pRoGetActivationFactory( str, &IID_IGamepadStatics, (void **)&gamepad_statics );
5054 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
5055 pWindowsDeleteString( str );
5056 hr = IGamepadStatics_get_Gamepads( gamepad_statics, &gamepads_view );
5057 ok( hr == S_OK, "get_Gamepads returned %#lx\n", hr );
5058 hr = IVectorView_Gamepad_get_Size( gamepads_view, &size );
5059 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5060 todo_wine /* but Wine currently intentionally does */
5061 ok( size == 0, "got size %u\n", size );
5062 IVectorView_Gamepad_Release( gamepads_view );
5063 IGamepadStatics_Release( gamepad_statics );
5065 check_runtimeclass( raw_controller, RuntimeClass_Windows_Gaming_Input_RawGameController );
5066 check_interface( raw_controller, &IID_IUnknown, TRUE );
5067 check_interface( raw_controller, &IID_IInspectable, TRUE );
5068 check_interface( raw_controller, &IID_IAgileObject, TRUE );
5069 check_interface( raw_controller, &IID_IRawGameController, TRUE );
5070 todo_wine
5071 check_interface( raw_controller, &IID_IRawGameController2, TRUE );
5072 check_interface( raw_controller, &IID_IGameController, TRUE );
5073 check_interface( raw_controller, &IID_IGamepad, FALSE );
5075 hr = IRawGameController_QueryInterface( raw_controller, &IID_IGameController, (void **)&game_controller );
5076 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5078 check_runtimeclass( game_controller, RuntimeClass_Windows_Gaming_Input_RawGameController );
5079 check_interface( game_controller, &IID_IUnknown, TRUE );
5080 check_interface( game_controller, &IID_IInspectable, TRUE );
5081 check_interface( game_controller, &IID_IAgileObject, TRUE );
5082 check_interface( game_controller, &IID_IRawGameController, TRUE );
5083 todo_wine
5084 check_interface( game_controller, &IID_IRawGameController2, TRUE );
5085 check_interface( game_controller, &IID_IGameController, TRUE );
5086 check_interface( game_controller, &IID_IGamepad, FALSE );
5088 hr = IRawGameControllerStatics_FromGameController( controller_statics, game_controller, &tmp_raw_controller );
5089 ok( hr == S_OK, "FromGameController returned %#lx\n", hr );
5090 ok( tmp_raw_controller == raw_controller, "got unexpected IGameController interface\n" );
5091 IRawGameController_Release( tmp_raw_controller );
5093 IGameController_Release( game_controller );
5094 IRawGameController_Release( raw_controller );
5096 hr = IRawGameControllerStatics_remove_RawGameControllerAdded( controller_statics, controller_added_token );
5097 ok( hr == S_OK, "remove_RawGameControllerAdded returned %#lx\n", hr );
5099 hid_device_stop( &desc, 1 );
5102 desc.report_descriptor_len = sizeof(wheel_threepedals_desc);
5103 memcpy( desc.report_descriptor_buf, wheel_threepedals_desc, sizeof(wheel_threepedals_desc) );
5104 fill_context( desc.context, ARRAY_SIZE(desc.context) );
5106 controller_added.event = CreateEventW( NULL, FALSE, FALSE, NULL );
5107 ok( !!controller_added.event, "CreateEventW failed, error %lu\n", GetLastError() );
5109 hr = IRawGameControllerStatics_add_RawGameControllerAdded( controller_statics, &controller_added.IEventHandler_RawGameController_iface,
5110 &controller_added_token );
5111 ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
5112 ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
5114 if (!hid_device_start( &desc, 1 )) goto done;
5115 res = WaitForSingleObject( controller_added.event, 5000 );
5116 ok( !res, "WaitForSingleObject returned %#lx\n", res );
5117 CloseHandle( controller_added.event );
5119 hr = IRawGameControllerStatics_get_RawGameControllers( controller_statics, &controllers_view );
5120 ok( hr == S_OK, "get_RawGameControllers returned %#lx\n", hr );
5121 hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
5122 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5123 ok( size == 1, "got size %u\n", size );
5124 hr = IVectorView_RawGameController_GetAt( controllers_view, 0, &raw_controller );
5125 ok( hr == S_OK, "GetAt returned %#lx\n", hr );
5126 IVectorView_RawGameController_Release( controllers_view );
5128 hr = IRawGameControllerStatics_remove_RawGameControllerAdded( controller_statics, controller_added_token );
5129 ok( hr == S_OK, "remove_RawGameControllerAdded returned %#lx\n", hr );
5131 hr = pWindowsCreateString( racing_wheel_class_name, wcslen( racing_wheel_class_name ), &str );
5132 ok( hr == S_OK, "WindowsCreateString returned %#lx\n", hr );
5133 hr = pRoGetActivationFactory( str, &IID_IRacingWheelStatics, (void **)&racing_wheel_statics );
5134 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
5135 hr = pRoGetActivationFactory( str, &IID_IRacingWheelStatics2, (void **)&racing_wheel_statics2 );
5136 ok( hr == S_OK, "RoGetActivationFactory returned %#lx\n", hr );
5137 pWindowsDeleteString( str );
5139 /* HID driving wheels aren't exposed as WGI RacingWheel on Windows */
5141 hr = IRacingWheelStatics_get_RacingWheels( racing_wheel_statics, &racing_wheels_view );
5142 ok( hr == S_OK, "get_RacingWheels returned %#lx\n", hr );
5143 hr = IVectorView_RacingWheel_get_Size( racing_wheels_view, &size );
5144 ok( hr == S_OK, "get_Size returned %#lx\n", hr );
5145 todo_wine /* but Wine currently intentionally does */
5146 ok( size == 0, "got size %u\n", size );
5147 IVectorView_RacingWheel_Release( racing_wheels_view );
5148 IRacingWheelStatics_Release( racing_wheel_statics );
5150 hr = IRawGameController_QueryInterface( raw_controller, &IID_IGameController, (void **)&game_controller );
5151 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
5152 hr = IRacingWheelStatics2_FromGameController( racing_wheel_statics2, game_controller, &racing_wheel );
5153 ok( hr == S_OK, "FromGameController returned %#lx\n", hr );
5154 todo_wine
5155 ok( racing_wheel == NULL, "got racing_wheel %p\n", racing_wheel );
5156 if (racing_wheel) IRacingWheel_Release( racing_wheel );
5157 IGameController_Release( game_controller );
5158 IRacingWheelStatics2_Release( racing_wheel_statics2 );
5160 IRawGameController_Release( raw_controller );
5161 IRawGameControllerStatics_Release( controller_statics );
5163 done:
5164 hid_device_stop( &desc, 1 );
5165 cleanup_registry_keys();
5168 static HANDLE rawinput_device_added, rawinput_device_removed, rawinput_event;
5169 static char wm_input_buf[1024];
5170 static UINT wm_input_len;
5172 static LRESULT CALLBACK rawinput_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
5174 UINT size = sizeof(wm_input_buf);
5176 if (msg == WM_INPUT_DEVICE_CHANGE)
5178 if (wparam == GIDC_ARRIVAL) ReleaseSemaphore( rawinput_device_added, 1, NULL );
5179 else ReleaseSemaphore( rawinput_device_removed, 1, NULL );
5181 if (msg == WM_INPUT)
5183 wm_input_len = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, (RAWINPUT *)wm_input_buf,
5184 &size, sizeof(RAWINPUTHEADER) );
5185 ReleaseSemaphore( rawinput_event, 1, NULL );
5188 return DefWindowProcW( hwnd, msg, wparam, lparam );
5191 static void test_rawinput(void)
5193 #include "psh_hid_macros.h"
5194 static const unsigned char report_desc[] =
5196 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
5197 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5198 COLLECTION(1, Application),
5199 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5200 COLLECTION(1, Report),
5201 REPORT_ID(1, 1),
5203 USAGE(1, HID_USAGE_GENERIC_WHEEL),
5204 USAGE(4, (0xff01u<<16)|(0x1234)),
5205 USAGE(1, HID_USAGE_GENERIC_X),
5206 USAGE(1, HID_USAGE_GENERIC_Y),
5207 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_RUDDER),
5208 USAGE(4, (HID_USAGE_PAGE_DIGITIZER<<16)|HID_USAGE_DIGITIZER_TIP_PRESSURE),
5209 USAGE(4, (HID_USAGE_PAGE_CONSUMER<<16)|HID_USAGE_CONSUMER_VOLUME),
5210 LOGICAL_MINIMUM(1, 0xe7),
5211 LOGICAL_MAXIMUM(1, 0x38),
5212 PHYSICAL_MINIMUM(1, 0xe7),
5213 PHYSICAL_MAXIMUM(1, 0x38),
5214 REPORT_SIZE(1, 8),
5215 REPORT_COUNT(1, 7),
5216 INPUT(1, Data|Var|Abs),
5218 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
5219 LOGICAL_MINIMUM(1, 1),
5220 LOGICAL_MAXIMUM(1, 8),
5221 PHYSICAL_MINIMUM(1, 0),
5222 PHYSICAL_MAXIMUM(1, 8),
5223 REPORT_SIZE(1, 4),
5224 REPORT_COUNT(1, 1),
5225 INPUT(1, Data|Var|Abs|Null),
5227 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
5228 USAGE_MINIMUM(1, 1),
5229 USAGE_MAXIMUM(1, 2),
5230 LOGICAL_MINIMUM(1, 0),
5231 LOGICAL_MAXIMUM(1, 1),
5232 PHYSICAL_MINIMUM(1, 0),
5233 PHYSICAL_MAXIMUM(1, 1),
5234 REPORT_SIZE(1, 1),
5235 REPORT_COUNT(1, 4),
5236 INPUT(1, Data|Var|Abs),
5237 END_COLLECTION,
5238 END_COLLECTION,
5240 C_ASSERT(sizeof(report_desc) < MAX_HID_DESCRIPTOR_LEN);
5241 #include "pop_hid_macros.h"
5243 struct hid_device_desc desc =
5245 .use_report_id = TRUE,
5246 .caps = { .InputReportByteLength = 9 },
5247 .attributes = default_attributes,
5249 struct hid_expect injected_input[] =
5252 .code = IOCTL_HID_READ_REPORT,
5253 .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0},
5256 .code = IOCTL_HID_READ_REPORT,
5257 .report_buf = {1,0x10,0x10,0x38,0x38,0x10,0x10,0x10,0xf8},
5260 .code = IOCTL_HID_READ_REPORT,
5261 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
5264 .code = IOCTL_HID_READ_REPORT,
5265 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
5268 .code = IOCTL_HID_READ_REPORT,
5269 .report_buf = {1,0x10,0x10,0x80,0x80,0x10,0x10,0x10,0xff},
5272 .code = IOCTL_HID_READ_REPORT,
5273 .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54},
5276 WNDCLASSEXW class =
5278 .cbSize = sizeof(WNDCLASSEXW),
5279 .hInstance = GetModuleHandleW( NULL ),
5280 .lpszClassName = L"rawinput",
5281 .lpfnWndProc = rawinput_wndproc,
5283 RAWINPUT *rawinput = (RAWINPUT *)wm_input_buf;
5284 RAWINPUTDEVICELIST raw_device_list[16];
5285 RAWINPUTDEVICE raw_devices[16];
5286 ULONG i, res, device_count;
5287 WCHAR path[MAX_PATH] = {0};
5288 HANDLE file;
5289 UINT count;
5290 HWND hwnd;
5291 BOOL ret;
5293 RegisterClassExW( &class );
5295 cleanup_registry_keys();
5297 desc.report_descriptor_len = sizeof(report_desc);
5298 memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
5299 fill_context( desc.context, ARRAY_SIZE(desc.context) );
5301 rawinput_device_added = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL );
5302 ok( !!rawinput_device_added, "CreateSemaphoreW failed, error %lu\n", GetLastError() );
5303 rawinput_device_removed = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL );
5304 ok( !!rawinput_device_removed, "CreateSemaphoreW failed, error %lu\n", GetLastError() );
5305 rawinput_event = CreateSemaphoreW( NULL, 0, LONG_MAX, NULL );
5306 ok( !!rawinput_event, "CreateSemaphoreW failed, error %lu\n", GetLastError() );
5308 hwnd = CreateWindowW( class.lpszClassName, L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
5309 NULL, NULL, NULL, NULL );
5310 ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() );
5312 count = ARRAY_SIZE(raw_devices);
5313 res = GetRegisteredRawInputDevices( raw_devices, &count, sizeof(RAWINPUTDEVICE) );
5314 ok( res == 0, "GetRegisteredRawInputDevices returned %lu\n", res );
5315 todo_wine
5316 ok( count == ARRAY_SIZE(raw_devices), "got count %u\n", count );
5318 count = ARRAY_SIZE(raw_device_list);
5319 res = GetRawInputDeviceList( raw_device_list, &count, sizeof(RAWINPUTDEVICELIST) );
5320 ok( res >= 2, "GetRawInputDeviceList returned %lu\n", res );
5321 ok( count == ARRAY_SIZE(raw_device_list), "got count %u\n", count );
5322 device_count = res;
5324 if (!hid_device_start( &desc, 1 )) goto done;
5326 count = ARRAY_SIZE(raw_devices);
5327 res = GetRegisteredRawInputDevices( raw_devices, &count, sizeof(RAWINPUTDEVICE) );
5328 ok( res == 0, "GetRegisteredRawInputDevices returned %lu\n", res );
5329 todo_wine
5330 ok( count == ARRAY_SIZE(raw_devices), "got count %u\n", count );
5332 res = msg_wait_for_events( 1, &rawinput_device_added, 10 );
5333 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5334 res = msg_wait_for_events( 1, &rawinput_device_removed, 10 );
5335 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5336 res = msg_wait_for_events( 1, &rawinput_event, 10 );
5337 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5339 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
5340 raw_devices[0].usUsage = HID_USAGE_GENERIC_GAMEPAD;
5341 raw_devices[0].dwFlags = RIDEV_DEVNOTIFY;
5342 raw_devices[0].hwndTarget = hwnd;
5343 count = ARRAY_SIZE(raw_devices);
5344 ret = RegisterRawInputDevices( raw_devices, 1, sizeof(RAWINPUTDEVICE) );
5345 ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() );
5347 hid_device_stop( &desc, 1 );
5349 res = msg_wait_for_events( 1, &rawinput_device_added, 10 );
5350 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5351 res = msg_wait_for_events( 1, &rawinput_device_removed, 10 );
5352 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5353 res = msg_wait_for_events( 1, &rawinput_event, 10 );
5354 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5356 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
5357 raw_devices[0].usUsage = HID_USAGE_GENERIC_JOYSTICK;
5358 raw_devices[0].dwFlags = RIDEV_DEVNOTIFY;
5359 raw_devices[0].hwndTarget = hwnd;
5360 count = ARRAY_SIZE(raw_devices);
5361 ret = RegisterRawInputDevices( raw_devices, 1, sizeof(RAWINPUTDEVICE) );
5362 ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() );
5364 hid_device_start( &desc, 1 );
5366 res = msg_wait_for_events( 1, &rawinput_device_added, 1000 );
5367 ok( !res, "WaitForSingleObject returned %#lx\n", res );
5369 res = msg_wait_for_events( 1, &rawinput_device_added, 10 );
5370 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5371 res = msg_wait_for_events( 1, &rawinput_device_removed, 10 );
5372 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5373 res = msg_wait_for_events( 1, &rawinput_event, 10 );
5374 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5376 raw_devices[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
5377 raw_devices[0].usUsage = HID_USAGE_GENERIC_JOYSTICK;
5378 raw_devices[0].dwFlags = RIDEV_INPUTSINK;
5379 raw_devices[0].hwndTarget = hwnd;
5380 count = ARRAY_SIZE(raw_devices);
5381 ret = RegisterRawInputDevices( raw_devices, 1, sizeof(RAWINPUTDEVICE) );
5382 ok( ret, "RegisterRawInputDevices failed, error %lu\n", GetLastError() );
5384 hid_device_stop( &desc, 1 );
5385 hid_device_start( &desc, 1 );
5387 res = msg_wait_for_events( 1, &rawinput_device_added, 10 );
5388 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5389 res = msg_wait_for_events( 1, &rawinput_device_removed, 10 );
5390 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5391 res = msg_wait_for_events( 1, &rawinput_event, 10 );
5392 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5395 count = ARRAY_SIZE(raw_device_list);
5396 res = GetRawInputDeviceList( raw_device_list, &count, sizeof(RAWINPUTDEVICELIST) );
5397 if (!strcmp( winetest_platform, "wine" ) && res == device_count)
5399 /* Wine refreshes its device list every 2s, but GetRawInputDeviceInfoW with an unknown handle will force it */
5400 GetRawInputDeviceInfoW( (HANDLE)0xdeadbeef, RIDI_DEVICEINFO, NULL, &count );
5401 res = GetRawInputDeviceList( raw_device_list, &count, sizeof(RAWINPUTDEVICELIST) );
5403 ok( res == device_count + 1, "GetRawInputDeviceList returned %lu\n", res );
5404 ok( count == ARRAY_SIZE(raw_device_list), "got count %u\n", count );
5405 device_count = res;
5407 while (device_count--)
5409 if (raw_device_list[device_count].dwType != RIM_TYPEHID) continue;
5411 count = ARRAY_SIZE(path);
5412 res = GetRawInputDeviceInfoW( raw_device_list[device_count].hDevice, RIDI_DEVICENAME, path, &count );
5413 ok( res == wcslen( path ) + 1, "GetRawInputDeviceInfoW returned %lu\n", res );
5414 todo_wine
5415 ok( count == ARRAY_SIZE(path), "got count %u\n", count );
5417 if (wcsstr( path, expect_vidpid_str )) break;
5420 ok( !!wcsstr( path, expect_vidpid_str ), "got path %s\n", debugstr_w(path) );
5423 file = CreateFileW( path, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
5424 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
5425 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
5426 ok( file != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() );
5428 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
5430 winetest_push_context( "state[%ld]", i );
5432 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
5434 res = msg_wait_for_events( 1, &rawinput_event, 1000 );
5435 ok( !res, "WaitForSingleObject returned %#lx\n", res );
5437 res = msg_wait_for_events( 1, &rawinput_device_added, 10 );
5438 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5439 res = msg_wait_for_events( 1, &rawinput_device_removed, 10 );
5440 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5441 res = msg_wait_for_events( 1, &rawinput_event, 10 );
5442 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res );
5444 ok( wm_input_len == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength]),
5445 "got wm_input_len %u\n", wm_input_len );
5446 ok( !memcmp( rawinput->data.hid.bRawData, injected_input[i].report_buf, desc.caps.InputReportByteLength ),
5447 "got unexpected report data\n" );
5449 winetest_pop_context();
5452 CloseHandle( rawinput_device_added );
5453 CloseHandle( rawinput_device_removed );
5454 CloseHandle( rawinput_event );
5455 CloseHandle( file );
5457 done:
5458 hid_device_stop( &desc, 1 );
5459 cleanup_registry_keys();
5461 DestroyWindow( hwnd );
5462 UnregisterClassW( class.lpszClassName, class.hInstance );
5465 START_TEST( joystick8 )
5467 dinput_test_init();
5468 if (!bus_device_start()) goto done;
5470 winetest_mute_threshold = 3;
5472 if (test_device_types( 0x800 ))
5474 /* This needs to be done before doing anything involving dinput.dll
5475 * on Windows, or the tests will fail, dinput8.dll is fine though. */
5476 test_winmm_joystick();
5478 test_device_types( 0x500 );
5479 test_device_types( 0x700 );
5481 test_simple_joystick( 0x500 );
5482 test_simple_joystick( 0x700 );
5483 test_simple_joystick( 0x800 );
5485 test_many_axes_joystick();
5486 test_driving_wheel_axes();
5487 test_rawinput();
5488 test_windows_gaming_input();
5491 done:
5492 bus_device_stop();
5493 dinput_test_exit();