[DINPUT_WINETEST] Sync with Wine Staging 1.9.4. CORE-10912
[reactos.git] / rostests / winetests / dinput / keyboard.c
1 /*
2 * Copyright (c) 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 WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #define DIRECTINPUT_VERSION 0x0700
24
25 #define COBJMACROS
26 //#include <windows.h>
27
28 //#include <math.h>
29 //#include <stdio.h>
30 //#include <stdlib.h>
31
32 #include <wine/test.h>
33 //#include "windef.h"
34 //#include "wingdi.h"
35 #include <dinput.h>
36
37 static void acquire_tests(IDirectInputA *pDI, HWND hwnd)
38 {
39 HRESULT hr;
40 IDirectInputDeviceA *pKeyboard;
41 BYTE kbd_state[256];
42 LONG custom_state[6];
43 int i;
44 DIOBJECTDATAFORMAT dodf[] =
45 {
46 { &GUID_Key, sizeof(LONG) * 0, DIDFT_MAKEINSTANCE(DIK_Q)|DIDFT_BUTTON, 0 },
47 { &GUID_Key, sizeof(LONG) * 1, DIDFT_MAKEINSTANCE(DIK_W)|DIDFT_BUTTON, 0 },
48 { &GUID_Key, sizeof(LONG) * 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 },
49 { &GUID_Key, sizeof(LONG) * 4, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 },
50 };
51
52 DIDATAFORMAT df;
53 df.dwSize = sizeof( df );
54 df.dwObjSize = sizeof( DIOBJECTDATAFORMAT );
55 df.dwFlags = DIDF_RELAXIS;
56 df.dwDataSize = sizeof( custom_state );
57 df.dwNumObjs = sizeof( dodf )/sizeof( dodf[0] );
58 df.rgodf = dodf;
59
60 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL);
61 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
62 if (FAILED(hr)) return;
63
64 hr = IDirectInputDevice_SetDataFormat(pKeyboard, &c_dfDIKeyboard);
65 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr);
66 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
67 ok(SUCCEEDED(hr), "IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr);
68 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state);
69 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr);
70 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state);
71 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState() should have failed: %08x\n", hr);
72 hr = IDirectInputDevice_Unacquire(pKeyboard);
73 ok(hr == S_FALSE, "IDirectInputDevice_Unacquire() should have failed: %08x\n", hr);
74 hr = IDirectInputDevice_Acquire(pKeyboard);
75 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
76 hr = IDirectInputDevice_Acquire(pKeyboard);
77 ok(hr == S_FALSE, "IDirectInputDevice_Acquire() should have failed: %08x\n", hr);
78 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state);
79 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr);
80 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state);
81 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
82 hr = IDirectInputDevice_Unacquire(pKeyboard);
83 ok(SUCCEEDED(hr), "IDirectInputDevice_Uncquire() failed: %08x\n", hr);
84 hr = IDirectInputDevice_SetDataFormat( pKeyboard , &df );
85 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr);
86 hr = IDirectInputDevice_Acquire(pKeyboard);
87 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
88 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
89 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState(4,) failed: %08x\n", hr);
90 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state);
91 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(256,) should have failed: %08x\n", hr);
92
93 memset(custom_state, 0x56, sizeof(custom_state));
94 IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
95 for (i = 0; i < sizeof(custom_state) / sizeof(custom_state[0]); i++)
96 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]);
97
98 /* simulate some keyboard input */
99 SetFocus(hwnd);
100 keybd_event('Q', 0, 0, 0);
101 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
102 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr);
103 if (!custom_state[0])
104 win_skip("Keyboard event not processed, skipping test\n");
105 else
106 {
107 /* unacquiring should reset the device state */
108 hr = IDirectInputDevice_Unacquire(pKeyboard);
109 ok(SUCCEEDED(hr), "IDirectInputDevice_Unacquire() failed: %08x\n", hr);
110 hr = IDirectInputDevice_Acquire(pKeyboard);
111 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr);
112 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state);
113 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState failed: %08x\n", hr);
114 for (i = 0; i < sizeof(custom_state) / sizeof(custom_state[0]); i++)
115 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]);
116 }
117 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0);
118
119 if (pKeyboard) IUnknown_Release(pKeyboard);
120 }
121
122 static const HRESULT SetCoop_null_window[16] = {
123 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
124 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
125 E_INVALIDARG, E_HANDLE, S_OK, E_INVALIDARG,
126 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
127
128 static const HRESULT SetCoop_invalid_window[16] = {
129 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
130 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
131 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
132 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
133
134 static const HRESULT SetCoop_real_window[16] = {
135 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
136 E_INVALIDARG, S_OK, S_OK, E_INVALIDARG,
137 E_INVALIDARG, E_NOTIMPL, S_OK, E_INVALIDARG,
138 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
139
140 static const HRESULT SetCoop_child_window[16] = {
141 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG,
142 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
143 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG,
144 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG};
145
146 static void test_set_coop(IDirectInputA *pDI, HWND hwnd)
147 {
148 HRESULT hr;
149 IDirectInputDeviceA *pKeyboard = NULL;
150 int i;
151 HWND child;
152
153 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL);
154 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
155 if (FAILED(hr)) return;
156
157 for (i=0; i<16; i++)
158 {
159 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, i);
160 ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %08x\n", i, hr);
161 }
162 for (i=0; i<16; i++)
163 {
164 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, (HWND)0x400000, i);
165 ok(hr == SetCoop_invalid_window[i], "SetCooperativeLevel(invalid, %d): %08x\n", i, hr);
166 }
167 for (i=0; i<16; i++)
168 {
169 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, hwnd, i);
170 ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %08x\n", i, hr);
171 }
172
173 child = CreateWindowA("static", "Title", WS_CHILD | WS_VISIBLE, 10, 10, 50, 50, hwnd, NULL,
174 NULL, NULL);
175 ok(child != NULL, "err: %d\n", GetLastError());
176
177 for (i=0; i<16; i++)
178 {
179 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, child, i);
180 ok(hr == SetCoop_child_window[i], "SetCooperativeLevel(child, %d): %08x\n", i, hr);
181 }
182
183 DestroyWindow(child);
184 if (pKeyboard) IUnknown_Release(pKeyboard);
185 }
186
187 static void test_get_prop(IDirectInputA *pDI, HWND hwnd)
188 {
189 HRESULT hr;
190 IDirectInputDeviceA *pKeyboard = NULL;
191 DIPROPRANGE diprg;
192
193 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL);
194 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
195 if (FAILED(hr)) return;
196
197 memset(&diprg, 0, sizeof(diprg));
198 diprg.diph.dwSize = sizeof(DIPROPRANGE);
199 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
200 diprg.diph.dwHow = DIPH_DEVICE;
201 diprg.diph.dwObj = 0;
202
203 hr = IDirectInputDevice_GetProperty(pKeyboard, DIPROP_RANGE, &diprg.diph);
204 ok(hr == DIERR_UNSUPPORTED, "IDirectInputDevice_GetProperty() did not return DIPROP_RANGE but: %08x\n", hr);
205
206 if (pKeyboard) IUnknown_Release(pKeyboard);
207 }
208
209 static void test_capabilities(IDirectInputA *pDI, HWND hwnd)
210 {
211 HRESULT hr;
212 IDirectInputDeviceA *pKeyboard = NULL;
213 DIDEVCAPS caps;
214
215 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL);
216 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
217 if (FAILED(hr)) return;
218
219 caps.dwSize = sizeof(caps);
220 hr = IDirectInputDevice_GetCapabilities(pKeyboard, &caps);
221
222 ok (SUCCEEDED(hr), "GetCapabilities failed: 0x%08x\n", hr);
223 ok (caps.dwFlags & DIDC_ATTACHED, "GetCapabilities dwFlags: 0x%08x\n", caps.dwFlags);
224 ok (LOWORD(LOBYTE(caps.dwDevType)) == DIDEVTYPE_KEYBOARD,
225 "GetCapabilities invalid device type for dwDevType: 0x%08x\n", caps.dwDevType);
226 ok (LOWORD(HIBYTE(caps.dwDevType)) != DIDEVTYPEKEYBOARD_UNKNOWN,
227 "GetCapabilities invalid device subtype for dwDevType: 0x%08x\n", caps.dwDevType);
228
229 IUnknown_Release(pKeyboard);
230 }
231
232 static void keyboard_tests(DWORD version)
233 {
234 HRESULT hr;
235 IDirectInputA *pDI = NULL;
236 HINSTANCE hInstance = GetModuleHandleW(NULL);
237 HWND hwnd;
238 ULONG ref = 0;
239
240 hr = DirectInputCreateA(hInstance, version, &pDI, NULL);
241 if (hr == DIERR_OLDDIRECTINPUTVERSION)
242 {
243 skip("Tests require a newer dinput version\n");
244 return;
245 }
246 ok(SUCCEEDED(hr), "DirectInputCreateA() failed: %08x\n", hr);
247 if (FAILED(hr)) return;
248
249 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
250 NULL, NULL, NULL, NULL);
251 ok(hwnd != NULL, "err: %d\n", GetLastError());
252
253 if (hwnd)
254 {
255 acquire_tests(pDI, hwnd);
256 test_set_coop(pDI, hwnd);
257 test_get_prop(pDI, hwnd);
258 test_capabilities(pDI, hwnd);
259 }
260
261 DestroyWindow(hwnd);
262 if (pDI) ref = IUnknown_Release(pDI);
263 ok(!ref, "IDirectInput_Release() reference count = %d\n", ref);
264 }
265
266 START_TEST(keyboard)
267 {
268 CoInitialize(NULL);
269
270 keyboard_tests(0x0700);
271
272 CoUninitialize();
273 }