include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / windows.gaming.input / controller.c
blobe1749a3032d3d0064e6c5b0081610b4f05e62630
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
20 #include "private.h"
21 #include "provider.h"
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 =
30 0, 0, &controller_cs,
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,
49 HRESULT hr;
51 EnterCriticalSection( &controller_cs );
52 if (controllers) hr = S_OK;
53 else hr = vector_create( &iids, (void **)&controllers );
54 LeaveCriticalSection( &controller_cs );
56 return hr;
59 struct controller
61 IGameControllerImpl IGameControllerImpl_iface;
62 IGameControllerInputSink IGameControllerInputSink_iface;
63 IRawGameController IRawGameController_iface;
64 IRawGameController2 IRawGameController2_iface;
65 IGameController *IGameController_outer;
66 LONG ref;
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) );
88 return S_OK;
91 if (IsEqualGUID( iid, &IID_IGameControllerInputSink ))
93 IInspectable_AddRef( (*out = &impl->IGameControllerInputSink_iface) );
94 return S_OK;
97 if (IsEqualGUID( iid, &IID_IRawGameController ))
99 IInspectable_AddRef( (*out = &impl->IRawGameController_iface) );
100 return S_OK;
103 if (IsEqualGUID( iid, &IID_IRawGameController2 ))
105 IInspectable_AddRef( (*out = &impl->IRawGameController2_iface) );
106 return S_OK;
109 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
110 *out = NULL;
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 );
119 return 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 );
129 if (!ref)
131 if (impl->wine_provider)
132 IWineGameControllerProvider_Release( impl->wine_provider );
133 IGameControllerProvider_Release( impl->provider );
134 free( impl );
137 return ref;
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 );
143 return E_NOTIMPL;
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),
150 class_name );
153 static HRESULT WINAPI controller_GetTrustLevel( IGameControllerImpl *iface, TrustLevel *trust_level )
155 FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level );
156 return E_NOTIMPL;
159 static HRESULT WINAPI controller_Initialize( IGameControllerImpl *iface, IGameController *outer,
160 IGameControllerProvider *provider )
162 struct controller *impl = impl_from_IGameControllerImpl( iface );
163 HRESULT hr;
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 );
179 return hr;
182 static const struct IGameControllerImplVtbl controller_vtbl =
184 controller_QueryInterface,
185 controller_AddRef,
186 controller_Release,
187 /* IInspectable methods */
188 controller_GetIids,
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 );
200 return E_NOTIMPL;
203 static HRESULT WINAPI input_sink_OnInputSuspended( IGameControllerInputSink *iface, UINT64 timestamp )
205 FIXME( "iface %p, timestamp %I64u stub!\n", iface, timestamp );
206 return E_NOTIMPL;
209 static const struct IGameControllerInputSinkVtbl input_sink_vtbl =
211 input_sink_QueryInterface,
212 input_sink_AddRef,
213 input_sink_Release,
214 /* IInspectable methods */
215 input_sink_GetIids,
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;
249 HRESULT hr;
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 );
264 return hr;
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 );
289 return E_NOTIMPL;
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;
298 HRESULT hr;
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;
310 return hr;
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 );
316 return E_NOTIMPL;
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;
352 HRESULT hr;
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 );
362 return hr;
365 static HRESULT WINAPI raw_controller_2_get_NonRoamableId( IRawGameController2 *iface, HSTRING* value )
367 FIXME( "iface %p, value %p stub!\n", iface, value );
368 return E_NOTIMPL;
371 static HRESULT WINAPI raw_controller_2_get_DisplayName( IRawGameController2 *iface, HSTRING* value )
373 FIXME( "iface %p, value %p stub!\n", iface, value );
374 return E_NOTIMPL;
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;
397 LONG ref;
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) );
417 return S_OK;
420 if (IsEqualGUID( iid, &IID_IRawGameControllerStatics ))
422 IInspectable_AddRef( (*out = &impl->IRawGameControllerStatics_iface) );
423 return S_OK;
426 if (IsEqualGUID( iid, &IID_ICustomGameControllerFactory ))
428 IInspectable_AddRef( (*out = &impl->ICustomGameControllerFactory_iface) );
429 return S_OK;
432 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
433 *out = NULL;
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 );
442 return 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 );
450 return 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 );
456 return E_NOTIMPL;
459 static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name )
461 FIXME( "iface %p, class_name %p stub!\n", iface, class_name );
462 return E_NOTIMPL;
465 static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level )
467 FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level );
468 return E_NOTIMPL;
471 static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance )
473 FIXME( "iface %p, instance %p stub!\n", iface, instance );
474 return E_NOTIMPL;
477 static const struct IActivationFactoryVtbl factory_vtbl =
479 factory_QueryInterface,
480 factory_AddRef,
481 factory_Release,
482 /* IInspectable methods */
483 factory_GetIids,
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 )
524 HRESULT hr;
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 );
533 return hr;
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;
541 HRESULT hr;
543 TRACE( "iface %p, game_controller %p, value %p.\n", iface, game_controller, value );
545 *value = NULL;
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 );
553 return hr;
556 static const struct IRawGameControllerStaticsVtbl statics_vtbl =
558 statics_QueryInterface,
559 statics_AddRef,
560 statics_Release,
561 /* IInspectable methods */
562 statics_GetIids,
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;
588 impl->ref = 1;
590 TRACE( "created RawGameController %p\n", impl );
592 *value = (IInspectable *)&impl->IGameControllerImpl_iface;
593 return S_OK;
596 static HRESULT WINAPI controller_factory_OnGameControllerAdded( ICustomGameControllerFactory *iface, IGameController *value )
598 IRawGameController *controller;
599 HRESULT hr;
601 TRACE( "iface %p, value %p.\n", iface, value );
603 if (FAILED(hr = IGameController_QueryInterface( value, &IID_IRawGameController, (void **)&controller )))
604 return hr;
605 event_handlers_notify( &controller_added_handlers, (IInspectable *)controller );
606 IRawGameController_Release( controller );
608 return S_OK;
611 static HRESULT WINAPI controller_factory_OnGameControllerRemoved( ICustomGameControllerFactory *iface, IGameController *value )
613 IRawGameController *controller;
614 BOOLEAN found;
615 UINT32 index;
616 HRESULT hr;
618 TRACE( "iface %p, value %p.\n", iface, value );
620 if (FAILED(hr = IGameController_QueryInterface( value, &IID_IRawGameController, (void **)&controller )))
621 return hr;
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 );
628 else
629 hr = IVector_RawGameController_RemoveAt( controllers, index );
631 LeaveCriticalSection( &controller_cs );
633 if (FAILED(hr))
634 WARN( "Failed to remove controller %p, hr %#lx!\n", controller, hr );
635 else if (found)
637 TRACE( "Removed controller %p.\n", controller );
638 event_handlers_notify( &controller_removed_handlers, (IInspectable *)controller );
640 IRawGameController_Release( controller );
642 return S_OK;
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 =
662 {&factory_vtbl},
663 {&statics_vtbl},
664 {&controller_factory_vtbl},
668 ICustomGameControllerFactory *controller_factory = &controller_statics.ICustomGameControllerFactory_iface;