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 WIN32_NO_STATUS
21 #define COM_NO_WINDOWS_H
23 #define DIRECTINPUT_VERSION 0x0700
26 //#include <windows.h>
32 #include <wine/test.h>
38 #define numObjects(x) (sizeof(x) / sizeof(x[0]))
40 typedef struct tagUserData
{
45 static const DIOBJECTDATAFORMAT dfDIJoystickTest
[] = {
46 { &GUID_XAxis
,DIJOFS_X
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
47 { &GUID_YAxis
,DIJOFS_Y
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
48 { &GUID_ZAxis
,DIJOFS_Z
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
49 { &GUID_RxAxis
,DIJOFS_RX
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
50 { &GUID_RyAxis
,DIJOFS_RY
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
51 { &GUID_RzAxis
,DIJOFS_RZ
,DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_ANYINSTANCE
,0},
52 { &GUID_Button
,DIJOFS_BUTTON(0),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
53 { &GUID_Button
,DIJOFS_BUTTON(1),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
54 { &GUID_Button
,DIJOFS_BUTTON(2),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
55 { &GUID_Button
,DIJOFS_BUTTON(3),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
56 { &GUID_Button
,DIJOFS_BUTTON(4),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
57 { &GUID_Button
,DIJOFS_BUTTON(5),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
58 { &GUID_Button
,DIJOFS_BUTTON(6),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
59 { &GUID_Button
,DIJOFS_BUTTON(7),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
60 { &GUID_Button
,DIJOFS_BUTTON(8),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
61 { &GUID_Button
,DIJOFS_BUTTON(9),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
62 { &GUID_Button
,DIJOFS_BUTTON(10),DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_ANYINSTANCE
,0},
65 static const DIDATAFORMAT c_dfDIJoystickTest
= {
67 sizeof(DIOBJECTDATAFORMAT
),
70 numObjects(dfDIJoystickTest
),
71 (LPDIOBJECTDATAFORMAT
)dfDIJoystickTest
74 static HWND
get_hwnd(void)
76 HWND hwnd
=GetForegroundWindow();
78 hwnd
=GetDesktopWindow();
82 typedef struct tagJoystickInfo
84 LPDIRECTINPUTDEVICE pJoystick
;
92 static int get_refcount(IUnknown
*object
)
94 IUnknown_AddRef( object
);
95 return IUnknown_Release( object
);
98 static BOOL CALLBACK
EnumAxes(
99 const DIDEVICEOBJECTINSTANCE
* pdidoi
,
103 JoystickInfo
* info
= pContext
;
105 if (IsEqualIID(&pdidoi
->guidType
, &GUID_XAxis
) ||
106 IsEqualIID(&pdidoi
->guidType
, &GUID_YAxis
) ||
107 IsEqualIID(&pdidoi
->guidType
, &GUID_ZAxis
) ||
108 IsEqualIID(&pdidoi
->guidType
, &GUID_RxAxis
) ||
109 IsEqualIID(&pdidoi
->guidType
, &GUID_RyAxis
) ||
110 IsEqualIID(&pdidoi
->guidType
, &GUID_RzAxis
) ||
111 IsEqualIID(&pdidoi
->guidType
, &GUID_Slider
))
116 diprg
.diph
.dwSize
= sizeof(DIPROPRANGE
);
117 diprg
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
118 diprg
.diph
.dwHow
= DIPH_BYID
;
119 diprg
.diph
.dwObj
= pdidoi
->dwType
;
121 dipdw
.diph
.dwSize
= sizeof(dipdw
);
122 dipdw
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
123 dipdw
.diph
.dwHow
= DIPH_BYID
;
124 dipdw
.diph
.dwObj
= pdidoi
->dwType
;
126 hr
= IDirectInputDevice_GetProperty(info
->pJoystick
, DIPROP_RANGE
, &diprg
.diph
);
127 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
128 ok(info
->lMin
== diprg
.lMin
&& info
->lMax
== diprg
.lMax
, "Min/Max range invalid: "
129 "expected %d..%d got %d..%d\n", info
->lMin
, info
->lMax
, diprg
.lMin
, diprg
.lMax
);
134 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_RANGE
, NULL
);
135 ok(hr
==E_INVALIDARG
,"IDirectInputDevice_SetProperty() should have returned "
136 "E_INVALIDARG, returned: %08x\n", hr
);
138 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_RANGE
, &diprg
.diph
);
139 ok(hr
==DI_OK
,"IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
142 hr
= IDirectInputDevice_GetProperty(info
->pJoystick
, DIPROP_DEADZONE
, &dipdw
.diph
);
143 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
144 ok(info
->dZone
== dipdw
.dwData
, "deadzone invalid: expected %d got %d\n",
145 info
->dZone
, dipdw
.dwData
);
149 hr
= IDirectInputDevice_SetProperty(info
->pJoystick
, DIPROP_DEADZONE
, &dipdw
.diph
);
150 ok(hr
==DI_OK
,"IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
153 } else if (IsEqualIID(&pdidoi
->guidType
, &GUID_POV
))
155 else if (IsEqualIID(&pdidoi
->guidType
, &GUID_Button
))
158 return DIENUM_CONTINUE
;
161 static const HRESULT SetCoop_null_window
[16] = {
162 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
,
163 E_INVALIDARG
, E_HANDLE
, E_HANDLE
, E_INVALIDARG
,
164 E_INVALIDARG
, E_HANDLE
, S_OK
, E_INVALIDARG
,
165 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
};
167 static const HRESULT SetCoop_real_window
[16] = {
168 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
,
169 E_INVALIDARG
, S_OK
, S_OK
, E_INVALIDARG
,
170 E_INVALIDARG
, S_OK
, S_OK
, E_INVALIDARG
,
171 E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
, E_INVALIDARG
};
173 static BOOL CALLBACK
EnumJoysticks(
174 LPCDIDEVICEINSTANCE lpddi
,
178 UserData
* data
= pvRef
;
179 LPDIRECTINPUTDEVICE pJoystick
;
186 DIDEVICEINSTANCE inst
;
187 DIDEVICEINSTANCE_DX3 inst3
;
190 DIPROPGUIDANDPATH dpg
;
191 WCHAR nameBuffer
[MAX_PATH
];
192 HWND hWnd
= get_hwnd();
193 char oldstate
[248], curstate
[248];
195 ok(data
->version
> 0x0300, "Joysticks not supported in version 0x%04x\n", data
->version
);
197 hr
= IDirectInput_CreateDevice(data
->pDI
, &lpddi
->guidInstance
, NULL
, NULL
);
198 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
199 "E_POINTER, returned: %08x\n", hr
);
201 hr
= IDirectInput_CreateDevice(data
->pDI
, NULL
, &pJoystick
, NULL
);
202 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
203 "E_POINTER, returned: %08x\n", hr
);
205 hr
= IDirectInput_CreateDevice(data
->pDI
, NULL
, NULL
, NULL
);
206 ok(hr
==E_POINTER
,"IDirectInput_CreateDevice() should have returned "
207 "E_POINTER, returned: %08x\n", hr
);
209 hr
= IDirectInput_CreateDevice(data
->pDI
, &lpddi
->guidInstance
,
211 ok(hr
==DI_OK
,"IDirectInput_CreateDevice() failed: %08x\n", hr
);
215 trace("---- %s ----\n", lpddi
->tszProductName
);
217 /* Test for joystick ID property */
218 ZeroMemory(&dipw
, sizeof(dipw
));
219 dipw
.diph
.dwSize
= sizeof(DIPROPDWORD
);
220 dipw
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
222 dipw
.diph
.dwHow
= DIPH_DEVICE
;
224 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_JOYSTICKID
, &dipw
.diph
);
225 ok(SUCCEEDED(hr
), "IDirectInputDevice_GetProperty() for DIPROP_JOYSTICKID failed\n");
227 /* Test for INSTANCENAME property */
228 memset(&dps
, 0, sizeof(dps
));
229 dps
.diph
.dwSize
= sizeof(DIPROPSTRING
);
230 dps
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
231 dps
.diph
.dwHow
= DIPH_DEVICE
;
233 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_INSTANCENAME
, &dps
.diph
);
234 ok(SUCCEEDED(hr
), "IDirectInput_GetProperty() for DIPROP_INSTANCENAME failed: %08x\n", hr
);
236 /* Test if instance name is the same as present in DIDEVICEINSTANCE */
237 MultiByteToWideChar(CP_ACP
, 0, lpddi
->tszInstanceName
, -1, nameBuffer
, MAX_PATH
);
238 ok(!lstrcmpW(nameBuffer
, dps
.wsz
), "DIPROP_INSTANCENAME returned is wrong. Expected: %s Got: %s\n",
239 wine_dbgstr_w(nameBuffer
), wine_dbgstr_w(dps
.wsz
));
241 /* Test for GUIDPATH properties */
242 memset(&dpg
, 0, sizeof(dpg
));
243 dpg
.diph
.dwSize
= sizeof(DIPROPGUIDANDPATH
);
244 dpg
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
245 dpg
.diph
.dwHow
= DIPH_DEVICE
;
247 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_GUIDANDPATH
, &dpg
.diph
);
248 todo_wine
ok(SUCCEEDED(hr
), "IDirectInput_GetProperty() for DIPROP_GUIDANDPATH failed: %08x\n", hr
);
250 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, NULL
);
251 ok(hr
==E_POINTER
,"IDirectInputDevice_SetDataFormat() should have returned "
252 "E_POINTER, returned: %08x\n", hr
);
254 ZeroMemory(&format
, sizeof(format
));
255 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &format
);
256 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputDevice_SetDataFormat() should have "
257 "returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
259 /* try the default formats */
260 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick
);
261 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
263 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
264 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
266 /* try an alternate format */
267 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystickTest
);
268 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
270 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
271 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
277 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, NULL
, i
);
278 ok(hr
== SetCoop_null_window
[i
], "SetCooperativeLevel(NULL, %d): %08x\n", i
, hr
);
282 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
, i
);
283 ok(hr
== SetCoop_real_window
[i
], "SetCooperativeLevel(hwnd, %d): %08x\n", i
, hr
);
286 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
,
287 DISCL_NONEXCLUSIVE
| DISCL_BACKGROUND
);
288 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
290 /* get capabilities */
291 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, NULL
);
292 ok(hr
==E_POINTER
,"IDirectInputDevice_GetCapabilities() "
293 "should have returned E_POINTER, returned: %08x\n", hr
);
295 ZeroMemory(&caps
, sizeof(caps
));
296 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, &caps
);
297 ok(hr
==DIERR_INVALIDPARAM
,"IDirectInputDevice_GetCapabilities() "
298 "should have returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
300 caps
.dwSize
= sizeof(caps
);
301 hr
= IDirectInputDevice_GetCapabilities(pJoystick
, &caps
);
302 ok(hr
==DI_OK
,"IDirectInputDevice_GetCapabilities() failed: %08x\n", hr
);
304 ZeroMemory(&info
, sizeof(info
));
305 info
.pJoystick
= pJoystick
;
307 /* default min/max limits */
310 /* enumerate objects */
311 hr
= IDirectInputDevice_EnumObjects(pJoystick
, EnumAxes
, &info
, DIDFT_ALL
);
312 ok(hr
==DI_OK
,"IDirectInputDevice_EnumObjects() failed: %08x\n", hr
);
314 ok(caps
.dwAxes
== info
.axis
, "Number of enumerated axes (%d) doesn't match capabilities (%d)\n", info
.axis
, caps
.dwAxes
);
315 ok(caps
.dwButtons
== info
.button
, "Number of enumerated buttons (%d) doesn't match capabilities (%d)\n", info
.button
, caps
.dwButtons
);
316 ok(caps
.dwPOVs
== info
.pov
, "Number of enumerated POVs (%d) doesn't match capabilities (%d)\n", info
.pov
, caps
.dwPOVs
);
318 /* Set format and check limits again */
319 hr
= IDirectInputDevice_SetDataFormat(pJoystick
, &c_dfDIJoystick2
);
320 ok(hr
==DI_OK
,"IDirectInputDevice_SetDataFormat() failed: %08x\n", hr
);
324 hr
= IDirectInputDevice_EnumObjects(pJoystick
, EnumAxes
, &info
, DIDFT_ALL
);
325 ok(hr
==DI_OK
,"IDirectInputDevice_EnumObjects() failed: %08x\n", hr
);
327 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, 0);
328 ok(hr
==E_POINTER
, "IDirectInputDevice_GetDeviceInfo() "
329 "should have returned E_POINTER, returned: %08x\n", hr
);
331 ZeroMemory(&inst
, sizeof(inst
));
332 ZeroMemory(&inst3
, sizeof(inst3
));
334 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, &inst
);
335 ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_GetDeviceInfo() "
336 "should have returned DIERR_INVALIDPARAM, returned: %08x\n", hr
);
338 inst
.dwSize
= sizeof(inst
);
339 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, &inst
);
340 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceInfo() failed: %08x\n", hr
);
342 inst3
.dwSize
= sizeof(inst3
);
343 hr
= IDirectInputDevice_GetDeviceInfo(pJoystick
, (LPDIDEVICEINSTANCE
)&inst3
);
344 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceInfo() failed: %08x\n", hr
);
346 hr
= IDirectInputDevice_Unacquire(pJoystick
);
347 ok(hr
== S_FALSE
, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %08x\n", hr
);
349 hr
= IDirectInputDevice_Acquire(pJoystick
);
350 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
354 hr
= IDirectInputDevice_Acquire(pJoystick
);
355 ok(hr
== S_FALSE
, "IDirectInputDevice_Acquire() should have returned S_FALSE, got: %08x\n", hr
);
359 hr
= IDirectInputDevice_GetDeviceState(pJoystick
, sizeof(DIJOYSTATE2
), &js
);
360 ok(hr
== DI_OK
, "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr
);
361 ok(js
.rgdwPOV
[3] == -1, "Default for unassigned POV should be -1 not: %d\n", js
.rgdwPOV
[3]);
364 if (caps
.dwFlags
& DIDC_FORCEFEEDBACK
)
366 DWORD axes
[2] = {DIJOFS_X
, DIJOFS_Y
};
367 LONG direction
[2] = {0, 0};
368 DICONSTANTFORCE force
= {0};
370 LPDIRECTINPUTEFFECT effect
= NULL
;
373 HINSTANCE hInstance
= GetModuleHandle(NULL
);
374 DIPROPDWORD dip_gain_set
, dip_gain_get
;
376 trace("Testing force-feedback\n");
377 memset(&eff
, 0, sizeof(eff
));
378 eff
.dwSize
= sizeof(eff
);
379 eff
.dwFlags
= DIEFF_CARTESIAN
| DIEFF_OBJECTOFFSETS
;
380 eff
.dwDuration
= INFINITE
;
381 eff
.dwGain
= DI_FFNOMINALMAX
;
382 eff
.dwTriggerButton
= DIEB_NOTRIGGER
;
383 eff
.cAxes
= sizeof(axes
) / sizeof(axes
[0]);
385 eff
.rglDirection
= direction
;
386 eff
.cbTypeSpecificParams
= sizeof(force
);
387 eff
.lpvTypeSpecificParams
= &force
;
389 /* Sending effects to joystick requires
390 * calling IDirectInputEffect_Initialize, which requires
391 * having exclusive access to the device, which requires
392 * - not having acquired the joystick when calling
393 * IDirectInputDevice_SetCooperativeLevel
396 real_hWnd
= CreateWindowEx(0, "EDIT", "Test text", 0, 10, 10, 300,
397 300, NULL
, NULL
, hInstance
, NULL
);
398 ok(real_hWnd
!=0,"CreateWindowEx failed: %p\n", real_hWnd
);
399 ShowWindow(real_hWnd
, SW_SHOW
);
400 hr
= IDirectInputDevice_Unacquire(pJoystick
);
401 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
402 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, real_hWnd
,
403 DISCL_EXCLUSIVE
| DISCL_FOREGROUND
);
404 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
405 hr
= IDirectInputDevice_Acquire(pJoystick
);
406 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
408 cnt1
= get_refcount((IUnknown
*)pJoystick
);
410 hr
= IDirectInputDevice2_CreateEffect((LPDIRECTINPUTDEVICE2
)pJoystick
, &GUID_ConstantForce
,
411 &eff
, &effect
, NULL
);
412 ok(hr
== DI_OK
, "IDirectInputDevice_CreateEffect() failed: %08x\n", hr
);
413 cnt2
= get_refcount((IUnknown
*)pJoystick
);
414 ok(cnt1
== cnt2
, "Ref count is wrong %d != %d\n", cnt1
, cnt2
);
419 struct DIPROPDWORD diprop_word
;
422 hr
= IDirectInputEffect_Initialize(effect
, hInstance
, data
->version
,
423 &GUID_ConstantForce
);
424 ok(hr
==DI_OK
,"IDirectInputEffect_Initialize failed: %08x\n", hr
);
425 hr
= IDirectInputEffect_SetParameters(effect
, &eff
, DIEP_AXES
| DIEP_DIRECTION
|
426 DIEP_TYPESPECIFICPARAMS
);
427 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
429 /* Test that upload, unacquire, acquire still permits updating
430 * uploaded effect. */
431 hr
= IDirectInputDevice_Unacquire(pJoystick
);
432 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
433 hr
= IDirectInputDevice_Acquire(pJoystick
);
434 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
435 hr
= IDirectInputEffect_SetParameters(effect
, &eff
, DIEP_GAIN
);
436 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
439 /* Check effect status.
440 * State: initially stopped
443 * unacquire, acquire, download
449 * - effects are stopped after Unacquire + Acquire
450 * - effects are preserved (Download + Start doesn't complain
451 * about incomplete effect)
453 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
454 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
455 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
456 hr
= IDirectInputEffect_SetParameters(effect
, &eff
, DIEP_START
);
457 ok(hr
==DI_OK
,"IDirectInputEffect_SetParameters failed: %08x\n", hr
);
458 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
459 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
460 todo_wine
ok(effect_status
!=0,"IDirectInputEffect_GetEffectStatus() reported effect as stopped\n");
461 hr
= IDirectInputDevice_Unacquire(pJoystick
);
462 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
463 hr
= IDirectInputDevice_Acquire(pJoystick
);
464 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
465 hr
= IDirectInputEffect_Download(effect
);
466 ok(hr
==DI_OK
,"IDirectInputEffect_Download() failed: %08x\n", hr
);
467 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
468 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
469 ok(effect_status
==0,"IDirectInputEffect_GetEffectStatus() reported effect as started\n");
470 hr
= IDirectInputEffect_Start(effect
, 1, 0);
471 ok(hr
==DI_OK
,"IDirectInputEffect_Start() failed: %08x\n", hr
);
472 hr
= IDirectInputEffect_GetEffectStatus(effect
, &effect_status
);
473 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectStatus() failed: %08x\n", hr
);
474 todo_wine
ok(effect_status
!=0,"IDirectInputEffect_GetEffectStatus() reported effect as stopped\n");
475 hr
= IDirectInputEffect_GetEffectGuid(effect
, &guid
);
476 ok(hr
==DI_OK
,"IDirectInputEffect_GetEffectGuid() failed: %08x\n", hr
);
477 ok(IsEqualGUID(&GUID_ConstantForce
, &guid
), "Wrong guid returned\n");
479 /* Check autocenter status
480 * State: initially stopped
488 * IDirectInputDevice2_SetProperty(DIPROP_AUTOCENTER) can only be
489 * executed when the device is released.
491 * If Executed interactively, user can feel that autocenter is
492 * only disabled when the joystick is acquired.
494 diprop_word
.diph
.dwSize
= sizeof(diprop_word
);
495 diprop_word
.diph
.dwHeaderSize
= sizeof(diprop_word
.diph
);
496 diprop_word
.diph
.dwObj
= 0;
497 diprop_word
.diph
.dwHow
= DIPH_DEVICE
;
498 hr
= IDirectInputDevice_Unacquire(pJoystick
);
499 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
500 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
501 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
502 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_ON
,"IDirectInputDevice2_GetProperty() reported autocenter as disabled\n");
503 diprop_word
.dwData
= DIPROPAUTOCENTER_OFF
;
504 hr
= IDirectInputDevice2_SetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
505 ok(hr
==DI_OK
,"IDirectInputDevice2_SetProperty() failed: %08x\n", hr
);
506 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
507 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
508 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
509 if (winetest_interactive
) {
510 trace("Acquiring in 2s, autocenter will be disabled.\n");
513 hr
= IDirectInputDevice_Acquire(pJoystick
);
514 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
515 if (winetest_interactive
)
516 trace("Acquired.\n");
517 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
518 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
519 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
520 if (winetest_interactive
) {
521 trace("Releasing in 2s, autocenter will be re-enabled.\n");
524 hr
= IDirectInputDevice_Unacquire(pJoystick
);
525 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
526 if (winetest_interactive
)
528 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
529 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
530 ok(diprop_word
.dwData
==DIPROPAUTOCENTER_OFF
,"IDirectInputDevice2_GetProperty() reported autocenter as enabled\n");
531 hr
= IDirectInputDevice_Acquire(pJoystick
);
532 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
533 hr
= IDirectInputDevice2_GetProperty(pJoystick
, DIPROP_AUTOCENTER
, &diprop_word
.diph
);
534 ok(hr
==DI_OK
,"IDirectInputDevice2_GetProperty() failed: %08x\n", hr
);
536 /* Device gain (DIPROP_FFGAIN).
538 * 0..10000 range, otherwise DIERR_INVALIDPARAM.
539 * Can be changed even if device is acquired.
540 * Difference found by tests:
541 * <0 is refused, >10000 is accepted
543 dip_gain_set
.diph
.dwSize
= sizeof(DIPROPDWORD
);
544 dip_gain_set
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
545 dip_gain_set
.diph
.dwObj
= 0;
546 dip_gain_set
.diph
.dwHow
= DIPH_DEVICE
;
547 dip_gain_set
.dwData
= 10000;
548 dip_gain_get
.diph
.dwSize
= sizeof(DIPROPDWORD
);
549 dip_gain_get
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
550 dip_gain_get
.diph
.dwObj
= 0;
551 dip_gain_get
.diph
.dwHow
= DIPH_DEVICE
;
552 dip_gain_get
.dwData
= 0;
554 /* Test device is acquisition (non)impact. */
555 hr
= IDirectInputDevice_Unacquire(pJoystick
);
556 ok(hr
== DI_OK
, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %08x\n", hr
);
557 dip_gain_set
.dwData
= 1;
558 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
559 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
560 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
561 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
562 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not udated: %i\n", dip_gain_get
.dwData
);
563 hr
= IDirectInputDevice_Acquire(pJoystick
);
564 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
565 dip_gain_set
.dwData
= 2;
566 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
567 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
568 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
569 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
570 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not udated: %i\n", dip_gain_get
.dwData
);
571 /* Test range and internal clamping. */
572 dip_gain_set
.dwData
= -1;
573 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
574 todo_wine
ok(hr
==DIERR_INVALIDPARAM
, "IDirectInputDevice_SetProperty() should have returned %08x: %08x\n", DIERR_INVALIDPARAM
, hr
);
575 dip_gain_set
.dwData
= 0;
576 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
577 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
578 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
579 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
580 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
581 dip_gain_set
.dwData
= 10000;
582 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
583 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
584 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
585 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
586 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
587 /* WARNING: This call succeeds, on the contrary of what is stated on MSDN. */
588 dip_gain_set
.dwData
= 10001;
589 hr
= IDirectInputDevice_SetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_set
.diph
);
590 ok(hr
==DI_OK
, "IDirectInputDevice_SetProperty() failed: %08x\n", hr
);
591 hr
= IDirectInputDevice_GetProperty(pJoystick
, DIPROP_FFGAIN
, &dip_gain_get
.diph
);
592 ok(hr
==DI_OK
, "IDirectInputDevice_GetProperty() failed: %08x\n", hr
);
593 ok(dip_gain_get
.dwData
==dip_gain_set
.dwData
, "Gain not updated: %i\n", dip_gain_get
.dwData
);
595 ref
= IUnknown_Release(effect
);
596 ok(ref
== 0, "IDirectInputDevice_Release() reference count = %d\n", ref
);
598 cnt1
= get_refcount((IUnknown
*)pJoystick
);
599 ok(cnt1
== cnt2
, "Ref count is wrong %d != %d\n", cnt1
, cnt2
);
601 /* Before destroying the window, release joystick to revert to
602 * non-exclusive, background cooperative level. */
603 hr
= IDirectInputDevice_Unacquire(pJoystick
);
604 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
605 hr
= IDirectInputDevice_SetCooperativeLevel(pJoystick
, hWnd
,
606 DISCL_NONEXCLUSIVE
| DISCL_BACKGROUND
);
607 ok(hr
==DI_OK
,"IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr
);
608 DestroyWindow (real_hWnd
);
609 hr
= IDirectInputDevice_Acquire(pJoystick
);
610 ok(hr
==DI_OK
,"IDirectInputDevice_Acquire() failed: %08x\n", hr
);
613 if (winetest_interactive
) {
614 trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
621 for (i
= 0; i
< count
; i
++) {
622 hr
= IDirectInputDevice_GetDeviceState(pJoystick
, sizeof(DIJOYSTATE2
), &js
);
623 ok(hr
==DI_OK
,"IDirectInputDevice_GetDeviceState() failed: %08x\n", hr
);
626 sprintf(curstate
, "X%5d Y%5d Z%5d Rx%5d Ry%5d Rz%5d "
627 "S0%5d S1%5d POV0%5d POV1%5d POV2%5d POV3%5d "
628 "B %d %d %d %d %d %d %d %d %d %d %d %d\n",
629 js
.lX
, js
.lY
, js
.lZ
, js
.lRx
, js
.lRy
, js
.lRz
,
630 js
.rglSlider
[0], js
.rglSlider
[1],
631 js
.rgdwPOV
[0], js
.rgdwPOV
[1], js
.rgdwPOV
[2], js
.rgdwPOV
[3],
632 js
.rgbButtons
[0]>>7, js
.rgbButtons
[1]>>7, js
.rgbButtons
[2]>>7,
633 js
.rgbButtons
[3]>>7, js
.rgbButtons
[4]>>7, js
.rgbButtons
[5]>>7,
634 js
.rgbButtons
[6]>>7, js
.rgbButtons
[7]>>7, js
.rgbButtons
[8]>>7,
635 js
.rgbButtons
[9]>>7, js
.rgbButtons
[10]>>7, js
.rgbButtons
[11]>>7);
636 if (strcmp(oldstate
, curstate
) != 0)
638 trace("%s\n", curstate
);
639 strcpy(oldstate
, curstate
);
645 hr
= IDirectInputDevice_Unacquire(pJoystick
);
646 ok(hr
==DI_OK
,"IDirectInputDevice_Unacquire() failed: %08x\n", hr
);
649 ref
= IDirectInputDevice_Release(pJoystick
);
650 ok(ref
==0,"IDirectInputDevice_Release() reference count = %d\n", ref
);
653 return DIENUM_CONTINUE
;
656 static void joystick_tests(DWORD version
)
661 HINSTANCE hInstance
= GetModuleHandle(NULL
);
663 trace("-- Testing Direct Input Version 0x%04x --\n", version
);
664 hr
= DirectInputCreate(hInstance
, version
, &pDI
, NULL
);
665 ok(hr
==DI_OK
||hr
==DIERR_OLDDIRECTINPUTVERSION
,
666 "DirectInputCreate() failed: %08x\n", hr
);
667 if (hr
==DI_OK
&& pDI
!=0) {
670 data
.version
= version
;
671 hr
= IDirectInput_EnumDevices(pDI
, DIDEVTYPE_JOYSTICK
, EnumJoysticks
,
672 &data
, DIEDFL_ALLDEVICES
);
673 ok(hr
==DI_OK
,"IDirectInput_EnumDevices() failed: %08x\n", hr
);
674 ref
= IDirectInput_Release(pDI
);
675 ok(ref
==0,"IDirectInput_Release() reference count = %d\n", ref
);
676 } else if (hr
==DIERR_OLDDIRECTINPUTVERSION
)
677 trace(" Version Not Supported\n");
684 joystick_tests(0x0700);
685 joystick_tests(0x0500);
686 joystick_tests(0x0300);