include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / windows.security.credentials.ui.userconsentverifier / async.c
blob89edb50ce3ce0dd179e4e8a04b7e720668dd5d9d
1 /* WinRT Windows.Security.Credentials.UI 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
21 #include "private.h"
22 #include "wine/debug.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(credentials);
26 #define Closed 4
27 #define HANDLER_NOT_SET ((void *)~(ULONG_PTR)0)
29 struct async_info
31 IWineAsyncInfoImpl IWineAsyncInfoImpl_iface;
32 IAsyncInfo IAsyncInfo_iface;
33 IInspectable *IInspectable_outer;
34 LONG ref;
36 async_operation_callback callback;
37 TP_WORK *async_run_work;
38 IUnknown *invoker;
39 IUnknown *param;
41 CRITICAL_SECTION cs;
42 IWineAsyncOperationCompletedHandler *handler;
43 PROPVARIANT result;
44 AsyncStatus status;
45 HRESULT hr;
48 static inline struct async_info *impl_from_IWineAsyncInfoImpl( IWineAsyncInfoImpl *iface )
50 return CONTAINING_RECORD( iface, struct async_info, IWineAsyncInfoImpl_iface );
53 static HRESULT WINAPI async_impl_QueryInterface( IWineAsyncInfoImpl *iface, REFIID iid, void **out )
55 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
57 TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out );
59 if (IsEqualGUID( iid, &IID_IUnknown ) ||
60 IsEqualGUID( iid, &IID_IInspectable ) ||
61 IsEqualGUID( iid, &IID_IAgileObject ) ||
62 IsEqualGUID( iid, &IID_IWineAsyncInfoImpl ))
64 IInspectable_AddRef( (*out = &impl->IWineAsyncInfoImpl_iface) );
65 return S_OK;
68 if (IsEqualGUID( iid, &IID_IAsyncInfo ))
70 IInspectable_AddRef( (*out = &impl->IAsyncInfo_iface) );
71 return S_OK;
74 FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
75 *out = NULL;
76 return E_NOINTERFACE;
79 static ULONG WINAPI async_impl_AddRef( IWineAsyncInfoImpl *iface )
81 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
82 ULONG ref = InterlockedIncrement( &impl->ref );
83 TRACE( "iface %p, ref %lu.\n", iface, ref );
84 return ref;
87 static ULONG WINAPI async_impl_Release( IWineAsyncInfoImpl *iface )
89 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
90 ULONG ref = InterlockedDecrement( &impl->ref );
91 TRACE( "iface %p, ref %lu.\n", iface, ref );
93 if (!ref)
95 if (impl->handler && impl->handler != HANDLER_NOT_SET) IWineAsyncOperationCompletedHandler_Release( impl->handler );
96 IAsyncInfo_Close( &impl->IAsyncInfo_iface );
97 if (impl->param) IUnknown_Release( impl->param );
98 if (impl->invoker) IUnknown_Release( impl->invoker );
99 impl->cs.DebugInfo->Spare[0] = 0;
100 DeleteCriticalSection( &impl->cs );
101 free( impl );
104 return ref;
107 static HRESULT WINAPI async_impl_put_Completed( IWineAsyncInfoImpl *iface, IWineAsyncOperationCompletedHandler *handler )
109 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
110 HRESULT hr = S_OK;
112 TRACE( "iface %p, handler %p.\n", iface, handler );
114 EnterCriticalSection( &impl->cs );
115 if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL;
116 else if (impl->handler != HANDLER_NOT_SET) hr = E_ILLEGAL_DELEGATE_ASSIGNMENT;
117 else if ((impl->handler = handler))
119 IWineAsyncOperationCompletedHandler_AddRef( impl->handler );
121 if (impl->status > Started)
123 IInspectable *operation = impl->IInspectable_outer;
124 AsyncStatus status = impl->status;
125 impl->handler = NULL; /* Prevent concurrent invoke. */
126 LeaveCriticalSection( &impl->cs );
128 IWineAsyncOperationCompletedHandler_Invoke( handler, operation, status );
129 IWineAsyncOperationCompletedHandler_Release( handler );
131 return S_OK;
134 LeaveCriticalSection( &impl->cs );
136 return hr;
139 static HRESULT WINAPI async_impl_get_Completed( IWineAsyncInfoImpl *iface, IWineAsyncOperationCompletedHandler **handler )
141 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
142 HRESULT hr = S_OK;
144 TRACE( "iface %p, handler %p.\n", iface, handler );
146 EnterCriticalSection( &impl->cs );
147 if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL;
148 if (impl->handler == NULL || impl->handler == HANDLER_NOT_SET) *handler = NULL;
149 else IWineAsyncOperationCompletedHandler_AddRef( (*handler = impl->handler) );
150 LeaveCriticalSection( &impl->cs );
152 return hr;
155 static HRESULT WINAPI async_impl_get_Result( IWineAsyncInfoImpl *iface, PROPVARIANT *result )
157 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
158 HRESULT hr = E_ILLEGAL_METHOD_CALL;
160 TRACE( "iface %p, result %p.\n", iface, result );
162 EnterCriticalSection( &impl->cs );
163 if (impl->status == Completed || impl->status == Error)
165 PropVariantCopy( result, &impl->result );
166 hr = impl->hr;
168 LeaveCriticalSection( &impl->cs );
170 return hr;
173 static HRESULT WINAPI async_impl_Start( IWineAsyncInfoImpl *iface )
175 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
177 TRACE( "iface %p.\n", iface );
179 /* keep the async alive in the callback */
180 IInspectable_AddRef( impl->IInspectable_outer );
181 SubmitThreadpoolWork( impl->async_run_work );
183 return S_OK;
186 static const struct IWineAsyncInfoImplVtbl async_impl_vtbl =
188 /* IUnknown methods */
189 async_impl_QueryInterface,
190 async_impl_AddRef,
191 async_impl_Release,
192 /* IWineAsyncInfoImpl */
193 async_impl_put_Completed,
194 async_impl_get_Completed,
195 async_impl_get_Result,
196 async_impl_Start,
199 DEFINE_IINSPECTABLE_OUTER( async_info, IAsyncInfo, struct async_info, IInspectable_outer )
201 static HRESULT WINAPI async_info_get_Id( IAsyncInfo *iface, UINT32 *id )
203 struct async_info *impl = impl_from_IAsyncInfo( iface );
204 HRESULT hr = S_OK;
206 TRACE( "iface %p, id %p.\n", iface, id );
208 EnterCriticalSection( &impl->cs );
209 if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL;
210 *id = 1;
211 LeaveCriticalSection( &impl->cs );
213 return hr;
216 static HRESULT WINAPI async_info_get_Status( IAsyncInfo *iface, AsyncStatus *status )
218 struct async_info *impl = impl_from_IAsyncInfo( iface );
219 HRESULT hr = S_OK;
221 TRACE( "iface %p, status %p.\n", iface, status );
223 EnterCriticalSection( &impl->cs );
224 if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL;
225 *status = impl->status;
226 LeaveCriticalSection( &impl->cs );
228 return hr;
231 static HRESULT WINAPI async_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code )
233 struct async_info *impl = impl_from_IAsyncInfo( iface );
234 HRESULT hr = S_OK;
236 TRACE( "iface %p, error_code %p.\n", iface, error_code );
238 EnterCriticalSection( &impl->cs );
239 if (impl->status == Closed) *error_code = hr = E_ILLEGAL_METHOD_CALL;
240 else *error_code = impl->hr;
241 LeaveCriticalSection( &impl->cs );
243 return hr;
246 static HRESULT WINAPI async_info_Cancel( IAsyncInfo *iface )
248 struct async_info *impl = impl_from_IAsyncInfo( iface );
249 HRESULT hr = S_OK;
251 TRACE( "iface %p.\n", iface );
253 EnterCriticalSection( &impl->cs );
254 if (impl->status == Closed) hr = E_ILLEGAL_METHOD_CALL;
255 else if (impl->status == Started) impl->status = Canceled;
256 LeaveCriticalSection( &impl->cs );
258 return hr;
261 static HRESULT WINAPI async_info_Close( IAsyncInfo *iface )
263 struct async_info *impl = impl_from_IAsyncInfo( iface );
264 HRESULT hr = S_OK;
266 TRACE( "iface %p.\n", iface );
268 EnterCriticalSection( &impl->cs );
269 if (impl->status == Started)
270 hr = E_ILLEGAL_STATE_CHANGE;
271 else if (impl->status != Closed)
273 CloseThreadpoolWork( impl->async_run_work );
274 impl->async_run_work = NULL;
275 impl->status = Closed;
277 LeaveCriticalSection( &impl->cs );
279 return hr;
282 static const struct IAsyncInfoVtbl async_info_vtbl =
284 /* IUnknown methods */
285 async_info_QueryInterface,
286 async_info_AddRef,
287 async_info_Release,
288 /* IInspectable methods */
289 async_info_GetIids,
290 async_info_GetRuntimeClassName,
291 async_info_GetTrustLevel,
292 /* IAsyncInfo */
293 async_info_get_Id,
294 async_info_get_Status,
295 async_info_get_ErrorCode,
296 async_info_Cancel,
297 async_info_Close,
300 static void CALLBACK async_info_callback( TP_CALLBACK_INSTANCE *instance, void *iface, TP_WORK *work )
302 struct async_info *impl = impl_from_IWineAsyncInfoImpl( iface );
303 IInspectable *operation = impl->IInspectable_outer;
304 PROPVARIANT result;
305 HRESULT hr;
307 hr = impl->callback( impl->invoker, impl->param, &result );
309 EnterCriticalSection( &impl->cs );
310 if (impl->status != Closed) impl->status = FAILED(hr) ? Error : Completed;
311 PropVariantCopy( &impl->result, &result );
312 impl->hr = hr;
314 if (impl->handler != NULL && impl->handler != HANDLER_NOT_SET)
316 IWineAsyncOperationCompletedHandler *handler = impl->handler;
317 AsyncStatus status = impl->status;
318 impl->handler = NULL; /* Prevent concurrent invoke. */
319 LeaveCriticalSection( &impl->cs );
321 IWineAsyncOperationCompletedHandler_Invoke( handler, operation, status );
322 IWineAsyncOperationCompletedHandler_Release( handler );
324 else LeaveCriticalSection( &impl->cs );
326 /* release refcount acquired in Start */
327 IInspectable_Release( operation );
329 PropVariantClear( &result );
332 static HRESULT async_info_create( IUnknown *invoker, IUnknown *param, async_operation_callback callback,
333 IInspectable *outer, IWineAsyncInfoImpl **out )
335 struct async_info *impl;
336 HRESULT hr;
338 if (!(impl = calloc( 1, sizeof(struct async_info) ))) return E_OUTOFMEMORY;
339 impl->IWineAsyncInfoImpl_iface.lpVtbl = &async_impl_vtbl;
340 impl->IAsyncInfo_iface.lpVtbl = &async_info_vtbl;
341 impl->IInspectable_outer = outer;
342 impl->ref = 1;
344 impl->callback = callback;
345 impl->handler = HANDLER_NOT_SET;
346 impl->status = Started;
347 if (!(impl->async_run_work = CreateThreadpoolWork( async_info_callback, &impl->IWineAsyncInfoImpl_iface, NULL )))
349 hr = HRESULT_FROM_WIN32( GetLastError() );
350 free( impl );
351 return hr;
354 if ((impl->invoker = invoker)) IUnknown_AddRef( impl->invoker );
355 if ((impl->param = param)) IUnknown_AddRef( impl->param );
357 InitializeCriticalSectionEx( &impl->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO );
358 impl->cs.DebugInfo->Spare[0] = (DWORD_PTR)( __FILE__ ": async_info.cs" );
360 *out = &impl->IWineAsyncInfoImpl_iface;
361 return S_OK;
364 struct async_user_consent_verifier_availability
366 IAsyncOperation_UserConsentVerifierAvailability IAsyncOperation_UserConsentVerifierAvailability_iface;
367 IWineAsyncInfoImpl *IWineAsyncInfoImpl_inner;
368 LONG ref;
371 static inline struct async_user_consent_verifier_availability *impl_from_IAsyncOperation_UserConsentVerifierAvailability( IAsyncOperation_UserConsentVerifierAvailability *iface )
373 return CONTAINING_RECORD( iface, struct async_user_consent_verifier_availability, IAsyncOperation_UserConsentVerifierAvailability_iface );
376 static HRESULT WINAPI async_user_consent_verifier_availability_QueryInterface( IAsyncOperation_UserConsentVerifierAvailability *iface, REFIID iid, void **out )
378 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
380 TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out );
382 if (IsEqualGUID( iid, &IID_IUnknown ) ||
383 IsEqualGUID( iid, &IID_IInspectable ) ||
384 IsEqualGUID( iid, &IID_IAgileObject ) ||
385 IsEqualGUID( iid, &IID_IAsyncOperation_UserConsentVerifierAvailability ))
387 IInspectable_AddRef( (*out = &impl->IAsyncOperation_UserConsentVerifierAvailability_iface) );
388 return S_OK;
391 return IWineAsyncInfoImpl_QueryInterface( impl->IWineAsyncInfoImpl_inner, iid, out );
394 static ULONG WINAPI async_user_consent_verifier_availability_AddRef( IAsyncOperation_UserConsentVerifierAvailability *iface )
396 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
397 ULONG ref = InterlockedIncrement( &impl->ref );
398 TRACE( "iface %p, ref %lu.\n", iface, ref );
399 return ref;
402 static ULONG WINAPI async_user_consent_verifier_availability_Release( IAsyncOperation_UserConsentVerifierAvailability *iface )
404 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
405 ULONG ref = InterlockedDecrement( &impl->ref );
406 TRACE( "iface %p, ref %lu.\n", iface, ref );
408 if (!ref)
410 /* guard against re-entry if inner releases an outer iface */
411 InterlockedIncrement( &impl->ref );
412 IWineAsyncInfoImpl_Release( impl->IWineAsyncInfoImpl_inner );
413 free( impl );
416 return ref;
419 static HRESULT WINAPI async_user_consent_verifier_availability_GetIids( IAsyncOperation_UserConsentVerifierAvailability *iface, ULONG *iid_count, IID **iids )
421 FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids );
422 return E_NOTIMPL;
425 static HRESULT WINAPI async_user_consent_verifier_availability_GetRuntimeClassName( IAsyncOperation_UserConsentVerifierAvailability *iface, HSTRING *class_name )
427 return WindowsCreateString( L"Windows.Foundation.IAsyncOperation`1<Windows.Security.Credentials.UI.UserConsentVerifierAvailability>",
428 ARRAY_SIZE(L"Windows.Foundation.IAsyncOperation`1<Windows.Security.Credentials.UI.UserConsentVerifierAvailability>"),
429 class_name );
432 static HRESULT WINAPI async_user_consent_verifier_availability_GetTrustLevel( IAsyncOperation_UserConsentVerifierAvailability *iface, TrustLevel *trust_level )
434 FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level );
435 return E_NOTIMPL;
438 static HRESULT WINAPI async_user_consent_verifier_availability_put_Completed( IAsyncOperation_UserConsentVerifierAvailability *iface,
439 IAsyncOperationCompletedHandler_UserConsentVerifierAvailability *UserConsentVerifierAvailability_handler )
441 IWineAsyncOperationCompletedHandler *handler = (IWineAsyncOperationCompletedHandler *)UserConsentVerifierAvailability_handler;
442 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
443 TRACE( "iface %p, handler %p.\n", iface, handler );
444 return IWineAsyncInfoImpl_put_Completed( impl->IWineAsyncInfoImpl_inner, (IWineAsyncOperationCompletedHandler *)handler );
447 static HRESULT WINAPI async_user_consent_verifier_availability_get_Completed( IAsyncOperation_UserConsentVerifierAvailability *iface,
448 IAsyncOperationCompletedHandler_UserConsentVerifierAvailability **UserConsentVerifierAvailability_handler )
450 IWineAsyncOperationCompletedHandler **handler = (IWineAsyncOperationCompletedHandler **)UserConsentVerifierAvailability_handler;
451 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
452 TRACE( "iface %p, handler %p.\n", iface, handler );
453 return IWineAsyncInfoImpl_get_Completed( impl->IWineAsyncInfoImpl_inner, (IWineAsyncOperationCompletedHandler **)handler );
456 static HRESULT WINAPI async_user_consent_verifier_availability_GetResults( IAsyncOperation_UserConsentVerifierAvailability *iface, UserConsentVerifierAvailability *results )
458 struct async_user_consent_verifier_availability *impl = impl_from_IAsyncOperation_UserConsentVerifierAvailability( iface );
459 PROPVARIANT result = {.vt = VT_UI4};
460 HRESULT hr;
462 TRACE( "iface %p, results %p.\n", iface, results );
464 hr = IWineAsyncInfoImpl_get_Result( impl->IWineAsyncInfoImpl_inner, &result );
466 *results = result.ulVal;
467 PropVariantClear( &result );
468 return hr;
471 static const struct IAsyncOperation_UserConsentVerifierAvailabilityVtbl async_user_consent_verifier_availability_vtbl =
473 /* IUnknown methods */
474 async_user_consent_verifier_availability_QueryInterface,
475 async_user_consent_verifier_availability_AddRef,
476 async_user_consent_verifier_availability_Release,
477 /* IInspectable methods */
478 async_user_consent_verifier_availability_GetIids,
479 async_user_consent_verifier_availability_GetRuntimeClassName,
480 async_user_consent_verifier_availability_GetTrustLevel,
481 /* IAsyncOperation<UserConsentVerifierAvailability> */
482 async_user_consent_verifier_availability_put_Completed,
483 async_user_consent_verifier_availability_get_Completed,
484 async_user_consent_verifier_availability_GetResults,
487 HRESULT async_operation_user_consent_verifier_availability_create( IUnknown *invoker, IUnknown *param, async_operation_callback callback,
488 IAsyncOperation_UserConsentVerifierAvailability **out )
490 struct async_user_consent_verifier_availability *impl;
491 HRESULT hr;
493 *out = NULL;
494 if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY;
495 impl->IAsyncOperation_UserConsentVerifierAvailability_iface.lpVtbl = &async_user_consent_verifier_availability_vtbl;
496 impl->ref = 1;
498 if (FAILED(hr = async_info_create( invoker, param, callback, (IInspectable *)&impl->IAsyncOperation_UserConsentVerifierAvailability_iface, &impl->IWineAsyncInfoImpl_inner )) ||
499 FAILED(hr = IWineAsyncInfoImpl_Start( impl->IWineAsyncInfoImpl_inner )))
501 if (impl->IWineAsyncInfoImpl_inner) IWineAsyncInfoImpl_Release( impl->IWineAsyncInfoImpl_inner );
502 free( impl );
503 return hr;
506 *out = &impl->IAsyncOperation_UserConsentVerifierAvailability_iface;
507 TRACE( "created IAsyncOperation_UserConsentVerifierAvailability %p\n", *out );
508 return S_OK;