windows.gaming.input: Fake IEventHandler_RawGameController support.
[wine/zf.git] / dlls / windows.gaming.input / tests / input.c
blob62822b30c286904c80ed52def6ab79c4c48e9377
1 /*
2 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
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.
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.
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
18 #define COBJMACROS
19 #include <stdarg.h>
21 #include "windef.h"
22 #include "winbase.h"
23 #include "winerror.h"
24 #include "winstring.h"
26 #include "initguid.h"
27 #include "roapi.h"
29 #define WIDL_using_Windows_Foundation
30 #define WIDL_using_Windows_Foundation_Collections
31 #include "windows.foundation.h"
32 #define WIDL_using_Windows_Gaming_Input
33 #include "windows.gaming.input.h"
35 #include "wine/test.h"
37 static HRESULT (WINAPI *pRoActivateInstance)(HSTRING, IInspectable **);
38 static HRESULT (WINAPI *pRoGetActivationFactory)(HSTRING, REFIID, void **);
39 static HRESULT (WINAPI *pRoInitialize)(RO_INIT_TYPE);
40 static void (WINAPI *pRoUninitialize)(void);
41 static HRESULT (WINAPI *pWindowsCreateString)(LPCWSTR, UINT32, HSTRING *);
42 static HRESULT (WINAPI *pWindowsDeleteString)(HSTRING);
44 struct gamepad_event_handler
46 IEventHandler_Gamepad IEventHandler_Gamepad_iface;
47 LONG ref;
50 static inline struct gamepad_event_handler *impl_from_IEventHandler_Gamepad(IEventHandler_Gamepad *iface)
52 return CONTAINING_RECORD(iface, struct gamepad_event_handler, IEventHandler_Gamepad_iface);
55 static HRESULT STDMETHODCALLTYPE gamepad_event_handler_QueryInterface(
56 IEventHandler_Gamepad *iface, REFIID iid, void **out)
58 if (IsEqualGUID(iid, &IID_IUnknown) ||
59 IsEqualGUID(iid, &IID_IEventHandler_Gamepad))
61 IUnknown_AddRef(iface);
62 *out = iface;
63 return S_OK;
66 trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
67 *out = NULL;
68 return E_NOINTERFACE;
71 static ULONG STDMETHODCALLTYPE gamepad_event_handler_AddRef(
72 IEventHandler_Gamepad *iface)
74 struct gamepad_event_handler *impl = impl_from_IEventHandler_Gamepad(iface);
75 ULONG ref = InterlockedIncrement(&impl->ref);
76 return ref;
79 static ULONG STDMETHODCALLTYPE gamepad_event_handler_Release(
80 IEventHandler_Gamepad *iface)
82 struct gamepad_event_handler *impl = impl_from_IEventHandler_Gamepad(iface);
83 ULONG ref = InterlockedDecrement(&impl->ref);
84 return ref;
87 static HRESULT STDMETHODCALLTYPE gamepad_event_handler_Invoke(
88 IEventHandler_Gamepad *iface, IInspectable *sender, IGamepad *args)
90 trace("iface %p, sender %p, args %p\n", iface, sender, args);
91 return S_OK;
94 static const IEventHandler_GamepadVtbl gamepad_event_handler_vtbl =
96 gamepad_event_handler_QueryInterface,
97 gamepad_event_handler_AddRef,
98 gamepad_event_handler_Release,
99 /*** IEventHandler<ABI::Windows::Gaming::Input::Gamepad* > methods ***/
100 gamepad_event_handler_Invoke,
103 static void test_Gamepad(void)
105 static const WCHAR *gamepad_name = L"Windows.Gaming.Input.Gamepad";
107 struct gamepad_event_handler gamepad_event_handler;
108 EventRegistrationToken token;
109 IVectorView_Gamepad *gamepads = NULL;
110 IActivationFactory *factory = NULL;
111 IGamepadStatics *gamepad_statics = NULL;
112 IInspectable *inspectable = NULL, *tmp_inspectable = NULL;
113 IAgileObject *agile_object = NULL, *tmp_agile_object = NULL;
114 IGamepad *gamepad;
115 BOOLEAN found;
116 HSTRING str;
117 HRESULT hr;
118 ULONG size;
120 gamepad_event_handler.IEventHandler_Gamepad_iface.lpVtbl = &gamepad_event_handler_vtbl;
122 hr = pRoInitialize(RO_INIT_MULTITHREADED);
123 ok(hr == S_OK, "RoInitialize failed, hr %#x\n", hr);
125 hr = pWindowsCreateString(gamepad_name, wcslen(gamepad_name), &str);
126 ok(hr == S_OK, "WindowsCreateString failed, hr %#x\n", hr);
128 hr = pRoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
129 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#x\n", hr);
130 if (hr == REGDB_E_CLASSNOTREG)
132 win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(gamepad_name));
133 return;
136 hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable);
137 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IInspectable failed, hr %#x\n", hr);
139 hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object);
140 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IAgileObject failed, hr %#x\n", hr);
142 hr = IActivationFactory_QueryInterface(factory, &IID_IGamepadStatics, (void **)&gamepad_statics);
143 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IGamepadStatics failed, hr %#x\n", hr);
145 hr = IGamepadStatics_QueryInterface(gamepad_statics, &IID_IInspectable, (void **)&tmp_inspectable);
146 ok(hr == S_OK, "IGamepadStatics_QueryInterface IID_IInspectable failed, hr %#x\n", hr);
147 ok(tmp_inspectable == inspectable, "IGamepadStatics_QueryInterface IID_IInspectable returned %p, expected %p\n", tmp_inspectable, inspectable);
148 IInspectable_Release(tmp_inspectable);
150 hr = IGamepadStatics_QueryInterface(gamepad_statics, &IID_IAgileObject, (void **)&tmp_agile_object);
151 ok(hr == S_OK, "IGamepadStatics_QueryInterface IID_IAgileObject failed, hr %#x\n", hr);
152 ok(tmp_agile_object == agile_object, "IGamepadStatics_QueryInterface IID_IAgileObject returned %p, expected %p\n", tmp_agile_object, agile_object);
153 IAgileObject_Release(tmp_agile_object);
155 hr = IGamepadStatics_get_Gamepads(gamepad_statics, &gamepads);
156 ok(hr == S_OK, "IGamepadStatics_get_Gamepads failed, hr %#x\n", hr);
158 hr = IVectorView_Gamepad_QueryInterface(gamepads, &IID_IInspectable, (void **)&tmp_inspectable);
159 ok(hr == S_OK, "IVectorView_Gamepad_QueryInterface failed, hr %#x\n", hr);
160 ok(tmp_inspectable != inspectable, "IVectorView_Gamepad_QueryInterface returned %p, expected %p\n", tmp_inspectable, inspectable);
161 IInspectable_Release(tmp_inspectable);
163 hr = IVectorView_Gamepad_QueryInterface(gamepads, &IID_IAgileObject, (void **)&tmp_agile_object);
164 ok(hr == S_OK, "IVectorView_Gamepad_QueryInterface failed, hr %#x\n", hr);
165 ok(tmp_agile_object != agile_object, "IVectorView_Gamepad_QueryInterface IID_IAgileObject returned agile_object\n");
166 IAgileObject_Release(tmp_agile_object);
168 size = 0xdeadbeef;
169 hr = IVectorView_Gamepad_get_Size(gamepads, &size);
170 ok(hr == S_OK, "IVectorView_Gamepad_get_Size failed, hr %#x\n", hr);
171 ok(size != 0xdeadbeef, "IVectorView_Gamepad_get_Size returned %u\n", size);
173 gamepad = (IGamepad *)0xdeadbeef;
174 hr = IVectorView_Gamepad_GetAt(gamepads, size, &gamepad);
175 ok(hr == E_BOUNDS, "IVectorView_Gamepad_GetAt failed, hr %#x\n", hr);
176 ok(gamepad == NULL, "IVectorView_Gamepad_GetAt returned %p\n", gamepad);
178 size = 0xdeadbeef;
179 found = TRUE;
180 gamepad = (IGamepad *)0xdeadbeef;
181 hr = IVectorView_Gamepad_IndexOf(gamepads, gamepad, &size, &found);
182 ok(hr == S_OK, "IVectorView_Gamepad_IndexOf failed, hr %#x\n", hr);
183 ok(size == 0 && found == FALSE, "IVectorView_Gamepad_IndexOf returned size %d, found %d\n", size, found);
185 IVectorView_Gamepad_Release(gamepads);
187 token.value = 0xdeadbeef;
188 hr = IGamepadStatics_add_GamepadAdded(gamepad_statics, &gamepad_event_handler.IEventHandler_Gamepad_iface, &token);
189 ok(hr == S_OK, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr);
190 ok(token.value != 0xdeadbeef, "IGamepadStatics_add_GamepadAdded returned token %#I64x\n", token.value);
192 hr = IGamepadStatics_remove_GamepadAdded(gamepad_statics, token);
193 ok(hr == S_OK, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr);
195 token.value = 0xdeadbeef;
196 IGamepadStatics_add_GamepadRemoved(gamepad_statics, &gamepad_event_handler.IEventHandler_Gamepad_iface, &token);
197 ok(hr == S_OK, "IGamepadStatics_add_GamepadRemoved failed, hr %#x\n", hr);
198 ok(token.value != 0xdeadbeef, "IGamepadStatics_add_GamepadRemoved returned token %#I64x\n", token.value);
200 hr = IGamepadStatics_remove_GamepadRemoved(gamepad_statics, token);
201 ok(hr == S_OK, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr);
203 hr = IGamepadStatics_add_GamepadAdded(gamepad_statics, NULL, &token);
204 ok(hr == E_INVALIDARG, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr);
206 IGamepadStatics_Release(gamepad_statics);
208 IAgileObject_Release(agile_object);
209 IInspectable_Release(inspectable);
210 IActivationFactory_Release(factory);
212 pWindowsDeleteString(str);
214 pRoUninitialize();
217 struct controller_event_handler
219 IEventHandler_RawGameController IEventHandler_RawGameController_iface;
220 LONG ref;
223 static inline struct controller_event_handler *impl_from_IEventHandler_RawGameController(IEventHandler_RawGameController *iface)
225 return CONTAINING_RECORD(iface, struct controller_event_handler, IEventHandler_RawGameController_iface);
228 static HRESULT STDMETHODCALLTYPE controller_event_handler_QueryInterface(
229 IEventHandler_RawGameController *iface, REFIID iid, void **out)
231 if (IsEqualGUID(iid, &IID_IUnknown) ||
232 IsEqualGUID(iid, &IID_IEventHandler_RawGameController))
234 IUnknown_AddRef(iface);
235 *out = iface;
236 return S_OK;
239 trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
240 *out = NULL;
241 return E_NOINTERFACE;
244 static ULONG STDMETHODCALLTYPE controller_event_handler_AddRef(
245 IEventHandler_RawGameController *iface)
247 struct controller_event_handler *impl = impl_from_IEventHandler_RawGameController(iface);
248 ULONG ref = InterlockedIncrement(&impl->ref);
249 return ref;
252 static ULONG STDMETHODCALLTYPE controller_event_handler_Release(
253 IEventHandler_RawGameController *iface)
255 struct controller_event_handler *impl = impl_from_IEventHandler_RawGameController(iface);
256 ULONG ref = InterlockedDecrement(&impl->ref);
257 return ref;
260 static HRESULT STDMETHODCALLTYPE controller_event_handler_Invoke(
261 IEventHandler_RawGameController *iface, IInspectable *sender, IRawGameController *args)
263 trace("iface %p, sender %p, args %p\n", iface, sender, args);
264 return S_OK;
267 static const IEventHandler_RawGameControllerVtbl controller_event_handler_vtbl =
269 controller_event_handler_QueryInterface,
270 controller_event_handler_AddRef,
271 controller_event_handler_Release,
272 /*** IEventHandler<ABI::Windows::Gaming::Input::Gamepad* > methods ***/
273 controller_event_handler_Invoke,
276 static void test_RawGameController(void)
278 static const WCHAR *controller_name = L"Windows.Gaming.Input.RawGameController";
280 struct controller_event_handler controller_event_handler;
281 EventRegistrationToken token;
282 IVectorView_RawGameController *controllers = NULL;
283 IActivationFactory *factory = NULL;
284 IRawGameControllerStatics *controller_statics = NULL;
285 IInspectable *inspectable = NULL, *tmp_inspectable = NULL;
286 IAgileObject *agile_object = NULL, *tmp_agile_object = NULL;
287 IRawGameController *controller;
288 BOOLEAN found;
289 HSTRING str;
290 HRESULT hr;
291 ULONG size;
293 controller_event_handler.IEventHandler_RawGameController_iface.lpVtbl = &controller_event_handler_vtbl;
295 hr = pRoInitialize(RO_INIT_MULTITHREADED);
296 ok(hr == S_OK || hr == S_FALSE, "RoInitialize failed, hr %#x\n", hr);
298 hr = pWindowsCreateString(controller_name, wcslen(controller_name), &str);
299 ok(hr == S_OK, "WindowsCreateString failed, hr %#x\n", hr);
301 hr = pRoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
302 ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#x\n", hr);
303 if (hr == REGDB_E_CLASSNOTREG)
305 win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(controller_name));
306 return;
309 hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable);
310 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IInspectable failed, hr %#x\n", hr);
312 hr = IActivationFactory_QueryInterface(factory, &IID_IAgileObject, (void **)&agile_object);
313 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IAgileObject failed, hr %#x\n", hr);
315 hr = IActivationFactory_QueryInterface(factory, &IID_IRawGameControllerStatics, (void **)&controller_statics);
316 ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IRawGameControllerStatics failed, hr %#x\n", hr);
318 hr = IRawGameControllerStatics_QueryInterface(controller_statics, &IID_IInspectable, (void **)&tmp_inspectable);
319 ok(hr == S_OK, "IRawGameControllerStatics_QueryInterface IID_IInspectable failed, hr %#x\n", hr);
320 ok(tmp_inspectable == inspectable, "IRawGameControllerStatics_QueryInterface IID_IInspectable returned %p, expected %p\n", tmp_inspectable, inspectable);
321 IInspectable_Release(tmp_inspectable);
323 hr = IRawGameControllerStatics_QueryInterface(controller_statics, &IID_IAgileObject, (void **)&tmp_agile_object);
324 ok(hr == S_OK, "IRawGameControllerStatics_QueryInterface IID_IAgileObject failed, hr %#x\n", hr);
325 ok(tmp_agile_object == agile_object, "IRawGameControllerStatics_QueryInterface IID_IAgileObject returned %p, expected %p\n", tmp_agile_object, agile_object);
326 IAgileObject_Release(tmp_agile_object);
328 hr = IRawGameControllerStatics_get_RawGameControllers(controller_statics, &controllers);
329 ok(hr == S_OK, "IRawGameControllerStatics_get_RawGameControllers failed, hr %#x\n", hr);
331 hr = IVectorView_RawGameController_QueryInterface(controllers, &IID_IInspectable, (void **)&tmp_inspectable);
332 ok(hr == S_OK, "IVectorView_RawGameController_QueryInterface failed, hr %#x\n", hr);
333 ok(tmp_inspectable != inspectable, "IVectorView_RawGameController_QueryInterface returned %p, expected %p\n", tmp_inspectable, inspectable);
334 IInspectable_Release(tmp_inspectable);
336 hr = IVectorView_RawGameController_QueryInterface(controllers, &IID_IAgileObject, (void **)&tmp_agile_object);
337 ok(hr == S_OK, "IVectorView_RawGameController_QueryInterface failed, hr %#x\n", hr);
338 ok(tmp_agile_object != agile_object, "IVectorView_RawGameController_QueryInterface IID_IAgileObject returned agile_object\n");
339 IAgileObject_Release(tmp_agile_object);
341 size = 0xdeadbeef;
342 hr = IVectorView_RawGameController_get_Size(controllers, &size);
343 ok(hr == S_OK, "IVectorView_RawGameController_get_Size failed, hr %#x\n", hr);
344 ok(size != 0xdeadbeef, "IVectorView_RawGameController_get_Size returned %u\n", size);
346 controller = (IRawGameController *)0xdeadbeef;
347 hr = IVectorView_RawGameController_GetAt(controllers, size, &controller);
348 ok(hr == E_BOUNDS, "IVectorView_RawGameController_GetAt failed, hr %#x\n", hr);
349 ok(controller == NULL, "IVectorView_RawGameController_GetAt returned %p\n", controller);
351 size = 0xdeadbeef;
352 found = TRUE;
353 controller = (IRawGameController *)0xdeadbeef;
354 hr = IVectorView_RawGameController_IndexOf(controllers, controller, &size, &found);
355 ok(hr == S_OK, "IVectorView_RawGameController_IndexOf failed, hr %#x\n", hr);
356 ok(size == 0 && found == FALSE, "IVectorView_RawGameController_IndexOf returned size %d, found %d\n", size, found);
358 IVectorView_RawGameController_Release(controllers);
360 token.value = 0xdeadbeef;
361 hr = IRawGameControllerStatics_add_RawGameControllerAdded(controller_statics, &controller_event_handler.IEventHandler_RawGameController_iface, &token);
362 ok(hr == S_OK, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr);
363 ok(token.value != 0xdeadbeef, "IRawGameControllerStatics_add_RawGameControllerAdded returned token %#I64x\n", token.value);
365 hr = IRawGameControllerStatics_remove_RawGameControllerAdded(controller_statics, token);
366 ok(hr == S_OK, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr);
368 token.value = 0xdeadbeef;
369 IRawGameControllerStatics_add_RawGameControllerRemoved(controller_statics, &controller_event_handler.IEventHandler_RawGameController_iface, &token);
370 ok(hr == S_OK, "IRawGameControllerStatics_add_RawGameControllerRemoved failed, hr %#x\n", hr);
371 ok(token.value != 0xdeadbeef, "IRawGameControllerStatics_add_RawGameControllerRemoved returned token %#I64x\n", token.value);
373 hr = IRawGameControllerStatics_remove_RawGameControllerRemoved(controller_statics, token);
374 ok(hr == S_OK, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr);
376 hr = IRawGameControllerStatics_add_RawGameControllerAdded(controller_statics, NULL, &token);
377 ok(hr == E_INVALIDARG, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr);
379 IRawGameControllerStatics_Release(controller_statics);
381 IAgileObject_Release(agile_object);
382 IInspectable_Release(inspectable);
383 IActivationFactory_Release(factory);
385 pWindowsDeleteString(str);
387 pRoUninitialize();
390 START_TEST(input)
392 HMODULE combase;
394 if (!(combase = LoadLibraryW(L"combase.dll")))
396 win_skip("Failed to load combase.dll, skipping tests\n");
397 return;
400 #define LOAD_FUNCPTR(x) \
401 if (!(p##x = (void*)GetProcAddress(combase, #x))) \
403 win_skip("Failed to find %s in combase.dll, skipping tests.\n", #x); \
404 return; \
407 LOAD_FUNCPTR(RoActivateInstance);
408 LOAD_FUNCPTR(RoGetActivationFactory);
409 LOAD_FUNCPTR(RoInitialize);
410 LOAD_FUNCPTR(RoUninitialize);
411 LOAD_FUNCPTR(WindowsCreateString);
412 LOAD_FUNCPTR(WindowsDeleteString);
413 #undef LOAD_FUNCPTR
415 test_Gamepad();
416 test_RawGameController();