server: Move socket async activation to sock_poll_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 "initguid.h"
27 #include "dinput.h"
28
29 static const DIOBJECTDATAFORMAT obj_data_format[] = {
30   { &GUID_YAxis, 16, DIDFT_OPTIONAL|DIDFT_AXIS  |DIDFT_MAKEINSTANCE(1), 0},
31   { &GUID_Button,15, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(3), 0},
32   { &GUID_Key,    0, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(16),0},
33   { &GUID_Key,    1, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(17),0},
34   { &GUID_Key,    2, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(18),0},
35   { &GUID_Key,    3, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(19),0},
36   { &GUID_Key,    4, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(20),0},
37   { &GUID_Key,    5, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(21),0},
38   { &GUID_Key,    6, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(22),0},
39   { &GUID_Key,    7, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(23),0},
40   { &GUID_Key,    8, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(24),0},
41   { &GUID_Key,    9, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(25),0},
42   { &GUID_Key,   10, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(26),0},
43   { &GUID_Key,   11, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(27),0},
44   { &GUID_Key,   12, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(28),0},
45   { NULL,        13, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(5),0},
46
47   { &GUID_Button,14, DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_MAKEINSTANCE(32),0}
48 };
49
50 static const DIDATAFORMAT data_format = {
51     sizeof(DIDATAFORMAT),
52     sizeof(DIOBJECTDATAFORMAT),
53     DIDF_ABSAXIS,
54     32,
55     sizeof(obj_data_format) / sizeof(obj_data_format[0]),
56     (LPDIOBJECTDATAFORMAT)obj_data_format
57 };
58
59 static BOOL CALLBACK enum_callback(LPCDIDEVICEOBJECTINSTANCE oi, LPVOID info)
60 {
61     if (winetest_debug > 1)
62         trace(" Type:%4x Ofs:%3d Flags:%08x Name:%s\n",
63               oi->dwType, oi->dwOfs, oi->dwFlags, oi->tszName);
64     (*(int*)info)++;
65     return DIENUM_CONTINUE;
66 }
67
68 static void test_object_info(LPDIRECTINPUTDEVICE device, HWND hwnd)
69 {
70     HRESULT hr;
71     DIPROPDWORD dp;
72     DIDEVICEOBJECTINSTANCE obj_info;
73     int cnt = 0, cnt1 = 0;
74
75     hr = IDirectInputDevice_EnumObjects(device, enum_callback, &cnt, DIDFT_ALL);
76     ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
77
78     hr = IDirectInputDevice_SetDataFormat(device, &data_format);
79     ok(SUCCEEDED(hr), "SetDataFormat() failed: %08x\n", hr);
80
81     hr = IDirectInputDevice_EnumObjects(device, enum_callback, &cnt1, DIDFT_ALL);
82     ok(SUCCEEDED(hr), "EnumObjects() failed: %08x\n", hr);
83     if (0) /* fails for joystick only */
84     ok(cnt == cnt1, "Enum count changed from %d to %d\n", cnt, cnt1);
85
86     /* No need to test devices without axis */
87     obj_info.dwSize = sizeof(obj_info);
88     hr = IDirectInputDevice_GetObjectInfo(device, &obj_info, 16, DIPH_BYOFFSET);
89     if (SUCCEEDED(hr))
90     {
91         /* No device supports per axis relative/absolute mode */
92         memset(&dp, 0, sizeof(dp));
93         dp.diph.dwSize = sizeof(DIPROPDWORD);
94         dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
95         dp.diph.dwHow = DIPH_BYOFFSET;
96         dp.diph.dwObj = 16;
97         dp.dwData = DIPROPAXISMODE_ABS;
98         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
99         ok(hr == DIERR_UNSUPPORTED, "SetProperty() returned: %08x\n", hr);
100         dp.diph.dwHow = DIPH_DEVICE;
101         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
102         ok(hr == DIERR_INVALIDPARAM, "SetProperty() returned: %08x\n", hr);
103         dp.diph.dwObj = 0;
104         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
105         ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
106
107         /* Cannot change mode while acquired */
108         hr = IDirectInputDevice_Acquire(device);
109         ok(hr == DI_OK, "Acquire() failed: %08x\n", hr);
110         hr = IDirectInputDevice_SetProperty(device, DIPROP_AXISMODE, &dp.diph);
111         ok(hr == DIERR_ACQUIRED, "SetProperty() returned: %08x\n", hr);
112     }
113 }
114
115 struct enum_data
116 {
117     LPDIRECTINPUT pDI;
118     HWND hwnd;
119 };
120
121 static BOOL CALLBACK enum_devices(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
122 {
123     struct enum_data *data = pvRef;
124     LPDIRECTINPUTDEVICE device;
125     HRESULT hr;
126
127     hr = IDirectInput_GetDeviceStatus(data->pDI, &lpddi->guidInstance);
128     ok(hr == DI_OK, "IDirectInput_GetDeviceStatus() failed: %08x\n", hr);
129
130     if (hr == DI_OK)
131     {
132         hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, &device, NULL);
133         ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
134         trace("Testing device \"%s\"\n", lpddi->tszInstanceName);
135         test_object_info(device, data->hwnd);
136         IUnknown_Release(device);
137     }
138     return DIENUM_CONTINUE;
139 }
140
141 static void device_tests(void)
142 {
143     HRESULT hr;
144     LPDIRECTINPUT pDI = NULL;
145     HINSTANCE hInstance = GetModuleHandle(NULL);
146     HWND hwnd;
147     struct enum_data data;
148
149     hr = DirectInputCreate(hInstance, DIRECTINPUT_VERSION, &pDI, NULL);
150     if (hr == DIERR_OLDDIRECTINPUTVERSION)
151     {
152         skip("Tests require a newer dinput version\n");
153         return;
154     }
155     ok(SUCCEEDED(hr), "DirectInputCreate() failed: %08x\n", hr);
156     if (FAILED(hr)) return;
157
158     hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW,
159                         10, 10, 200, 200, NULL, NULL, NULL, NULL);
160     ok(hwnd != NULL, "err: %d\n", GetLastError());
161     if (hwnd)
162     {
163         ShowWindow(hwnd, SW_SHOW);
164
165         data.pDI = pDI;
166         data.hwnd = hwnd;
167         hr = IDirectInput_EnumDevices(pDI, 0, enum_devices, &data, DIEDFL_ALLDEVICES);
168         ok(SUCCEEDED(hr), "IDirectInput_EnumDevices() failed: %08x\n", hr);
169
170
171         /* If GetDeviceStatus returns DI_OK the device must exist */
172         hr = IDirectInput_GetDeviceStatus(pDI, &GUID_Joystick);
173         if (hr == DI_OK)
174         {
175             LPDIRECTINPUTDEVICE device = NULL;
176
177             hr = IDirectInput_CreateDevice(pDI, &GUID_Joystick, &device, NULL);
178             ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
179             if (device) IUnknown_Release(device);
180         }
181
182         DestroyWindow(hwnd);
183     }
184     if (pDI) IUnknown_Release(pDI);
185 }
186
187 START_TEST(device)
188 {
189     CoInitialize(NULL);
190
191     device_tests();
192
193     CoUninitialize();
194 }