gdiplus: Implement GdipGetEmHeight.
[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 COBJMACROS
22 #include <windows.h>
23
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "dinput.h"
32 #include "dxerr8.h"
33 #include "dinput_test.h"
34
35 #define numObjects(x) (sizeof(x) / sizeof(x[0]))
36
37 typedef struct tagUserData {
38     LPDIRECTINPUT pDI;
39     DWORD version;
40 } UserData;
41
42 static const DIOBJECTDATAFORMAT dfDIJoystickTest[] = {
43   { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
44   { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
45   { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
46   { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
47   { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
48   { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
49   { &GUID_Button,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
50   { &GUID_Button,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
51   { &GUID_Button,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
52   { &GUID_Button,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
53   { &GUID_Button,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
54   { &GUID_Button,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
55   { &GUID_Button,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
56   { &GUID_Button,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
57   { &GUID_Button,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
58   { &GUID_Button,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
59   { &GUID_Button,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
60 };
61
62 static const DIDATAFORMAT c_dfDIJoystickTest = {
63     sizeof(DIDATAFORMAT),
64     sizeof(DIOBJECTDATAFORMAT),
65     DIDF_ABSAXIS,
66     sizeof(DIJOYSTATE2),
67     numObjects(dfDIJoystickTest),
68     (LPDIOBJECTDATAFORMAT)dfDIJoystickTest
69 };
70
71 static HWND get_hwnd(void)
72 {
73     HWND hwnd=GetForegroundWindow();
74     if (!hwnd)
75         hwnd=GetDesktopWindow();
76     return hwnd;
77 }
78
79 typedef struct tagJoystickInfo
80 {
81     LPDIRECTINPUTDEVICE pJoystick;
82     DWORD axis;
83     DWORD pov;
84     DWORD button;
85     LONG  lMin, lMax;
86     DWORD dZone;
87 } JoystickInfo;
88
89 static int get_refcount(IUnknown *object)
90 {
91     IUnknown_AddRef( object );
92     return IUnknown_Release( object );
93 }
94
95 static BOOL CALLBACK EnumAxes(
96     const DIDEVICEOBJECTINSTANCE* pdidoi,
97     VOID* pContext)
98 {
99     HRESULT hr;
100     JoystickInfo * info = (JoystickInfo *)pContext;
101
102     if (IsEqualIID(&pdidoi->guidType, &GUID_XAxis) ||
103         IsEqualIID(&pdidoi->guidType, &GUID_YAxis) ||
104         IsEqualIID(&pdidoi->guidType, &GUID_ZAxis) ||
105         IsEqualIID(&pdidoi->guidType, &GUID_RxAxis) ||
106         IsEqualIID(&pdidoi->guidType, &GUID_RyAxis) ||
107         IsEqualIID(&pdidoi->guidType, &GUID_RzAxis) ||
108         IsEqualIID(&pdidoi->guidType, &GUID_Slider))
109     {
110         DIPROPRANGE diprg;
111         DIPROPDWORD dipdw;
112
113         diprg.diph.dwSize       = sizeof(DIPROPRANGE);
114         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
115         diprg.diph.dwHow        = DIPH_BYID;
116         diprg.diph.dwObj        = pdidoi->dwType;
117
118         dipdw.diph.dwSize       = sizeof(dipdw);
119         dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
120         dipdw.diph.dwHow        = DIPH_BYID;
121         dipdw.diph.dwObj        = pdidoi->dwType;
122
123         hr = IDirectInputDevice_GetProperty(info->pJoystick, DIPROP_RANGE, &diprg.diph);
124         ok(SUCCEEDED(hr), "IDirectInputDevice_GetProperty() failed: %s\n", DXGetErrorString8(hr));
125         ok(info->lMin == diprg.lMin && info->lMax == diprg.lMax, "Min/Max range invalid: "
126            "expected %d..%d got %d..%d\n", info->lMin, info->lMax, diprg.lMin, diprg.lMax);
127
128         diprg.lMin = -2000;
129         diprg.lMax = +2000;
130
131         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, NULL);
132         ok(hr==E_INVALIDARG,"IDirectInputDevice_SetProperty() should have returned "
133            "E_INVALIDARG, returned: %s\n", DXGetErrorString8(hr));
134
135         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, &diprg.diph);
136         ok(hr==DI_OK,"IDirectInputDevice_SetProperty() failed: %s\n", DXGetErrorString8(hr));
137
138         /* dead zone */
139         hr = IDirectInputDevice_GetProperty(info->pJoystick, DIPROP_DEADZONE, &dipdw.diph);
140         ok(SUCCEEDED(hr), "IDirectInputDevice_GetProperty() failed: %s\n", DXGetErrorString8(hr));
141         ok(info->dZone == dipdw.dwData, "deadzone invalid: expected %d got %d\n",
142            info->dZone, dipdw.dwData);
143
144         dipdw.dwData = 123;
145
146         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_DEADZONE, &dipdw.diph);
147         ok(hr==DI_OK,"IDirectInputDevice_SetProperty() failed: %s\n", DXGetErrorString8(hr));
148
149         info->axis++;
150     } else if (IsEqualIID(&pdidoi->guidType, &GUID_POV))
151         info->pov++;
152     else if (IsEqualIID(&pdidoi->guidType, &GUID_Button))
153         info->button++;
154
155     return DIENUM_CONTINUE;
156 }
157
158 static const HRESULT SetCoop_null_window[16] =  {
159     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
160     E_INVALIDARG, E_HANDLE,     E_HANDLE,     E_INVALIDARG,
161     E_INVALIDARG, E_HANDLE,     S_OK,         E_INVALIDARG,
162     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
163
164 static const HRESULT SetCoop_real_window[16] =  {
165     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
166     E_INVALIDARG, S_OK,         S_OK,         E_INVALIDARG,
167     E_INVALIDARG, S_OK,         S_OK,         E_INVALIDARG,
168     E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
169
170 static BOOL CALLBACK EnumJoysticks(
171     LPCDIDEVICEINSTANCE lpddi,
172     LPVOID pvRef)
173 {
174     HRESULT hr;
175     UserData * data = (UserData *)pvRef;
176     LPDIRECTINPUTDEVICE pJoystick;
177     DIDATAFORMAT format;
178     DIDEVCAPS caps;
179     DIJOYSTATE2 js;
180     JoystickInfo info;
181     int i, count;
182     ULONG ref;
183     DIDEVICEINSTANCE inst;
184     DIDEVICEINSTANCE_DX3 inst3;
185     HWND hWnd = get_hwnd();
186     char oldstate[248], curstate[248];
187
188     ok(data->version > 0x0300, "Joysticks not supported in version 0x%04x\n", data->version);
189  
190     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, NULL, NULL);
191     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
192        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
193
194     hr = IDirectInput_CreateDevice(data->pDI, NULL, &pJoystick, NULL);
195     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
196        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
197
198     hr = IDirectInput_CreateDevice(data->pDI, NULL, NULL, NULL);
199     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
200        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
201
202     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance,
203                                    &pJoystick, NULL);
204     ok(hr==DI_OK,"IDirectInput_CreateDevice() failed: %s\n",
205        DXGetErrorString8(hr));
206     if (hr!=DI_OK)
207         goto DONE;
208
209     trace("---- %s ----\n", lpddi->tszProductName);
210
211     hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL);
212     ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned "
213        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
214
215     ZeroMemory(&format, sizeof(format));
216     hr = IDirectInputDevice_SetDataFormat(pJoystick, &format);
217     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_SetDataFormat() should have "
218        "returned DIERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(hr));
219
220     /* try the default formats */
221     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick);
222     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
223        DXGetErrorString8(hr));
224
225     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
226     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
227        DXGetErrorString8(hr));
228
229     /* try an alternate format */
230     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystickTest);
231     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
232        DXGetErrorString8(hr));
233
234     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
235     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
236        DXGetErrorString8(hr));
237     if (hr != DI_OK)
238         goto RELEASE;
239
240     for (i=0; i<16; i++)
241     {
242         hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, NULL, i);
243         ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %s\n", i, DXGetErrorString8(hr));
244     }
245     for (i=0; i<16; i++)
246     {
247         hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd, i);
248         ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %s\n", i, DXGetErrorString8(hr));
249     }
250
251     hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
252                                                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
253     ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %s\n",
254        DXGetErrorString8(hr));
255
256     /* get capabilities */
257     hr = IDirectInputDevice_GetCapabilities(pJoystick, NULL);
258     ok(hr==E_POINTER,"IDirectInputDevice_GetCapabilities() "
259        "should have returned E_POINTER, returned: %s\n",
260        DXGetErrorString8(hr));
261
262     ZeroMemory(&caps, sizeof(caps));
263     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
264     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_GetCapabilities() "
265        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
266        DXGetErrorString8(hr));
267
268     caps.dwSize = sizeof(caps);
269     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
270     ok(hr==DI_OK,"IDirectInputDevice_GetCapabilities() failed: %s\n",
271        DXGetErrorString8(hr));
272
273     ZeroMemory(&info, sizeof(info));
274     info.pJoystick = pJoystick;
275
276     /* default min/max limits */
277     info.lMin = 0;
278     info.lMax = 0xffff;
279     /* enumerate objects */
280     hr = IDirectInputDevice_EnumObjects(pJoystick, EnumAxes, (VOID*)&info, DIDFT_ALL);
281     ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %s\n",
282        DXGetErrorString8(hr));
283
284     ok(caps.dwAxes == info.axis, "Number of enumerated axes (%d) doesn't match capabilities (%d)\n", info.axis, caps.dwAxes);
285     ok(caps.dwButtons == info.button, "Number of enumerated buttons (%d) doesn't match capabilities (%d)\n", info.button, caps.dwButtons);
286     ok(caps.dwPOVs == info.pov, "Number of enumerated POVs (%d) doesn't match capabilities (%d)\n", info.pov, caps.dwPOVs);
287
288     /* Set format and check limits again */
289     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
290     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n", DXGetErrorString8(hr));
291     info.lMin = -2000;
292     info.lMax = +2000;
293     info.dZone= 123;
294     hr = IDirectInputDevice_EnumObjects(pJoystick, EnumAxes, (VOID*)&info, DIDFT_ALL);
295     ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %s\n", DXGetErrorString8(hr));
296
297     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, 0);
298     ok(hr==E_POINTER, "IDirectInputDevice_GetDeviceInfo() "
299        "should have returned E_POINTER, returned: %s\n",
300        DXGetErrorString8(hr));
301
302     ZeroMemory(&inst, sizeof(inst));
303     ZeroMemory(&inst3, sizeof(inst3));
304
305     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
306     ok(hr==DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceInfo() "
307        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
308        DXGetErrorString8(hr));
309
310     inst.dwSize = sizeof(inst);
311     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
312     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
313        DXGetErrorString8(hr));
314
315     inst3.dwSize = sizeof(inst3);
316     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, (LPDIDEVICEINSTANCE)&inst3);
317     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
318        DXGetErrorString8(hr));
319
320     hr = IDirectInputDevice_Unacquire(pJoystick);
321     ok(hr == S_FALSE, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %s\n",
322        DXGetErrorString8(hr));
323
324     hr = IDirectInputDevice_Acquire(pJoystick);
325     ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %s\n",
326        DXGetErrorString8(hr));
327     if (hr != DI_OK)
328         goto RELEASE;
329
330     hr = IDirectInputDevice_Acquire(pJoystick);
331     ok(hr == S_FALSE, "IDirectInputDevice_Acquire() should have returned S_FALSE, got: %s\n",
332        DXGetErrorString8(hr));
333
334     if (info.pov < 4)
335     {
336         hr = IDirectInputDevice_GetDeviceState(pJoystick, sizeof(DIJOYSTATE2), &js);
337         ok(hr == DI_OK, "IDirectInputDevice_GetDeviceState() failed: %s\n", DXGetErrorString8(hr));
338         ok(js.rgdwPOV[3] == -1, "Default for unassigned POV should be -1 not: %d\n", js.rgdwPOV[3]);
339     }
340
341     if (caps.dwFlags & DIDC_FORCEFEEDBACK)
342     {
343         DWORD axes[2] = {DIJOFS_X, DIJOFS_Y};
344         LONG  direction[2] = {0, 0};
345         DICONSTANTFORCE force = {0};
346         DIEFFECT eff;
347         LPDIRECTINPUTEFFECT effect = NULL;
348         LONG cnt1, cnt2;
349
350         trace("Testing force-feedback\n");
351         memset(&eff, 0, sizeof(eff));
352         eff.dwSize                = sizeof(eff);
353         eff.dwFlags               = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
354         eff.dwDuration            = INFINITE;
355         eff.dwGain                = DI_FFNOMINALMAX;
356         eff.dwTriggerButton       = DIEB_NOTRIGGER;
357         eff.cAxes                 = sizeof(axes) / sizeof(axes[0]);
358         eff.rgdwAxes              = axes;
359         eff.rglDirection          = direction;
360         eff.cbTypeSpecificParams  = sizeof(force);
361         eff.lpvTypeSpecificParams = &force;
362
363         cnt1 = get_refcount((IUnknown*)pJoystick);
364
365         hr = IDirectInputDevice2_CreateEffect((LPDIRECTINPUTDEVICE2)pJoystick, &GUID_ConstantForce,
366                                               &eff, &effect, NULL);
367         ok(hr == DI_OK, "IDirectInputDevice_CreateEffect() failed: %s\n", DXGetErrorString8(hr));
368         cnt2 = get_refcount((IUnknown*)pJoystick);
369         ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
370
371         if (effect)
372         {
373             ref = IUnknown_Release(effect);
374             ok(ref == 0, "IDirectInputDevice_Release() reference count = %d\n", ref);
375         }
376         cnt1 = get_refcount((IUnknown*)pJoystick);
377         ok(cnt1 == cnt2, "Ref count is wrong %d != %d\n", cnt1, cnt2);
378     }
379
380     if (winetest_interactive) {
381         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
382         count = 300;
383     } else
384         count = 1;
385
386     trace("\n");
387     oldstate[0]='\0';
388     for (i = 0; i < count; i++) {
389         hr = IDirectInputDevice_GetDeviceState(pJoystick, sizeof(DIJOYSTATE2), &js);
390         ok(hr==DI_OK,"IDirectInputDevice_GetDeviceState() failed: %s\n",
391            DXGetErrorString8(hr));
392         if (hr != DI_OK)
393             break;
394         sprintf(curstate, "X%5d Y%5d Z%5d Rx%5d Ry%5d Rz%5d "
395               "S0%5d S1%5d POV0%5d POV1%5d POV2%5d POV3%5d "
396               "B %d %d %d %d %d %d %d %d %d %d %d %d\n",
397               js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz,
398               js.rglSlider[0], js.rglSlider[1],
399               js.rgdwPOV[0], js.rgdwPOV[1], js.rgdwPOV[2], js.rgdwPOV[3],
400               js.rgbButtons[0]>>7, js.rgbButtons[1]>>7, js.rgbButtons[2]>>7,
401               js.rgbButtons[3]>>7, js.rgbButtons[4]>>7, js.rgbButtons[5]>>7,
402               js.rgbButtons[6]>>7, js.rgbButtons[7]>>7, js.rgbButtons[8]>>7,
403               js.rgbButtons[9]>>7, js.rgbButtons[10]>>7, js.rgbButtons[11]>>7);
404         if (strcmp(oldstate, curstate) != 0)
405         {
406             trace(curstate);
407             strcpy(oldstate, curstate);
408         }
409         Sleep(100);
410     }
411     trace("\n");
412
413     hr = IDirectInputDevice_Unacquire(pJoystick);
414     ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %s\n",
415        DXGetErrorString8(hr));
416
417 RELEASE:
418     ref = IDirectInputDevice_Release(pJoystick);
419     ok(ref==0,"IDirectInputDevice_Release() reference count = %d\n", ref);
420
421 DONE:
422     return DIENUM_CONTINUE;
423 }
424
425 static void joystick_tests(DWORD version)
426 {
427     HRESULT hr;
428     LPDIRECTINPUT pDI;
429     ULONG ref;
430     HINSTANCE hInstance = GetModuleHandle(NULL);
431
432     trace("-- Testing Direct Input Version 0x%04x --\n", version);
433     hr = DirectInputCreate(hInstance, version, &pDI, NULL);
434     ok(hr==DI_OK||hr==DIERR_OLDDIRECTINPUTVERSION,
435        "DirectInputCreate() failed: %s\n", DXGetErrorString8(hr));
436     if (hr==DI_OK && pDI!=0) {
437         UserData data;
438         data.pDI = pDI;
439         data.version = version;
440         hr = IDirectInput_EnumDevices(pDI, DIDEVTYPE_JOYSTICK, EnumJoysticks,
441                                       &data, DIEDFL_ALLDEVICES);
442         ok(hr==DI_OK,"IDirectInput_EnumDevices() failed: %s\n",
443            DXGetErrorString8(hr));
444         ref = IDirectInput_Release(pDI);
445         ok(ref==0,"IDirectInput_Release() reference count = %d\n", ref);
446     } else if (hr==DIERR_OLDDIRECTINPUTVERSION)
447         trace("  Version Not Supported\n");
448 }
449
450 START_TEST(joystick)
451 {
452     CoInitialize(NULL);
453
454     trace("DLL Version: %s\n", get_file_version("dinput.dll"));
455
456     joystick_tests(0x0700);
457     joystick_tests(0x0500);
458     joystick_tests(0x0300);
459
460     CoUninitialize();
461 }