2 * Copyright (c) 2006 Vitaliy Margolen
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>
28 #include <wine/test.h>
32 static const DIOBJECTDATAFORMAT obj_data_format
[] = {
33 { &GUID_YAxis
, 16, DIDFT_OPTIONAL
|DIDFT_AXIS
|DIDFT_MAKEINSTANCE(1), 0},
34 { &GUID_Button
,15, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(3), 0},
35 { &GUID_Key
, 0, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(16),0},
36 { &GUID_Key
, 1, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(17),0},
37 { &GUID_Key
, 2, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(18),0},
38 { &GUID_Key
, 3, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(19),0},
39 { &GUID_Key
, 4, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(20),0},
40 { &GUID_Key
, 5, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(21),0},
41 { &GUID_Key
, 6, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(22),0},
42 { &GUID_Key
, 7, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(23),0},
43 { &GUID_Key
, 8, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(24),0},
44 { &GUID_Key
, 9, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(25),0},
45 { &GUID_Key
, 10, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(26),0},
46 { &GUID_Key
, 11, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(27),0},
47 { &GUID_Key
, 12, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(28),0},
48 { NULL
, 13, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(5),0},
50 { &GUID_Button
,14, DIDFT_OPTIONAL
|DIDFT_BUTTON
|DIDFT_MAKEINSTANCE(32),0}
53 static const DIDATAFORMAT data_format
= {
55 sizeof(DIOBJECTDATAFORMAT
),
58 sizeof(obj_data_format
) / sizeof(obj_data_format
[0]),
59 (LPDIOBJECTDATAFORMAT
)obj_data_format
62 static BOOL CALLBACK
enum_callback(LPCDIDEVICEOBJECTINSTANCE oi
, LPVOID info
)
64 if (winetest_debug
> 1)
65 trace(" Type:%4x Ofs:%3d Flags:%08x Name:%s\n",
66 oi
->dwType
, oi
->dwOfs
, oi
->dwFlags
, oi
->tszName
);
68 return DIENUM_CONTINUE
;
71 static BOOL CALLBACK
enum_type_callback(LPCDIDEVICEOBJECTINSTANCE oi
, LPVOID info
)
73 DWORD expected
= *(DWORD
*)info
;
74 ok (expected
& DIDFT_GETTYPE(oi
->dwType
), "EnumObjects() enumerated wrong type for obj %s, expected: %08x got: %08x\n", oi
->tszName
, expected
, oi
->dwType
);
75 return DIENUM_CONTINUE
;
78 static void test_object_info(LPDIRECTINPUTDEVICE device
, HWND hwnd
)
82 DIDEVICEOBJECTINSTANCE obj_info
;
83 DWORD obj_types
[] = {DIDFT_BUTTON
, DIDFT_AXIS
, DIDFT_POV
};
87 DIDEVICEOBJECTDATA buffer
[5];
89 hr
= IDirectInputDevice_EnumObjects(device
, enum_callback
, &cnt
, DIDFT_ALL
);
90 ok(SUCCEEDED(hr
), "EnumObjects() failed: %08x\n", hr
);
92 hr
= IDirectInputDevice_SetDataFormat(device
, &data_format
);
93 ok(SUCCEEDED(hr
), "SetDataFormat() failed: %08x\n", hr
);
95 hr
= IDirectInputDevice_EnumObjects(device
, enum_callback
, &cnt1
, DIDFT_ALL
);
96 ok(SUCCEEDED(hr
), "EnumObjects() failed: %08x\n", hr
);
97 if (0) /* fails for joystick only */
98 ok(cnt
== cnt1
, "Enum count changed from %d to %d\n", cnt
, cnt1
);
100 /* Testing EnumObjects with different types of device objects */
101 for (type_index
=0; type_index
< sizeof(obj_types
)/sizeof(obj_types
[0]); type_index
++)
103 hr
= IDirectInputDevice_EnumObjects(device
, enum_type_callback
, &obj_types
[type_index
], obj_types
[type_index
]);
104 ok(SUCCEEDED(hr
), "EnumObjects() failed: %08x\n", hr
);
107 /* Test buffered mode */
108 memset(&dp
, 0, sizeof(dp
));
109 dp
.diph
.dwSize
= sizeof(DIPROPDWORD
);
110 dp
.diph
.dwHeaderSize
= sizeof(DIPROPHEADER
);
111 dp
.diph
.dwHow
= DIPH_DEVICE
;
115 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_BUFFERSIZE
, (LPCDIPROPHEADER
)&dp
.diph
);
116 ok(hr
== DI_OK
, "SetProperty() failed: %08x\n", hr
);
118 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(buffer
[0]), buffer
, &cnt
, 0);
119 ok(hr
== DI_OK
&& cnt
== 5, "GetDeviceData() failed: %08x cnt: %d\n", hr
, cnt
);
120 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(DIDEVICEOBJECTDATA_DX3
), buffer
, &cnt
, 0);
121 ok(hr
== DIERR_NOTBUFFERED
, "GetDeviceData() should have failed: %08x\n", hr
);
122 IDirectInputDevice_Acquire(device
);
123 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(DIDEVICEOBJECTDATA_DX3
), buffer
, &cnt
, 0);
124 ok(hr
== DIERR_NOTBUFFERED
, "GetDeviceData() should have failed: %08x\n", hr
);
125 IDirectInputDevice_Unacquire(device
);
128 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_BUFFERSIZE
, (LPCDIPROPHEADER
)&dp
.diph
);
129 ok(hr
== DI_OK
, "SetProperty() failed: %08x\n", hr
);
131 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(buffer
[0]), buffer
, &cnt
, 0);
132 ok(hr
== DI_OK
, "GetDeviceData() failed: %08x\n", hr
);
133 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(DIDEVICEOBJECTDATA_DX3
), buffer
, &cnt
, 0);
134 ok(hr
== DIERR_NOTACQUIRED
, "GetDeviceData() should have failed: %08x\n", hr
);
135 hr
= IDirectInputDevice_Acquire(device
);
136 ok(hr
== DI_OK
, "Acquire() failed: %08x\n", hr
);
138 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(buffer
[0]), buffer
, &cnt
, 0);
139 ok(hr
== DI_OK
, "GetDeviceData() failed: %08x\n", hr
);
140 hr
= IDirectInputDevice_Unacquire(device
);
141 ok(hr
== DI_OK
, "Unacquire() failed: %08x\n", hr
);
143 hr
= IDirectInputDevice_GetDeviceData(device
, sizeof(buffer
[0]), buffer
, &cnt
, 0);
144 ok(hr
== DI_OK
, "GetDeviceData() failed: %08x\n", hr
);
146 /* No need to test devices without axis */
147 obj_info
.dwSize
= sizeof(obj_info
);
148 hr
= IDirectInputDevice_GetObjectInfo(device
, &obj_info
, 16, DIPH_BYOFFSET
);
151 /* No device supports per axis relative/absolute mode */
152 dp
.diph
.dwHow
= DIPH_BYOFFSET
;
154 dp
.dwData
= DIPROPAXISMODE_ABS
;
155 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_AXISMODE
, &dp
.diph
);
156 ok(hr
== DIERR_UNSUPPORTED
, "SetProperty() returned: %08x\n", hr
);
157 dp
.diph
.dwHow
= DIPH_DEVICE
;
158 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_AXISMODE
, &dp
.diph
);
159 ok(hr
== DIERR_INVALIDPARAM
, "SetProperty() returned: %08x\n", hr
);
161 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_AXISMODE
, &dp
.diph
);
162 ok(hr
== DI_OK
, "SetProperty() failed: %08x\n", hr
);
164 /* Cannot change mode while acquired */
165 hr
= IDirectInputDevice_Acquire(device
);
166 ok(hr
== DI_OK
, "Acquire() failed: %08x\n", hr
);
168 hr
= IDirectInputDevice_SetProperty(device
, DIPROP_AXISMODE
, &dp
.diph
);
169 ok(hr
== DIERR_ACQUIRED
, "SetProperty() returned: %08x\n", hr
);
170 hr
= IDirectInputDevice_Unacquire(device
);
171 ok(hr
== DI_OK
, "Unacquire() failed: %08x\n", hr
);
181 static BOOL CALLBACK
enum_devices(LPCDIDEVICEINSTANCE lpddi
, LPVOID pvRef
)
183 struct enum_data
*data
= pvRef
;
184 LPDIRECTINPUTDEVICE device
, obj
= NULL
;
187 hr
= IDirectInput_GetDeviceStatus(data
->pDI
, &lpddi
->guidInstance
);
188 ok(hr
== DI_OK
, "IDirectInput_GetDeviceStatus() failed: %08x\n", hr
);
192 hr
= IDirectInput_CreateDevice(data
->pDI
, &lpddi
->guidInstance
, &device
, NULL
);
193 ok(SUCCEEDED(hr
), "IDirectInput_CreateDevice() failed: %08x\n", hr
);
194 trace("Testing device %p \"%s\"\n", device
, lpddi
->tszInstanceName
);
196 hr
= IUnknown_QueryInterface(device
, &IID_IDirectInputDevice2A
, (LPVOID
*)&obj
);
197 ok(SUCCEEDED(hr
), "IUnknown_QueryInterface(IID_IDirectInputDevice7A) failed: %08x\n", hr
);
198 test_object_info(obj
, data
->hwnd
);
199 if (obj
) IUnknown_Release(obj
);
202 hr
= IUnknown_QueryInterface(device
, &IID_IDirectInputDevice2W
, (LPVOID
*)&obj
);
203 ok(SUCCEEDED(hr
), "IUnknown_QueryInterface(IID_IDirectInputDevice7W) failed: %08x\n", hr
);
204 test_object_info(obj
, data
->hwnd
);
205 if (obj
) IUnknown_Release(obj
);
207 IUnknown_Release(device
);
209 return DIENUM_CONTINUE
;
212 static void device_tests(void)
215 LPDIRECTINPUT pDI
= NULL
, obj
= NULL
;
216 HINSTANCE hInstance
= GetModuleHandle(NULL
);
218 struct enum_data data
;
220 hr
= CoCreateInstance(&CLSID_DirectInput
, 0, 1, &IID_IDirectInput2A
, (LPVOID
*)&pDI
);
221 if (hr
== DIERR_OLDDIRECTINPUTVERSION
|| hr
== DIERR_DEVICENOTREG
)
223 skip("Tests require a newer dinput version\n");
226 ok(SUCCEEDED(hr
), "DirectInputCreate() failed: %08x\n", hr
);
227 if (FAILED(hr
)) return;
229 hr
= IDirectInput_Initialize(pDI
, hInstance
, DIRECTINPUT_VERSION
);
230 ok(SUCCEEDED(hr
), "Initialize() failed: %08x\n", hr
);
231 if (FAILED(hr
)) return;
233 hr
= IUnknown_QueryInterface(pDI
, &IID_IDirectInput2W
, (LPVOID
*)&obj
);
234 ok(SUCCEEDED(hr
), "QueryInterface(IDirectInput7W) failed: %08x\n", hr
);
236 hwnd
= CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW
,
237 10, 10, 200, 200, NULL
, NULL
, NULL
, NULL
);
238 ok(hwnd
!= NULL
, "err: %d\n", GetLastError());
241 ShowWindow(hwnd
, SW_SHOW
);
245 hr
= IDirectInput_EnumDevices(pDI
, 0, enum_devices
, &data
, DIEDFL_ALLDEVICES
);
246 ok(SUCCEEDED(hr
), "IDirectInput_EnumDevices() failed: %08x\n", hr
);
249 /* If GetDeviceStatus returns DI_OK the device must exist */
250 hr
= IDirectInput_GetDeviceStatus(pDI
, &GUID_Joystick
);
253 LPDIRECTINPUTDEVICE device
= NULL
;
255 hr
= IDirectInput_CreateDevice(pDI
, &GUID_Joystick
, &device
, NULL
);
256 ok(SUCCEEDED(hr
), "IDirectInput_CreateDevice() failed: %08x\n", hr
);
257 if (device
) IUnknown_Release(device
);
262 if (obj
) IUnknown_Release(obj
);
263 if (pDI
) IUnknown_Release(pDI
);