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
);
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
);
217 struct controller_event_handler
219 IEventHandler_RawGameController IEventHandler_RawGameController_iface
;
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
);
239 trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
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
);
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
);
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
);
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
;
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
));
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
);
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
);
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
);
394 if (!(combase
= LoadLibraryW(L
"combase.dll")))
396 win_skip("Failed to load combase.dll, skipping tests\n");
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); \
407 LOAD_FUNCPTR(RoActivateInstance
);
408 LOAD_FUNCPTR(RoGetActivationFactory
);
409 LOAD_FUNCPTR(RoInitialize
);
410 LOAD_FUNCPTR(RoUninitialize
);
411 LOAD_FUNCPTR(WindowsCreateString
);
412 LOAD_FUNCPTR(WindowsDeleteString
);
416 test_RawGameController();