1 /* WinRT Windows.Gaming.Input implementation
3 * Copyright 2022 Bernhard Kölbl for CodeWeavers
4 * Copyright 2022 Rémi Bernon for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(input
);
29 #define HANDLER_NOT_SET ((void *)~(ULONG_PTR)0)
33 IWineAsyncInfoImpl IWineAsyncInfoImpl_iface
;
34 IAsyncInfo IAsyncInfo_iface
;
35 IInspectable
*IInspectable_outer
;
38 async_operation_callback callback
;
39 TP_WORK
*async_run_work
;
44 IWineAsyncOperationCompletedHandler
*handler
;
50 static inline struct async_info
*impl_from_IWineAsyncInfoImpl( IWineAsyncInfoImpl
*iface
)
52 return CONTAINING_RECORD( iface
, struct async_info
, IWineAsyncInfoImpl_iface
);
55 static HRESULT WINAPI
async_impl_QueryInterface( IWineAsyncInfoImpl
*iface
, REFIID iid
, void **out
)
57 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
59 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
61 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
62 IsEqualGUID( iid
, &IID_IInspectable
) ||
63 IsEqualGUID( iid
, &IID_IAgileObject
) ||
64 IsEqualGUID( iid
, &IID_IWineAsyncInfoImpl
))
66 IInspectable_AddRef( (*out
= &impl
->IWineAsyncInfoImpl_iface
) );
70 if (IsEqualGUID( iid
, &IID_IAsyncInfo
))
72 IInspectable_AddRef( (*out
= &impl
->IAsyncInfo_iface
) );
76 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid
) );
81 static ULONG WINAPI
async_impl_AddRef( IWineAsyncInfoImpl
*iface
)
83 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
84 ULONG ref
= InterlockedIncrement( &impl
->ref
);
85 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
89 static ULONG WINAPI
async_impl_Release( IWineAsyncInfoImpl
*iface
)
91 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
92 ULONG ref
= InterlockedDecrement( &impl
->ref
);
93 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
97 if (impl
->handler
&& impl
->handler
!= HANDLER_NOT_SET
) IWineAsyncOperationCompletedHandler_Release( impl
->handler
);
98 IAsyncInfo_Close( &impl
->IAsyncInfo_iface
);
99 if (impl
->param
) IUnknown_Release( impl
->param
);
100 if (impl
->invoker
) IUnknown_Release( impl
->invoker
);
101 impl
->cs
.DebugInfo
->Spare
[0] = 0;
102 DeleteCriticalSection( &impl
->cs
);
109 static HRESULT WINAPI
async_impl_put_Completed( IWineAsyncInfoImpl
*iface
, IWineAsyncOperationCompletedHandler
*handler
)
111 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
114 TRACE( "iface %p, handler %p.\n", iface
, handler
);
116 EnterCriticalSection( &impl
->cs
);
117 if (impl
->status
== Closed
) hr
= E_ILLEGAL_METHOD_CALL
;
118 else if (impl
->handler
!= HANDLER_NOT_SET
) hr
= E_ILLEGAL_DELEGATE_ASSIGNMENT
;
119 else if ((impl
->handler
= handler
))
121 IWineAsyncOperationCompletedHandler_AddRef( impl
->handler
);
123 if (impl
->status
> Started
)
125 IInspectable
*operation
= impl
->IInspectable_outer
;
126 AsyncStatus status
= impl
->status
;
127 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
128 LeaveCriticalSection( &impl
->cs
);
130 IWineAsyncOperationCompletedHandler_Invoke( handler
, operation
, status
);
131 IWineAsyncOperationCompletedHandler_Release( handler
);
136 LeaveCriticalSection( &impl
->cs
);
141 static HRESULT WINAPI
async_impl_get_Completed( IWineAsyncInfoImpl
*iface
, IWineAsyncOperationCompletedHandler
**handler
)
143 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
146 TRACE( "iface %p, handler %p.\n", iface
, handler
);
148 EnterCriticalSection( &impl
->cs
);
149 if (impl
->status
== Closed
) hr
= E_ILLEGAL_METHOD_CALL
;
150 if (impl
->handler
== NULL
|| impl
->handler
== HANDLER_NOT_SET
) *handler
= NULL
;
151 else IWineAsyncOperationCompletedHandler_AddRef( (*handler
= impl
->handler
) );
152 LeaveCriticalSection( &impl
->cs
);
157 static HRESULT WINAPI
async_impl_get_Result( IWineAsyncInfoImpl
*iface
, PROPVARIANT
*result
)
159 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
160 HRESULT hr
= E_ILLEGAL_METHOD_CALL
;
162 TRACE( "iface %p, result %p.\n", iface
, result
);
164 EnterCriticalSection( &impl
->cs
);
165 if (impl
->status
== Completed
|| impl
->status
== Error
)
167 PropVariantCopy( result
, &impl
->result
);
170 LeaveCriticalSection( &impl
->cs
);
175 static HRESULT WINAPI
async_impl_Start( IWineAsyncInfoImpl
*iface
)
177 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
179 TRACE( "iface %p.\n", iface
);
181 /* keep the async alive in the callback */
182 IInspectable_AddRef( impl
->IInspectable_outer
);
183 SubmitThreadpoolWork( impl
->async_run_work
);
188 static const struct IWineAsyncInfoImplVtbl async_impl_vtbl
=
190 /* IUnknown methods */
191 async_impl_QueryInterface
,
194 /* IWineAsyncInfoImpl */
195 async_impl_put_Completed
,
196 async_impl_get_Completed
,
197 async_impl_get_Result
,
201 DEFINE_IINSPECTABLE_OUTER( async_info
, IAsyncInfo
, struct async_info
, IInspectable_outer
)
203 static HRESULT WINAPI
async_info_get_Id( IAsyncInfo
*iface
, UINT32
*id
)
205 struct async_info
*impl
= impl_from_IAsyncInfo( iface
);
208 TRACE( "iface %p, id %p.\n", iface
, id
);
210 EnterCriticalSection( &impl
->cs
);
211 if (impl
->status
== Closed
) hr
= E_ILLEGAL_METHOD_CALL
;
213 LeaveCriticalSection( &impl
->cs
);
218 static HRESULT WINAPI
async_info_get_Status( IAsyncInfo
*iface
, AsyncStatus
*status
)
220 struct async_info
*impl
= impl_from_IAsyncInfo( iface
);
223 TRACE( "iface %p, status %p.\n", iface
, status
);
225 EnterCriticalSection( &impl
->cs
);
226 if (impl
->status
== Closed
) hr
= E_ILLEGAL_METHOD_CALL
;
227 *status
= impl
->status
;
228 LeaveCriticalSection( &impl
->cs
);
233 static HRESULT WINAPI
async_info_get_ErrorCode( IAsyncInfo
*iface
, HRESULT
*error_code
)
235 struct async_info
*impl
= impl_from_IAsyncInfo( iface
);
238 TRACE( "iface %p, error_code %p.\n", iface
, error_code
);
240 EnterCriticalSection( &impl
->cs
);
241 if (impl
->status
== Closed
) *error_code
= hr
= E_ILLEGAL_METHOD_CALL
;
242 else *error_code
= impl
->hr
;
243 LeaveCriticalSection( &impl
->cs
);
248 static HRESULT WINAPI
async_info_Cancel( IAsyncInfo
*iface
)
250 struct async_info
*impl
= impl_from_IAsyncInfo( iface
);
253 TRACE( "iface %p.\n", iface
);
255 EnterCriticalSection( &impl
->cs
);
256 if (impl
->status
== Closed
) hr
= E_ILLEGAL_METHOD_CALL
;
257 else if (impl
->status
== Started
) impl
->status
= Canceled
;
258 LeaveCriticalSection( &impl
->cs
);
263 static HRESULT WINAPI
async_info_Close( IAsyncInfo
*iface
)
265 struct async_info
*impl
= impl_from_IAsyncInfo( iface
);
268 TRACE( "iface %p.\n", iface
);
270 EnterCriticalSection( &impl
->cs
);
271 if (impl
->status
== Started
)
272 hr
= E_ILLEGAL_STATE_CHANGE
;
273 else if (impl
->status
!= Closed
)
275 CloseThreadpoolWork( impl
->async_run_work
);
276 impl
->async_run_work
= NULL
;
277 impl
->status
= Closed
;
279 LeaveCriticalSection( &impl
->cs
);
284 static const struct IAsyncInfoVtbl async_info_vtbl
=
286 /* IUnknown methods */
287 async_info_QueryInterface
,
290 /* IInspectable methods */
292 async_info_GetRuntimeClassName
,
293 async_info_GetTrustLevel
,
296 async_info_get_Status
,
297 async_info_get_ErrorCode
,
302 static void CALLBACK
async_info_callback( TP_CALLBACK_INSTANCE
*instance
, void *iface
, TP_WORK
*work
)
304 struct async_info
*impl
= impl_from_IWineAsyncInfoImpl( iface
);
305 IInspectable
*operation
= impl
->IInspectable_outer
;
309 hr
= impl
->callback( impl
->invoker
, impl
->param
, &result
);
311 EnterCriticalSection( &impl
->cs
);
312 if (impl
->status
!= Closed
) impl
->status
= FAILED(hr
) ? Error
: Completed
;
313 PropVariantCopy( &impl
->result
, &result
);
316 if (impl
->handler
!= NULL
&& impl
->handler
!= HANDLER_NOT_SET
)
318 IWineAsyncOperationCompletedHandler
*handler
= impl
->handler
;
319 AsyncStatus status
= impl
->status
;
320 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
321 LeaveCriticalSection( &impl
->cs
);
323 IWineAsyncOperationCompletedHandler_Invoke( handler
, operation
, status
);
324 IWineAsyncOperationCompletedHandler_Release( handler
);
326 else LeaveCriticalSection( &impl
->cs
);
328 /* release refcount acquired in Start */
329 IInspectable_Release( operation
);
331 PropVariantClear( &result
);
334 static HRESULT
async_info_create( IUnknown
*invoker
, IUnknown
*param
, async_operation_callback callback
,
335 IInspectable
*outer
, IWineAsyncInfoImpl
**out
)
337 struct async_info
*impl
;
340 if (!(impl
= calloc( 1, sizeof(struct async_info
) ))) return E_OUTOFMEMORY
;
341 impl
->IWineAsyncInfoImpl_iface
.lpVtbl
= &async_impl_vtbl
;
342 impl
->IAsyncInfo_iface
.lpVtbl
= &async_info_vtbl
;
343 impl
->IInspectable_outer
= outer
;
346 impl
->callback
= callback
;
347 impl
->handler
= HANDLER_NOT_SET
;
348 impl
->status
= Started
;
349 if (!(impl
->async_run_work
= CreateThreadpoolWork( async_info_callback
, &impl
->IWineAsyncInfoImpl_iface
, NULL
)))
351 hr
= HRESULT_FROM_WIN32( GetLastError() );
356 if ((impl
->invoker
= invoker
)) IUnknown_AddRef( impl
->invoker
);
357 if ((impl
->param
= param
)) IUnknown_AddRef( impl
->param
);
359 InitializeCriticalSection( &impl
->cs
);
360 impl
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)( __FILE__
": async_info.cs" );
362 *out
= &impl
->IWineAsyncInfoImpl_iface
;
368 IAsyncOperation_boolean IAsyncOperation_boolean_iface
;
369 IWineAsyncInfoImpl
*IWineAsyncInfoImpl_inner
;
373 static inline struct async_bool
*impl_from_IAsyncOperation_boolean( IAsyncOperation_boolean
*iface
)
375 return CONTAINING_RECORD( iface
, struct async_bool
, IAsyncOperation_boolean_iface
);
378 static HRESULT WINAPI
async_bool_QueryInterface( IAsyncOperation_boolean
*iface
, REFIID iid
, void **out
)
380 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
382 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
384 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
385 IsEqualGUID( iid
, &IID_IInspectable
) ||
386 IsEqualGUID( iid
, &IID_IAgileObject
) ||
387 IsEqualGUID( iid
, &IID_IAsyncOperation_boolean
))
389 IInspectable_AddRef( (*out
= &impl
->IAsyncOperation_boolean_iface
) );
393 return IWineAsyncInfoImpl_QueryInterface( impl
->IWineAsyncInfoImpl_inner
, iid
, out
);
396 static ULONG WINAPI
async_bool_AddRef( IAsyncOperation_boolean
*iface
)
398 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
399 ULONG ref
= InterlockedIncrement( &impl
->ref
);
400 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
404 static ULONG WINAPI
async_bool_Release( IAsyncOperation_boolean
*iface
)
406 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
407 ULONG ref
= InterlockedDecrement( &impl
->ref
);
408 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
412 /* guard against re-entry if inner releases an outer iface */
413 InterlockedIncrement( &impl
->ref
);
414 IWineAsyncInfoImpl_Release( impl
->IWineAsyncInfoImpl_inner
);
421 static HRESULT WINAPI
async_bool_GetIids( IAsyncOperation_boolean
*iface
, ULONG
*iid_count
, IID
**iids
)
423 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
427 static HRESULT WINAPI
async_bool_GetRuntimeClassName( IAsyncOperation_boolean
*iface
, HSTRING
*class_name
)
429 return WindowsCreateString( L
"Windows.Foundation.IAsyncOperation`1<Boolean>",
430 ARRAY_SIZE(L
"Windows.Foundation.IAsyncOperation`1<Boolean>"),
434 static HRESULT WINAPI
async_bool_GetTrustLevel( IAsyncOperation_boolean
*iface
, TrustLevel
*trust_level
)
436 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
440 static HRESULT WINAPI
async_bool_put_Completed( IAsyncOperation_boolean
*iface
, IAsyncOperationCompletedHandler_boolean
*bool_handler
)
442 IWineAsyncOperationCompletedHandler
*handler
= (IWineAsyncOperationCompletedHandler
*)bool_handler
;
443 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
444 TRACE( "iface %p, handler %p.\n", iface
, handler
);
445 return IWineAsyncInfoImpl_put_Completed( impl
->IWineAsyncInfoImpl_inner
, handler
);
448 static HRESULT WINAPI
async_bool_get_Completed( IAsyncOperation_boolean
*iface
, IAsyncOperationCompletedHandler_boolean
**bool_handler
)
450 IWineAsyncOperationCompletedHandler
**handler
= (IWineAsyncOperationCompletedHandler
**)bool_handler
;
451 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
452 TRACE( "iface %p, handler %p.\n", iface
, handler
);
453 return IWineAsyncInfoImpl_get_Completed( impl
->IWineAsyncInfoImpl_inner
, handler
);
456 static HRESULT WINAPI
async_bool_GetResults( IAsyncOperation_boolean
*iface
, BOOLEAN
*results
)
458 struct async_bool
*impl
= impl_from_IAsyncOperation_boolean( iface
);
459 PROPVARIANT result
= {.vt
= VT_BOOL
};
462 TRACE( "iface %p, results %p.\n", iface
, results
);
464 hr
= IWineAsyncInfoImpl_get_Result( impl
->IWineAsyncInfoImpl_inner
, &result
);
466 *results
= result
.boolVal
;
467 PropVariantClear( &result
);
471 static const struct IAsyncOperation_booleanVtbl async_bool_vtbl
=
473 /* IUnknown methods */
474 async_bool_QueryInterface
,
477 /* IInspectable methods */
479 async_bool_GetRuntimeClassName
,
480 async_bool_GetTrustLevel
,
481 /* IAsyncOperation<boolean> */
482 async_bool_put_Completed
,
483 async_bool_get_Completed
,
484 async_bool_GetResults
,
487 HRESULT
async_operation_boolean_create( IUnknown
*invoker
, IUnknown
*param
, async_operation_callback callback
,
488 IAsyncOperation_boolean
**out
)
490 struct async_bool
*impl
;
494 if (!(impl
= calloc( 1, sizeof(*impl
) ))) return E_OUTOFMEMORY
;
495 impl
->IAsyncOperation_boolean_iface
.lpVtbl
= &async_bool_vtbl
;
498 if (FAILED(hr
= async_info_create( invoker
, param
, callback
, (IInspectable
*)&impl
->IAsyncOperation_boolean_iface
, &impl
->IWineAsyncInfoImpl_inner
)) ||
499 FAILED(hr
= IWineAsyncInfoImpl_Start( impl
->IWineAsyncInfoImpl_inner
)))
501 if (impl
->IWineAsyncInfoImpl_inner
) IWineAsyncInfoImpl_Release( impl
->IWineAsyncInfoImpl_inner
);
506 *out
= &impl
->IAsyncOperation_boolean_iface
;
507 TRACE( "created IAsyncOperation_boolean %p\n", *out
);
513 IAsyncOperation_ForceFeedbackLoadEffectResult IAsyncOperation_ForceFeedbackLoadEffectResult_iface
;
514 IWineAsyncInfoImpl
*IWineAsyncInfoImpl_inner
;
518 static inline struct async_result
*impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
)
520 return CONTAINING_RECORD( iface
, struct async_result
, IAsyncOperation_ForceFeedbackLoadEffectResult_iface
);
523 static HRESULT WINAPI
async_result_QueryInterface( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, REFIID iid
, void **out
)
525 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
527 TRACE( "iface %p, iid %s, out %p.\n", iface
, debugstr_guid( iid
), out
);
529 if (IsEqualGUID( iid
, &IID_IUnknown
) ||
530 IsEqualGUID( iid
, &IID_IInspectable
) ||
531 IsEqualGUID( iid
, &IID_IAgileObject
) ||
532 IsEqualGUID( iid
, &IID_IAsyncOperation_ForceFeedbackLoadEffectResult
))
534 IInspectable_AddRef( (*out
= &impl
->IAsyncOperation_ForceFeedbackLoadEffectResult_iface
) );
538 return IWineAsyncInfoImpl_QueryInterface( impl
->IWineAsyncInfoImpl_inner
, iid
, out
);
541 static ULONG WINAPI
async_result_AddRef( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
)
543 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
544 ULONG ref
= InterlockedIncrement( &impl
->ref
);
545 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
549 static ULONG WINAPI
async_result_Release( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
)
551 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
552 ULONG ref
= InterlockedDecrement( &impl
->ref
);
553 TRACE( "iface %p, ref %lu.\n", iface
, ref
);
557 /* guard against re-entry if inner releases an outer iface */
558 InterlockedIncrement( &impl
->ref
);
559 IWineAsyncInfoImpl_Release( impl
->IWineAsyncInfoImpl_inner
);
566 static HRESULT WINAPI
async_result_GetIids( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, ULONG
*iid_count
, IID
**iids
)
568 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
572 static HRESULT WINAPI
async_result_GetRuntimeClassName( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, HSTRING
*class_name
)
574 return WindowsCreateString( L
"Windows.Foundation.IAsyncOperation`1<Windows.Gaming.Input.ForceFeedback.ForceFeedbackLoadEffectResult>",
575 ARRAY_SIZE(L
"Windows.Foundation.IAsyncOperation`1<Windows.Gaming.Input.ForceFeedback.ForceFeedbackLoadEffectResult>"),
579 static HRESULT WINAPI
async_result_GetTrustLevel( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, TrustLevel
*trust_level
)
581 FIXME( "iface %p, trust_level %p stub!\n", iface
, trust_level
);
585 static HRESULT WINAPI
async_result_put_Completed( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult
*handler
)
587 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
588 TRACE( "iface %p, handler %p.\n", iface
, handler
);
589 return IWineAsyncInfoImpl_put_Completed( impl
->IWineAsyncInfoImpl_inner
, (IWineAsyncOperationCompletedHandler
*)handler
);
592 static HRESULT WINAPI
async_result_get_Completed( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, IAsyncOperationCompletedHandler_ForceFeedbackLoadEffectResult
**handler
)
594 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
595 TRACE( "iface %p, handler %p.\n", iface
, handler
);
596 return IWineAsyncInfoImpl_get_Completed( impl
->IWineAsyncInfoImpl_inner
, (IWineAsyncOperationCompletedHandler
**)handler
);
599 static HRESULT WINAPI
async_result_GetResults( IAsyncOperation_ForceFeedbackLoadEffectResult
*iface
, ForceFeedbackLoadEffectResult
*results
)
601 struct async_result
*impl
= impl_from_IAsyncOperation_ForceFeedbackLoadEffectResult( iface
);
602 PROPVARIANT result
= {.vt
= VT_UI4
};
605 TRACE( "iface %p, results %p.\n", iface
, results
);
607 hr
= IWineAsyncInfoImpl_get_Result( impl
->IWineAsyncInfoImpl_inner
, &result
);
609 *results
= result
.ulVal
;
610 PropVariantClear( &result
);
614 static const struct IAsyncOperation_ForceFeedbackLoadEffectResultVtbl async_result_vtbl
=
616 /* IUnknown methods */
617 async_result_QueryInterface
,
619 async_result_Release
,
620 /* IInspectable methods */
621 async_result_GetIids
,
622 async_result_GetRuntimeClassName
,
623 async_result_GetTrustLevel
,
624 /* IAsyncOperation<ForceFeedbackLoadEffectResult> */
625 async_result_put_Completed
,
626 async_result_get_Completed
,
627 async_result_GetResults
,
630 HRESULT
async_operation_effect_result_create( IUnknown
*invoker
, IUnknown
*param
, async_operation_callback callback
,
631 IAsyncOperation_ForceFeedbackLoadEffectResult
**out
)
633 struct async_result
*impl
;
637 if (!(impl
= calloc( 1, sizeof(*impl
) ))) return E_OUTOFMEMORY
;
638 impl
->IAsyncOperation_ForceFeedbackLoadEffectResult_iface
.lpVtbl
= &async_result_vtbl
;
641 if (FAILED(hr
= async_info_create( invoker
, param
, callback
, (IInspectable
*)&impl
->IAsyncOperation_ForceFeedbackLoadEffectResult_iface
, &impl
->IWineAsyncInfoImpl_inner
)) ||
642 FAILED(hr
= IWineAsyncInfoImpl_Start( impl
->IWineAsyncInfoImpl_inner
)))
644 if (impl
->IWineAsyncInfoImpl_inner
) IWineAsyncInfoImpl_Release( impl
->IWineAsyncInfoImpl_inner
);
649 *out
= &impl
->IAsyncOperation_ForceFeedbackLoadEffectResult_iface
;
650 TRACE( "created IAsyncOperation_ForceFeedbackLoadEffectResult %p\n", *out
);