Fixes for -Wmissing-declaration and -Wwrite-string warnings.
[wine] / dlls / dinput / tests / joystick.c
1 /*
2  * Copyright (c) 2004-2005 Robert Reif
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define STRICT
20 #define DIRECTINPUT_VERSION 0x0700
21
22 #define NONAMELESSSTRUCT
23 #define NONAMELESSUNION
24 #include <windows.h>
25
26 #include <math.h>
27 #include <stdlib.h>
28
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "dinput.h"
33 #include "dxerr8.h"
34 #include "dinput_test.h"
35
36 #define numObjects(x) (sizeof(x) / sizeof(x[0]))
37
38 typedef struct tagUserData {
39     LPDIRECTINPUT pDI;
40     DWORD version;
41 } UserData;
42
43 static const DIOBJECTDATAFORMAT dfDIJoystickTest[] = {
44   { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
45   { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
46   { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
47   { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
48   { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
49   { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
50   { &GUID_Button,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
51   { &GUID_Button,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
52   { &GUID_Button,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
53   { &GUID_Button,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
54   { &GUID_Button,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
55   { &GUID_Button,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
56   { &GUID_Button,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
57   { &GUID_Button,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
58   { &GUID_Button,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
59   { &GUID_Button,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
60   { &GUID_Button,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
61 };
62
63 static const DIDATAFORMAT c_dfDIJoystickTest = {
64     sizeof(DIDATAFORMAT),
65     sizeof(DIOBJECTDATAFORMAT),
66     DIDF_ABSAXIS,
67     sizeof(DIJOYSTATE2),
68     numObjects(dfDIJoystickTest),
69     (LPDIOBJECTDATAFORMAT)dfDIJoystickTest
70 };
71
72 HWND get_hwnd()
73 {
74     HWND hwnd=GetForegroundWindow();
75     if (!hwnd)
76         hwnd=GetDesktopWindow();
77     return hwnd;
78 }
79
80 typedef struct tagJoystickInfo
81 {
82     LPDIRECTINPUTDEVICE pJoystick;
83     DWORD axis;
84     DWORD pov;
85     DWORD button;
86 } JoystickInfo;
87
88 static BOOL CALLBACK EnumAxes(
89     const DIDEVICEOBJECTINSTANCE* pdidoi,
90     VOID* pContext)
91 {
92     HRESULT hr;
93     JoystickInfo * info = (JoystickInfo *)pContext;
94
95     if (IsEqualIID(&pdidoi->guidType, &GUID_XAxis) ||
96         IsEqualIID(&pdidoi->guidType, &GUID_YAxis) ||
97         IsEqualIID(&pdidoi->guidType, &GUID_ZAxis) ||
98         IsEqualIID(&pdidoi->guidType, &GUID_RxAxis) ||
99         IsEqualIID(&pdidoi->guidType, &GUID_RyAxis) ||
100         IsEqualIID(&pdidoi->guidType, &GUID_RzAxis) ||
101         IsEqualIID(&pdidoi->guidType, &GUID_Slider)) {
102         DIPROPRANGE diprg;
103         diprg.diph.dwSize       = sizeof(DIPROPRANGE);
104         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
105         diprg.diph.dwHow        = DIPH_BYID;
106         diprg.diph.dwObj        = pdidoi->dwType;
107         diprg.lMin              = -1000;
108         diprg.lMax              = +1000;
109
110         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, NULL);
111         ok(hr==E_INVALIDARG,"IDirectInputDevice_SetProperty() should have returned "
112            "E_INVALIDARG, returned: %s\n", DXGetErrorString8(hr));
113
114         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, &diprg.diph);
115         ok(hr==DI_OK,"IDirectInputDevice_SetProperty() failed: %s\n", DXGetErrorString8(hr));
116
117         info->axis++;
118     } else if (IsEqualIID(&pdidoi->guidType, &GUID_POV))
119         info->pov++;
120     else if (IsEqualIID(&pdidoi->guidType, &GUID_Button))
121         info->button++;
122
123     return DIENUM_CONTINUE;
124 }
125
126 static BOOL CALLBACK EnumJoysticks(
127     LPCDIDEVICEINSTANCE lpddi,
128     LPVOID pvRef)
129 {
130     HRESULT hr;
131     UserData * data = (UserData *)pvRef;
132     LPDIRECTINPUTDEVICE pJoystick;
133     DIDATAFORMAT format;
134     DIDEVCAPS caps;
135     DIJOYSTATE2 js;
136     JoystickInfo info;
137     int i, count;
138     ULONG ref;
139     DIDEVICEINSTANCE inst;
140     DIDEVICEINSTANCE_DX3 inst3;
141     HWND hWnd = get_hwnd();
142
143     ok(data->version > 0x0300, "Joysticks not supported in version 0x%04lx\n", data->version);
144  
145     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, NULL, NULL);
146     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
147        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
148
149     hr = IDirectInput_CreateDevice(data->pDI, NULL, &pJoystick, NULL);
150     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
151        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
152
153     hr = IDirectInput_CreateDevice(data->pDI, NULL, NULL, NULL);
154     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
155        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
156
157     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance,
158                                    &pJoystick, NULL);
159     ok(hr==DI_OK,"IDirectInput_CreateDevice() failed: %s\n",
160        DXGetErrorString8(hr));
161     if (hr!=DI_OK)
162         goto DONE;
163
164     trace("---- %s ----\n", lpddi->tszProductName);
165
166     hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL);
167     ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned "
168        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
169
170     ZeroMemory(&format, sizeof(format));
171     hr = IDirectInputDevice_SetDataFormat(pJoystick, &format);
172     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_SetDataFormat() should have "
173        "returned DIERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(hr));
174
175     /* try the default formats */
176     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick);
177     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
178        DXGetErrorString8(hr));
179
180     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
181     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
182        DXGetErrorString8(hr));
183
184     /* try an alternate format */
185     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystickTest);
186     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
187        DXGetErrorString8(hr));
188
189     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
190     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
191        DXGetErrorString8(hr));
192     if (hr != DI_OK)
193         goto RELEASE;
194
195     hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
196                                                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
197     ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %s\n",
198        DXGetErrorString8(hr));
199
200     /* get capabilities */
201     hr = IDirectInputDevice_GetCapabilities(pJoystick, NULL);
202     ok(hr==E_POINTER,"IDirectInputDevice_GetCapabilities() "
203        "should have returned E_POINTER, returned: %s\n",
204        DXGetErrorString8(hr));
205
206     ZeroMemory(&caps, sizeof(caps));
207     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
208     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_GetCapabilities() "
209        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
210        DXGetErrorString8(hr));
211
212     caps.dwSize = sizeof(caps);
213     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
214     ok(hr==DI_OK,"IDirectInputDevice_GetCapabilities() failed: %s\n",
215        DXGetErrorString8(hr));
216
217     ZeroMemory(&info, sizeof(info));
218     info.pJoystick = pJoystick;
219
220     /* enumerate objects */
221     hr = IDirectInputDevice_EnumObjects(pJoystick, EnumAxes, (VOID*)&info, DIDFT_ALL);
222     ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %s\n",
223        DXGetErrorString8(hr));
224
225     ok(caps.dwAxes == info.axis, "Number of enumerated axes doesn't match capabilities\n");
226     ok(caps.dwButtons == info.button, "Number of enumerated buttons doesn't match capabilities\n");
227     ok(caps.dwPOVs == info.pov, "Number of enumerated POVs doesn't match capabilities\n");
228
229     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, 0);
230     ok(hr==E_POINTER, "IDirectInputDevice_GetDeviceInfo() "
231        "should have returned E_POINTER, returned: %s\n",
232        DXGetErrorString8(hr));
233
234     ZeroMemory(&inst, sizeof(inst));
235     ZeroMemory(&inst3, sizeof(inst3));
236
237     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
238     ok(hr==DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceInfo() "
239        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
240        DXGetErrorString8(hr));
241
242     inst.dwSize = sizeof(inst);
243     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
244     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
245        DXGetErrorString8(hr));
246
247     inst3.dwSize = sizeof(inst3);
248     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, (LPDIDEVICEINSTANCE)&inst3);
249     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
250        DXGetErrorString8(hr));
251
252     hr = IDirectInputDevice_Acquire(pJoystick);
253     ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %s\n",
254        DXGetErrorString8(hr));
255     if (hr != DI_OK)
256         goto RELEASE;
257
258     if (winetest_interactive) {
259         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
260         count = 300;
261     } else
262         count = 1;
263
264     trace("\n");
265     for (i = 0; i < count; i++) {
266         hr = IDirectInputDevice_GetDeviceState(pJoystick, sizeof(DIJOYSTATE2), &js);
267         ok(hr==DI_OK,"IDirectInputDevice_GetDeviceState() failed: %s\n",
268            DXGetErrorString8(hr));
269         if (hr != DI_OK)
270             break;
271         trace("X%5ld Y%5ld Z%5ld Rx%5ld Ry%5ld Rz%5ld "
272               "S0%5ld S1%5ld POV0%5ld POV1%5ld POV2%5ld POV3%5ld "
273               "B %d %d %d %d %d %d %d %d %d %d %d %d\r",
274               js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz,
275               js.rglSlider[0], js.rglSlider[1],
276               js.rgdwPOV[0], js.rgdwPOV[1], js.rgdwPOV[2], js.rgdwPOV[3],
277               js.rgbButtons[0]>>7, js.rgbButtons[1]>>7, js.rgbButtons[2]>>7,
278               js.rgbButtons[3]>>7, js.rgbButtons[4]>>7, js.rgbButtons[5]>>7,
279               js.rgbButtons[6]>>7, js.rgbButtons[7]>>7, js.rgbButtons[8]>>7,
280               js.rgbButtons[9]>>7, js.rgbButtons[10]>>7, js.rgbButtons[11]>>7);
281         Sleep(100);
282     }
283     trace("\n");
284
285     hr = IDirectInputDevice_Unacquire(pJoystick);
286     ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %s\n",
287        DXGetErrorString8(hr));
288
289 RELEASE:
290     ref = IDirectInputDevice_Release(pJoystick);
291     ok(ref==0,"IDirectInputDevice_Release() reference count = %ld\n", ref);
292
293 DONE:
294     return DIENUM_CONTINUE;
295 }
296
297 static void joystick_tests(DWORD version)
298 {
299     HRESULT hr;
300     LPDIRECTINPUT pDI;
301     ULONG ref;
302     HINSTANCE hInstance = GetModuleHandle(NULL);
303
304     trace("-- Testing Direct Input Version 0x%04lx --\n", version);
305     hr = DirectInputCreate(hInstance, version, &pDI, NULL);
306     ok(hr==DI_OK||hr==DIERR_OLDDIRECTINPUTVERSION,
307        "DirectInputCreate() failed: %s\n", DXGetErrorString8(hr));
308     if (hr==DI_OK && pDI!=0) {
309         UserData data;
310         data.pDI = pDI;
311         data.version = version;
312         hr = IDirectInput_EnumDevices(pDI, DIDEVTYPE_JOYSTICK, EnumJoysticks,
313                                       &data, DIEDFL_ALLDEVICES);
314         ok(hr==DI_OK,"IDirectInput_EnumDevices() failed: %s\n",
315            DXGetErrorString8(hr));
316         ref = IDirectInput_Release(pDI);
317         ok(ref==0,"IDirectInput_Release() reference count = %ld\n", ref);
318     } else if (hr==DIERR_OLDDIRECTINPUTVERSION)
319         trace("  Version Not Supported\n");
320 }
321
322 START_TEST(joystick)
323 {
324     CoInitialize(NULL);
325
326     trace("DLL Version: %s\n", get_file_version("dinput.dll"));
327
328     joystick_tests(0x0700);
329     joystick_tests(0x0500);
330     joystick_tests(0x0300);
331
332     CoUninitialize();
333 }