mshtml: Print wine_gecko version in load_wine_gecko.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define DIRECTINPUT_VERSION 0x0700
20
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
23 #include <windows.h>
24
25 #include <math.h>
26 #include <stdio.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(void)
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 const HRESULT SetCoop_null_window[16] =  {
127     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
128     E_INVALIDARG, E_HANDLE,     E_HANDLE,     E_INVALIDARG,
129     E_INVALIDARG, E_HANDLE,     S_OK,         E_INVALIDARG,
130     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
131
132 static const HRESULT SetCoop_real_window[16] =  {
133     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
134     E_INVALIDARG, S_OK,         S_OK,         E_INVALIDARG,
135     E_INVALIDARG, S_OK,         S_OK,         E_INVALIDARG,
136     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
137
138 static BOOL CALLBACK EnumJoysticks(
139     LPCDIDEVICEINSTANCE lpddi,
140     LPVOID pvRef)
141 {
142     HRESULT hr;
143     UserData * data = (UserData *)pvRef;
144     LPDIRECTINPUTDEVICE pJoystick;
145     DIDATAFORMAT format;
146     DIDEVCAPS caps;
147     DIJOYSTATE2 js;
148     JoystickInfo info;
149     int i, count;
150     ULONG ref;
151     DIDEVICEINSTANCE inst;
152     DIDEVICEINSTANCE_DX3 inst3;
153     HWND hWnd = get_hwnd();
154     char oldstate[248], curstate[248];
155
156     ok(data->version > 0x0300, "Joysticks not supported in version 0x%04x\n", data->version);
157  
158     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, NULL, NULL);
159     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
160        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
161
162     hr = IDirectInput_CreateDevice(data->pDI, NULL, &pJoystick, NULL);
163     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
164        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
165
166     hr = IDirectInput_CreateDevice(data->pDI, NULL, NULL, NULL);
167     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
168        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
169
170     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance,
171                                    &pJoystick, NULL);
172     ok(hr==DI_OK,"IDirectInput_CreateDevice() failed: %s\n",
173        DXGetErrorString8(hr));
174     if (hr!=DI_OK)
175         goto DONE;
176
177     trace("---- %s ----\n", lpddi->tszProductName);
178
179     hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL);
180     ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned "
181        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
182
183     ZeroMemory(&format, sizeof(format));
184     hr = IDirectInputDevice_SetDataFormat(pJoystick, &format);
185     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_SetDataFormat() should have "
186        "returned DIERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(hr));
187
188     /* try the default formats */
189     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick);
190     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
191        DXGetErrorString8(hr));
192
193     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
194     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
195        DXGetErrorString8(hr));
196
197     /* try an alternate format */
198     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystickTest);
199     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
200        DXGetErrorString8(hr));
201
202     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
203     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
204        DXGetErrorString8(hr));
205     if (hr != DI_OK)
206         goto RELEASE;
207
208     for (i=0; i<16; i++)
209     {
210         hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, NULL, i);
211         ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %s\n", i, DXGetErrorString8(hr));
212     }
213     for (i=0; i<16; i++)
214     {
215         hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd, i);
216         ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %s\n", i, DXGetErrorString8(hr));
217     }
218
219     hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
220                                                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
221     ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %s\n",
222        DXGetErrorString8(hr));
223
224     /* get capabilities */
225     hr = IDirectInputDevice_GetCapabilities(pJoystick, NULL);
226     ok(hr==E_POINTER,"IDirectInputDevice_GetCapabilities() "
227        "should have returned E_POINTER, returned: %s\n",
228        DXGetErrorString8(hr));
229
230     ZeroMemory(&caps, sizeof(caps));
231     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
232     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_GetCapabilities() "
233        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
234        DXGetErrorString8(hr));
235
236     caps.dwSize = sizeof(caps);
237     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
238     ok(hr==DI_OK,"IDirectInputDevice_GetCapabilities() failed: %s\n",
239        DXGetErrorString8(hr));
240
241     ZeroMemory(&info, sizeof(info));
242     info.pJoystick = pJoystick;
243
244     /* enumerate objects */
245     hr = IDirectInputDevice_EnumObjects(pJoystick, EnumAxes, (VOID*)&info, DIDFT_ALL);
246     ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %s\n",
247        DXGetErrorString8(hr));
248
249     ok(caps.dwAxes == info.axis, "Number of enumerated axes doesn't match capabilities\n");
250     ok(caps.dwButtons == info.button, "Number of enumerated buttons doesn't match capabilities\n");
251     ok(caps.dwPOVs == info.pov, "Number of enumerated POVs doesn't match capabilities\n");
252
253     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, 0);
254     ok(hr==E_POINTER, "IDirectInputDevice_GetDeviceInfo() "
255        "should have returned E_POINTER, returned: %s\n",
256        DXGetErrorString8(hr));
257
258     ZeroMemory(&inst, sizeof(inst));
259     ZeroMemory(&inst3, sizeof(inst3));
260
261     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
262     ok(hr==DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceInfo() "
263        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
264        DXGetErrorString8(hr));
265
266     inst.dwSize = sizeof(inst);
267     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
268     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
269        DXGetErrorString8(hr));
270
271     inst3.dwSize = sizeof(inst3);
272     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, (LPDIDEVICEINSTANCE)&inst3);
273     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
274        DXGetErrorString8(hr));
275
276     hr = IDirectInputDevice_Acquire(pJoystick);
277     ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %s\n",
278        DXGetErrorString8(hr));
279     if (hr != DI_OK)
280         goto RELEASE;
281
282     if (winetest_interactive) {
283         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
284         count = 300;
285     } else
286         count = 1;
287
288     trace("\n");
289     oldstate[0]='\0';
290     for (i = 0; i < count; i++) {
291         hr = IDirectInputDevice_GetDeviceState(pJoystick, sizeof(DIJOYSTATE2), &js);
292         ok(hr==DI_OK,"IDirectInputDevice_GetDeviceState() failed: %s\n",
293            DXGetErrorString8(hr));
294         if (hr != DI_OK)
295             break;
296         sprintf(curstate, "X%5d Y%5d Z%5d Rx%5d Ry%5d Rz%5d "
297               "S0%5d S1%5d POV0%5d POV1%5d POV2%5d POV3%5d "
298               "B %d %d %d %d %d %d %d %d %d %d %d %d\n",
299               js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz,
300               js.rglSlider[0], js.rglSlider[1],
301               js.rgdwPOV[0], js.rgdwPOV[1], js.rgdwPOV[2], js.rgdwPOV[3],
302               js.rgbButtons[0]>>7, js.rgbButtons[1]>>7, js.rgbButtons[2]>>7,
303               js.rgbButtons[3]>>7, js.rgbButtons[4]>>7, js.rgbButtons[5]>>7,
304               js.rgbButtons[6]>>7, js.rgbButtons[7]>>7, js.rgbButtons[8]>>7,
305               js.rgbButtons[9]>>7, js.rgbButtons[10]>>7, js.rgbButtons[11]>>7);
306         if (strcmp(oldstate, curstate) != 0)
307         {
308             trace(curstate);
309             strcpy(oldstate, curstate);
310         }
311         Sleep(100);
312     }
313     trace("\n");
314
315     hr = IDirectInputDevice_Unacquire(pJoystick);
316     ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %s\n",
317        DXGetErrorString8(hr));
318
319 RELEASE:
320     ref = IDirectInputDevice_Release(pJoystick);
321     ok(ref==0,"IDirectInputDevice_Release() reference count = %d\n", ref);
322
323 DONE:
324     return DIENUM_CONTINUE;
325 }
326
327 static void joystick_tests(DWORD version)
328 {
329     HRESULT hr;
330     LPDIRECTINPUT pDI;
331     ULONG ref;
332     HINSTANCE hInstance = GetModuleHandle(NULL);
333
334     trace("-- Testing Direct Input Version 0x%04x --\n", version);
335     hr = DirectInputCreate(hInstance, version, &pDI, NULL);
336     ok(hr==DI_OK||hr==DIERR_OLDDIRECTINPUTVERSION,
337        "DirectInputCreate() failed: %s\n", DXGetErrorString8(hr));
338     if (hr==DI_OK && pDI!=0) {
339         UserData data;
340         data.pDI = pDI;
341         data.version = version;
342         hr = IDirectInput_EnumDevices(pDI, DIDEVTYPE_JOYSTICK, EnumJoysticks,
343                                       &data, DIEDFL_ALLDEVICES);
344         ok(hr==DI_OK,"IDirectInput_EnumDevices() failed: %s\n",
345            DXGetErrorString8(hr));
346         ref = IDirectInput_Release(pDI);
347         ok(ref==0,"IDirectInput_Release() reference count = %d\n", ref);
348     } else if (hr==DIERR_OLDDIRECTINPUTVERSION)
349         trace("  Version Not Supported\n");
350 }
351
352 START_TEST(joystick)
353 {
354     CoInitialize(NULL);
355
356     trace("DLL Version: %s\n", get_file_version("dinput.dll"));
357
358     joystick_tests(0x0700);
359     joystick_tests(0x0500);
360     joystick_tests(0x0300);
361
362     CoUninitialize();
363 }