ReactOS 0.4.16-dev-297-gc569aee
dinput.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Andrew Nguyen
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 0x0800
20
21#define COBJMACROS
22#include <initguid.h>
23#include <windows.h>
24#include <dinput.h>
25#include <dinputd.h>
26
27#include "wine/test.h"
28
30
32{
33 ok(0, "Callback was invoked with parameters (%p, %p)\n", instance, context);
34 return DIENUM_STOP;
35}
36
37static void test_preinitialization(void)
38{
39 static const struct
40 {
41 REFGUID rguid;
42 BOOL pdev;
43 HRESULT expected_hr;
44 } create_device_tests[] =
45 {
48 {&GUID_Unknown, FALSE, E_POINTER},
49 {&GUID_Unknown, TRUE, DIERR_NOTINITIALIZED},
50 {&GUID_SysMouse, FALSE, E_POINTER},
51 {&GUID_SysMouse, TRUE, DIERR_NOTINITIALIZED},
52 };
53
54 static const struct
55 {
56 DWORD dwDevType;
57 LPDIENUMDEVICESCALLBACKA lpCallback;
59 HRESULT expected_hr;
60 int todo;
61 } enum_devices_tests[] =
62 {
63 {0, NULL, 0, DIERR_INVALIDPARAM},
64 {0, NULL, ~0u, DIERR_INVALIDPARAM},
67 {0xdeadbeef, NULL, 0, DIERR_INVALIDPARAM},
68 {0xdeadbeef, NULL, ~0u, DIERR_INVALIDPARAM},
69 {0xdeadbeef, dummy_callback, 0, DIERR_INVALIDPARAM},
70 {0xdeadbeef, dummy_callback, ~0u, DIERR_INVALIDPARAM},
71 };
72
73 IDirectInput8A *pDI;
74 HRESULT hr;
75 int i;
76 IDirectInputDevice8A *pDID;
77
78 hr = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (void **)&pDI);
79 if (FAILED(hr))
80 {
81 skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
82 return;
83 }
84
85 for (i = 0; i < ARRAY_SIZE(create_device_tests); i++)
86 {
87 if (create_device_tests[i].pdev) pDID = (void *)0xdeadbeef;
88 hr = IDirectInput8_CreateDevice(pDI, create_device_tests[i].rguid,
89 create_device_tests[i].pdev ? &pDID : NULL,
90 NULL);
91 ok(hr == create_device_tests[i].expected_hr, "[%d] IDirectInput8_CreateDevice returned 0x%08x\n", i, hr);
92 if (create_device_tests[i].pdev)
93 ok(pDID == NULL, "[%d] Output interface pointer is %p\n", i, pDID);
94 }
95
96 for (i = 0; i < ARRAY_SIZE(enum_devices_tests); i++)
97 {
98 hr = IDirectInput8_EnumDevices(pDI, enum_devices_tests[i].dwDevType,
99 enum_devices_tests[i].lpCallback,
100 NULL,
101 enum_devices_tests[i].dwFlags);
102 todo_wine_if(enum_devices_tests[i].todo)
103 ok(hr == enum_devices_tests[i].expected_hr, "[%d] IDirectInput8_EnumDevice returned 0x%08x\n", i, hr);
104 }
105
107 ok(hr == E_POINTER, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
108
109 hr = IDirectInput8_GetDeviceStatus(pDI, &GUID_Unknown);
110 ok(hr == DIERR_NOTINITIALIZED, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
111
112 hr = IDirectInput8_GetDeviceStatus(pDI, &GUID_SysMouse);
113 ok(hr == DIERR_NOTINITIALIZED, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
114
116 ok(hr == DIERR_NOTINITIALIZED, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
117
119 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
120
121 hr = IDirectInput8_RunControlPanel(pDI, (HWND)0xdeadbeef, 0);
122 ok(hr == E_HANDLE, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
123
124 hr = IDirectInput8_RunControlPanel(pDI, (HWND)0xdeadbeef, ~0u);
125 ok(hr == E_HANDLE, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
126
128}
129
130static void test_DirectInput8Create(void)
131{
132 static const struct
133 {
134 BOOL hinst;
136 REFIID riid;
137 BOOL ppdi;
138 HRESULT expected_hr;
139 } invalid_param_list[] =
140 {
141 {FALSE, 0, &IID_IDirectInputA, FALSE, E_POINTER},
142 {FALSE, 0, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
143 {FALSE, 0, &IID_IDirectInput8A, FALSE, E_POINTER},
144 {FALSE, 0, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM},
145 {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInputA, FALSE, E_POINTER},
146 {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
147 {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, FALSE, E_POINTER},
148 {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM},
149 {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, FALSE, E_POINTER},
150 {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
151 {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, FALSE, E_POINTER},
152 {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM},
153 {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, FALSE, E_POINTER},
154 {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
155 {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, FALSE, E_POINTER},
156 {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM},
157 {TRUE, 0, &IID_IDirectInputA, FALSE, E_POINTER},
158 {TRUE, 0, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
159 {TRUE, 0, &IID_IDirectInput8A, FALSE, E_POINTER},
160 {TRUE, 0, &IID_IDirectInput8A, TRUE, DIERR_NOTINITIALIZED},
161 {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInputA, FALSE, E_POINTER},
162 {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
163 {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, FALSE, E_POINTER},
164 {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, FALSE, E_POINTER},
165 {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
166 {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, FALSE, E_POINTER},
167 {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, TRUE, DIERR_BETADIRECTINPUTVERSION},
168 {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, FALSE, E_POINTER},
169 {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE},
170 {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, FALSE, E_POINTER},
171 {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, TRUE, DIERR_OLDDIRECTINPUTVERSION},
172 };
173
174 static REFIID no_interface_list[] = {&IID_IDirectInputA, &IID_IDirectInputW,
175 &IID_IDirectInput2A, &IID_IDirectInput2W,
176 &IID_IDirectInput7A, &IID_IDirectInput7W,
177 &IID_IDirectInputDeviceA, &IID_IDirectInputDeviceW,
178 &IID_IDirectInputDevice2A, &IID_IDirectInputDevice2W,
179 &IID_IDirectInputDevice7A, &IID_IDirectInputDevice7W,
180 &IID_IDirectInputDevice8A, &IID_IDirectInputDevice8W,
181 &IID_IDirectInputEffect};
182
183 static REFIID iid_list[] = {&IID_IUnknown, &IID_IDirectInput8A, &IID_IDirectInput8W};
184
185 int i;
186 IUnknown *pUnk;
187 HRESULT hr;
188
189 for (i = 0; i < ARRAY_SIZE(invalid_param_list); i++)
190 {
191 if (invalid_param_list[i].ppdi) pUnk = (void *)0xdeadbeef;
192 hr = DirectInput8Create(invalid_param_list[i].hinst ? hInstance : NULL,
193 invalid_param_list[i].dwVersion,
194 invalid_param_list[i].riid,
195 invalid_param_list[i].ppdi ? (void **)&pUnk : NULL,
196 NULL);
197 ok(hr == invalid_param_list[i].expected_hr, "[%d] DirectInput8Create returned 0x%08x\n", i, hr);
198 if (invalid_param_list[i].ppdi)
199 ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk);
200 }
201
202 for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
203 {
204 pUnk = (void *)0xdeadbeef;
205 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, no_interface_list[i], (void **)&pUnk, NULL);
206 ok(hr == DIERR_NOINTERFACE, "[%d] DirectInput8Create returned 0x%08x\n", i, hr);
207 ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk);
208 }
209
210 for (i = 0; i < ARRAY_SIZE(iid_list); i++)
211 {
212 pUnk = NULL;
213 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, iid_list[i], (void **)&pUnk, NULL);
214 ok(hr == DI_OK, "[%d] DirectInput8Create returned 0x%08x\n", i, hr);
215 ok(pUnk != NULL, "[%d] Output interface pointer is NULL\n", i);
216 if (pUnk)
217 IUnknown_Release(pUnk);
218 }
219}
220
221static void test_QueryInterface(void)
222{
223 static REFIID iid_list[] = {&IID_IUnknown, &IID_IDirectInput8A, &IID_IDirectInput8W, &IID_IDirectInputJoyConfig8};
224
225 static REFIID no_interface_list[] =
226 {
227 &IID_IDirectInputA,
228 &IID_IDirectInputW,
229 &IID_IDirectInput2A,
230 &IID_IDirectInput2W,
231 &IID_IDirectInput7A,
232 &IID_IDirectInput7W,
233 &IID_IDirectInputDeviceA,
234 &IID_IDirectInputDeviceW,
235 &IID_IDirectInputDevice2A,
236 &IID_IDirectInputDevice2W,
237 &IID_IDirectInputDevice7A,
238 &IID_IDirectInputDevice7W,
239 &IID_IDirectInputDevice8A,
240 &IID_IDirectInputDevice8W,
241 &IID_IDirectInputEffect,
242 };
243
244 IDirectInput8A *pDI;
245 HRESULT hr;
246 IUnknown *pUnk;
247 int i;
248
249 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
250 if (FAILED(hr))
251 {
252 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
253 return;
254 }
255
257 ok(hr == E_POINTER, "IDirectInput8_QueryInterface returned 0x%08x\n", hr);
258
259 pUnk = (void *)0xdeadbeef;
260 hr = IDirectInput8_QueryInterface(pDI, NULL, (void **)&pUnk);
261 ok(hr == E_POINTER, "IDirectInput8_QueryInterface returned 0x%08x\n", hr);
262 ok(pUnk == (void *)0xdeadbeef, "Output interface pointer is %p\n", pUnk);
263
265 ok(hr == E_POINTER, "IDirectInput8_QueryInterface returned 0x%08x\n", hr);
266
267 for (i = 0; i < ARRAY_SIZE(iid_list); i++)
268 {
269 pUnk = NULL;
270 hr = IDirectInput8_QueryInterface(pDI, iid_list[i], (void **)&pUnk);
271 ok(hr == S_OK, "[%d] IDirectInput8_QueryInterface returned 0x%08x\n", i, hr);
272 ok(pUnk != NULL, "[%d] Output interface pointer is NULL\n", i);
273 if (pUnk)
274 {
275 int j;
276 for (j = 0; j < ARRAY_SIZE(iid_list); j++)
277 {
278 IUnknown *pUnk1 = NULL;
279 hr = IDirectInput8_QueryInterface(pUnk, iid_list[j], (void **)&pUnk1);
280 ok(hr == S_OK, "[%d] IDirectInput8_QueryInterface(pUnk) returned 0x%08x\n", j, hr);
281 ok(pUnk1 != NULL, "[%d] Output interface pointer is NULL\n", i);
282 if (pUnk1) IUnknown_Release(pUnk1);
283 }
284 IUnknown_Release(pUnk);
285 }
286 }
287
288 for (i = 0; i < ARRAY_SIZE(no_interface_list); i++)
289 {
290 pUnk = (void *)0xdeadbeef;
291 hr = IDirectInput8_QueryInterface(pDI, no_interface_list[i], (void **)&pUnk);
292
293 ok(hr == E_NOINTERFACE, "[%d] IDirectInput8_QueryInterface returned 0x%08x\n", i, hr);
294 ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk);
295 }
296
298}
299
300static void test_CreateDevice(void)
301{
302 IDirectInput8A *pDI;
303 HRESULT hr;
304 IDirectInputDevice8A *pDID;
305
306 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
307 if (FAILED(hr))
308 {
309 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
310 return;
311 }
312
314 ok(hr == E_POINTER, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
315
316 pDID = (void *)0xdeadbeef;
317 hr = IDirectInput8_CreateDevice(pDI, NULL, &pDID, NULL);
318 ok(hr == E_POINTER, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
319 ok(pDID == NULL, "Output interface pointer is %p\n", pDID);
320
321 hr = IDirectInput8_CreateDevice(pDI, &GUID_Unknown, NULL, NULL);
322 ok(hr == E_POINTER, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
323
324 pDID = (void *)0xdeadbeef;
325 hr = IDirectInput8_CreateDevice(pDI, &GUID_Unknown, &pDID, NULL);
326 ok(hr == DIERR_DEVICENOTREG, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
327 ok(pDID == NULL, "Output interface pointer is %p\n", pDID);
328
329 hr = IDirectInput8_CreateDevice(pDI, &GUID_SysMouse, NULL, NULL);
330 ok(hr == E_POINTER, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
331
332 hr = IDirectInput8_CreateDevice(pDI, &GUID_SysMouse, &pDID, NULL);
333 ok(hr == DI_OK, "IDirectInput8_CreateDevice returned 0x%08x\n", hr);
334
337}
338
340{
341 unsigned int device_count;
343};
344
346{
347 struct enum_devices_test *enum_test = context;
348
349 trace("---- Device Information ----\n"
350 "Product Name : %s\n"
351 "Instance Name : %s\n"
352 "devType : 0x%08x\n"
353 "GUID Product : %s\n"
354 "GUID Instance : %s\n"
355 "HID Page : 0x%04x\n"
356 "HID Usage : 0x%04x\n",
357 instance->tszProductName,
358 instance->tszInstanceName,
359 instance->dwDevType,
360 wine_dbgstr_guid(&instance->guidProduct),
361 wine_dbgstr_guid(&instance->guidInstance),
362 instance->wUsagePage,
363 instance->wUsage);
364
365 if ((instance->dwDevType & 0xff) == DI8DEVTYPE_KEYBOARD ||
366 (instance->dwDevType & 0xff) == DI8DEVTYPE_MOUSE) {
367 const char *device = ((instance->dwDevType & 0xff) ==
368 DI8DEVTYPE_KEYBOARD) ? "Keyboard" : "Mouse";
369 ok(IsEqualGUID(&instance->guidInstance, &instance->guidProduct),
370 "%s guidInstance (%s) does not match guidProduct (%s)\n",
371 device, wine_dbgstr_guid(&instance->guidInstance),
372 wine_dbgstr_guid(&instance->guidProduct));
373 }
374
375 enum_test->device_count++;
376 return enum_test->return_value;
377}
378
379static void test_EnumDevices(void)
380{
381 IDirectInput8A *pDI;
382 HRESULT hr;
383 struct enum_devices_test enum_test, enum_test_return;
384
385 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
386 if (FAILED(hr))
387 {
388 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
389 return;
390 }
391
392 hr = IDirectInput8_EnumDevices(pDI, 0, NULL, NULL, 0);
393 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
394
395 hr = IDirectInput8_EnumDevices(pDI, 0, NULL, NULL, ~0u);
396 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
397
398 /* Test crashes on Wine. */
399 if (0)
400 {
402 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
403 }
404
405 hr = IDirectInput8_EnumDevices(pDI, 0xdeadbeef, NULL, NULL, 0);
406 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
407
408 hr = IDirectInput8_EnumDevices(pDI, 0xdeadbeef, NULL, NULL, ~0u);
409 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
410
412 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
413
415 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
416
417 enum_test.device_count = 0;
418 enum_test.return_value = DIENUM_CONTINUE;
419 hr = IDirectInput8_EnumDevices(pDI, 0, enum_devices_callback, &enum_test, 0);
420 ok(hr == DI_OK, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
421 ok(enum_test.device_count != 0, "Device count is %u\n", enum_test.device_count);
422
423 /* Enumeration only stops with an explicit DIENUM_STOP. */
424 enum_test_return.device_count = 0;
425 enum_test_return.return_value = 42;
426 hr = IDirectInput8_EnumDevices(pDI, 0, enum_devices_callback, &enum_test_return, 0);
427 ok(hr == DI_OK, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
428 ok(enum_test_return.device_count == enum_test.device_count,
429 "Device count is %u vs. %u\n", enum_test_return.device_count, enum_test.device_count);
430
431 enum_test.device_count = 0;
432 enum_test.return_value = DIENUM_STOP;
433 hr = IDirectInput8_EnumDevices(pDI, 0, enum_devices_callback, &enum_test, 0);
434 ok(hr == DI_OK, "IDirectInput8_EnumDevices returned 0x%08x\n", hr);
435 ok(enum_test.device_count == 1, "Device count is %u\n", enum_test.device_count);
436
438}
439
441{
442 unsigned int device_count;
447 const char* username;
448};
449
451{
452 /* axis */
453 { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */, 0, { "Steer.\0" } },
454 /* button */
455 { 1, 0x01000C01 /* DIBUTTON_DRIVINGR_SHIFTUP */, 0, { "Upshift.\0" } },
456 /* keyboard key */
457 { 2, DIKEYBOARD_SPACE, 0, { "Missile.\0" } },
458 /* mouse button */
459 { 3, DIMOUSE_BUTTON0, 0, { "Select\0" } },
460 /* mouse axis */
461 { 4, DIMOUSE_YAXIS, 0, { "Y Axis\0" } }
462};
463/* By placing the memory pointed to by lptszActionName right before memory with PAGE_NOACCESS
464 * one can find out that the regular ansi string termination is not respected by EnumDevicesBySemantics.
465 * Adding a double termination, making it a valid wide string termination, made the test succeed.
466 * Therefore it looks like ansi version of EnumDevicesBySemantics forwards the string to
467 * the wide variant without conversation. */
468
469static BOOL CALLBACK enum_semantics_callback(const DIDEVICEINSTANCEA *lpddi, IDirectInputDevice8A *lpdid, DWORD dwFlags, DWORD dwRemaining, void *context)
470{
472
473 if (context == NULL) return DIENUM_STOP;
474
475 if (!data->device_count) {
476 data->first_remaining = dwRemaining;
477 }
478 ok (dwRemaining == data->first_remaining - data->device_count,
479 "enum semantics remaining devices is wrong, expected %d, had %d\n",
480 data->first_remaining - data->device_count, dwRemaining);
481 data->device_count++;
482
483 if (IsEqualGUID(&lpddi->guidInstance, &GUID_SysKeyboard)) data->keyboard = TRUE;
484
485 if (IsEqualGUID(&lpddi->guidInstance, &GUID_SysMouse)) data->mouse = TRUE;
486
487 return DIENUM_CONTINUE;
488}
489
490static BOOL CALLBACK set_action_map_callback(const DIDEVICEINSTANCEA *lpddi, IDirectInputDevice8A *lpdid, DWORD dwFlags, DWORD dwRemaining, void *context)
491{
492 HRESULT hr;
494
495 /* Building and setting an action map */
496 /* It should not use any pre-stored mappings so we use DIDBAM_INITIALIZE */
498 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
499
500 hr = IDirectInputDevice8_SetActionMap(lpdid, data->lpdiaf, data->username, 0);
501 ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
502
503 return DIENUM_CONTINUE;
504}
505
507{
508 IDirectInput8A *pDI;
509 HRESULT hr;
510 DIACTIONFORMATA diaf;
511 const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
512 struct enum_semantics_test data = { 0, 0, FALSE, FALSE, &diaf, NULL };
513 int device_total = 0;
514
515 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
516 if (FAILED(hr))
517 {
518 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
519 return;
520 }
521
522 memset (&diaf, 0, sizeof(diaf));
523 diaf.dwSize = sizeof(diaf);
524 diaf.dwActionSize = sizeof(DIACTIONA);
526 diaf.dwDataSize = 4 * diaf.dwNumActions;
529 diaf.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
530 diaf.dwBufferSize = 32;
531
532 /* Test enumerating all attached and installed devices */
533 data.keyboard = FALSE;
534 data.mouse = FALSE;
535 data.device_count = 0;
537 ok (data.device_count > 0, "EnumDevicesBySemantics did not call the callback hr=%08x\n", hr);
538 ok (data.keyboard, "EnumDevicesBySemantics should enumerate the keyboard\n");
539 ok (data.mouse, "EnumDevicesBySemantics should enumerate the mouse\n");
540
541 /* Enumerate Force feedback devices. We should get no mouse nor keyboard */
542 data.keyboard = FALSE;
543 data.mouse = FALSE;
544 data.device_count = 0;
546 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
547 ok (!data.keyboard, "Keyboard should not be enumerated when asking for forcefeedback\n");
548 ok (!data.mouse, "Mouse should not be enumerated when asking for forcefeedback\n");
549
550 /* Enumerate available devices. That is devices not owned by any user.
551 Before setting the action map for all devices we still have them available. */
552 data.device_count = 0;
554 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
555 ok (data.device_count > 0, "There should be devices available before action mapping available=%d\n", data.device_count);
556
557 /* Keep the device total */
558 device_total = data.device_count;
559
560 /* There should be no devices for any user. No device should be enumerated with DIEDBSFL_THISUSER.
561 MSDN defines that all unowned devices are also enumerated but this doesn't seem to be happening. */
562 data.device_count = 0;
564 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
565 ok (data.device_count == 0, "No devices should be assigned for this user assigned=%d\n", data.device_count);
566
567 /* This enumeration builds and sets the action map for all devices with a NULL username */
569 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
570
571 /* After a successful action mapping we should have no devices available */
572 data.device_count = 0;
574 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
575 ok (data.device_count == 0, "No device should be available after action mapping available=%d\n", data.device_count);
576
577 /* Now we'll give all the devices to a specific user */
578 data.username = "Sh4d0w M4g3";
580 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
581
582 /* Testing with the default user, DIEDBSFL_THISUSER has no effect */
583 data.device_count = 0;
585 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
586 ok (data.device_count == device_total, "THISUSER has no effect with NULL username owned=%d, expected=%d\n", data.device_count, device_total);
587
588 /* Using an empty user string is the same as passing NULL, DIEDBSFL_THISUSER has no effect */
589 data.device_count = 0;
591 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
592 ok (data.device_count == device_total, "THISUSER has no effect with \"\" as username owned=%d, expected=%d\n", data.device_count, device_total);
593
594 /* Testing with a user with no ownership of the devices */
595 data.device_count = 0;
597 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
598 ok (data.device_count == 0, "This user should own no devices owned=%d\n", data.device_count);
599
600 /* Sh4d0w M4g3 has ownership of all devices */
601 data.device_count = 0;
603 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
604 ok (data.device_count == device_total, "This user should own %d devices owned=%d\n", device_total, data.device_count);
605
606 /* The call fails with a zeroed GUID */
607 memset(&diaf.guidActionMap, 0, sizeof(GUID));
608 data.device_count = 0;
610 todo_wine ok(FAILED(hr), "EnumDevicesBySemantics succeeded with invalid GUID hr=%08x\n", hr);
611
613}
614
615static void test_GetDeviceStatus(void)
616{
617 IDirectInput8A *pDI;
618 HRESULT hr;
619
620 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
621 if (FAILED(hr))
622 {
623 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
624 return;
625 }
626
628 ok(hr == E_POINTER, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
629
630 hr = IDirectInput8_GetDeviceStatus(pDI, &GUID_Unknown);
632 ok(hr == DIERR_DEVICENOTREG, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
633
634 hr = IDirectInput8_GetDeviceStatus(pDI, &GUID_SysMouse);
635 ok(hr == DI_OK, "IDirectInput8_GetDeviceStatus returned 0x%08x\n", hr);
636
638}
639
640static void test_RunControlPanel(void)
641{
642 IDirectInput8A *pDI;
643 HRESULT hr;
644
645 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
646 if (FAILED(hr))
647 {
648 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
649 return;
650 }
651
653 {
655 ok(hr == S_OK, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
656
658 ok(hr == S_OK, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
659 }
660
662 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
663
664 hr = IDirectInput8_RunControlPanel(pDI, (HWND)0xdeadbeef, 0);
665 ok(hr == E_HANDLE, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
666
667 hr = IDirectInput8_RunControlPanel(pDI, (HWND)0xdeadbeef, ~0u);
668 ok(hr == E_HANDLE, "IDirectInput8_RunControlPanel returned 0x%08x\n", hr);
669
671}
672
673static void test_Initialize(void)
674{
675 IDirectInput8A *pDI;
676 HRESULT hr;
677
678 hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL);
679 if (FAILED(hr))
680 {
681 win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
682 return;
683 }
684
686 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_Initialize returned 0x%08x\n", hr);
687
689 ok(hr == DIERR_INVALIDPARAM, "IDirectInput8_Initialize returned 0x%08x\n", hr);
690
692 ok(hr == DIERR_NOTINITIALIZED, "IDirectInput8_Initialize returned 0x%08x\n", hr);
693
694 /* Invalid DirectInput versions less than DIRECTINPUT_VERSION yield DIERR_BETADIRECTINPUTVERSION. */
696 ok(hr == DIERR_BETADIRECTINPUTVERSION, "IDirectInput8_Initialize returned 0x%08x\n", hr);
697
698 /* Invalid DirectInput versions greater than DIRECTINPUT_VERSION yield DIERR_BETADIRECTINPUTVERSION. */
700 ok(hr == DIERR_OLDDIRECTINPUTVERSION, "IDirectInput8_Initialize returned 0x%08x\n", hr);
701
703 ok(hr == DI_OK, "IDirectInput8_Initialize returned 0x%08x\n", hr);
704
705 /* Parameters are still validated after successful initialization. */
707 ok(hr == DIERR_NOTINITIALIZED, "IDirectInput8_Initialize returned 0x%08x\n", hr);
708
710}
711
713{
715
727}
DWORD dwVersion
Definition: LocaleTests.cpp:63
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ARRAY_SIZE(A)
Definition: main.h:20
const GUID IID_IUnknown
static void test_DirectInput8Create(void)
Definition: dinput.c:130
static void test_EnumDevicesBySemantics(void)
Definition: dinput.c:506
static BOOL CALLBACK enum_semantics_callback(const DIDEVICEINSTANCEA *lpddi, IDirectInputDevice8A *lpdid, DWORD dwFlags, DWORD dwRemaining, void *context)
Definition: dinput.c:469
static DIACTIONA actionMapping[]
Definition: dinput.c:450
static BOOL CALLBACK set_action_map_callback(const DIDEVICEINSTANCEA *lpddi, IDirectInputDevice8A *lpdid, DWORD dwFlags, DWORD dwRemaining, void *context)
Definition: dinput.c:490
static void test_Initialize(void)
Definition: dinput.c:503
static BOOL CALLBACK dummy_callback(const DIDEVICEINSTANCEA *instance, void *context)
Definition: dinput.c:55
#define DIRECTINPUT_VERSION
Definition: dinput.c:19
HINSTANCE hInstance
Definition: dinput.c:29
static void test_GetDeviceStatus(void)
Definition: dinput.c:478
static void test_QueryInterface(void)
Definition: dinput.c:266
static BOOL CALLBACK enum_devices_callback(const DIDEVICEINSTANCEA *instance, void *context)
Definition: dinput.c:375
static void test_EnumDevices(void)
Definition: dinput.c:417
static REFIID
Definition: dinput.c:53
static void test_CreateDevice(void)
Definition: dinput.c:330
static void test_RunControlPanel(void)
Definition: dinput.c:546
static void test_preinitialization(void)
Definition: dinput.c:61
#define IDirectInput8_QueryInterface(p, a, b)
Definition: dinput.h:2509
#define DIENUM_STOP
Definition: dinput.h:187
#define DIERR_INVALIDPARAM
Definition: dinput.h:152
#define DIENUM_CONTINUE
Definition: dinput.h:188
#define DIERR_NOINTERFACE
Definition: dinput.h:153
#define IDirectInput8_GetDeviceStatus(p, a)
Definition: dinput.h:2515
BOOL(CALLBACK * LPDIENUMDEVICESCALLBACKA)(LPCDIDEVICEINSTANCEA, LPVOID)
Definition: dinput.h:441
#define IDirectInput8_EnumDevices(p, a, b, c, d)
Definition: dinput.h:2514
#define DIEDBSFL_AVAILABLEDEVICES
Definition: dinput.h:453
#define DIEDBSFL_ATTACHEDONLY
Definition: dinput.h:450
#define IDirectInput8_Initialize(p, a, b)
Definition: dinput.h:2517
#define IDirectInput8_RunControlPanel(p, a, b)
Definition: dinput.h:2516
#define IDirectInput8_CreateDevice(p, a, b, c)
Definition: dinput.h:2513
#define DIKEYBOARD_SPACE
Definition: dinput.h:667
#define IDirectInput8_Release(p)
Definition: dinput.h:2511
#define DIERR_DEVICENOTREG
Definition: dinput.h:147
#define DIEDBSFL_THISUSER
Definition: dinput.h:451
#define DIDBAM_INITIALIZE
Definition: dinput.h:1354
#define DIERR_OLDDIRECTINPUTVERSION
Definition: dinput.h:141
#define DI_OK
Definition: dinput.h:128
#define DIERR_BETADIRECTINPUTVERSION
Definition: dinput.h:143
#define DIEDBSFL_FORCEFEEDBACK
Definition: dinput.h:452
#define DIMOUSE_BUTTON0
Definition: dinput.h:2145
#define IDirectInputDevice8_BuildActionMap(p, a, b, c)
Definition: dinput.h:2067
#define DIMOUSE_YAXIS
Definition: dinput.h:2143
#define DIERR_NOTINITIALIZED
Definition: dinput.h:157
struct _DIACTIONA DIACTIONA
#define IDirectInputDevice_Release(p)
Definition: dinput.h:1602
#define IDirectInput8_EnumDevicesBySemantics(p, a, b, c, d, e)
Definition: dinput.h:2519
#define IDirectInputDevice8_SetActionMap(p, a, b, c)
Definition: dinput.h:2068
#define DI8DEVTYPE_MOUSE
Definition: dinput.h:210
#define DI8DEVTYPE_KEYBOARD
Definition: dinput.h:211
HRESULT WINAPI DECLSPEC_HOTPATCH DirectInput8Create(HINSTANCE hinst, DWORD version, REFIID iid, void **out, IUnknown *outer)
Definition: dinput_main.c:172
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:40
#define CALLBACK
Definition: compat.h:35
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CoInitialize(LPVOID lpReserved)
Definition: compobj.c:1964
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
static HINSTANCE hinst
Definition: edit.c:551
BOOL todo
Definition: filedlg.c:313
static const GUID ACTION_MAPPING_GUID
Definition: device.c:39
#define todo_wine_if(is_todo)
Definition: custom.c:86
#define todo_wine
Definition: custom.c:89
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
#define win_skip
Definition: test.h:163
int winetest_interactive
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
GUID guidInstance
Definition: dinput.h:413
DWORD dwDataSize
Definition: dinput.h:1310
LPDIACTIONA rgoAction
Definition: dinput.h:1312
DWORD dwBufferSize
Definition: dinput.h:1315
DWORD dwNumActions
Definition: dinput.h:1311
DWORD dwActionSize
Definition: dinput.h:1309
GUID guidActionMap
Definition: dinput.h:1313
Definition: scsiwmi.h:51
Definition: http.c:7252
Definition: devices.h:37
BOOL return_value
Definition: dinput.c:372
unsigned int device_count
Definition: dinput.c:371
DIACTIONFORMATA * lpdiaf
Definition: dinput.c:446
const char * username
Definition: dinput.c:447
DWORD first_remaining
Definition: dinput.c:443
unsigned int device_count
Definition: dinput.c:442
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_HANDLE
Definition: winerror.h:2850
#define E_POINTER
Definition: winerror.h:2365
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:628