mshtml: Rename call_event to fire_event.
[wine] / dlls / dinput / tests / device.c
1 /*
2  * Copyright (c) 2006 Vitaliy Margolen
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #define DIRECTINPUT_VERSION 0x0700
20
21 #define COBJMACROS
22 #include <windows.h>
23
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "dinput.h"
27
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},
45
46   { &GUID_Button,14, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(32),0}
47 };
48
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
56 };
57
58 static BOOL CALLBACK enum_callback(LPCDIDEVICEOBJECTINSTANCE oi, LPVOID info)
59 {
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;
65 }
66
67 static BOOL CALLBACK enum_type_callback(LPCDIDEVICEOBJECTINSTANCE oi, LPVOID info)
68 {
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;
72 }
73
74 static void test_object_info(LPDIRECTINPUTDEVICE device, HWND hwnd)
75 {
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;
82
83     hr = IDirectInputDevice_EnumObjects(device, enum_callback, &cnt, DIDFT_ALL);
84     ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
85
86     hr = IDirectInputDevice_SetDataFormat(device, &data_format);
87     ok(SUCCEEDED(hr), "SetDataFormat() failed: %08x\n", hr);
88
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);
93
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++)
96     {
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);
99     }
100
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))
105     {
106         /* No device supports per axis relative/absolute mode */
107         memset(&dp, 0, sizeof(dp));
108         dp.diph.dwSize = sizeof(DIPROPDWORD);
109         dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
110         dp.diph.dwHow = DIPH_BYOFFSET;
111         dp.diph.dwObj = 16;
112         dp.dwData = DIPROPAXISMODE_ABS;
113         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
114         ok(hr == DIERR_UNSUPPORTED, "SetProperty() returned: %08x\n", hr);
115         dp.diph.dwHow = DIPH_DEVICE;
116         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
117         ok(hr == DIERR_INVALIDPARAM, "SetProperty() returned: %08x\n", hr);
118         dp.diph.dwObj = 0;
119         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
120         ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
121
122         /* Cannot change mode while acquired */
123         hr = IDirectInputDevice_Acquire(device);
124         ok(hr == DI_OK, "Acquire() failed: %08x\n", hr);
125         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
126         ok(hr == DIERR_ACQUIRED, "SetProperty() returned: %08x\n", hr);
127         hr = IDirectInputDevice_Unacquire(device);
128         ok(hr == DI_OK, "Unacquire() failed: %08x\n", hr);
129     }
130 }
131
132 struct enum_data
133 {
134     LPDIRECTINPUT pDI;
135     HWND hwnd;
136 };
137
138 static BOOL CALLBACK enum_devices(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
139 {
140     struct enum_data *data = pvRef;
141     LPDIRECTINPUTDEVICE device, obj = NULL;
142     HRESULT hr;
143
144     hr = IDirectInput_GetDeviceStatus(data->pDI, &lpddi->guidInstance);
145     ok(hr == DI_OK, "IDirectInput_GetDeviceStatus() failed: %08x\n", hr);
146
147     if (hr == DI_OK)
148     {
149         hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, &device, NULL);
150         ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
151         trace("Testing device %p \"%s\"\n", device, lpddi->tszInstanceName);
152
153         hr = IUnknown_QueryInterface(device, &IID_IDirectInputDevice2A, (LPVOID*)&obj);
154         ok(SUCCEEDED(hr), "IUnknown_QueryInterface(IID_IDirectInputDevice7A) failed: %08x\n", hr);
155         test_object_info(obj, data->hwnd);
156         if (obj) IUnknown_Release(obj);
157         obj = NULL;
158
159         hr = IUnknown_QueryInterface(device, &IID_IDirectInputDevice2W, (LPVOID*)&obj);
160         ok(SUCCEEDED(hr), "IUnknown_QueryInterface(IID_IDirectInputDevice7W) failed: %08x\n", hr);
161         test_object_info(obj, data->hwnd);
162         if (obj) IUnknown_Release(obj);
163
164         IUnknown_Release(device);
165     }
166     return DIENUM_CONTINUE;
167 }
168
169 static void device_tests(void)
170 {
171     HRESULT hr;
172     LPDIRECTINPUT pDI = NULL, obj = NULL;
173     HINSTANCE hInstance = GetModuleHandle(NULL);
174     HWND hwnd;
175     struct enum_data data;
176
177     hr = CoCreateInstance(&CLSID_DirectInput, 0, 1, &IID_IDirectInput2A, (LPVOID*)&pDI);
178     if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_DEVICENOTREG)
179     {
180         skip("Tests require a newer dinput version\n");
181         return;
182     }
183     ok(SUCCEEDED(hr), "DirectInputCreate() failed: %08x\n", hr);
184     if (FAILED(hr)) return;
185
186     hr = IDirectInput_Initialize(pDI, hInstance, DIRECTINPUT_VERSION);
187     ok(SUCCEEDED(hr), "Initialize() failed: %08x\n", hr);
188     if (FAILED(hr)) return;
189
190     hr = IUnknown_QueryInterface(pDI, &IID_IDirectInput2W, (LPVOID*)&obj);
191     ok(SUCCEEDED(hr), "QueryInterface(IDirectInput7W) failed: %08x\n", hr);
192
193     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
194                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
195     ok(hwnd != NULL, "err: %d\n", GetLastError());
196     if (hwnd)
197     {
198         ShowWindow(hwnd, SW_SHOW);
199
200         data.pDI = pDI;
201         data.hwnd = hwnd;
202         hr = IDirectInput_EnumDevices(pDI, 0, enum_devices, &data, DIEDFL_ALLDEVICES);
203         ok(SUCCEEDED(hr), "IDirectInput_EnumDevices() failed: %08x\n", hr);
204
205
206         /* If GetDeviceStatus returns DI_OK the device must exist */
207         hr = IDirectInput_GetDeviceStatus(pDI, &GUID_Joystick);
208         if (hr == DI_OK)
209         {
210             LPDIRECTINPUTDEVICE device = NULL;
211
212             hr = IDirectInput_CreateDevice(pDI, &GUID_Joystick, &device, NULL);
213             ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
214             if (device) IUnknown_Release(device);
215         }
216
217         DestroyWindow(hwnd);
218     }
219     if (obj) IUnknown_Release(obj);
220     if (pDI) IUnknown_Release(pDI);
221 }
222
223 START_TEST(device)
224 {
225     CoInitialize(NULL);
226
227     device_tests();
228
229     CoUninitialize();
230 }