dinput: GetDeviceData always succeeds regardless if buffering is enabled or device...
[wine/multimedia.git] / dlls / dinput / tests / device.c
blob2e4e4f8da861378ceadc1c80ef33359ddd8a0eb5
1 /*
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 DIRECTINPUT_VERSION 0x0700
21 #define COBJMACROS
22 #include <windows.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "dinput.h"
28 static const DIOBJECTDATAFORMAT obj_data_format[] = {
29 { &GUID_YAxis, 16, DIDFT_OPTIONAL|DIDFT_AXIS |DIDFT_MAKEINSTANCE(1), 0},
30 { &GUID_Button,15, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(3), 0},
31 { &GUID_Key, 0, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(16),0},
32 { &GUID_Key, 1, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(17),0},
33 { &GUID_Key, 2, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(18),0},
34 { &GUID_Key, 3, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(19),0},
35 { &GUID_Key, 4, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(20),0},
36 { &GUID_Key, 5, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(21),0},
37 { &GUID_Key, 6, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(22),0},
38 { &GUID_Key, 7, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(23),0},
39 { &GUID_Key, 8, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(24),0},
40 { &GUID_Key, 9, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(25),0},
41 { &GUID_Key, 10, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(26),0},
42 { &GUID_Key, 11, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(27),0},
43 { &GUID_Key, 12, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(28),0},
44 { NULL, 13, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(5),0},
46 { &GUID_Button,14, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(32),0}
49 static const DIDATAFORMAT data_format = {
50 sizeof(DIDATAFORMAT),
51 sizeof(DIOBJECTDATAFORMAT),
52 DIDF_ABSAXIS,
53 32,
54 sizeof(obj_data_format) / sizeof(obj_data_format[0]),
55 (LPDIOBJECTDATAFORMAT)obj_data_format
58 static BOOL CALLBACK enum_callback(LPCDIDEVICEOBJECTINSTANCE oi, LPVOID info)
60 if (winetest_debug > 1)
61 trace(" Type:%4x Ofs:%3d Flags:%08x Name:%s\n",
62 oi->dwType, oi->dwOfs, oi->dwFlags, oi->tszName);
63 (*(int*)info)++;
64 return DIENUM_CONTINUE;
67 static BOOL CALLBACK enum_type_callback(LPCDIDEVICEOBJECTINSTANCE oi, LPVOID info)
69 DWORD expected = *(DWORD*)info;
70 ok (expected & DIDFT_GETTYPE(oi->dwType), "EnumObjects() enumerated wrong type for obj %s, expected: %08x got: %08x\n", oi->tszName, expected, oi->dwType);
71 return DIENUM_CONTINUE;
74 static void test_object_info(LPDIRECTINPUTDEVICE device, HWND hwnd)
76 HRESULT hr;
77 DIPROPDWORD dp;
78 DIDEVICEOBJECTINSTANCE obj_info;
79 DWORD obj_types[] = {DIDFT_BUTTON, DIDFT_AXIS, DIDFT_POV};
80 int type_index;
81 int cnt = 0, cnt1 = 0;
83 hr = IDirectInputDevice_EnumObjects(device, enum_callback, &cnt, DIDFT_ALL);
84 ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
86 hr = IDirectInputDevice_SetDataFormat(device, &data_format);
87 ok(SUCCEEDED(hr), "SetDataFormat() failed: %08x\n", hr);
89 hr = IDirectInputDevice_EnumObjects(device, enum_callback, &cnt1, DIDFT_ALL);
90 ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
91 if (0) /* fails for joystick only */
92 ok(cnt == cnt1, "Enum count changed from %d to %d\n", cnt, cnt1);
94 /* Testing EnumObjects with different types of device objects */
95 for (type_index=0; type_index < sizeof(obj_types)/sizeof(obj_types[0]); type_index++)
97 hr = IDirectInputDevice_EnumObjects(device, enum_type_callback, &obj_types[type_index], obj_types[type_index]);
98 ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
101 /* No need to test devices without axis */
102 obj_info.dwSize = sizeof(obj_info);
103 hr = IDirectInputDevice_GetObjectInfo(device, &obj_info, 16, DIPH_BYOFFSET);
104 if (SUCCEEDED(hr))
106 DWORD cnt;
107 DIDEVICEOBJECTDATA buffer[5];
109 /* No device supports per axis relative/absolute mode */
110 memset(&dp, 0, sizeof(dp));
111 dp.diph.dwSize = sizeof(DIPROPDWORD);
112 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
113 dp.diph.dwHow = DIPH_BYOFFSET;
114 dp.diph.dwObj = 16;
115 dp.dwData = DIPROPAXISMODE_ABS;
116 hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
117 ok(hr == DIERR_UNSUPPORTED, "SetProperty() returned: %08x\n", hr);
118 dp.diph.dwHow = DIPH_DEVICE;
119 hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
120 ok(hr == DIERR_INVALIDPARAM, "SetProperty() returned: %08x\n", hr);
121 dp.diph.dwObj = 0;
122 hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
123 ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
125 dp.dwData = 0;
126 hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph);
127 ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
129 cnt = 5;
130 hr = IDirectInputDevice_GetDeviceData(device, sizeof(buffer), buffer, &cnt, 0);
131 ok(hr == DI_OK && cnt == 5, "GetDeviceData() failed: %08x cnt: %d\n", hr, cnt);
133 dp.dwData = 20;
134 hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph);
135 ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
137 cnt = 1;
138 hr = IDirectInputDevice_GetDeviceData(device, sizeof(buffer), buffer, &cnt, 0);
139 ok(hr == DI_OK, "GetDeviceData() failed: %08x\n", hr);
141 /* Cannot change mode while acquired */
142 hr = IDirectInputDevice_Acquire(device);
143 ok(hr == DI_OK, "Acquire() failed: %08x\n", hr);
144 cnt = 1;
145 hr = IDirectInputDevice_GetDeviceData(device, sizeof(buffer), buffer, &cnt, 0);
146 ok(hr == DI_OK, "GetDeviceData() failed: %08x\n", hr);
147 hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
148 ok(hr == DIERR_ACQUIRED, "SetProperty() returned: %08x\n", hr);
149 hr = IDirectInputDevice_Unacquire(device);
150 ok(hr == DI_OK, "Unacquire() failed: %08x\n", hr);
154 struct enum_data
156 LPDIRECTINPUT pDI;
157 HWND hwnd;
160 static BOOL CALLBACK enum_devices(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
162 struct enum_data *data = pvRef;
163 LPDIRECTINPUTDEVICE device, obj = NULL;
164 HRESULT hr;
166 hr = IDirectInput_GetDeviceStatus(data->pDI, &lpddi->guidInstance);
167 ok(hr == DI_OK, "IDirectInput_GetDeviceStatus() failed: %08x\n", hr);
169 if (hr == DI_OK)
171 hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, &device, NULL);
172 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
173 trace("Testing device %p \"%s\"\n", device, lpddi->tszInstanceName);
175 hr = IUnknown_QueryInterface(device, &IID_IDirectInputDevice2A, (LPVOID*)&obj);
176 ok(SUCCEEDED(hr), "IUnknown_QueryInterface(IID_IDirectInputDevice7A) failed: %08x\n", hr);
177 test_object_info(obj, data->hwnd);
178 if (obj) IUnknown_Release(obj);
179 obj = NULL;
181 hr = IUnknown_QueryInterface(device, &IID_IDirectInputDevice2W, (LPVOID*)&obj);
182 ok(SUCCEEDED(hr), "IUnknown_QueryInterface(IID_IDirectInputDevice7W) failed: %08x\n", hr);
183 test_object_info(obj, data->hwnd);
184 if (obj) IUnknown_Release(obj);
186 IUnknown_Release(device);
188 return DIENUM_CONTINUE;
191 static void device_tests(void)
193 HRESULT hr;
194 LPDIRECTINPUT pDI = NULL, obj = NULL;
195 HINSTANCE hInstance = GetModuleHandle(NULL);
196 HWND hwnd;
197 struct enum_data data;
199 hr = CoCreateInstance(&CLSID_DirectInput, 0, 1, &IID_IDirectInput2A, (LPVOID*)&pDI);
200 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_DEVICENOTREG)
202 skip("Tests require a newer dinput version\n");
203 return;
205 ok(SUCCEEDED(hr), "DirectInputCreate() failed: %08x\n", hr);
206 if (FAILED(hr)) return;
208 hr = IDirectInput_Initialize(pDI, hInstance, DIRECTINPUT_VERSION);
209 ok(SUCCEEDED(hr), "Initialize() failed: %08x\n", hr);
210 if (FAILED(hr)) return;
212 hr = IUnknown_QueryInterface(pDI, &IID_IDirectInput2W, (LPVOID*)&obj);
213 ok(SUCCEEDED(hr), "QueryInterface(IDirectInput7W) failed: %08x\n", hr);
215 hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
216 10, 10, 200, 200, NULL, NULL, NULL, NULL);
217 ok(hwnd != NULL, "err: %d\n", GetLastError());
218 if (hwnd)
220 ShowWindow(hwnd, SW_SHOW);
222 data.pDI = pDI;
223 data.hwnd = hwnd;
224 hr = IDirectInput_EnumDevices(pDI, 0, enum_devices, &data, DIEDFL_ALLDEVICES);
225 ok(SUCCEEDED(hr), "IDirectInput_EnumDevices() failed: %08x\n", hr);
228 /* If GetDeviceStatus returns DI_OK the device must exist */
229 hr = IDirectInput_GetDeviceStatus(pDI, &GUID_Joystick);
230 if (hr == DI_OK)
232 LPDIRECTINPUTDEVICE device = NULL;
234 hr = IDirectInput_CreateDevice(pDI, &GUID_Joystick, &device, NULL);
235 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
236 if (device) IUnknown_Release(device);
239 DestroyWindow(hwnd);
241 if (obj) IUnknown_Release(obj);
242 if (pDI) IUnknown_Release(pDI);
245 START_TEST(device)
247 CoInitialize(NULL);
249 device_tests();
251 CoUninitialize();