1 /* WinRT Windows.Media.Speech implementation
3 * Copyright 2022 Bernhard Kölbl 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
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(speech
);
27 #define HANDLER_NOT_SET ((void *)~(ULONG_PTR)0)
37 IAsyncAction IAsyncAction_iface
;
38 IAsyncInfo IAsyncInfo_iface
;
41 IAsyncActionCompletedHandler
*handler
;
43 async_action_callback callback
;
44 TP_WORK
*async_run_work
;
45 IInspectable
*invoker
;
52 static inline struct async_void
*impl_from_IAsyncAction( IAsyncAction
*iface
)
54 return CONTAINING_RECORD(iface
, struct async_void
, IAsyncAction_iface
);
57 HRESULT WINAPI
async_void_QueryInterface( IAsyncAction
*iface
, REFIID iid
, void **out
)
59 struct async_void
*impl
= impl_from_IAsyncAction(iface
);
61 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
63 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
64 IsEqualGUID(iid
, &IID_IInspectable
) ||
65 IsEqualGUID(iid
, &IID_IAgileObject
) ||
66 IsEqualGUID(iid
, &IID_IAsyncAction
))
68 IInspectable_AddRef((*out
= &impl
->IAsyncAction_iface
));
72 if (IsEqualGUID(iid
, &IID_IAsyncInfo
))
74 IInspectable_AddRef((*out
= &impl
->IAsyncInfo_iface
));
78 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
83 ULONG WINAPI
async_void_AddRef( IAsyncAction
*iface
)
85 struct async_void
*impl
= impl_from_IAsyncAction(iface
);
86 ULONG ref
= InterlockedIncrement(&impl
->ref
);
87 TRACE("iface %p, ref %lu.\n", iface
, ref
);
91 ULONG WINAPI
async_void_Release( IAsyncAction
*iface
)
93 struct async_void
*impl
= impl_from_IAsyncAction(iface
);
94 ULONG ref
= InterlockedDecrement(&impl
->ref
);
95 TRACE("iface %p, ref %lu.\n", iface
, ref
);
99 IAsyncInfo_Close(&impl
->IAsyncInfo_iface
);
102 IInspectable_Release(impl
->invoker
);
103 if (impl
->handler
&& impl
->handler
!= HANDLER_NOT_SET
)
104 IAsyncActionCompletedHandler_Release(impl
->handler
);
106 impl
->cs
.DebugInfo
->Spare
[0] = 0;
107 DeleteCriticalSection(&impl
->cs
);
114 HRESULT WINAPI
async_void_GetIids( IAsyncAction
*iface
, ULONG
*iid_count
, IID
**iids
)
116 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
120 HRESULT WINAPI
async_void_GetRuntimeClassName( IAsyncAction
*iface
, HSTRING
*class_name
)
122 FIXME("iface %p, class_name %p stub!\n", iface
, class_name
);
126 HRESULT WINAPI
async_void_GetTrustLevel( IAsyncAction
*iface
, TrustLevel
*trust_level
)
128 FIXME("iface %p, trust_level %p stub!\n", iface
, trust_level
);
132 HRESULT WINAPI
async_void_put_Completed( IAsyncAction
*iface
, IAsyncActionCompletedHandler
*handler
)
134 struct async_void
*impl
= impl_from_IAsyncAction(iface
);
137 TRACE("iface %p, handler %p.\n", iface
, handler
);
139 EnterCriticalSection(&impl
->cs
);
140 if (impl
->status
== Closed
)
141 hr
= E_ILLEGAL_METHOD_CALL
;
142 else if (impl
->handler
!= HANDLER_NOT_SET
)
143 hr
= E_ILLEGAL_DELEGATE_ASSIGNMENT
;
145 impl->handler can only be set once with async_void_put_Completed,
146 so by default we set a non HANDLER_NOT_SET value, in this case handler.
148 else if ((impl
->handler
= handler
))
150 IAsyncActionCompletedHandler_AddRef(impl
->handler
);
152 if (impl
->status
> Started
)
154 IAsyncAction
*action
= &impl
->IAsyncAction_iface
;
155 AsyncStatus status
= impl
->status
;
156 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
157 LeaveCriticalSection(&impl
->cs
);
159 IAsyncActionCompletedHandler_Invoke(handler
, action
, status
);
160 IAsyncActionCompletedHandler_Release(handler
);
165 LeaveCriticalSection(&impl
->cs
);
170 HRESULT WINAPI
async_void_get_Completed( IAsyncAction
*iface
, IAsyncActionCompletedHandler
**handler
)
172 struct async_void
*impl
= impl_from_IAsyncAction(iface
);
175 FIXME("iface %p, handler %p semi stub!\n", iface
, handler
);
177 EnterCriticalSection(&impl
->cs
);
178 if (impl
->status
== Closed
)
179 hr
= E_ILLEGAL_METHOD_CALL
;
180 *handler
= (impl
->handler
!= HANDLER_NOT_SET
) ? impl
->handler
: NULL
;
181 LeaveCriticalSection(&impl
->cs
);
186 HRESULT WINAPI
async_void_GetResults( IAsyncAction
*iface
)
188 /* According to the docs, this function doesn't return anything, so it's left empty. */
189 TRACE("iface %p.\n", iface
);
193 static const struct IAsyncActionVtbl async_void_vtbl
=
195 /* IUnknown methods */
196 async_void_QueryInterface
,
199 /* IInspectable methods */
201 async_void_GetRuntimeClassName
,
202 async_void_GetTrustLevel
,
203 /* IAsyncAction methods */
204 async_void_put_Completed
,
205 async_void_get_Completed
,
206 async_void_GetResults
211 * IAsyncInfo for IAsyncAction
215 DEFINE_IINSPECTABLE_(async_void_info
, IAsyncInfo
, struct async_void
, impl_from_async_void_IAsyncInfo
, IAsyncInfo_iface
, &impl
->IAsyncAction_iface
)
217 static HRESULT WINAPI
async_void_info_get_Id( IAsyncInfo
*iface
, UINT32
*id
)
219 FIXME("iface %p, id %p stub!\n", iface
, id
);
223 static HRESULT WINAPI
async_void_info_get_Status( IAsyncInfo
*iface
, AsyncStatus
*status
)
225 struct async_void
*impl
= impl_from_async_void_IAsyncInfo(iface
);
228 TRACE("iface %p, status %p.\n", iface
, status
);
230 EnterCriticalSection(&impl
->cs
);
231 if (impl
->status
== Closed
)
232 hr
= E_ILLEGAL_METHOD_CALL
;
233 *status
= impl
->status
;
234 LeaveCriticalSection(&impl
->cs
);
239 static HRESULT WINAPI
async_void_info_get_ErrorCode( IAsyncInfo
*iface
, HRESULT
*error_code
)
241 struct async_void
*impl
= impl_from_async_void_IAsyncInfo(iface
);
244 TRACE("iface %p, error_code %p.\n", iface
, error_code
);
246 EnterCriticalSection(&impl
->cs
);
247 if (impl
->status
== Closed
)
248 *error_code
= hr
= E_ILLEGAL_METHOD_CALL
;
250 *error_code
= impl
->hr
;
251 LeaveCriticalSection(&impl
->cs
);
256 static HRESULT WINAPI
async_void_info_Cancel( IAsyncInfo
*iface
)
258 struct async_void
*impl
= impl_from_async_void_IAsyncInfo(iface
);
261 TRACE("iface %p.\n", iface
);
263 EnterCriticalSection(&impl
->cs
);
264 if (impl
->status
== Closed
)
265 hr
= E_ILLEGAL_METHOD_CALL
;
266 else if (impl
->status
== Started
)
267 impl
->status
= Canceled
;
268 LeaveCriticalSection(&impl
->cs
);
273 static HRESULT WINAPI
async_void_info_Close( IAsyncInfo
*iface
)
275 struct async_void
*impl
= impl_from_async_void_IAsyncInfo(iface
);
278 TRACE("iface %p.\n", iface
);
280 EnterCriticalSection(&impl
->cs
);
281 if (impl
->status
== Started
)
282 hr
= E_ILLEGAL_STATE_CHANGE
;
283 else if (impl
->status
!= Closed
)
285 CloseThreadpoolWork(impl
->async_run_work
);
286 impl
->async_run_work
= NULL
;
287 impl
->status
= Closed
;
289 LeaveCriticalSection(&impl
->cs
);
294 static const struct IAsyncInfoVtbl async_void_info_vtbl
=
296 /* IUnknown methods */
297 async_void_info_QueryInterface
,
298 async_void_info_AddRef
,
299 async_void_info_Release
,
300 /* IInspectable methods */
301 async_void_info_GetIids
,
302 async_void_info_GetRuntimeClassName
,
303 async_void_info_GetTrustLevel
,
305 async_void_info_get_Id
,
306 async_void_info_get_Status
,
307 async_void_info_get_ErrorCode
,
308 async_void_info_Cancel
,
309 async_void_info_Close
312 static void CALLBACK
async_void_run_cb(TP_CALLBACK_INSTANCE
*instance
, void *data
, TP_WORK
*work
)
314 IAsyncAction
*action
= data
;
315 struct async_void
*impl
= impl_from_IAsyncAction(action
);
318 hr
= impl
->callback(impl
->invoker
);
320 EnterCriticalSection(&impl
->cs
);
321 if (impl
->status
< Closed
)
322 impl
->status
= FAILED(hr
) ? Error
: Completed
;
326 if (impl
->handler
!= NULL
&& impl
->handler
!= HANDLER_NOT_SET
)
328 IAsyncActionCompletedHandler
*handler
= impl
->handler
;
329 AsyncStatus status
= impl
->status
;
330 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
331 LeaveCriticalSection(&impl
->cs
);
333 IAsyncActionCompletedHandler_Invoke(handler
, action
, status
);
334 IAsyncActionCompletedHandler_Release(handler
);
336 else LeaveCriticalSection(&impl
->cs
);
338 IAsyncAction_Release(action
);
341 HRESULT
async_action_create( IInspectable
*invoker
, async_action_callback callback
, IAsyncAction
**out
)
343 struct async_void
*impl
;
345 TRACE("invoker %p, callback %p, out %p.\n", invoker
, callback
, out
);
347 if (!(impl
= calloc(1, sizeof(*impl
))))
350 return E_OUTOFMEMORY
;
353 impl
->IAsyncAction_iface
.lpVtbl
= &async_void_vtbl
;
354 impl
->IAsyncInfo_iface
.lpVtbl
= &async_void_info_vtbl
;
357 impl
->handler
= HANDLER_NOT_SET
;
358 impl
->callback
= callback
;
359 impl
->status
= Started
;
361 if (!(impl
->async_run_work
= CreateThreadpoolWork(async_void_run_cb
, &impl
->IAsyncAction_iface
, NULL
)))
364 return HRESULT_FROM_WIN32(GetLastError());
367 if (invoker
) IInspectable_AddRef((impl
->invoker
= invoker
));
369 InitializeCriticalSectionEx(&impl
->cs
, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
);
370 impl
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": async_action.cs");
372 /* AddRef to keep the obj alive in the callback. */
373 IAsyncAction_AddRef(&impl
->IAsyncAction_iface
);
374 SubmitThreadpoolWork(impl
->async_run_work
);
376 *out
= &impl
->IAsyncAction_iface
;
377 TRACE("created %p\n", *out
);
383 * IAsyncOperation<IInspectable*>
387 struct async_inspectable
389 IAsyncOperation_IInspectable IAsyncOperation_IInspectable_iface
;
390 IAsyncInfo IAsyncInfo_iface
;
394 IAsyncOperationCompletedHandler_IInspectable
*handler
;
395 IInspectable
*result
;
397 async_operation_inspectable_callback callback
;
398 TP_WORK
*async_run_work
;
399 IInspectable
*invoker
;
406 static inline struct async_inspectable
*impl_from_IAsyncOperation_IInspectable(IAsyncOperation_IInspectable
*iface
)
408 return CONTAINING_RECORD(iface
, struct async_inspectable
, IAsyncOperation_IInspectable_iface
);
411 static HRESULT WINAPI
async_inspectable_QueryInterface( IAsyncOperation_IInspectable
*iface
, REFIID iid
, void **out
)
413 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
415 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
417 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
418 IsEqualGUID(iid
, &IID_IInspectable
) ||
419 IsEqualGUID(iid
, &IID_IAgileObject
) ||
420 IsEqualGUID(iid
, impl
->iid
))
422 IInspectable_AddRef((*out
= &impl
->IAsyncOperation_IInspectable_iface
));
426 if (IsEqualGUID(iid
, &IID_IAsyncInfo
))
428 IInspectable_AddRef((*out
= &impl
->IAsyncInfo_iface
));
432 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
434 return E_NOINTERFACE
;
437 static ULONG WINAPI
async_inspectable_AddRef( IAsyncOperation_IInspectable
*iface
)
439 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
440 ULONG ref
= InterlockedIncrement(&impl
->ref
);
441 TRACE("iface %p, ref %lu.\n", iface
, ref
);
445 static ULONG WINAPI
async_inspectable_Release( IAsyncOperation_IInspectable
*iface
)
447 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
449 ULONG ref
= InterlockedDecrement(&impl
->ref
);
450 TRACE("iface %p, ref %lu.\n", iface
, ref
);
454 IAsyncInfo_Close(&impl
->IAsyncInfo_iface
);
457 IInspectable_Release(impl
->invoker
);
458 if (impl
->handler
&& impl
->handler
!= HANDLER_NOT_SET
)
459 IAsyncOperationCompletedHandler_IInspectable_Release(impl
->handler
);
461 IInspectable_Release(impl
->result
);
463 impl
->cs
.DebugInfo
->Spare
[0] = 0;
464 DeleteCriticalSection(&impl
->cs
);
471 static HRESULT WINAPI
async_inspectable_GetIids( IAsyncOperation_IInspectable
*iface
, ULONG
*iid_count
, IID
**iids
)
473 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
477 static HRESULT WINAPI
async_inspectable_GetRuntimeClassName( IAsyncOperation_IInspectable
*iface
, HSTRING
*class_name
)
479 FIXME("iface %p, class_name %p stub!\n", iface
, class_name
);
483 static HRESULT WINAPI
async_inspectable_GetTrustLevel( IAsyncOperation_IInspectable
*iface
, TrustLevel
*trust_level
)
485 FIXME("iface %p, trust_level %p stub!\n", iface
, trust_level
);
489 static HRESULT WINAPI
async_inspectable_put_Completed( IAsyncOperation_IInspectable
*iface
,
490 IAsyncOperationCompletedHandler_IInspectable
*handler
)
492 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
495 TRACE("iface %p, handler %p.\n", iface
, handler
);
497 EnterCriticalSection(&impl
->cs
);
498 if (impl
->status
== Closed
)
499 hr
= E_ILLEGAL_METHOD_CALL
;
500 else if (impl
->handler
!= HANDLER_NOT_SET
)
501 hr
= E_ILLEGAL_DELEGATE_ASSIGNMENT
;
503 impl->handler can only be set once with async_inspectable_put_Completed,
504 so by default we set a non HANDLER_NOT_SET value, in this case handler.
506 else if ((impl
->handler
= handler
))
508 IAsyncOperationCompletedHandler_IInspectable_AddRef(impl
->handler
);
510 if (impl
->status
> Started
)
512 IAsyncOperation_IInspectable
*operation
= &impl
->IAsyncOperation_IInspectable_iface
;
513 AsyncStatus status
= impl
->status
;
514 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
515 LeaveCriticalSection(&impl
->cs
);
517 IAsyncOperationCompletedHandler_IInspectable_Invoke(handler
, operation
, status
);
518 IAsyncOperationCompletedHandler_IInspectable_Release(handler
);
523 LeaveCriticalSection(&impl
->cs
);
528 static HRESULT WINAPI
async_inspectable_get_Completed( IAsyncOperation_IInspectable
*iface
,
529 IAsyncOperationCompletedHandler_IInspectable
**handler
)
531 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
534 FIXME("iface %p, handler %p semi stub!\n", iface
, handler
);
536 EnterCriticalSection(&impl
->cs
);
537 if (impl
->status
== Closed
)
538 hr
= E_ILLEGAL_METHOD_CALL
;
539 *handler
= (impl
->handler
!= HANDLER_NOT_SET
) ? impl
->handler
: NULL
;
540 LeaveCriticalSection(&impl
->cs
);
545 static HRESULT WINAPI
async_inspectable_GetResults( IAsyncOperation_IInspectable
*iface
, IInspectable
**results
)
547 /* NOTE: Despite the name, this function only returns one result! */
548 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(iface
);
551 TRACE("iface %p, results %p.\n", iface
, results
);
553 EnterCriticalSection(&impl
->cs
);
554 if (impl
->status
!= Completed
&& impl
->status
!= Error
)
555 hr
= E_ILLEGAL_METHOD_CALL
;
556 else if (!impl
->result
)
560 *results
= impl
->result
;
561 impl
->result
= NULL
; /* NOTE: AsyncOperation gives up it's reference to result here! */
564 LeaveCriticalSection(&impl
->cs
);
569 static const struct IAsyncOperation_IInspectableVtbl async_inspectable_vtbl
=
571 /* IUnknown methods */
572 async_inspectable_QueryInterface
,
573 async_inspectable_AddRef
,
574 async_inspectable_Release
,
575 /* IInspectable methods */
576 async_inspectable_GetIids
,
577 async_inspectable_GetRuntimeClassName
,
578 async_inspectable_GetTrustLevel
,
579 /* IAsyncOperation<IInspectable*> */
580 async_inspectable_put_Completed
,
581 async_inspectable_get_Completed
,
582 async_inspectable_GetResults
587 * IAsyncInfo for IAsyncOperation<IInspectable*>
591 DEFINE_IINSPECTABLE_(async_inspectable_info
, IAsyncInfo
, struct async_inspectable
,
592 async_inspectable_impl_from_IAsyncInfo
, IAsyncInfo_iface
, &impl
->IAsyncOperation_IInspectable_iface
)
594 static HRESULT WINAPI
async_inspectable_info_get_Id( IAsyncInfo
*iface
, UINT32
*id
)
596 FIXME("iface %p, id %p stub!\n", iface
, id
);
600 static HRESULT WINAPI
async_inspectable_info_get_Status( IAsyncInfo
*iface
, AsyncStatus
*status
)
602 struct async_inspectable
*impl
= async_inspectable_impl_from_IAsyncInfo(iface
);
605 TRACE("iface %p, status %p.\n", iface
, status
);
607 EnterCriticalSection(&impl
->cs
);
608 if (impl
->status
== Closed
)
609 hr
= E_ILLEGAL_METHOD_CALL
;
610 *status
= impl
->status
;
611 LeaveCriticalSection(&impl
->cs
);
616 static HRESULT WINAPI
async_inspectable_info_get_ErrorCode( IAsyncInfo
*iface
, HRESULT
*error_code
)
618 struct async_inspectable
*impl
= async_inspectable_impl_from_IAsyncInfo(iface
);
621 TRACE("iface %p, error_code %p.\n", iface
, error_code
);
623 EnterCriticalSection(&impl
->cs
);
624 if (impl
->status
== Closed
)
625 *error_code
= hr
= E_ILLEGAL_METHOD_CALL
;
627 *error_code
= impl
->hr
;
628 LeaveCriticalSection(&impl
->cs
);
633 static HRESULT WINAPI
async_inspectable_info_Cancel( IAsyncInfo
*iface
)
635 struct async_inspectable
*impl
= async_inspectable_impl_from_IAsyncInfo(iface
);
638 TRACE("iface %p.\n", iface
);
640 EnterCriticalSection(&impl
->cs
);
641 if (impl
->status
== Closed
)
642 hr
= E_ILLEGAL_METHOD_CALL
;
643 else if (impl
->status
== Started
)
644 impl
->status
= Canceled
;
645 LeaveCriticalSection(&impl
->cs
);
650 static HRESULT WINAPI
async_inspectable_info_Close( IAsyncInfo
*iface
)
652 struct async_inspectable
*impl
= async_inspectable_impl_from_IAsyncInfo(iface
);
655 TRACE("iface %p.\n", iface
);
657 EnterCriticalSection(&impl
->cs
);
658 if (impl
->status
== Started
)
659 hr
= E_ILLEGAL_STATE_CHANGE
;
660 else if (impl
->status
!= Closed
)
662 CloseThreadpoolWork(impl
->async_run_work
);
663 impl
->async_run_work
= NULL
;
664 impl
->status
= Closed
;
666 LeaveCriticalSection(&impl
->cs
);
671 static const struct IAsyncInfoVtbl async_inspectable_info_vtbl
=
673 /* IUnknown methods */
674 async_inspectable_info_QueryInterface
,
675 async_inspectable_info_AddRef
,
676 async_inspectable_info_Release
,
677 /* IInspectable methods */
678 async_inspectable_info_GetIids
,
679 async_inspectable_info_GetRuntimeClassName
,
680 async_inspectable_info_GetTrustLevel
,
682 async_inspectable_info_get_Id
,
683 async_inspectable_info_get_Status
,
684 async_inspectable_info_get_ErrorCode
,
685 async_inspectable_info_Cancel
,
686 async_inspectable_info_Close
689 static void CALLBACK
async_inspectable_run_cb(TP_CALLBACK_INSTANCE
*instance
, void *data
, TP_WORK
*work
)
691 IAsyncOperation_IInspectable
*operation
= data
;
692 IInspectable
*result
= NULL
;
693 struct async_inspectable
*impl
= impl_from_IAsyncOperation_IInspectable(operation
);
696 hr
= impl
->callback(impl
->invoker
, &result
);
698 EnterCriticalSection(&impl
->cs
);
699 if (impl
->status
< Closed
)
700 impl
->status
= FAILED(hr
) ? Error
: Completed
;
702 impl
->result
= result
;
705 if (impl
->handler
!= NULL
&& impl
->handler
!= HANDLER_NOT_SET
)
707 IAsyncOperationCompletedHandler_IInspectable
*handler
= impl
->handler
;
708 AsyncStatus status
= impl
->status
;
709 impl
->handler
= NULL
; /* Prevent concurrent invoke. */
710 LeaveCriticalSection(&impl
->cs
);
712 IAsyncOperationCompletedHandler_IInspectable_Invoke(handler
, operation
, status
);
713 IAsyncOperationCompletedHandler_IInspectable_Release(handler
);
715 else LeaveCriticalSection(&impl
->cs
);
717 IAsyncOperation_IInspectable_Release(operation
);
720 HRESULT
async_operation_inspectable_create( const GUID
*iid
,
721 IInspectable
*invoker
,
722 async_operation_inspectable_callback callback
,
723 IAsyncOperation_IInspectable
**out
)
725 struct async_inspectable
*impl
;
727 TRACE("iid %s, invoker %p, callback %p, out %p.\n", debugstr_guid(iid
), invoker
, callback
, out
);
730 if (!(impl
= calloc(1, sizeof(*impl
)))) return E_OUTOFMEMORY
;
731 impl
->IAsyncOperation_IInspectable_iface
.lpVtbl
= &async_inspectable_vtbl
;
732 impl
->IAsyncInfo_iface
.lpVtbl
= &async_inspectable_info_vtbl
;
736 impl
->handler
= HANDLER_NOT_SET
;
737 impl
->callback
= callback
;
738 impl
->status
= Started
;
740 if (!(impl
->async_run_work
= CreateThreadpoolWork(async_inspectable_run_cb
, &impl
->IAsyncOperation_IInspectable_iface
, NULL
)))
743 return HRESULT_FROM_WIN32(GetLastError());
746 if (invoker
) IInspectable_AddRef((impl
->invoker
= invoker
));
748 InitializeCriticalSectionEx(&impl
->cs
, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO
);
749 impl
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": async_operation.cs");
751 /* AddRef to keep the obj alive in the callback. */
752 IAsyncOperation_IInspectable_AddRef(&impl
->IAsyncOperation_IInspectable_iface
);
753 SubmitThreadpoolWork(impl
->async_run_work
);
755 *out
= &impl
->IAsyncOperation_IInspectable_iface
;
756 TRACE("created %p\n", *out
);