1 /* WinRT Windows.Gaming.Input implementation
3 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(input
);
27 static CRITICAL_SECTION controller_cs
;
28 static CRITICAL_SECTION_DEBUG controller_cs_debug
=
31 { &controller_cs_debug
.ProcessLocksList
, &controller_cs_debug
.ProcessLocksList
},
32 0, 0, { (DWORD_PTR
)(__FILE__
": controller_cs") }
34 static CRITICAL_SECTION controller_cs
= { &controller_cs_debug
, -1, 0, 0, 0, 0 };
36 static IVector_RawGameController
*controllers
;
37 static struct list controller_added_handlers
= LIST_INIT( controller_added_handlers
);
38 static struct list controller_removed_handlers
= LIST_INIT( controller_removed_handlers
);
40 static HRESULT
init_controllers(void)
42 static const struct vector_iids iids
=
44 .vector
= &IID_IVector_RawGameController
,
45 .view
= &IID_IVectorView_RawGameController
,
46 .iterable
= &IID_IIterable_RawGameController
,
47 .iterator
= &IID_IIterator_RawGameController
,
51 EnterCriticalSection( &controller_cs
);
52 if (controllers
) hr
= S_OK
;
53 else hr
= vector_create( &iids
, (void **)&controllers
);
54 LeaveCriticalSection( &controller_cs
);
61 IGameControllerImpl IGameControllerImpl_iface
;
62 IGameControllerInputSink IGameControllerInputSink_iface
;
63 IRawGameController IRawGameController_iface
;
64 IRawGameController2 IRawGameController2_iface
;
65 IGameController
*IGameController_outer
;
68 IGameControllerProvider
*provider
;
69 IWineGameControllerProvider
*wine_provider
;
72 static inline struct controller
*impl_from_IGameControllerImpl( IGameControllerImpl
*iface
)
74 return CONTAINING_RECORD( iface
, struct controller
, IGameControllerImpl_iface
);
77 static HRESULT WINAPI
controller_QueryInterface( IGameControllerImpl
*iface
, REFIID iid
, void **out
)
79 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
81 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
83 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
84 IsEqualGUID( iid
, &IID_IInspectable
) ||
85 IsEqualGUID( iid
, &IID_IGameControllerImpl
))
87 IInspectable_AddRef( (*out
= &impl
->IGameControllerImpl_iface
) );
91 if (IsEqualGUID( iid
, &IID_IGameControllerInputSink
))
93 IInspectable_AddRef( (*out
= &impl
->IGameControllerInputSink_iface
) );
97 if (IsEqualGUID( iid
, &IID_IRawGameController
))
99 IInspectable_AddRef( (*out
= &impl
->IRawGameController_iface
) );
103 if (IsEqualGUID( iid
, &IID_IRawGameController2
))
105 IInspectable_AddRef( (*out
= &impl
->IRawGameController2_iface
) );
109 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
111 return E_NOINTERFACE
;
114 static ULONG WINAPI
controller_AddRef( IGameControllerImpl
*iface
)
116 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
117 ULONG ref
= InterlockedIncrement( &impl
->ref
);
118 TRACE( "iface %p increasing refcount to %lu.\n", iface
, ref
);
122 static ULONG WINAPI
controller_Release( IGameControllerImpl
*iface
)
124 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
125 ULONG ref
= InterlockedDecrement( &impl
->ref
);
127 TRACE( "iface %p decreasing refcount to %lu.\n", iface
, ref
);
131 if (impl
->wine_provider
)
132 IWineGameControllerProvider_Release( impl
->wine_provider
);
133 IGameControllerProvider_Release( impl
->provider
);
140 static HRESULT WINAPI
controller_GetIids( IGameControllerImpl
*iface
, ULONG
*iid_count
, IID
**iids
)
142 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
146 static HRESULT WINAPI
controller_GetRuntimeClassName( IGameControllerImpl
*iface
, HSTRING
*class_name
)
148 return WindowsCreateString( RuntimeClass_Windows_Gaming_Input_RawGameController
,
149 ARRAY_SIZE(RuntimeClass_Windows_Gaming_Input_RawGameController
),
153 static HRESULT WINAPI
controller_GetTrustLevel( IGameControllerImpl
*iface
, TrustLevel
*trust_level
)
155 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
159 static HRESULT WINAPI
controller_Initialize( IGameControllerImpl
*iface
, IGameController
*outer
,
160 IGameControllerProvider
*provider
)
162 struct controller
*impl
= impl_from_IGameControllerImpl( iface
);
165 TRACE( "iface %p, outer %p, provider %p.\n", iface
, outer
, provider
);
167 impl
->IGameController_outer
= outer
;
168 IGameControllerProvider_AddRef( (impl
->provider
= provider
) );
170 hr
= IGameControllerProvider_QueryInterface( provider
, &IID_IWineGameControllerProvider
,
171 (void **)&impl
->wine_provider
);
172 if (FAILED(hr
)) return hr
;
174 EnterCriticalSection( &controller_cs
);
175 if (SUCCEEDED(hr
= init_controllers()))
176 hr
= IVector_RawGameController_Append( controllers
, &impl
->IRawGameController_iface
);
177 LeaveCriticalSection( &controller_cs
);
182 static const struct IGameControllerImplVtbl controller_vtbl
=
184 controller_QueryInterface
,
187 /* IInspectable methods */
189 controller_GetRuntimeClassName
,
190 controller_GetTrustLevel
,
191 /* IGameControllerImpl methods */
192 controller_Initialize
,
195 DEFINE_IINSPECTABLE_OUTER( input_sink
, IGameControllerInputSink
, struct controller
, IGameController_outer
)
197 static HRESULT WINAPI
input_sink_OnInputResumed( IGameControllerInputSink
*iface
, UINT64 timestamp
)
199 FIXME( "iface %p, timestamp %I64u stub!\n", iface
, timestamp
);
203 static HRESULT WINAPI
input_sink_OnInputSuspended( IGameControllerInputSink
*iface
, UINT64 timestamp
)
205 FIXME( "iface %p, timestamp %I64u stub!\n", iface
, timestamp
);
209 static const struct IGameControllerInputSinkVtbl input_sink_vtbl
=
211 input_sink_QueryInterface
,
214 /* IInspectable methods */
216 input_sink_GetRuntimeClassName
,
217 input_sink_GetTrustLevel
,
218 /* IGameControllerInputSink methods */
219 input_sink_OnInputResumed
,
220 input_sink_OnInputSuspended
,
223 DEFINE_IINSPECTABLE_OUTER( raw_controller
, IRawGameController
, struct controller
, IGameController_outer
)
225 static HRESULT WINAPI
raw_controller_get_AxisCount( IRawGameController
*iface
, INT32
*value
)
227 struct controller
*impl
= impl_from_IRawGameController( iface
);
228 return IWineGameControllerProvider_get_AxisCount( impl
->wine_provider
, value
);
231 static HRESULT WINAPI
raw_controller_get_ButtonCount( IRawGameController
*iface
, INT32
*value
)
233 struct controller
*impl
= impl_from_IRawGameController( iface
);
234 return IWineGameControllerProvider_get_ButtonCount( impl
->wine_provider
, value
);
237 static HRESULT WINAPI
raw_controller_get_ForceFeedbackMotors( IRawGameController
*iface
, IVectorView_ForceFeedbackMotor
**value
)
239 static const struct vector_iids iids
=
241 .vector
= &IID_IVector_ForceFeedbackMotor
,
242 .view
= &IID_IVectorView_ForceFeedbackMotor
,
243 .iterable
= &IID_IIterable_ForceFeedbackMotor
,
244 .iterator
= &IID_IIterator_ForceFeedbackMotor
,
246 struct controller
*impl
= impl_from_IRawGameController( iface
);
247 IVector_ForceFeedbackMotor
*vector
;
248 IForceFeedbackMotor
*motor
;
251 TRACE( "iface %p, value %p\n", iface
, value
);
253 if (FAILED(hr
= vector_create( &iids
, (void **)&vector
))) return hr
;
255 if (SUCCEEDED(IWineGameControllerProvider_get_ForceFeedbackMotor( impl
->wine_provider
, &motor
)) && motor
)
257 hr
= IVector_ForceFeedbackMotor_Append( vector
, motor
);
258 IForceFeedbackMotor_Release( motor
);
261 if (SUCCEEDED(hr
)) hr
= IVector_ForceFeedbackMotor_GetView( vector
, value
);
262 IVector_ForceFeedbackMotor_Release( vector
);
267 static HRESULT WINAPI
raw_controller_get_HardwareProductId( IRawGameController
*iface
, UINT16
*value
)
269 struct controller
*impl
= impl_from_IRawGameController( iface
);
270 return IGameControllerProvider_get_HardwareProductId( impl
->provider
, value
);
273 static HRESULT WINAPI
raw_controller_get_HardwareVendorId( IRawGameController
*iface
, UINT16
*value
)
275 struct controller
*impl
= impl_from_IRawGameController( iface
);
276 return IGameControllerProvider_get_HardwareVendorId( impl
->provider
, value
);
279 static HRESULT WINAPI
raw_controller_get_SwitchCount( IRawGameController
*iface
, INT32
*value
)
281 struct controller
*impl
= impl_from_IRawGameController( iface
);
282 return IWineGameControllerProvider_get_SwitchCount( impl
->wine_provider
, value
);
285 static HRESULT WINAPI
raw_controller_GetButtonLabel( IRawGameController
*iface
, INT32 index
,
286 enum GameControllerButtonLabel
*value
)
288 FIXME( "iface %p, index %d, value %p stub!\n", iface
, index
, value
);
292 static HRESULT WINAPI
raw_controller_GetCurrentReading( IRawGameController
*iface
, UINT32 buttons_size
, BOOLEAN
*buttons
,
293 UINT32 switches_size
, enum GameControllerSwitchPosition
*switches
,
294 UINT32 axes_size
, DOUBLE
*axes
, UINT64
*timestamp
)
296 struct controller
*impl
= impl_from_IRawGameController( iface
);
297 WineGameControllerState state
;
300 TRACE( "iface %p, buttons_size %u, buttons %p, switches_size %u, switches %p, axes_size %u, axes %p, timestamp %p.\n",
301 iface
, buttons_size
, buttons
, switches_size
, switches
, axes_size
, axes
, timestamp
);
303 if (FAILED(hr
= IWineGameControllerProvider_get_State( impl
->wine_provider
, &state
))) return hr
;
305 memcpy( axes
, state
.axes
, axes_size
* sizeof(*axes
) );
306 memcpy( buttons
, state
.buttons
, buttons_size
* sizeof(*buttons
) );
307 memcpy( switches
, state
.switches
, switches_size
* sizeof(*switches
) );
308 *timestamp
= state
.timestamp
;
313 static HRESULT WINAPI
raw_controller_GetSwitchKind( IRawGameController
*iface
, INT32 index
, enum GameControllerSwitchKind
*value
)
315 FIXME( "iface %p, index %d, value %p stub!\n", iface
, index
, value
);
319 static const struct IRawGameControllerVtbl raw_controller_vtbl
=
321 raw_controller_QueryInterface
,
322 raw_controller_AddRef
,
323 raw_controller_Release
,
324 /* IInspectable methods */
325 raw_controller_GetIids
,
326 raw_controller_GetRuntimeClassName
,
327 raw_controller_GetTrustLevel
,
328 /* IRawGameController methods */
329 raw_controller_get_AxisCount
,
330 raw_controller_get_ButtonCount
,
331 raw_controller_get_ForceFeedbackMotors
,
332 raw_controller_get_HardwareProductId
,
333 raw_controller_get_HardwareVendorId
,
334 raw_controller_get_SwitchCount
,
335 raw_controller_GetButtonLabel
,
336 raw_controller_GetCurrentReading
,
337 raw_controller_GetSwitchKind
,
340 DEFINE_IINSPECTABLE_OUTER( raw_controller_2
, IRawGameController2
, struct controller
, IGameController_outer
)
342 static HRESULT WINAPI
raw_controller_2_get_SimpleHapticsControllers( IRawGameController2
*iface
, IVectorView_SimpleHapticsController
** value
)
344 static const struct vector_iids iids
=
346 .vector
= &IID_IVector_SimpleHapticsController
,
347 .view
= &IID_IVectorView_SimpleHapticsController
,
348 .iterable
= &IID_IIterable_SimpleHapticsController
,
349 .iterator
= &IID_IIterator_SimpleHapticsController
,
351 IVector_SimpleHapticsController
*vector
;
354 FIXME( "iface %p, value %p stub!\n", iface
, value
);
356 if (SUCCEEDED(hr
= vector_create( &iids
, (void **)&vector
)))
358 hr
= IVector_SimpleHapticsController_GetView( vector
, value
);
359 IVector_SimpleHapticsController_Release( vector
);
365 static HRESULT WINAPI
raw_controller_2_get_NonRoamableId( IRawGameController2
*iface
, HSTRING
* value
)
367 FIXME( "iface %p, value %p stub!\n", iface
, value
);
371 static HRESULT WINAPI
raw_controller_2_get_DisplayName( IRawGameController2
*iface
, HSTRING
* value
)
373 FIXME( "iface %p, value %p stub!\n", iface
, value
);
377 static const struct IRawGameController2Vtbl raw_controller_2_vtbl
=
379 raw_controller_2_QueryInterface
,
380 raw_controller_2_AddRef
,
381 raw_controller_2_Release
,
382 /* IInspectable methods */
383 raw_controller_2_GetIids
,
384 raw_controller_2_GetRuntimeClassName
,
385 raw_controller_2_GetTrustLevel
,
386 /* IRawGameController2 methods */
387 raw_controller_2_get_SimpleHapticsControllers
,
388 raw_controller_2_get_NonRoamableId
,
389 raw_controller_2_get_DisplayName
,
392 struct controller_statics
394 IActivationFactory IActivationFactory_iface
;
395 IRawGameControllerStatics IRawGameControllerStatics_iface
;
396 ICustomGameControllerFactory ICustomGameControllerFactory_iface
;
400 static inline struct controller_statics
*impl_from_IActivationFactory( IActivationFactory
*iface
)
402 return CONTAINING_RECORD( iface
, struct controller_statics
, IActivationFactory_iface
);
405 static HRESULT WINAPI
factory_QueryInterface( IActivationFactory
*iface
, REFIID iid
, void **out
)
407 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
409 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
411 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
412 IsEqualGUID( iid
, &IID_IInspectable
) ||
413 IsEqualGUID( iid
, &IID_IAgileObject
) ||
414 IsEqualGUID( iid
, &IID_IActivationFactory
))
416 IInspectable_AddRef( (*out
= &impl
->IActivationFactory_iface
) );
420 if (IsEqualGUID( iid
, &IID_IRawGameControllerStatics
))
422 IInspectable_AddRef( (*out
= &impl
->IRawGameControllerStatics_iface
) );
426 if (IsEqualGUID( iid
, &IID_ICustomGameControllerFactory
))
428 IInspectable_AddRef( (*out
= &impl
->ICustomGameControllerFactory_iface
) );
432 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
434 return E_NOINTERFACE
;
437 static ULONG WINAPI
factory_AddRef( IActivationFactory
*iface
)
439 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
440 ULONG ref
= InterlockedIncrement( &impl
->ref
);
441 TRACE( "iface %p increasing refcount to %lu.\n", iface
, ref
);
445 static ULONG WINAPI
factory_Release( IActivationFactory
*iface
)
447 struct controller_statics
*impl
= impl_from_IActivationFactory( iface
);
448 ULONG ref
= InterlockedDecrement( &impl
->ref
);
449 TRACE( "iface %p decreasing refcount to %lu.\n", iface
, ref
);
453 static HRESULT WINAPI
factory_GetIids( IActivationFactory
*iface
, ULONG
*iid_count
, IID
**iids
)
455 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
459 static HRESULT WINAPI
factory_GetRuntimeClassName( IActivationFactory
*iface
, HSTRING
*class_name
)
461 FIXME( "iface %p, class_name %p stub!\n", iface
, class_name
);
465 static HRESULT WINAPI
factory_GetTrustLevel( IActivationFactory
*iface
, TrustLevel
*trust_level
)
467 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
471 static HRESULT WINAPI
factory_ActivateInstance( IActivationFactory
*iface
, IInspectable
**instance
)
473 FIXME( "iface %p, instance %p stub!\n", iface
, instance
);
477 static const struct IActivationFactoryVtbl factory_vtbl
=
479 factory_QueryInterface
,
482 /* IInspectable methods */
484 factory_GetRuntimeClassName
,
485 factory_GetTrustLevel
,
486 /* IActivationFactory methods */
487 factory_ActivateInstance
,
490 DEFINE_IINSPECTABLE( statics
, IRawGameControllerStatics
, struct controller_statics
, IActivationFactory_iface
)
492 static HRESULT WINAPI
statics_add_RawGameControllerAdded( IRawGameControllerStatics
*iface
,
493 IEventHandler_RawGameController
*handler
,
494 EventRegistrationToken
*token
)
496 TRACE( "iface %p, handler %p, token %p.\n", iface
, handler
, token
);
497 if (!handler
) return E_INVALIDARG
;
498 return event_handlers_append( &controller_added_handlers
, (IEventHandler_IInspectable
*)handler
, token
);
501 static HRESULT WINAPI
statics_remove_RawGameControllerAdded( IRawGameControllerStatics
*iface
, EventRegistrationToken token
)
503 TRACE( "iface %p, token %#I64x.\n", iface
, token
.value
);
504 return event_handlers_remove( &controller_added_handlers
, &token
);
507 static HRESULT WINAPI
statics_add_RawGameControllerRemoved( IRawGameControllerStatics
*iface
,
508 IEventHandler_RawGameController
*handler
,
509 EventRegistrationToken
*token
)
511 TRACE( "iface %p, handler %p, token %p.\n", iface
, handler
, token
);
512 if (!handler
) return E_INVALIDARG
;
513 return event_handlers_append( &controller_removed_handlers
, (IEventHandler_IInspectable
*)handler
, token
);
516 static HRESULT WINAPI
statics_remove_RawGameControllerRemoved( IRawGameControllerStatics
*iface
, EventRegistrationToken token
)
518 TRACE( "iface %p, token %#I64x.\n", iface
, token
.value
);
519 return event_handlers_remove( &controller_removed_handlers
, &token
);
522 static HRESULT WINAPI
statics_get_RawGameControllers( IRawGameControllerStatics
*iface
, IVectorView_RawGameController
**value
)
526 TRACE( "iface %p, value %p.\n", iface
, value
);
528 EnterCriticalSection( &controller_cs
);
529 if (SUCCEEDED(hr
= init_controllers()))
530 hr
= IVector_RawGameController_GetView( controllers
, value
);
531 LeaveCriticalSection( &controller_cs
);
536 static HRESULT WINAPI
statics_FromGameController( IRawGameControllerStatics
*iface
, IGameController
*game_controller
,
537 IRawGameController
**value
)
539 struct controller_statics
*impl
= impl_from_IRawGameControllerStatics( iface
);
540 IGameController
*controller
;
543 TRACE( "iface %p, game_controller %p, value %p.\n", iface
, game_controller
, value
);
546 hr
= IGameControllerFactoryManagerStatics2_TryGetFactoryControllerFromGameController( manager_factory
, &impl
->ICustomGameControllerFactory_iface
,
547 game_controller
, &controller
);
548 if (FAILED(hr
) || !controller
) return hr
;
550 hr
= IGameController_QueryInterface( controller
, &IID_IRawGameController
, (void **)value
);
551 IGameController_Release( controller
);
556 static const struct IRawGameControllerStaticsVtbl statics_vtbl
=
558 statics_QueryInterface
,
561 /* IInspectable methods */
563 statics_GetRuntimeClassName
,
564 statics_GetTrustLevel
,
565 /* IRawGameControllerStatics methods */
566 statics_add_RawGameControllerAdded
,
567 statics_remove_RawGameControllerAdded
,
568 statics_add_RawGameControllerRemoved
,
569 statics_remove_RawGameControllerRemoved
,
570 statics_get_RawGameControllers
,
571 statics_FromGameController
,
574 DEFINE_IINSPECTABLE( controller_factory
, ICustomGameControllerFactory
, struct controller_statics
, IActivationFactory_iface
)
576 static HRESULT WINAPI
controller_factory_CreateGameController( ICustomGameControllerFactory
*iface
, IGameControllerProvider
*provider
,
577 IInspectable
**value
)
579 struct controller
*impl
;
581 TRACE( "iface %p, provider %p, value %p.\n", iface
, provider
, value
);
583 if (!(impl
= calloc( 1, sizeof(*impl
) ))) return E_OUTOFMEMORY
;
584 impl
->IGameControllerImpl_iface
.lpVtbl
= &controller_vtbl
;
585 impl
->IGameControllerInputSink_iface
.lpVtbl
= &input_sink_vtbl
;
586 impl
->IRawGameController_iface
.lpVtbl
= &raw_controller_vtbl
;
587 impl
->IRawGameController2_iface
.lpVtbl
= &raw_controller_2_vtbl
;
590 TRACE( "created RawGameController %p\n", impl
);
592 *value
= (IInspectable
*)&impl
->IGameControllerImpl_iface
;
596 static HRESULT WINAPI
controller_factory_OnGameControllerAdded( ICustomGameControllerFactory
*iface
, IGameController
*value
)
598 IRawGameController
*controller
;
601 TRACE( "iface %p, value %p.\n", iface
, value
);
603 if (FAILED(hr
= IGameController_QueryInterface( value
, &IID_IRawGameController
, (void **)&controller
)))
605 event_handlers_notify( &controller_added_handlers
, (IInspectable
*)controller
);
606 IRawGameController_Release( controller
);
611 static HRESULT WINAPI
controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory
*iface
, IGameController
*value
)
613 IRawGameController
*controller
;
618 TRACE( "iface %p, value %p.\n", iface
, value
);
620 if (FAILED(hr
= IGameController_QueryInterface( value
, &IID_IRawGameController
, (void **)&controller
)))
623 EnterCriticalSection( &controller_cs
);
624 if (SUCCEEDED(hr
= init_controllers()))
626 if (FAILED(hr
= IVector_RawGameController_IndexOf( controllers
, controller
, &index
, &found
)) || !found
)
627 WARN( "Could not find controller %p, hr %#lx!\n", controller
, hr
);
629 hr
= IVector_RawGameController_RemoveAt( controllers
, index
);
631 LeaveCriticalSection( &controller_cs
);
634 WARN( "Failed to remove controller %p, hr %#lx!\n", controller
, hr
);
637 TRACE( "Removed controller %p.\n", controller
);
638 event_handlers_notify( &controller_removed_handlers
, (IInspectable
*)controller
);
640 IRawGameController_Release( controller
);
645 static const struct ICustomGameControllerFactoryVtbl controller_factory_vtbl
=
647 controller_factory_QueryInterface
,
648 controller_factory_AddRef
,
649 controller_factory_Release
,
650 /* IInspectable methods */
651 controller_factory_GetIids
,
652 controller_factory_GetRuntimeClassName
,
653 controller_factory_GetTrustLevel
,
654 /* ICustomGameControllerFactory methods */
655 controller_factory_CreateGameController
,
656 controller_factory_OnGameControllerAdded
,
657 controller_factory_OnGameControllerRemoved
,
660 static struct controller_statics controller_statics
=
664 {&controller_factory_vtbl
},
668 ICustomGameControllerFactory
*controller_factory
= &controller_statics
.ICustomGameControllerFactory_iface
;