2 * Copyright (c) 2004-2005 Robert Reif
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 0x0700
28 #include "wine/test.h"
33 typedef struct tagUserData
{
38 static const DIOBJECTDATAFORMAT dfDIJoystickTest
[] = {
39 { &GUID_XAxis
,DIJOFS_X
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
40 { &GUID_YAxis
,DIJOFS_Y
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
41 { &GUID_ZAxis
,DIJOFS_Z
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
42 { &GUID_RxAxis
,DIJOFS_RX
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
43 { &GUID_RyAxis
,DIJOFS_RY
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
44 { &GUID_RzAxis
,DIJOFS_RZ
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
45 { &GUID_Button
,DIJOFS_BUTTON(0),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
46 { &GUID_Button
,DIJOFS_BUTTON(1),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
47 { &GUID_Button
,DIJOFS_BUTTON(2),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
48 { &GUID_Button
,DIJOFS_BUTTON(3),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
49 { &GUID_Button
,DIJOFS_BUTTON(4),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
50 { &GUID_Button
,DIJOFS_BUTTON(5),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
51 { &GUID_Button
,DIJOFS_BUTTON(6),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
52 { &GUID_Button
,DIJOFS_BUTTON(7),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
53 { &GUID_Button
,DIJOFS_BUTTON(8),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
54 { &GUID_Button
,DIJOFS_BUTTON(9),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
55 { &GUID_Button
,DIJOFS_BUTTON(10),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
58 static const DIDATAFORMAT c_dfDIJoystickTest
= {
60 sizeof(DIOBJECTDATAFORMAT
),
63 ARRAY_SIZE(dfDIJoystickTest
),
64 (LPDIOBJECTDATAFORMAT
)dfDIJoystickTest
67 static HWND
get_hwnd(void)
69 HWND hwnd
=GetForegroundWindow();
71 hwnd
=GetDesktopWindow();
75 typedef struct tagJoystickInfo
77 IDirectInputDeviceA
*pJoystick
;
85 static int get_refcount(IUnknown
*object
)
87 IUnknown_AddRef( object
);
88 return IUnknown_Release( object
);
91 static BOOL CALLBACK
EnumAxes(const DIDEVICEOBJECTINSTANCEA
*pdidoi
, void *pContext
)
94 JoystickInfo
* info
= pContext
;
96 if (IsEqualIID(&pdidoi
->guidType
, &GUID_XAxis
) ||
97 IsEqualIID(&pdidoi
->guidType
, &GUID_YAxis
) ||
98 IsEqualIID(&pdidoi
->guidType
, &GUID_ZAxis
) ||
99 IsEqualIID(&pdidoi
->guidType
, &GUID_RxAxis
) ||
100 IsEqualIID(&pdidoi
->guidType
, &GUID_RyAxis
) ||
101 IsEqualIID(&pdidoi
->guidType
, &GUID_RzAxis
) ||
102 IsEqualIID(&pdidoi
->guidType
, &GUID_Slider
))
107 diprg
.diph
.dwSize
= sizeof(DIPROPRANGE
);
108 diprg
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
109 diprg
.diph
.dwHow
= DIPH_BYID
;
110 diprg
.diph
.dwObj
= pdidoi
->dwType
;
112 dipdw
.diph
.dwSize
= sizeof(dipdw
);
113 dipdw
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
114 dipdw
.diph
.dwHow
= DIPH_BYID
;
115 dipdw
.diph
.dwObj
= pdidoi
->dwType
;
117 hr
= IDirectInputDevice_GetProperty(info
->pJoystick
, DIPROP_RANGE
, &diprg
.diph
);
118 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
119 ok(info
->lMin
== diprg
.lMin
&& info
->lMax
== diprg
.lMax
, "Min/Max range invalid: "
120 "expected %d..%d got %d..%d\n", info
->lMin
, info
->lMax
, diprg
.lMin
, diprg
.lMax
);
125 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_RANGE
, NULL
);
126 ok(hr
==E_INVALIDARG
,"IDirectInputDevice_SetProperty() should have returned "
127 "E_INVALIDARG, returned: %08x\n", hr
);
129 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_RANGE
, &diprg
.diph
);
130 ok(hr
==DI_OK
,"IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
133 hr
= IDirectInputDevice_GetProperty(info
->pJoystick
, DIPROP_DEADZONE
, &dipdw
.diph
);
134 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
135 ok(info
->dZone
== dipdw
.dwData
, "deadzone invalid: expected %d got %d\n",
136 info
->dZone
, dipdw
.dwData
);
140 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_DEADZONE
, &dipdw
.diph
);
141 ok(hr
==DI_OK
,"IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
143 /* ensure DIDOI_ASPECTPOSITION is set for axes objects */
144 ok(pdidoi
->dwFlags
& DIDOI_ASPECTPOSITION
, "Missing DIDOI_ASPECTPOSITION, flags are 0x%x\n",
148 } else if (IsEqualIID(&pdidoi
->guidType
, &GUID_POV
))
150 else if (IsEqualIID(&pdidoi
->guidType
, &GUID_Button
))
153 return DIENUM_CONTINUE
;
156 static const struct effect_id
161 } effect_conversion
[] = {
162 {&GUID_ConstantForce
, DIEFT_CONSTANTFORCE
, "Constant"},
163 {&GUID_RampForce
, DIEFT_RAMPFORCE
, "Ramp"},
164 {&GUID_Square
, DIEFT_PERIODIC
, "Square"},
165 {&GUID_Sine
, DIEFT_PERIODIC
, "Sine"},
166 {&GUID_Triangle
, DIEFT_PERIODIC
, "Triangle"},
167 {&GUID_SawtoothUp
, DIEFT_PERIODIC
, "Saw Tooth Up"},
168 {&GUID_SawtoothDown
, DIEFT_PERIODIC
, "Saw Tooth Down"},
169 {&GUID_Spring
, DIEFT_CONDITION
, "Spring"},
170 {&GUID_Damper
, DIEFT_CONDITION
, "Damper"},
171 {&GUID_Inertia
, DIEFT_CONDITION
, "Inertia"},
172 {&GUID_Friction
, DIEFT_CONDITION
, "Friction"},
173 {&GUID_CustomForce
, DIEFT_CUSTOMFORCE
, "Custom"}
176 static const struct effect_id
* effect_from_guid(const GUID
*guid
)
179 for (i
= 0; i
< ARRAY_SIZE(effect_conversion
); i
++)
180 if (IsEqualGUID(guid
, effect_conversion
[i
].guid
))
181 return &effect_conversion
[i
];
190 const char *effect_name
;
193 /* The last enumerated effect will be used for force feedback testing */
194 static BOOL CALLBACK
EnumEffects(const DIEFFECTINFOA
*lpef
, void *ref
)
196 const struct effect_id
*id
= effect_from_guid(&lpef
->guid
);
199 DICONSTANTFORCE constant
;
202 DICONDITION condition
[2];
204 struct effect_enum
*data
= ref
;
205 int type
= DIDFT_GETTYPE(lpef
->dwEffType
);
210 ok(0, "unsupported effect enumerated, GUID %s!\n", wine_dbgstr_guid(&lpef
->guid
));
211 return DIENUM_CONTINUE
;
213 trace("controller supports '%s' effect\n", id
->name
);
214 ok(type
== id
->dieft
, "Invalid effect type, expected 0x%x, got 0x%x\n",
215 id
->dieft
, lpef
->dwEffType
);
217 /* Can't use custom for test as we don't know the data format */
218 if (type
== DIEFT_CUSTOMFORCE
)
219 return DIENUM_CONTINUE
;
221 data
->effect_count
++;
222 data
->effect_name
= id
->name
;
223 data
->guid
= *id
->guid
;
225 ZeroMemory(&specific
, sizeof(specific
));
229 data
->eff
.cbTypeSpecificParams
= sizeof(specific
.periodic
);
230 data
->eff
.lpvTypeSpecificParams
= &specific
.periodic
;
231 specific
.periodic
.dwMagnitude
= DI_FFNOMINALMAX
/ 2;
232 specific
.periodic
.dwPeriod
= DI_SECONDS
; /* 1 second */
234 case DIEFT_CONSTANTFORCE
:
235 data
->eff
.cbTypeSpecificParams
= sizeof(specific
.constant
);
236 data
->eff
.lpvTypeSpecificParams
= &specific
.constant
;
237 specific
.constant
.lMagnitude
= DI_FFNOMINALMAX
/ 2;
239 case DIEFT_RAMPFORCE
:
240 data
->eff
.cbTypeSpecificParams
= sizeof(specific
.ramp
);
241 data
->eff
.lpvTypeSpecificParams
= &specific
.ramp
;
242 specific
.ramp
.lStart
= -DI_FFNOMINALMAX
/ 2;
243 specific
.ramp
.lEnd
= +DI_FFNOMINALMAX
/ 2;
245 case DIEFT_CONDITION
:
248 data
->eff
.cbTypeSpecificParams
= sizeof(specific
.condition
);
249 data
->eff
.lpvTypeSpecificParams
= specific
.condition
;
250 for (i
= 0; i
< 2; i
++)
252 specific
.condition
[i
].lNegativeCoefficient
= -DI_FFNOMINALMAX
/ 2;
253 specific
.condition
[i
].lPositiveCoefficient
= +DI_FFNOMINALMAX
/ 2;
258 return DIENUM_CONTINUE
;
261 static const HRESULT SetCoop_null_window
[16] = {
262 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
,
263 E_INVALIDARG
, E_HANDLE
, E_HANDLE
, E_INVALIDARG
,
264 E_INVALIDARG
, E_HANDLE
, S_OK
, E_INVALIDARG
,
265 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
};
267 static const HRESULT SetCoop_real_window
[16] = {
268 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
,
269 E_INVALIDARG
, S_OK
, S_OK
, E_INVALIDARG
,
270 E_INVALIDARG
, S_OK
, S_OK
, E_INVALIDARG
,
271 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
};
273 static BOOL CALLBACK
EnumAllFeedback(const DIDEVICEINSTANCEA
*lpddi
, void *pvRef
)
275 trace("---- Device Information ----\n"
276 "Product Name : %s\n"
277 "Instance Name : %s\n"
279 "GUID Product : %s\n"
280 "GUID Instance : %s\n"
281 "HID Page : 0x%04x\n"
282 "HID Usage : 0x%04x\n",
283 lpddi
->tszProductName
,
284 lpddi
->tszInstanceName
,
286 wine_dbgstr_guid(&lpddi
->guidProduct
),
287 wine_dbgstr_guid(&lpddi
->guidInstance
),
291 ok(!(IsEqualGUID(&GUID_SysMouse
, &lpddi
->guidProduct
) || IsEqualGUID(&GUID_SysKeyboard
, &lpddi
->guidProduct
)), "Invalid device returned.\n");
293 return DIENUM_CONTINUE
;
296 static BOOL CALLBACK
EnumJoysticks(const DIDEVICEINSTANCEA
*lpddi
, void *pvRef
)
299 UserData
* data
= pvRef
;
300 IDirectInputDeviceA
*pJoystick
;
307 DIDEVICEINSTANCEA inst
;
308 DIDEVICEINSTANCE_DX3A inst3
;
311 DIPROPGUIDANDPATH dpg
;
312 WCHAR nameBuffer
[MAX_PATH
];
313 HWND hWnd
= get_hwnd();
314 char oldstate
[248], curstate
[248];
315 DWORD axes
[2] = {DIJOFS_X
, DIJOFS_Y
};
316 LONG direction
[2] = {0, 0};
317 LPDIRECTINPUTEFFECT effect
= NULL
;
320 HINSTANCE hInstance
= GetModuleHandleW(NULL
);
321 DIPROPDWORD dip_gain_set
, dip_gain_get
;
322 struct effect_enum effect_data
;
324 ok(data
->version
>= 0x0300, "Joysticks not supported in version 0x%04x\n", data
->version
);
326 hr
= IDirectInput_CreateDevice(data
->pDI
, &lpddi
->guidInstance
, NULL
, NULL
);
327 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
328 "E_POINTER, returned: %08x\n", hr
);
330 hr
= IDirectInput_CreateDevice(data
->pDI
, NULL
, &pJoystick
, NULL
);
331 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
332 "E_POINTER, returned: %08x\n", hr
);
334 hr
= IDirectInput_CreateDevice(data
->pDI
, NULL
, NULL
, NULL
);
335 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
336 "E_POINTER, returned: %08x\n", hr
);
338 hr
= IDirectInput_CreateDevice(data
->pDI
, &lpddi
->guidInstance
,
340 ok(hr
==DI_OK
,"IDirectInput_CreateDevice() failed: %08x\n", hr
);
344 trace("---- Controller Information ----\n"
345 "Product Name : %s\n"
346 "Instance Name : %s\n"
348 "GUID Product : %s\n"
349 "GUID Instance : %s\n"
350 "HID Page : 0x%04x\n"
351 "HID Usage : 0x%04x\n",
352 lpddi
->tszProductName
,
353 lpddi
->tszInstanceName
,
355 wine_dbgstr_guid(&lpddi
->guidProduct
),
356 wine_dbgstr_guid(&lpddi
->guidInstance
),
360 /* Check if this is a HID device */
361 if (lpddi
->dwDevType
& DIDEVTYPE_HID
)
362 ok(lpddi
->wUsagePage
== 0x01 && (lpddi
->wUsage
== 0x04 || lpddi
->wUsage
== 0x05),
363 "Expected a game controller HID UsagePage and Usage, got page 0x%x usage 0x%x\n",
364 lpddi
->wUsagePage
, lpddi
->wUsage
);
366 /* Test for joystick ID property */
367 ZeroMemory(&dipw
, sizeof(dipw
));
368 dipw
.diph
.dwSize
= sizeof(DIPROPDWORD
);
369 dipw
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
371 dipw
.diph
.dwHow
= DIPH_DEVICE
;
373 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_JOYSTICKID
, &dipw
.diph
);
374 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() for DIPROP_JOYSTICKID failed\n");
376 /* Test for INSTANCENAME property */
377 memset(&dps
, 0, sizeof(dps
));
378 dps
.diph
.dwSize
= sizeof(DIPROPSTRING
);
379 dps
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
380 dps
.diph
.dwHow
= DIPH_DEVICE
;
382 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_INSTANCENAME
, &dps
.diph
);
383 ok(SUCCEEDED(hr
), "IDirectInput_GetProperty() for DIPROP_INSTANCENAME failed: %08x\n", hr
);
385 /* Test if instance name is the same as present in DIDEVICEINSTANCE */
386 MultiByteToWideChar(CP_ACP
, 0, lpddi
->tszInstanceName
, -1, nameBuffer
, MAX_PATH
);
387 ok(!lstrcmpW(nameBuffer
, dps
.wsz
), "DIPROP_INSTANCENAME returned is wrong. Expected: %s Got: %s\n",
388 wine_dbgstr_w(nameBuffer
), wine_dbgstr_w(dps
.wsz
));
390 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_PRODUCTNAME
, &dps
.diph
);
391 ok(SUCCEEDED(hr
), "IDirectInput_GetProperty() for DIPROP_PRODUCTNAME failed: %08x\n", hr
);
393 /* Test if product name is the same as present in DIDEVICEINSTANCE */
394 MultiByteToWideChar(CP_ACP
, 0, lpddi
->tszProductName
, -1, nameBuffer
, MAX_PATH
);
395 ok(!lstrcmpW(nameBuffer
, dps
.wsz
), "DIPROP_PRODUCTNAME returned is wrong. Expected: %s Got: %s\n",
396 wine_dbgstr_w(nameBuffer
), wine_dbgstr_w(dps
.wsz
));
398 /* Test for GUIDPATH properties */
399 memset(&dpg
, 0, sizeof(dpg
));
400 dpg
.diph
.dwSize
= sizeof(DIPROPGUIDANDPATH
);
401 dpg
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
402 dpg
.diph
.dwHow
= DIPH_DEVICE
;
404 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_GUIDANDPATH
, &dpg
.diph
);
405 ok(SUCCEEDED(hr
), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr
);
408 static const WCHAR formatW
[] = {'\\','\\','?','\\','%','*','[','^','#',']','#','v','i','d','_',
409 '%','0','4','x','&','p','i','d','_','%','0','4','x',0};
410 static const WCHAR miW
[] = {'m','i','_',0};
411 static const WCHAR igW
[] = {'i','g','_',0};
414 _wcslwr(dpg
.wszPath
);
415 count
= swscanf(dpg
.wszPath
, formatW
, &vid
, &pid
);
416 ok(count
== 2, "DIPROP_GUIDANDPATH path has wrong format. Expected count: 2 Got: %i Path: %s\n",
417 count
, wine_dbgstr_w(dpg
.wszPath
));
418 ok(wcsstr(dpg
.wszPath
, miW
) != 0 || wcsstr(dpg
.wszPath
, igW
) != 0,
419 "DIPROP_GUIDANDPATH path should contain either 'ig_' or 'mi_' substring. Path: %s\n",
420 wine_dbgstr_w(dpg
.wszPath
));
423 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, NULL
);
424 ok(hr
==E_POINTER
,"IDirectInputDevice_SetDataFormat() should have returned "
425 "E_POINTER, returned: %08x\n", hr
);
427 ZeroMemory(&format
, sizeof(format
));
428 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &format
);
429 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputDevice_SetDataFormat() should have "
430 "returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
432 /* try the default formats */
433 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick
);
434 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
436 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
437 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
439 /* try an alternate format */
440 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystickTest
);
441 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
443 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
444 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
450 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, NULL
, i
);
451 ok(hr
== SetCoop_null_window
[i
], "SetCooperativeLevel(NULL, %d): %08x\n", i
, hr
);
455 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
, i
);
456 ok(hr
== SetCoop_real_window
[i
], "SetCooperativeLevel(hwnd, %d): %08x\n", i
, hr
);
459 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
,
460 DISCL_NONEXCLUSIVE
| DISCL_BACKGROUND
);
461 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
463 /* get capabilities */
464 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, NULL
);
465 ok(hr
==E_POINTER
,"IDirectInputDevice_GetCapabilities() "
466 "should have returned E_POINTER, returned: %08x\n", hr
);
468 ZeroMemory(&caps
, sizeof(caps
));
469 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, &caps
);
470 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputDevice_GetCapabilities() "
471 "should have returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
473 caps
.dwSize
= sizeof(caps
);
474 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, &caps
);
475 ok(hr
==DI_OK
,"IDirectInputDevice_GetCapabilities() failed: %08x\n", hr
);
477 ZeroMemory(&info
, sizeof(info
));
478 info
.pJoystick
= pJoystick
;
480 /* default min/max limits */
483 /* enumerate objects */
484 hr
= IDirectInputDevice_EnumObjects(pJoystick
, EnumAxes
, &info
, DIDFT_ALL
);
485 ok(hr
==DI_OK
,"IDirectInputDevice_EnumObjects() failed: %08x\n", hr
);
487 ok(caps
.dwAxes
== info
.axis
, "Number of enumerated axes (%d) doesn't match capabilities (%d)\n", info
.axis
, caps
.dwAxes
);
488 ok(caps
.dwButtons
== info
.button
, "Number of enumerated buttons (%d) doesn't match capabilities (%d)\n", info
.button
, caps
.dwButtons
);
489 ok(caps
.dwPOVs
== info
.pov
, "Number of enumerated POVs (%d) doesn't match capabilities (%d)\n", info
.pov
, caps
.dwPOVs
);
491 /* Set format and check limits again */
492 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
493 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
497 hr
= IDirectInputDevice_EnumObjects(pJoystick
, EnumAxes
, &info
, DIDFT_ALL
);
498 ok(hr
==DI_OK
,"IDirectInputDevice_EnumObjects() failed: %08x\n", hr
);
500 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, 0);
501 ok(hr
==E_POINTER
, "IDirectInputDevice_GetDeviceInfo() "
502 "should have returned E_POINTER, returned: %08x\n", hr
);
504 ZeroMemory(&inst
, sizeof(inst
));
505 ZeroMemory(&inst3
, sizeof(inst3
));
507 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, &inst
);
508 ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_GetDeviceInfo() "
509 "should have returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
511 inst
.dwSize
= sizeof(inst
);
512 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, &inst
);
513 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceInfo() failed: %08x\n", hr
);
515 inst3
.dwSize
= sizeof(inst3
);
516 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, (DIDEVICEINSTANCEA
*)&inst3
);
517 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceInfo() failed: %08x\n", hr
);
519 hr
= IDirectInputDevice_Unacquire(pJoystick
);
520 ok(hr
== S_FALSE
, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %08x\n", hr
);
522 hr
= IDirectInputDevice_Acquire(pJoystick
);
523 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
527 hr
= IDirectInputDevice_Acquire(pJoystick
);
528 ok(hr
== S_FALSE
, "IDirectInputDevice_Acquire() should have returned S_FALSE, got: %08x\n", hr
);
532 hr
= IDirectInputDevice_GetDeviceState(pJoystick
, sizeof(DIJOYSTATE2
), &js
);
533 ok(hr
== DI_OK
, "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr
);
534 ok(js
.rgdwPOV
[3] == -1, "Default for unassigned POV should be -1 not: %d\n", js
.rgdwPOV
[3]);
537 trace("Testing force feedback\n");
538 ZeroMemory(&effect_data
, sizeof(effect_data
));
539 effect_data
.eff
.dwSize
= sizeof(effect_data
.eff
);
540 effect_data
.eff
.dwFlags
= DIEFF_CARTESIAN
| DIEFF_OBJECTOFFSETS
;
541 effect_data
.eff
.dwDuration
= INFINITE
;
542 effect_data
.eff
.dwGain
= DI_FFNOMINALMAX
;
543 effect_data
.eff
.dwTriggerButton
= DIEB_NOTRIGGER
;
544 effect_data
.eff
.cAxes
= ARRAY_SIZE(axes
);
545 effect_data
.eff
.rgdwAxes
= axes
;
546 effect_data
.eff
.rglDirection
= direction
;
548 /* Sending effects to joystick requires
549 * calling IDirectInputEffect_Initialize, which requires
550 * having exclusive access to the device, which requires
551 * - not having acquired the joystick when calling
552 * IDirectInputDevice_SetCooperativeLevel
555 real_hWnd
= CreateWindowExA(0, "EDIT", "Test text", 0, 10, 10, 300, 300, NULL
, NULL
,
557 ok(real_hWnd
!=0,"CreateWindowExA failed: %p\n", real_hWnd
);
558 ShowWindow(real_hWnd
, SW_SHOW
);
559 hr
= IDirectInputDevice_Unacquire(pJoystick
);
560 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
561 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, real_hWnd
,
562 DISCL_EXCLUSIVE
| DISCL_FOREGROUND
);
563 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
564 hr
= IDirectInputDevice_Acquire(pJoystick
);
565 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
567 cnt1
= get_refcount((IUnknown
*)pJoystick
);
569 hr
= IDirectInputDevice2_EnumEffects((IDirectInputDevice2A
*)pJoystick
, EnumEffects
, &effect_data
, DIEFT_ALL
);
570 ok(hr
==DI_OK
,"IDirectInputDevice2_EnumEffects() failed: %08x\n", hr
);
572 /* If the controller does not support ANY effect use the constant effect to make
573 * CreateEffect fail but with the unsupported reason instead of invalid parameters. */
574 if (!effect_data
.effect_count
)
576 static DICONSTANTFORCE constant
;
577 effect_data
.guid
= GUID_ConstantForce
;
578 effect_data
.eff
.cbTypeSpecificParams
= sizeof(constant
);
579 effect_data
.eff
.lpvTypeSpecificParams
= &constant
;
580 effect_data
.effect_name
= "Constant";
581 constant
.lMagnitude
= DI_FFNOMINALMAX
/ 2;
583 ok(!(caps
.dwFlags
& DIDC_FORCEFEEDBACK
), "effect count is zero but controller supports force feedback?\n");
586 effect
= (void *)0xdeadbeef;
587 hr
= IDirectInputDevice2_CreateEffect((IDirectInputDevice2A
*)pJoystick
, &effect_data
.guid
,
588 &effect_data
.eff
, &effect
, NULL
);
589 if (caps
.dwFlags
& DIDC_FORCEFEEDBACK
)
591 trace("force feedback supported with %d effects, using '%s' for test\n",
592 effect_data
.effect_count
, effect_data
.effect_name
);
593 ok(hr
== DI_OK
, "IDirectInputDevice_CreateEffect() failed: %08x\n", hr
);
594 cnt2
= get_refcount((IUnknown
*)pJoystick
);
595 ok(cnt1
== cnt2
, "Ref count is wrong %d != %d\n", cnt1
, cnt2
);
600 struct DIPROPDWORD diprop_word
;
603 DIEFFECT effect_empty
;
605 hr
= IDirectInputEffect_Initialize(effect
, hInstance
, data
->version
,
607 ok(hr
==DI_OK
,"IDirectInputEffect_Initialize failed: %08x\n", hr
);
609 /* Test SetParameters with NULL pointers */
610 tmp
= effect_data
.eff
.rgdwAxes
;
611 effect_data
.eff
.rgdwAxes
= NULL
;
612 hr
= IDirectInputEffect_SetParameters(effect
, &effect_data
.eff
, DIEP_AXES
);
613 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputEffect_SetParameters should fail with INVALIDPARAM, got: %08x\n", hr
);
614 effect_data
.eff
.rgdwAxes
= tmp
;
616 tmp
= effect_data
.eff
.rglDirection
;
617 effect_data
.eff
.rglDirection
= NULL
;
618 hr
= IDirectInputEffect_SetParameters(effect
, &effect_data
.eff
, DIEP_DIRECTION
);
619 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputEffect_SetParameters should fail with INVALIDPARAM, got: %08x\n", hr
);
620 effect_data
.eff
.rglDirection
= tmp
;
622 tmp
= effect_data
.eff
.lpvTypeSpecificParams
;
623 effect_data
.eff
.lpvTypeSpecificParams
= NULL
;
624 hr
= IDirectInputEffect_SetParameters(effect
, &effect_data
.eff
, DIEP_TYPESPECIFICPARAMS
);
625 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputEffect_SetParameters should fail with INVALIDPARAM, got: %08x\n", hr
);
626 effect_data
.eff
.lpvTypeSpecificParams
= tmp
;
628 hr
= IDirectInputEffect_SetParameters(effect
, &effect_data
.eff
, DIEP_AXES
| DIEP_DIRECTION
|
629 DIEP_TYPESPECIFICPARAMS
);
630 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
632 /* Test that upload, unacquire, acquire still permits updating
633 * uploaded effect. */
634 hr
= IDirectInputDevice_Unacquire(pJoystick
);
635 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
636 hr
= IDirectInputDevice_Acquire(pJoystick
);
637 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
638 hr
= IDirectInputEffect_SetParameters(effect
, &effect_data
.eff
, DIEP_GAIN
);
639 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
642 /* Check effect status.
643 * State: initially stopped
646 * unacquire, acquire, download
652 * - effects are stopped after Unacquire + Acquire
653 * - effects are preserved (Download + Start doesn't complain
654 * about incomplete effect)
656 hr
= IDirectInputEffect_GetEffectStatus(effect
, NULL
);
657 ok(hr
==E_POINTER
,"IDirectInputEffect_GetEffectStatus() must fail with E_POINTER, got: %08x\n", hr
);
658 effect_status
= 0xdeadbeef;
659 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
660 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
661 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
662 /* SetParameters with a zeroed-out DIEFFECT and flags=0 should do nothing. */
663 memset(&effect_empty
, 0, sizeof(effect_empty
));
664 effect_empty
.dwSize
= sizeof(effect_empty
);
665 hr
= IDirectInputEffect_SetParameters(effect
, &effect_empty
, 0);
666 ok(hr
==DI_NOEFFECT
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
667 /* Start effect with SetParameters and a zeroed-out DIEFFECT. */
668 hr
= IDirectInputEffect_SetParameters(effect
, &effect_empty
, DIEP_START
);
669 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
670 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
671 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
672 todo_wine
ok(effect_status
!=0,"IDirectInputEffect_GetEffectStatus() reported effect as stopped\n");
673 hr
= IDirectInputDevice_Unacquire(pJoystick
);
674 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
675 hr
= IDirectInputDevice_Acquire(pJoystick
);
676 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
677 hr
= IDirectInputEffect_Download(effect
);
678 ok(hr
==DI_OK
,"IDirectInputEffect_Download() failed: %08x\n", hr
);
679 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
680 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
681 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
682 hr
= IDirectInputEffect_Start(effect
, 1, 0);
683 ok(hr
==DI_OK
,"IDirectInputEffect_Start() failed: %08x\n", hr
);
684 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
685 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
686 Sleep(250); /* feel the magic */
687 todo_wine
ok(effect_status
!=0,"IDirectInputEffect_GetEffectStatus() reported effect as stopped\n");
688 hr
= IDirectInputEffect_GetEffectGuid(effect
, &guid
);
689 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectGuid() failed: %08x\n", hr
);
690 ok(IsEqualGUID(&effect_data
.guid
, &guid
), "Wrong guid returned\n");
692 /* Check autocenter status
693 * State: initially stopped
701 * IDirectInputDevice2_SetProperty(DIPROP_AUTOCENTER) can only be
702 * executed when the device is released.
704 * If Executed interactively, user can feel that autocenter is
705 * only disabled when the joystick is acquired.
707 diprop_word
.diph
.dwSize
= sizeof(diprop_word
);
708 diprop_word
.diph
.dwHeaderSize
= sizeof(diprop_word
.diph
);
709 diprop_word
.diph
.dwObj
= 0;
710 diprop_word
.diph
.dwHow
= DIPH_DEVICE
;
711 hr
= IDirectInputDevice_Unacquire(pJoystick
);
712 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
713 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
714 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
715 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_ON
,"IDirectInputDevice2_GetProperty() reported autocenter as disabled\n");
716 diprop_word
.dwData
= DIPROPAUTOCENTER_OFF
;
717 hr
= IDirectInputDevice2_SetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
718 ok(hr
==DI_OK
,"IDirectInputDevice2_SetProperty() failed: %08x\n", hr
);
719 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
720 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
721 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
722 if (winetest_interactive
) {
723 trace("Acquiring in 2s, autocenter will be disabled.\n");
726 hr
= IDirectInputDevice_Acquire(pJoystick
);
727 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
728 if (winetest_interactive
)
729 trace("Acquired.\n");
730 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
731 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
732 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
733 if (winetest_interactive
) {
734 trace("Releasing in 2s, autocenter will be re-enabled.\n");
737 hr
= IDirectInputDevice_Unacquire(pJoystick
);
738 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
739 if (winetest_interactive
)
741 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
742 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
743 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
744 hr
= IDirectInputDevice_Acquire(pJoystick
);
745 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
746 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
747 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
749 /* Device gain (DIPROP_FFGAIN).
751 * 0..10000 range, otherwise DIERR_INVALIDPARAM.
752 * Can be changed even if device is acquired.
753 * Difference found by tests:
754 * <0 is refused, >10000 is accepted
756 dip_gain_set
.diph
.dwSize
= sizeof(DIPROPDWORD
);
757 dip_gain_set
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
758 dip_gain_set
.diph
.dwObj
= 0;
759 dip_gain_set
.diph
.dwHow
= DIPH_DEVICE
;
760 dip_gain_get
.diph
.dwSize
= sizeof(DIPROPDWORD
);
761 dip_gain_get
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
762 dip_gain_get
.diph
.dwObj
= 0;
763 dip_gain_get
.diph
.dwHow
= DIPH_DEVICE
;
764 dip_gain_get
.dwData
= 0;
766 /* Test device is acquisition (non)impact. */
767 hr
= IDirectInputDevice_Unacquire(pJoystick
);
768 ok(hr
== DI_OK
, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %08x\n", hr
);
769 dip_gain_set
.dwData
= 1;
770 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
771 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
772 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
773 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
774 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
775 hr
= IDirectInputDevice_Acquire(pJoystick
);
776 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
777 dip_gain_set
.dwData
= 2;
778 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
779 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
780 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
781 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
782 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
783 /* Test range and internal clamping. */
784 dip_gain_set
.dwData
= -1;
785 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
786 todo_wine
ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_SetProperty() should have returned %08x: %08x\n", DIERR_INVALIDPARAM
, hr
);
787 dip_gain_set
.dwData
= 0;
788 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
789 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
790 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
791 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
792 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
793 dip_gain_set
.dwData
= 10000;
794 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
795 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
796 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
797 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
798 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
799 /* WARNING: This call succeeds, on the contrary of what is stated on MSDN. */
800 dip_gain_set
.dwData
= 10001;
801 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
802 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
803 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
804 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
805 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
807 /* Test SendForceFeedbackCommand
808 * DISFFC_STOPALL - Should stop effects only
809 * DISFFC_RESET - Should stop effects and unload them (NOT release them)
810 * Tests for game Odallus (bug 41623) */
811 hr
= IDirectInputDevice2_SendForceFeedbackCommand((IDirectInputDevice2A
*)pJoystick
, 0);
812 ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_SendForceFeedbackCommand() failed: %08x\n", hr
);
813 hr
= IDirectInputDevice2_SendForceFeedbackCommand((IDirectInputDevice2A
*)pJoystick
, 0xFF);
814 ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_SendForceFeedbackCommand() failed: %08x\n", hr
);
816 hr
= IDirectInputEffect_Download(effect
);
817 ok(hr
==DI_OK
,"IDirectInputEffect_Download() failed: %08x\n", hr
);
819 /* Send STOPALL and prove that the effect can still be started */
820 hr
= IDirectInputDevice2_SendForceFeedbackCommand((IDirectInputDevice2A
*)pJoystick
, DISFFC_STOPALL
);
821 ok(hr
==DI_OK
, "IDirectInputDevice_SendForceFeedbackCommand() failed: %08x\n", hr
);
822 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
823 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
824 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
825 hr
= IDirectInputEffect_Start(effect
, 1, 0);
826 ok(hr
==DI_OK
,"IDirectInputEffect_Start() failed: %08x\n", hr
);
827 hr
= IDirectInputEffect_GetEffectGuid(effect
, &guid
);
828 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectGuid() failed: %08x\n", hr
);
829 ok(IsEqualGUID(&effect_data
.guid
, &guid
), "Wrong guid returned\n");
831 /* Send RESET and prove that we can still manipulate the effect, thus not released */
832 hr
= IDirectInputDevice2_SendForceFeedbackCommand((IDirectInputDevice2A
*)pJoystick
, DISFFC_RESET
);
833 ok(hr
==DI_OK
, "IDirectInputDevice_SendForceFeedbackCommand() failed: %08x\n", hr
);
834 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
835 ok(hr
==DIERR_NOTDOWNLOADED
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
836 hr
= IDirectInputEffect_Download(effect
);
837 ok(hr
==DI_OK
,"IDirectInputEffect_Download() failed: %08x\n", hr
);
838 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
839 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
840 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
841 hr
= IDirectInputEffect_Start(effect
, 1, 0);
842 ok(hr
==DI_OK
,"IDirectInputEffect_Start() failed: %08x\n", hr
);
843 hr
= IDirectInputEffect_GetEffectGuid(effect
, &guid
);
844 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectGuid() failed: %08x\n", hr
);
845 ok(IsEqualGUID(&effect_data
.guid
, &guid
), "Wrong guid returned\n");
847 ref
= IUnknown_Release(effect
);
848 ok(ref
== 0, "IDirectInputDevice_Release() reference count = %d\n", ref
);
850 cnt1
= get_refcount((IUnknown
*)pJoystick
);
851 ok(cnt1
== cnt2
, "Ref count is wrong %d != %d\n", cnt1
, cnt2
);
853 /* No force feedback support, CreateEffect is supposed to fail. Fairy Bloom Freesia
854 * calls CreateEffect without checking the DIDC_FORCEFEEDBACK. It expects the correct
855 * error return to determine if force feedback is unsupported. */
858 trace("No force feedback support\n");
859 ok(hr
==DIERR_UNSUPPORTED
, "IDirectInputDevice_CreateEffect() must fail with DIERR_UNSUPPORTED, got: %08x\n", hr
);
860 ok(effect
== NULL
, "effect must be NULL, got %p\n", effect
);
863 /* Before destroying the window, release joystick to revert to
864 * non-exclusive, background cooperative level. */
865 hr
= IDirectInputDevice_Unacquire(pJoystick
);
866 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
867 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
,
868 DISCL_NONEXCLUSIVE
| DISCL_BACKGROUND
);
869 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
870 DestroyWindow (real_hWnd
);
871 hr
= IDirectInputDevice_Acquire(pJoystick
);
872 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
874 if (winetest_interactive
) {
875 trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
882 for (i
= 0; i
< count
; i
++) {
883 hr
= IDirectInputDevice_GetDeviceState(pJoystick
, sizeof(DIJOYSTATE2
), &js
);
884 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceState() failed: %08x\n", hr
);
887 sprintf(curstate
, "X%5d Y%5d Z%5d Rx%5d Ry%5d Rz%5d "
888 "S0%5d S1%5d POV0%5d POV1%5d POV2%5d POV3%5d "
889 "B %d %d %d %d %d %d %d %d %d %d %d %d\n",
890 js
.lX
, js
.lY
, js
.lZ
, js
.lRx
, js
.lRy
, js
.lRz
,
891 js
.rglSlider
[0], js
.rglSlider
[1],
892 js
.rgdwPOV
[0], js
.rgdwPOV
[1], js
.rgdwPOV
[2], js
.rgdwPOV
[3],
893 js
.rgbButtons
[0]>>7, js
.rgbButtons
[1]>>7, js
.rgbButtons
[2]>>7,
894 js
.rgbButtons
[3]>>7, js
.rgbButtons
[4]>>7, js
.rgbButtons
[5]>>7,
895 js
.rgbButtons
[6]>>7, js
.rgbButtons
[7]>>7, js
.rgbButtons
[8]>>7,
896 js
.rgbButtons
[9]>>7, js
.rgbButtons
[10]>>7, js
.rgbButtons
[11]>>7);
897 if (strcmp(oldstate
, curstate
) != 0)
899 trace("%s\n", curstate
);
900 strcpy(oldstate
, curstate
);
906 hr
= IDirectInputDevice_Unacquire(pJoystick
);
907 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
910 ref
= IDirectInputDevice_Release(pJoystick
);
911 ok(ref
==0,"IDirectInputDevice_Release() reference count = %d\n", ref
);
914 return DIENUM_CONTINUE
;
917 static void joystick_tests(DWORD version
)
922 HINSTANCE hInstance
= GetModuleHandleW(NULL
);
924 trace("-- Testing Direct Input Version 0x%04x --\n", version
);
925 hr
= DirectInputCreateA(hInstance
, version
, &pDI
, NULL
);
926 ok(hr
==DI_OK
||hr
==DIERR_OLDDIRECTINPUTVERSION
, "DirectInputCreateA() failed: %08x\n", hr
);
927 if (hr
==DI_OK
&& pDI
!=0) {
930 data
.version
= version
;
931 hr
= IDirectInput_EnumDevices(pDI
, DIDEVTYPE_JOYSTICK
, EnumJoysticks
,
932 &data
, DIEDFL_ALLDEVICES
);
933 ok(hr
==DI_OK
,"IDirectInput_EnumDevices() failed: %08x\n", hr
);
934 ref
= IDirectInput_Release(pDI
);
935 ok(ref
==0,"IDirectInput_Release() reference count = %d\n", ref
);
936 } else if (hr
==DIERR_OLDDIRECTINPUTVERSION
)
937 trace(" Version Not Supported\n");
940 static void test_enum_feedback(void)
945 HINSTANCE hInstance
= GetModuleHandleW(NULL
);
947 hr
= DirectInputCreateA(hInstance
, 0x0700, &pDI
, NULL
);
948 ok(hr
==DI_OK
||hr
==DIERR_OLDDIRECTINPUTVERSION
, "DirectInputCreateA() failed: %08x\n", hr
);
949 if (hr
==DI_OK
&& pDI
!=0) {
950 hr
= IDirectInput_EnumDevices(pDI
, 0, EnumAllFeedback
, NULL
, DIEDFL_ATTACHEDONLY
| DIEDFL_FORCEFEEDBACK
);
951 ok(hr
==DI_OK
,"IDirectInput_EnumDevices() failed: %08x\n", hr
);
952 ref
= IDirectInput_Release(pDI
);
953 ok(ref
==0,"IDirectInput_Release() reference count = %d\n", ref
);
954 } else if (hr
==DIERR_OLDDIRECTINPUTVERSION
)
955 trace(" Version Not Supported\n");
962 joystick_tests(0x0700);
963 joystick_tests(0x0500);
964 joystick_tests(0x0300);
966 test_enum_feedback();