2 * Copyright (c) 2011 Andrew Nguyen
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
27 #include "wine/test.h"
31 static BOOL CALLBACK
dummy_callback(const DIDEVICEINSTANCEA
*instance
, void *context
)
33 ok(0, "Callback was invoked with parameters (%p, %p)\n", instance
, context
);
37 static void test_preinitialization(void)
44 } create_device_tests
[] =
46 {NULL
, FALSE
, E_POINTER
},
47 {NULL
, TRUE
, E_POINTER
},
48 {&GUID_Unknown
, FALSE
, E_POINTER
},
49 {&GUID_Unknown
, TRUE
, DIERR_NOTINITIALIZED
},
50 {&GUID_SysMouse
, FALSE
, E_POINTER
},
51 {&GUID_SysMouse
, TRUE
, DIERR_NOTINITIALIZED
},
57 LPDIENUMDEVICESCALLBACKA lpCallback
;
61 } enum_devices_tests
[] =
63 {0, NULL
, 0, DIERR_INVALIDPARAM
},
64 {0, NULL
, ~0u, DIERR_INVALIDPARAM
},
65 {0, dummy_callback
, 0, DIERR_NOTINITIALIZED
},
66 {0, dummy_callback
, ~0u, DIERR_INVALIDPARAM
},
67 {0xdeadbeef, NULL
, 0, DIERR_INVALIDPARAM
},
68 {0xdeadbeef, NULL
, ~0u, DIERR_INVALIDPARAM
},
69 {0xdeadbeef, dummy_callback
, 0, DIERR_INVALIDPARAM
},
70 {0xdeadbeef, dummy_callback
, ~0u, DIERR_INVALIDPARAM
},
76 IDirectInputDevice8A
*pDID
;
78 hr
= CoCreateInstance(&CLSID_DirectInput8
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectInput8A
, (void **)&pDI
);
81 skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
85 for (i
= 0; i
< ARRAY_SIZE(create_device_tests
); i
++)
87 if (create_device_tests
[i
].pdev
) pDID
= (void *)0xdeadbeef;
88 hr
= IDirectInput8_CreateDevice(pDI
, create_device_tests
[i
].rguid
,
89 create_device_tests
[i
].pdev
? &pDID
: NULL
,
91 ok(hr
== create_device_tests
[i
].expected_hr
, "[%d] IDirectInput8_CreateDevice returned 0x%08x\n", i
, hr
);
92 if (create_device_tests
[i
].pdev
)
93 ok(pDID
== NULL
, "[%d] Output interface pointer is %p\n", i
, pDID
);
96 for (i
= 0; i
< ARRAY_SIZE(enum_devices_tests
); i
++)
98 hr
= IDirectInput8_EnumDevices(pDI
, enum_devices_tests
[i
].dwDevType
,
99 enum_devices_tests
[i
].lpCallback
,
101 enum_devices_tests
[i
].dwFlags
);
102 todo_wine_if(enum_devices_tests
[i
].todo
)
103 ok(hr
== enum_devices_tests
[i
].expected_hr
, "[%d] IDirectInput8_EnumDevice returned 0x%08x\n", i
, hr
);
106 hr
= IDirectInput8_GetDeviceStatus(pDI
, NULL
);
107 ok(hr
== E_POINTER
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
109 hr
= IDirectInput8_GetDeviceStatus(pDI
, &GUID_Unknown
);
110 ok(hr
== DIERR_NOTINITIALIZED
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
112 hr
= IDirectInput8_GetDeviceStatus(pDI
, &GUID_SysMouse
);
113 ok(hr
== DIERR_NOTINITIALIZED
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
115 hr
= IDirectInput8_RunControlPanel(pDI
, NULL
, 0);
116 ok(hr
== DIERR_NOTINITIALIZED
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
118 hr
= IDirectInput8_RunControlPanel(pDI
, NULL
, ~0u);
119 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
121 hr
= IDirectInput8_RunControlPanel(pDI
, (HWND
)0xdeadbeef, 0);
122 ok(hr
== E_HANDLE
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
124 hr
= IDirectInput8_RunControlPanel(pDI
, (HWND
)0xdeadbeef, ~0u);
125 ok(hr
== E_HANDLE
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
127 IDirectInput8_Release(pDI
);
130 static void test_DirectInput8Create(void)
139 } invalid_param_list
[] =
141 {FALSE
, 0, &IID_IDirectInputA
, FALSE
, E_POINTER
},
142 {FALSE
, 0, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
143 {FALSE
, 0, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
144 {FALSE
, 0, &IID_IDirectInput8A
, TRUE
, DIERR_INVALIDPARAM
},
145 {FALSE
, DIRECTINPUT_VERSION
, &IID_IDirectInputA
, FALSE
, E_POINTER
},
146 {FALSE
, DIRECTINPUT_VERSION
, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
147 {FALSE
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
148 {FALSE
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, TRUE
, DIERR_INVALIDPARAM
},
149 {FALSE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInputA
, FALSE
, E_POINTER
},
150 {FALSE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
151 {FALSE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
152 {FALSE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInput8A
, TRUE
, DIERR_INVALIDPARAM
},
153 {FALSE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInputA
, FALSE
, E_POINTER
},
154 {FALSE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
155 {FALSE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
156 {FALSE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInput8A
, TRUE
, DIERR_INVALIDPARAM
},
157 {TRUE
, 0, &IID_IDirectInputA
, FALSE
, E_POINTER
},
158 {TRUE
, 0, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
159 {TRUE
, 0, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
160 {TRUE
, 0, &IID_IDirectInput8A
, TRUE
, DIERR_NOTINITIALIZED
},
161 {TRUE
, DIRECTINPUT_VERSION
, &IID_IDirectInputA
, FALSE
, E_POINTER
},
162 {TRUE
, DIRECTINPUT_VERSION
, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
163 {TRUE
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
164 {TRUE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInputA
, FALSE
, E_POINTER
},
165 {TRUE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
166 {TRUE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
167 {TRUE
, DIRECTINPUT_VERSION
- 1, &IID_IDirectInput8A
, TRUE
, DIERR_BETADIRECTINPUTVERSION
},
168 {TRUE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInputA
, FALSE
, E_POINTER
},
169 {TRUE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInputA
, TRUE
, DIERR_NOINTERFACE
},
170 {TRUE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInput8A
, FALSE
, E_POINTER
},
171 {TRUE
, DIRECTINPUT_VERSION
+ 1, &IID_IDirectInput8A
, TRUE
, DIERR_OLDDIRECTINPUTVERSION
},
174 static REFIID no_interface_list
[] = {&IID_IDirectInputA
, &IID_IDirectInputW
,
175 &IID_IDirectInput2A
, &IID_IDirectInput2W
,
176 &IID_IDirectInput7A
, &IID_IDirectInput7W
,
177 &IID_IDirectInputDeviceA
, &IID_IDirectInputDeviceW
,
178 &IID_IDirectInputDevice2A
, &IID_IDirectInputDevice2W
,
179 &IID_IDirectInputDevice7A
, &IID_IDirectInputDevice7W
,
180 &IID_IDirectInputDevice8A
, &IID_IDirectInputDevice8W
,
181 &IID_IDirectInputEffect
};
183 static REFIID iid_list
[] = {&IID_IUnknown
, &IID_IDirectInput8A
, &IID_IDirectInput8W
};
189 for (i
= 0; i
< ARRAY_SIZE(invalid_param_list
); i
++)
191 if (invalid_param_list
[i
].ppdi
) pUnk
= (void *)0xdeadbeef;
192 hr
= DirectInput8Create(invalid_param_list
[i
].hinst
? hInstance
: NULL
,
193 invalid_param_list
[i
].dwVersion
,
194 invalid_param_list
[i
].riid
,
195 invalid_param_list
[i
].ppdi
? (void **)&pUnk
: NULL
,
197 ok(hr
== invalid_param_list
[i
].expected_hr
, "[%d] DirectInput8Create returned 0x%08x\n", i
, hr
);
198 if (invalid_param_list
[i
].ppdi
)
199 ok(pUnk
== NULL
, "[%d] Output interface pointer is %p\n", i
, pUnk
);
202 for (i
= 0; i
< ARRAY_SIZE(no_interface_list
); i
++)
204 pUnk
= (void *)0xdeadbeef;
205 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, no_interface_list
[i
], (void **)&pUnk
, NULL
);
206 ok(hr
== DIERR_NOINTERFACE
, "[%d] DirectInput8Create returned 0x%08x\n", i
, hr
);
207 ok(pUnk
== NULL
, "[%d] Output interface pointer is %p\n", i
, pUnk
);
210 for (i
= 0; i
< ARRAY_SIZE(iid_list
); i
++)
213 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, iid_list
[i
], (void **)&pUnk
, NULL
);
214 ok(hr
== DI_OK
, "[%d] DirectInput8Create returned 0x%08x\n", i
, hr
);
215 ok(pUnk
!= NULL
, "[%d] Output interface pointer is NULL\n", i
);
217 IUnknown_Release(pUnk
);
221 static void test_QueryInterface(void)
223 static REFIID iid_list
[] = {&IID_IUnknown
, &IID_IDirectInput8A
, &IID_IDirectInput8W
, &IID_IDirectInputJoyConfig8
};
225 static REFIID no_interface_list
[] =
233 &IID_IDirectInputDeviceA
,
234 &IID_IDirectInputDeviceW
,
235 &IID_IDirectInputDevice2A
,
236 &IID_IDirectInputDevice2W
,
237 &IID_IDirectInputDevice7A
,
238 &IID_IDirectInputDevice7W
,
239 &IID_IDirectInputDevice8A
,
240 &IID_IDirectInputDevice8W
,
241 &IID_IDirectInputEffect
,
249 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
252 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
256 hr
= IDirectInput8_QueryInterface(pDI
, NULL
, NULL
);
257 ok(hr
== E_POINTER
, "IDirectInput8_QueryInterface returned 0x%08x\n", hr
);
259 pUnk
= (void *)0xdeadbeef;
260 hr
= IDirectInput8_QueryInterface(pDI
, NULL
, (void **)&pUnk
);
261 ok(hr
== E_POINTER
, "IDirectInput8_QueryInterface returned 0x%08x\n", hr
);
262 ok(pUnk
== (void *)0xdeadbeef, "Output interface pointer is %p\n", pUnk
);
264 hr
= IDirectInput8_QueryInterface(pDI
, &IID_IUnknown
, NULL
);
265 ok(hr
== E_POINTER
, "IDirectInput8_QueryInterface returned 0x%08x\n", hr
);
267 for (i
= 0; i
< ARRAY_SIZE(iid_list
); i
++)
270 hr
= IDirectInput8_QueryInterface(pDI
, iid_list
[i
], (void **)&pUnk
);
271 ok(hr
== S_OK
, "[%d] IDirectInput8_QueryInterface returned 0x%08x\n", i
, hr
);
272 ok(pUnk
!= NULL
, "[%d] Output interface pointer is NULL\n", i
);
276 for (j
= 0; j
< ARRAY_SIZE(iid_list
); j
++)
278 IUnknown
*pUnk1
= NULL
;
279 hr
= IDirectInput8_QueryInterface(pUnk
, iid_list
[j
], (void **)&pUnk1
);
280 ok(hr
== S_OK
, "[%d] IDirectInput8_QueryInterface(pUnk) returned 0x%08x\n", j
, hr
);
281 ok(pUnk1
!= NULL
, "[%d] Output interface pointer is NULL\n", i
);
282 if (pUnk1
) IUnknown_Release(pUnk1
);
284 IUnknown_Release(pUnk
);
288 for (i
= 0; i
< ARRAY_SIZE(no_interface_list
); i
++)
290 pUnk
= (void *)0xdeadbeef;
291 hr
= IDirectInput8_QueryInterface(pDI
, no_interface_list
[i
], (void **)&pUnk
);
293 ok(hr
== E_NOINTERFACE
, "[%d] IDirectInput8_QueryInterface returned 0x%08x\n", i
, hr
);
294 ok(pUnk
== NULL
, "[%d] Output interface pointer is %p\n", i
, pUnk
);
297 IDirectInput8_Release(pDI
);
300 static void test_CreateDevice(void)
304 IDirectInputDevice8A
*pDID
;
306 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
309 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
313 hr
= IDirectInput8_CreateDevice(pDI
, NULL
, NULL
, NULL
);
314 ok(hr
== E_POINTER
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
316 pDID
= (void *)0xdeadbeef;
317 hr
= IDirectInput8_CreateDevice(pDI
, NULL
, &pDID
, NULL
);
318 ok(hr
== E_POINTER
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
319 ok(pDID
== NULL
, "Output interface pointer is %p\n", pDID
);
321 hr
= IDirectInput8_CreateDevice(pDI
, &GUID_Unknown
, NULL
, NULL
);
322 ok(hr
== E_POINTER
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
324 pDID
= (void *)0xdeadbeef;
325 hr
= IDirectInput8_CreateDevice(pDI
, &GUID_Unknown
, &pDID
, NULL
);
326 ok(hr
== DIERR_DEVICENOTREG
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
327 ok(pDID
== NULL
, "Output interface pointer is %p\n", pDID
);
329 hr
= IDirectInput8_CreateDevice(pDI
, &GUID_SysMouse
, NULL
, NULL
);
330 ok(hr
== E_POINTER
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
332 hr
= IDirectInput8_CreateDevice(pDI
, &GUID_SysMouse
, &pDID
, NULL
);
333 ok(hr
== DI_OK
, "IDirectInput8_CreateDevice returned 0x%08x\n", hr
);
335 IDirectInputDevice_Release(pDID
);
336 IDirectInput8_Release(pDI
);
339 struct enum_devices_test
341 unsigned int device_count
;
345 static BOOL CALLBACK
enum_devices_callback(const DIDEVICEINSTANCEA
*instance
, void *context
)
347 struct enum_devices_test
*enum_test
= context
;
349 trace("---- Device Information ----\n"
350 "Product Name : %s\n"
351 "Instance Name : %s\n"
353 "GUID Product : %s\n"
354 "GUID Instance : %s\n"
355 "HID Page : 0x%04x\n"
356 "HID Usage : 0x%04x\n",
357 instance
->tszProductName
,
358 instance
->tszInstanceName
,
360 wine_dbgstr_guid(&instance
->guidProduct
),
361 wine_dbgstr_guid(&instance
->guidInstance
),
362 instance
->wUsagePage
,
365 if ((instance
->dwDevType
& 0xff) == DI8DEVTYPE_KEYBOARD
||
366 (instance
->dwDevType
& 0xff) == DI8DEVTYPE_MOUSE
) {
367 const char *device
= ((instance
->dwDevType
& 0xff) ==
368 DI8DEVTYPE_KEYBOARD
) ? "Keyboard" : "Mouse";
369 ok(IsEqualGUID(&instance
->guidInstance
, &instance
->guidProduct
),
370 "%s guidInstance (%s) does not match guidProduct (%s)\n",
371 device
, wine_dbgstr_guid(&instance
->guidInstance
),
372 wine_dbgstr_guid(&instance
->guidProduct
));
375 enum_test
->device_count
++;
376 return enum_test
->return_value
;
379 static void test_EnumDevices(void)
383 struct enum_devices_test enum_test
, enum_test_return
;
385 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
388 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
392 hr
= IDirectInput8_EnumDevices(pDI
, 0, NULL
, NULL
, 0);
393 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
395 hr
= IDirectInput8_EnumDevices(pDI
, 0, NULL
, NULL
, ~0u);
396 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
398 /* Test crashes on Wine. */
401 hr
= IDirectInput8_EnumDevices(pDI
, 0, enum_devices_callback
, NULL
, ~0u);
402 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
405 hr
= IDirectInput8_EnumDevices(pDI
, 0xdeadbeef, NULL
, NULL
, 0);
406 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
408 hr
= IDirectInput8_EnumDevices(pDI
, 0xdeadbeef, NULL
, NULL
, ~0u);
409 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
411 hr
= IDirectInput8_EnumDevices(pDI
, 0xdeadbeef, enum_devices_callback
, NULL
, 0);
412 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
414 hr
= IDirectInput8_EnumDevices(pDI
, 0xdeadbeef, enum_devices_callback
, NULL
, ~0u);
415 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
417 enum_test
.device_count
= 0;
418 enum_test
.return_value
= DIENUM_CONTINUE
;
419 hr
= IDirectInput8_EnumDevices(pDI
, 0, enum_devices_callback
, &enum_test
, 0);
420 ok(hr
== DI_OK
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
421 ok(enum_test
.device_count
!= 0, "Device count is %u\n", enum_test
.device_count
);
423 /* Enumeration only stops with an explicit DIENUM_STOP. */
424 enum_test_return
.device_count
= 0;
425 enum_test_return
.return_value
= 42;
426 hr
= IDirectInput8_EnumDevices(pDI
, 0, enum_devices_callback
, &enum_test_return
, 0);
427 ok(hr
== DI_OK
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
428 ok(enum_test_return
.device_count
== enum_test
.device_count
,
429 "Device count is %u vs. %u\n", enum_test_return
.device_count
, enum_test
.device_count
);
431 enum_test
.device_count
= 0;
432 enum_test
.return_value
= DIENUM_STOP
;
433 hr
= IDirectInput8_EnumDevices(pDI
, 0, enum_devices_callback
, &enum_test
, 0);
434 ok(hr
== DI_OK
, "IDirectInput8_EnumDevices returned 0x%08x\n", hr
);
435 ok(enum_test
.device_count
== 1, "Device count is %u\n", enum_test
.device_count
);
437 IDirectInput8_Release(pDI
);
440 struct enum_semantics_test
442 unsigned int device_count
;
443 DWORD first_remaining
;
446 DIACTIONFORMATA
*lpdiaf
;
447 const char* username
;
450 static DIACTIONA actionMapping
[]=
453 { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */, 0, { "Steer.\0" } },
455 { 1, 0x01000C01 /* DIBUTTON_DRIVINGR_SHIFTUP */, 0, { "Upshift.\0" } },
457 { 2, DIKEYBOARD_SPACE
, 0, { "Missile.\0" } },
459 { 3, DIMOUSE_BUTTON0
, 0, { "Select\0" } },
461 { 4, DIMOUSE_YAXIS
, 0, { "Y Axis\0" } }
463 /* By placing the memory pointed to by lptszActionName right before memory with PAGE_NOACCESS
464 * one can find out that the regular ansi string termination is not respected by EnumDevicesBySemantics.
465 * Adding a double termination, making it a valid wide string termination, made the test succeed.
466 * Therefore it looks like ansi version of EnumDevicesBySemantics forwards the string to
467 * the wide variant without conversation. */
469 static BOOL CALLBACK
enum_semantics_callback(const DIDEVICEINSTANCEA
*lpddi
, IDirectInputDevice8A
*lpdid
, DWORD dwFlags
, DWORD dwRemaining
, void *context
)
471 struct enum_semantics_test
*data
= context
;
473 if (context
== NULL
) return DIENUM_STOP
;
475 if (!data
->device_count
) {
476 data
->first_remaining
= dwRemaining
;
478 ok (dwRemaining
== data
->first_remaining
- data
->device_count
,
479 "enum semantics remaining devices is wrong, expected %d, had %d\n",
480 data
->first_remaining
- data
->device_count
, dwRemaining
);
481 data
->device_count
++;
483 if (IsEqualGUID(&lpddi
->guidInstance
, &GUID_SysKeyboard
)) data
->keyboard
= TRUE
;
485 if (IsEqualGUID(&lpddi
->guidInstance
, &GUID_SysMouse
)) data
->mouse
= TRUE
;
487 return DIENUM_CONTINUE
;
490 static BOOL CALLBACK
set_action_map_callback(const DIDEVICEINSTANCEA
*lpddi
, IDirectInputDevice8A
*lpdid
, DWORD dwFlags
, DWORD dwRemaining
, void *context
)
493 struct enum_semantics_test
*data
= context
;
495 /* Building and setting an action map */
496 /* It should not use any pre-stored mappings so we use DIDBAM_INITIALIZE */
497 hr
= IDirectInputDevice8_BuildActionMap(lpdid
, data
->lpdiaf
, NULL
, DIDBAM_INITIALIZE
);
498 ok (SUCCEEDED(hr
), "BuildActionMap failed hr=%08x\n", hr
);
500 hr
= IDirectInputDevice8_SetActionMap(lpdid
, data
->lpdiaf
, data
->username
, 0);
501 ok (SUCCEEDED(hr
), "SetActionMap failed hr=%08x\n", hr
);
503 return DIENUM_CONTINUE
;
506 static void test_EnumDevicesBySemantics(void)
510 DIACTIONFORMATA diaf
;
511 const GUID ACTION_MAPPING_GUID
= { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
512 struct enum_semantics_test data
= { 0, 0, FALSE
, FALSE
, &diaf
, NULL
};
513 int device_total
= 0;
515 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
518 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
522 memset (&diaf
, 0, sizeof(diaf
));
523 diaf
.dwSize
= sizeof(diaf
);
524 diaf
.dwActionSize
= sizeof(DIACTIONA
);
525 diaf
.dwNumActions
= ARRAY_SIZE(actionMapping
);
526 diaf
.dwDataSize
= 4 * diaf
.dwNumActions
;
527 diaf
.rgoAction
= actionMapping
;
528 diaf
.guidActionMap
= ACTION_MAPPING_GUID
;
529 diaf
.dwGenre
= 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
530 diaf
.dwBufferSize
= 32;
532 /* Test enumerating all attached and installed devices */
533 data
.keyboard
= FALSE
;
535 data
.device_count
= 0;
536 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_ATTACHEDONLY
);
537 ok (data
.device_count
> 0, "EnumDevicesBySemantics did not call the callback hr=%08x\n", hr
);
538 ok (data
.keyboard
, "EnumDevicesBySemantics should enumerate the keyboard\n");
539 ok (data
.mouse
, "EnumDevicesBySemantics should enumerate the mouse\n");
541 /* Enumerate Force feedback devices. We should get no mouse nor keyboard */
542 data
.keyboard
= FALSE
;
544 data
.device_count
= 0;
545 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_FORCEFEEDBACK
);
546 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
547 ok (!data
.keyboard
, "Keyboard should not be enumerated when asking for forcefeedback\n");
548 ok (!data
.mouse
, "Mouse should not be enumerated when asking for forcefeedback\n");
550 /* Enumerate available devices. That is devices not owned by any user.
551 Before setting the action map for all devices we still have them available. */
552 data
.device_count
= 0;
553 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_AVAILABLEDEVICES
);
554 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
555 ok (data
.device_count
> 0, "There should be devices available before action mapping available=%d\n", data
.device_count
);
557 /* Keep the device total */
558 device_total
= data
.device_count
;
560 /* There should be no devices for any user. No device should be enumerated with DIEDBSFL_THISUSER.
561 MSDN defines that all unowned devices are also enumerated but this doesn't seem to be happening. */
562 data
.device_count
= 0;
563 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, "Sh4d0w M4g3", &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_THISUSER
);
564 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
565 ok (data
.device_count
== 0, "No devices should be assigned for this user assigned=%d\n", data
.device_count
);
567 /* This enumeration builds and sets the action map for all devices with a NULL username */
568 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, set_action_map_callback
, &data
, DIEDBSFL_ATTACHEDONLY
);
569 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed: hr=%08x\n", hr
);
571 /* After a successful action mapping we should have no devices available */
572 data
.device_count
= 0;
573 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_AVAILABLEDEVICES
);
574 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
575 ok (data
.device_count
== 0, "No device should be available after action mapping available=%d\n", data
.device_count
);
577 /* Now we'll give all the devices to a specific user */
578 data
.username
= "Sh4d0w M4g3";
579 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, set_action_map_callback
, &data
, DIEDBSFL_ATTACHEDONLY
);
580 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed: hr=%08x\n", hr
);
582 /* Testing with the default user, DIEDBSFL_THISUSER has no effect */
583 data
.device_count
= 0;
584 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_THISUSER
);
585 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
586 ok (data
.device_count
== device_total
, "THISUSER has no effect with NULL username owned=%d, expected=%d\n", data
.device_count
, device_total
);
588 /* Using an empty user string is the same as passing NULL, DIEDBSFL_THISUSER has no effect */
589 data
.device_count
= 0;
590 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, "", &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_THISUSER
);
591 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
592 ok (data
.device_count
== device_total
, "THISUSER has no effect with \"\" as username owned=%d, expected=%d\n", data
.device_count
, device_total
);
594 /* Testing with a user with no ownership of the devices */
595 data
.device_count
= 0;
596 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, "Ninja Brian", &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_THISUSER
);
597 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
598 ok (data
.device_count
== 0, "This user should own no devices owned=%d\n", data
.device_count
);
600 /* Sh4d0w M4g3 has ownership of all devices */
601 data
.device_count
= 0;
602 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, "Sh4d0w M4g3", &diaf
, enum_semantics_callback
, &data
, DIEDBSFL_THISUSER
);
603 ok (SUCCEEDED(hr
), "EnumDevicesBySemantics failed hr=%08x\n", hr
);
604 ok (data
.device_count
== device_total
, "This user should own %d devices owned=%d\n", device_total
, data
.device_count
);
606 /* The call fails with a zeroed GUID */
607 memset(&diaf
.guidActionMap
, 0, sizeof(GUID
));
608 data
.device_count
= 0;
609 hr
= IDirectInput8_EnumDevicesBySemantics(pDI
, NULL
, &diaf
, enum_semantics_callback
, NULL
, 0);
610 todo_wine
ok(FAILED(hr
), "EnumDevicesBySemantics succeeded with invalid GUID hr=%08x\n", hr
);
612 IDirectInput8_Release(pDI
);
615 static void test_GetDeviceStatus(void)
620 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
623 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
627 hr
= IDirectInput8_GetDeviceStatus(pDI
, NULL
);
628 ok(hr
== E_POINTER
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
630 hr
= IDirectInput8_GetDeviceStatus(pDI
, &GUID_Unknown
);
632 ok(hr
== DIERR_DEVICENOTREG
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
634 hr
= IDirectInput8_GetDeviceStatus(pDI
, &GUID_SysMouse
);
635 ok(hr
== DI_OK
, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr
);
637 IDirectInput8_Release(pDI
);
640 static void test_RunControlPanel(void)
645 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
648 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
652 if (winetest_interactive
)
654 hr
= IDirectInput8_RunControlPanel(pDI
, NULL
, 0);
655 ok(hr
== S_OK
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
657 hr
= IDirectInput8_RunControlPanel(pDI
, GetDesktopWindow(), 0);
658 ok(hr
== S_OK
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
661 hr
= IDirectInput8_RunControlPanel(pDI
, NULL
, ~0u);
662 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
664 hr
= IDirectInput8_RunControlPanel(pDI
, (HWND
)0xdeadbeef, 0);
665 ok(hr
== E_HANDLE
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
667 hr
= IDirectInput8_RunControlPanel(pDI
, (HWND
)0xdeadbeef, ~0u);
668 ok(hr
== E_HANDLE
, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr
);
670 IDirectInput8_Release(pDI
);
673 static void test_Initialize(void)
678 hr
= DirectInput8Create(hInstance
, DIRECTINPUT_VERSION
, &IID_IDirectInput8A
, (void **)&pDI
, NULL
);
681 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr
);
685 hr
= IDirectInput8_Initialize(pDI
, NULL
, 0);
686 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
688 hr
= IDirectInput8_Initialize(pDI
, NULL
, DIRECTINPUT_VERSION
);
689 ok(hr
== DIERR_INVALIDPARAM
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
691 hr
= IDirectInput8_Initialize(pDI
, hInstance
, 0);
692 ok(hr
== DIERR_NOTINITIALIZED
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
694 /* Invalid DirectInput versions less than DIRECTINPUT_VERSION yield DIERR_BETADIRECTINPUTVERSION. */
695 hr
= IDirectInput8_Initialize(pDI
, hInstance
, DIRECTINPUT_VERSION
- 1);
696 ok(hr
== DIERR_BETADIRECTINPUTVERSION
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
698 /* Invalid DirectInput versions greater than DIRECTINPUT_VERSION yield DIERR_BETADIRECTINPUTVERSION. */
699 hr
= IDirectInput8_Initialize(pDI
, hInstance
, DIRECTINPUT_VERSION
+ 1);
700 ok(hr
== DIERR_OLDDIRECTINPUTVERSION
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
702 hr
= IDirectInput8_Initialize(pDI
, hInstance
, DIRECTINPUT_VERSION
);
703 ok(hr
== DI_OK
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
705 /* Parameters are still validated after successful initialization. */
706 hr
= IDirectInput8_Initialize(pDI
, hInstance
, 0);
707 ok(hr
== DIERR_NOTINITIALIZED
, "IDirectInput8_Initialize returned 0x%08x\n", hr
);
709 IDirectInput8_Release(pDI
);
714 hInstance
= GetModuleHandleA(NULL
);
717 test_preinitialization();
718 test_DirectInput8Create();
719 test_QueryInterface();
722 test_EnumDevicesBySemantics();
723 test_GetDeviceStatus();
724 test_RunControlPanel();