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
24 #include "winstring.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
;
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
);
66 trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
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
);
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
);
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
);
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
;
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
));
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
);
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 hr
= IVectorView_Gamepad_GetMany(gamepads
, size
, 1, &gamepad
, &size
);
179 ok(hr
== E_BOUNDS
, "IVectorView_Gamepad_GetMany failed, hr %#x\n", hr
);
180 ok(size
== 0, "IVectorView_Gamepad_GetMany returned count %u\n", size
);
184 gamepad
= (IGamepad
*)0xdeadbeef;
185 hr
= IVectorView_Gamepad_IndexOf(gamepads
, gamepad
, &size
, &found
);
186 ok(hr
== S_OK
, "IVectorView_Gamepad_IndexOf failed, hr %#x\n", hr
);
187 ok(size
== 0 && found
== FALSE
, "IVectorView_Gamepad_IndexOf returned size %d, found %d\n", size
, found
);
189 IVectorView_Gamepad_Release(gamepads
);
191 token
.value
= 0xdeadbeef;
192 hr
= IGamepadStatics_add_GamepadAdded(gamepad_statics
, &gamepad_event_handler
.IEventHandler_Gamepad_iface
, &token
);
193 ok(hr
== S_OK
, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr
);
194 ok(token
.value
!= 0xdeadbeef, "IGamepadStatics_add_GamepadAdded returned token %#I64x\n", token
.value
);
196 hr
= IGamepadStatics_remove_GamepadAdded(gamepad_statics
, token
);
197 ok(hr
== S_OK
, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr
);
199 token
.value
= 0xdeadbeef;
200 IGamepadStatics_add_GamepadRemoved(gamepad_statics
, &gamepad_event_handler
.IEventHandler_Gamepad_iface
, &token
);
201 ok(hr
== S_OK
, "IGamepadStatics_add_GamepadRemoved failed, hr %#x\n", hr
);
202 ok(token
.value
!= 0xdeadbeef, "IGamepadStatics_add_GamepadRemoved returned token %#I64x\n", token
.value
);
204 hr
= IGamepadStatics_remove_GamepadRemoved(gamepad_statics
, token
);
205 ok(hr
== S_OK
, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr
);
207 hr
= IGamepadStatics_add_GamepadAdded(gamepad_statics
, NULL
, &token
);
208 ok(hr
== E_INVALIDARG
, "IGamepadStatics_add_GamepadAdded failed, hr %#x\n", hr
);
210 IGamepadStatics_Release(gamepad_statics
);
212 IAgileObject_Release(agile_object
);
213 IInspectable_Release(inspectable
);
214 IActivationFactory_Release(factory
);
216 pWindowsDeleteString(str
);
221 struct controller_event_handler
223 IEventHandler_RawGameController IEventHandler_RawGameController_iface
;
227 static inline struct controller_event_handler
*impl_from_IEventHandler_RawGameController(IEventHandler_RawGameController
*iface
)
229 return CONTAINING_RECORD(iface
, struct controller_event_handler
, IEventHandler_RawGameController_iface
);
232 static HRESULT STDMETHODCALLTYPE
controller_event_handler_QueryInterface(
233 IEventHandler_RawGameController
*iface
, REFIID iid
, void **out
)
235 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
236 IsEqualGUID(iid
, &IID_IEventHandler_RawGameController
))
238 IUnknown_AddRef(iface
);
243 trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
245 return E_NOINTERFACE
;
248 static ULONG STDMETHODCALLTYPE
controller_event_handler_AddRef(
249 IEventHandler_RawGameController
*iface
)
251 struct controller_event_handler
*impl
= impl_from_IEventHandler_RawGameController(iface
);
252 ULONG ref
= InterlockedIncrement(&impl
->ref
);
256 static ULONG STDMETHODCALLTYPE
controller_event_handler_Release(
257 IEventHandler_RawGameController
*iface
)
259 struct controller_event_handler
*impl
= impl_from_IEventHandler_RawGameController(iface
);
260 ULONG ref
= InterlockedDecrement(&impl
->ref
);
264 static HRESULT STDMETHODCALLTYPE
controller_event_handler_Invoke(
265 IEventHandler_RawGameController
*iface
, IInspectable
*sender
, IRawGameController
*args
)
267 trace("iface %p, sender %p, args %p\n", iface
, sender
, args
);
271 static const IEventHandler_RawGameControllerVtbl controller_event_handler_vtbl
=
273 controller_event_handler_QueryInterface
,
274 controller_event_handler_AddRef
,
275 controller_event_handler_Release
,
276 /*** IEventHandler<ABI::Windows::Gaming::Input::Gamepad* > methods ***/
277 controller_event_handler_Invoke
,
280 static void test_RawGameController(void)
282 static const WCHAR
*controller_name
= L
"Windows.Gaming.Input.RawGameController";
284 struct controller_event_handler controller_event_handler
;
285 EventRegistrationToken token
;
286 IVectorView_RawGameController
*controllers
= NULL
;
287 IActivationFactory
*factory
= NULL
;
288 IRawGameControllerStatics
*controller_statics
= NULL
;
289 IInspectable
*inspectable
= NULL
, *tmp_inspectable
= NULL
;
290 IAgileObject
*agile_object
= NULL
, *tmp_agile_object
= NULL
;
291 IRawGameController
*controller
;
297 controller_event_handler
.IEventHandler_RawGameController_iface
.lpVtbl
= &controller_event_handler_vtbl
;
299 hr
= pRoInitialize(RO_INIT_MULTITHREADED
);
300 ok(hr
== S_OK
|| hr
== S_FALSE
, "RoInitialize failed, hr %#x\n", hr
);
302 hr
= pWindowsCreateString(controller_name
, wcslen(controller_name
), &str
);
303 ok(hr
== S_OK
, "WindowsCreateString failed, hr %#x\n", hr
);
305 hr
= pRoGetActivationFactory(str
, &IID_IActivationFactory
, (void **)&factory
);
306 ok(hr
== S_OK
|| broken(hr
== REGDB_E_CLASSNOTREG
), "RoGetActivationFactory failed, hr %#x\n", hr
);
307 if (hr
== REGDB_E_CLASSNOTREG
)
309 win_skip("%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w(controller_name
));
313 hr
= IActivationFactory_QueryInterface(factory
, &IID_IInspectable
, (void **)&inspectable
);
314 ok(hr
== S_OK
, "IActivationFactory_QueryInterface IID_IInspectable failed, hr %#x\n", hr
);
316 hr
= IActivationFactory_QueryInterface(factory
, &IID_IAgileObject
, (void **)&agile_object
);
317 ok(hr
== S_OK
, "IActivationFactory_QueryInterface IID_IAgileObject failed, hr %#x\n", hr
);
319 hr
= IActivationFactory_QueryInterface(factory
, &IID_IRawGameControllerStatics
, (void **)&controller_statics
);
320 ok(hr
== S_OK
, "IActivationFactory_QueryInterface IID_IRawGameControllerStatics failed, hr %#x\n", hr
);
322 hr
= IRawGameControllerStatics_QueryInterface(controller_statics
, &IID_IInspectable
, (void **)&tmp_inspectable
);
323 ok(hr
== S_OK
, "IRawGameControllerStatics_QueryInterface IID_IInspectable failed, hr %#x\n", hr
);
324 ok(tmp_inspectable
== inspectable
, "IRawGameControllerStatics_QueryInterface IID_IInspectable returned %p, expected %p\n", tmp_inspectable
, inspectable
);
325 IInspectable_Release(tmp_inspectable
);
327 hr
= IRawGameControllerStatics_QueryInterface(controller_statics
, &IID_IAgileObject
, (void **)&tmp_agile_object
);
328 ok(hr
== S_OK
, "IRawGameControllerStatics_QueryInterface IID_IAgileObject failed, hr %#x\n", hr
);
329 ok(tmp_agile_object
== agile_object
, "IRawGameControllerStatics_QueryInterface IID_IAgileObject returned %p, expected %p\n", tmp_agile_object
, agile_object
);
330 IAgileObject_Release(tmp_agile_object
);
332 hr
= IRawGameControllerStatics_get_RawGameControllers(controller_statics
, &controllers
);
333 ok(hr
== S_OK
, "IRawGameControllerStatics_get_RawGameControllers failed, hr %#x\n", hr
);
335 hr
= IVectorView_RawGameController_QueryInterface(controllers
, &IID_IInspectable
, (void **)&tmp_inspectable
);
336 ok(hr
== S_OK
, "IVectorView_RawGameController_QueryInterface failed, hr %#x\n", hr
);
337 ok(tmp_inspectable
!= inspectable
, "IVectorView_RawGameController_QueryInterface returned %p, expected %p\n", tmp_inspectable
, inspectable
);
338 IInspectable_Release(tmp_inspectable
);
340 hr
= IVectorView_RawGameController_QueryInterface(controllers
, &IID_IAgileObject
, (void **)&tmp_agile_object
);
341 ok(hr
== S_OK
, "IVectorView_RawGameController_QueryInterface failed, hr %#x\n", hr
);
342 ok(tmp_agile_object
!= agile_object
, "IVectorView_RawGameController_QueryInterface IID_IAgileObject returned agile_object\n");
343 IAgileObject_Release(tmp_agile_object
);
346 hr
= IVectorView_RawGameController_get_Size(controllers
, &size
);
347 ok(hr
== S_OK
, "IVectorView_RawGameController_get_Size failed, hr %#x\n", hr
);
348 ok(size
!= 0xdeadbeef, "IVectorView_RawGameController_get_Size returned %u\n", size
);
350 hr
= IVectorView_RawGameController_GetMany(controllers
, size
, 1, &controller
, &size
);
351 ok(hr
== E_BOUNDS
, "IVectorView_RawGameController_GetMany failed, hr %#x\n", hr
);
352 ok(size
== 0, "IVectorView_RawGameController_GetMany returned count %u\n", size
);
354 controller
= (IRawGameController
*)0xdeadbeef;
355 hr
= IVectorView_RawGameController_GetAt(controllers
, size
, &controller
);
356 ok(hr
== E_BOUNDS
, "IVectorView_RawGameController_GetAt failed, hr %#x\n", hr
);
357 ok(controller
== NULL
, "IVectorView_RawGameController_GetAt returned %p\n", controller
);
361 controller
= (IRawGameController
*)0xdeadbeef;
362 hr
= IVectorView_RawGameController_IndexOf(controllers
, controller
, &size
, &found
);
363 ok(hr
== S_OK
, "IVectorView_RawGameController_IndexOf failed, hr %#x\n", hr
);
364 ok(size
== 0 && found
== FALSE
, "IVectorView_RawGameController_IndexOf returned size %d, found %d\n", size
, found
);
366 IVectorView_RawGameController_Release(controllers
);
368 token
.value
= 0xdeadbeef;
369 hr
= IRawGameControllerStatics_add_RawGameControllerAdded(controller_statics
, &controller_event_handler
.IEventHandler_RawGameController_iface
, &token
);
370 ok(hr
== S_OK
, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr
);
371 ok(token
.value
!= 0xdeadbeef, "IRawGameControllerStatics_add_RawGameControllerAdded returned token %#I64x\n", token
.value
);
373 hr
= IRawGameControllerStatics_remove_RawGameControllerAdded(controller_statics
, token
);
374 ok(hr
== S_OK
, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr
);
376 token
.value
= 0xdeadbeef;
377 IRawGameControllerStatics_add_RawGameControllerRemoved(controller_statics
, &controller_event_handler
.IEventHandler_RawGameController_iface
, &token
);
378 ok(hr
== S_OK
, "IRawGameControllerStatics_add_RawGameControllerRemoved failed, hr %#x\n", hr
);
379 ok(token
.value
!= 0xdeadbeef, "IRawGameControllerStatics_add_RawGameControllerRemoved returned token %#I64x\n", token
.value
);
381 hr
= IRawGameControllerStatics_remove_RawGameControllerRemoved(controller_statics
, token
);
382 ok(hr
== S_OK
, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr
);
384 hr
= IRawGameControllerStatics_add_RawGameControllerAdded(controller_statics
, NULL
, &token
);
385 ok(hr
== E_INVALIDARG
, "IRawGameControllerStatics_add_RawGameControllerAdded failed, hr %#x\n", hr
);
387 IRawGameControllerStatics_Release(controller_statics
);
389 IAgileObject_Release(agile_object
);
390 IInspectable_Release(inspectable
);
391 IActivationFactory_Release(factory
);
393 pWindowsDeleteString(str
);
402 if (!(combase
= LoadLibraryW(L
"combase.dll")))
404 win_skip("Failed to load combase.dll, skipping tests\n");
408 #define LOAD_FUNCPTR(x) \
409 if (!(p##x = (void*)GetProcAddress(combase, #x))) \
411 win_skip("Failed to find %s in combase.dll, skipping tests.\n", #x); \
415 LOAD_FUNCPTR(RoActivateInstance
);
416 LOAD_FUNCPTR(RoGetActivationFactory
);
417 LOAD_FUNCPTR(RoInitialize
);
418 LOAD_FUNCPTR(RoUninitialize
);
419 LOAD_FUNCPTR(WindowsCreateString
);
420 LOAD_FUNCPTR(WindowsDeleteString
);
424 test_RawGameController();