windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / threadpoolwinrt / main.c
blobf58c381cbbc223a357b8e6716e03e9872947963f
1 /*
2 * Copyright 2022 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winstring.h"
26 #include "wine/debug.h"
27 #include "objbase.h"
29 #include "initguid.h"
30 #include "activation.h"
32 #define WIDL_using_Windows_Foundation
33 #define WIDL_using_Windows_Foundation_Collections
34 #include "windows.foundation.h"
35 #define WIDL_using_Windows_System_Threading
36 #include "windows.system.threading.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(threadpool);
40 struct threadpool_factory
42 IActivationFactory IActivationFactory_iface;
43 IThreadPoolStatics IThreadPoolStatics_iface;
44 LONG refcount;
47 struct async_action
49 IAsyncAction IAsyncAction_iface;
50 IAsyncInfo IAsyncInfo_iface;
51 LONG refcount;
54 static inline struct threadpool_factory *impl_from_IActivationFactory(IActivationFactory *iface)
56 return CONTAINING_RECORD(iface, struct threadpool_factory, IActivationFactory_iface);
59 static inline struct threadpool_factory *impl_from_IThreadPoolStatics(IThreadPoolStatics *iface)
61 return CONTAINING_RECORD(iface, struct threadpool_factory, IThreadPoolStatics_iface);
64 static inline struct async_action *impl_from_IAsyncAction(IAsyncAction *iface)
66 return CONTAINING_RECORD(iface, struct async_action, IAsyncAction_iface);
69 static inline struct async_action *impl_from_IAsyncInfo(IAsyncInfo *iface)
71 return CONTAINING_RECORD(iface, struct async_action, IAsyncInfo_iface);
74 static HRESULT STDMETHODCALLTYPE async_action_QueryInterface(IAsyncAction *iface, REFIID iid, void **out)
76 struct async_action *action = impl_from_IAsyncAction(iface);
78 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
80 if (IsEqualIID(iid, &IID_IAsyncAction)
81 || IsEqualIID(iid, &IID_IInspectable)
82 || IsEqualIID(iid, &IID_IUnknown))
84 *out = iface;
86 else if (IsEqualIID(iid, &IID_IAsyncInfo))
88 *out = &action->IAsyncInfo_iface;
90 else
92 *out = NULL;
93 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
96 IUnknown_AddRef((IUnknown *)*out);
97 return S_OK;
100 static ULONG STDMETHODCALLTYPE async_action_AddRef(IAsyncAction *iface)
102 struct async_action *action = impl_from_IAsyncAction(iface);
103 ULONG refcount = InterlockedIncrement(&action->refcount);
105 TRACE("iface %p, refcount %lu.\n", iface, refcount);
107 return refcount;
110 static ULONG STDMETHODCALLTYPE async_action_Release(IAsyncAction *iface)
112 struct async_action *action = impl_from_IAsyncAction(iface);
113 ULONG refcount = InterlockedDecrement(&action->refcount);
115 TRACE("iface %p, refcount %lu.\n", iface, refcount);
117 if (!refcount)
118 free(action);
120 return refcount;
123 static HRESULT STDMETHODCALLTYPE async_action_GetIids(
124 IAsyncAction *iface, ULONG *iid_count, IID **iids)
126 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
128 return E_NOTIMPL;
131 static HRESULT STDMETHODCALLTYPE async_action_GetRuntimeClassName(
132 IAsyncAction *iface, HSTRING *class_name)
134 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
136 return E_NOTIMPL;
139 static HRESULT STDMETHODCALLTYPE async_action_GetTrustLevel(
140 IAsyncAction *iface, TrustLevel *trust_level)
142 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
144 return E_NOTIMPL;
147 static HRESULT STDMETHODCALLTYPE async_action_put_Completed(IAsyncAction *iface, IAsyncActionCompletedHandler *handler)
149 FIXME("iface %p, handler %p stub!\n", iface, handler);
151 return E_NOTIMPL;
154 static HRESULT STDMETHODCALLTYPE async_action_get_Completed(IAsyncAction *iface, IAsyncActionCompletedHandler **handler)
156 FIXME("iface %p, handler %p stub!\n", iface, handler);
158 return E_NOTIMPL;
161 static HRESULT STDMETHODCALLTYPE async_action_GetResults(IAsyncAction *iface)
163 FIXME("iface %p stub!\n", iface);
165 return E_NOTIMPL;
168 static const IAsyncActionVtbl async_action_vtbl =
170 async_action_QueryInterface,
171 async_action_AddRef,
172 async_action_Release,
173 async_action_GetIids,
174 async_action_GetRuntimeClassName,
175 async_action_GetTrustLevel,
176 async_action_put_Completed,
177 async_action_get_Completed,
178 async_action_GetResults,
181 static HRESULT STDMETHODCALLTYPE async_info_QueryInterface(IAsyncInfo *iface, REFIID iid, void **out)
183 struct async_action *action = impl_from_IAsyncInfo(iface);
184 return IAsyncAction_QueryInterface(&action->IAsyncAction_iface, iid, out);
187 static ULONG STDMETHODCALLTYPE async_info_AddRef(IAsyncInfo *iface)
189 struct async_action *action = impl_from_IAsyncInfo(iface);
190 return IAsyncAction_AddRef(&action->IAsyncAction_iface);
193 static ULONG STDMETHODCALLTYPE async_info_Release(IAsyncInfo *iface)
195 struct async_action *action = impl_from_IAsyncInfo(iface);
196 return IAsyncAction_Release(&action->IAsyncAction_iface);
199 static HRESULT STDMETHODCALLTYPE async_info_GetIids(IAsyncInfo *iface, ULONG *iid_count, IID **iids)
201 struct async_action *action = impl_from_IAsyncInfo(iface);
202 return IAsyncAction_GetIids(&action->IAsyncAction_iface, iid_count, iids);
205 static HRESULT STDMETHODCALLTYPE async_info_GetRuntimeClassName(IAsyncInfo *iface, HSTRING *class_name)
207 struct async_action *action = impl_from_IAsyncInfo(iface);
208 return IAsyncAction_GetRuntimeClassName(&action->IAsyncAction_iface, class_name);
211 static HRESULT STDMETHODCALLTYPE async_info_GetTrustLevel(IAsyncInfo *iface, TrustLevel *trust_level)
213 struct async_action *action = impl_from_IAsyncInfo(iface);
214 return IAsyncAction_GetTrustLevel(&action->IAsyncAction_iface, trust_level);
217 static HRESULT STDMETHODCALLTYPE async_info_get_Id(IAsyncInfo *iface, UINT32 *id)
219 FIXME("iface %p, id %p stub!\n", iface, id);
221 return E_NOTIMPL;
224 static HRESULT STDMETHODCALLTYPE async_info_get_Status(IAsyncInfo *iface, AsyncStatus *status)
226 FIXME("iface %p, status %p stub!\n", iface, status);
228 return E_NOTIMPL;
231 static HRESULT STDMETHODCALLTYPE async_info_get_ErrorCode(IAsyncInfo *iface, HRESULT *error_code)
233 FIXME("iface %p, error_code %p stub!\n", iface, error_code);
235 return E_NOTIMPL;
238 static HRESULT STDMETHODCALLTYPE async_info_Cancel(IAsyncInfo *iface)
240 FIXME("iface %p stub!\n", iface);
242 return E_NOTIMPL;
245 static HRESULT STDMETHODCALLTYPE async_info_Close(IAsyncInfo *iface)
247 FIXME("iface %p stub!\n", iface);
249 return E_NOTIMPL;
252 static const IAsyncInfoVtbl async_info_vtbl =
254 async_info_QueryInterface,
255 async_info_AddRef,
256 async_info_Release,
257 async_info_GetIids,
258 async_info_GetRuntimeClassName,
259 async_info_GetTrustLevel,
260 async_info_get_Id,
261 async_info_get_Status,
262 async_info_get_ErrorCode,
263 async_info_Cancel,
264 async_info_Close,
267 static HRESULT async_action_create(IAsyncAction **ret)
269 struct async_action *object;
271 *ret = NULL;
273 if (!(object = calloc(1, sizeof(*object))))
274 return E_OUTOFMEMORY;
276 object->IAsyncAction_iface.lpVtbl = &async_action_vtbl;
277 object->IAsyncInfo_iface.lpVtbl = &async_info_vtbl;
278 object->refcount = 1;
280 *ret = &object->IAsyncAction_iface;
282 return S_OK;
285 struct work_item
287 IWorkItemHandler *handler;
288 IAsyncAction *action;
291 static void release_work_item(struct work_item *item)
293 IWorkItemHandler_Release(item->handler);
294 IAsyncAction_Release(item->action);
295 free(item);
298 static HRESULT alloc_work_item(IWorkItemHandler *handler, struct work_item **ret)
300 struct work_item *object;
301 HRESULT hr;
303 *ret = NULL;
305 if (!(object = calloc(1, sizeof(*object))))
306 return E_OUTOFMEMORY;
308 if (FAILED(hr = async_action_create(&object->action)))
310 free(object);
311 return hr;
314 IWorkItemHandler_AddRef((object->handler = handler));
316 *ret = object;
318 return S_OK;
321 static void work_item_invoke_release(struct work_item *item)
323 IWorkItemHandler_Invoke(item->handler, item->action);
324 release_work_item(item);
327 static DWORD WINAPI sliced_thread_proc(void *arg)
329 struct work_item *item = arg;
330 work_item_invoke_release(item);
331 return 0;
334 struct thread_pool
336 INIT_ONCE init_once;
337 TP_POOL *pool;
340 static struct thread_pool pools[3];
342 static BOOL CALLBACK pool_init_once(INIT_ONCE *init_once, void *param, void **context)
344 struct thread_pool *pool = param;
346 if (!(pool->pool = CreateThreadpool(NULL))) return FALSE;
348 SetThreadpoolThreadMaximum(pool->pool, 10);
350 return TRUE;
353 static void CALLBACK pool_work_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_WORK *work)
355 struct work_item *item = context;
356 work_item_invoke_release(item);
359 static HRESULT submit_threadpool_work(struct work_item *item, WorkItemPriority priority, IAsyncAction **action)
361 struct thread_pool *pool;
362 TP_WORK *work;
364 assert(priority == WorkItemPriority_Low
365 || priority == WorkItemPriority_Normal
366 || priority == WorkItemPriority_High);
368 pool = &pools[priority + 1];
370 if (!InitOnceExecuteOnce(&pool->init_once, pool_init_once, pool, NULL))
371 return E_FAIL;
373 if (!(work = CreateThreadpoolWork(pool_work_callback, item, NULL)))
374 return E_FAIL;
376 IAsyncAction_AddRef((*action = item->action));
377 SubmitThreadpoolWork(work);
379 return S_OK;
382 static HRESULT submit_standalone_thread_work(struct work_item *item, WorkItemPriority priority, IAsyncAction **action)
384 HANDLE thread;
386 if (!(thread = CreateThread(NULL, 0, sliced_thread_proc, item, priority == WorkItemPriority_Normal ?
387 0 : CREATE_SUSPENDED, NULL)))
389 WARN("Failed to create a thread, error %ld.\n", GetLastError());
390 return HRESULT_FROM_WIN32(GetLastError());
393 IAsyncAction_AddRef((*action = item->action));
394 if (priority != WorkItemPriority_Normal)
396 SetThreadPriority(thread, priority == WorkItemPriority_High ? THREAD_PRIORITY_HIGHEST : THREAD_PRIORITY_LOWEST);
397 ResumeThread(thread);
399 CloseHandle(thread);
401 return S_OK;
404 static HRESULT run_async(IWorkItemHandler *handler, WorkItemPriority priority, WorkItemOptions options,
405 IAsyncAction **action)
407 struct work_item *item;
408 HRESULT hr;
410 *action = NULL;
412 if (!handler)
413 return E_INVALIDARG;
415 if (priority < WorkItemPriority_Low || priority > WorkItemPriority_High)
416 return E_INVALIDARG;
418 if (FAILED(hr = alloc_work_item(handler, &item)))
419 return hr;
421 if (options == WorkItemOptions_TimeSliced)
422 hr = submit_standalone_thread_work(item, priority, action);
423 else
424 hr = submit_threadpool_work(item, priority, action);
426 if (FAILED(hr))
427 release_work_item(item);
429 return hr;
432 static HRESULT STDMETHODCALLTYPE threadpool_factory_QueryInterface(
433 IActivationFactory *iface, REFIID iid, void **out)
435 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
437 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
439 if (IsEqualGUID(iid, &IID_IUnknown) ||
440 IsEqualGUID(iid, &IID_IInspectable) ||
441 IsEqualGUID(iid, &IID_IAgileObject) ||
442 IsEqualGUID(iid, &IID_IActivationFactory))
444 IUnknown_AddRef(iface);
445 *out = &factory->IActivationFactory_iface;
446 return S_OK;
449 if (IsEqualGUID(iid, &IID_IThreadPoolStatics))
451 IUnknown_AddRef(iface);
452 *out = &factory->IThreadPoolStatics_iface;
453 return S_OK;
456 FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
457 *out = NULL;
458 return E_NOINTERFACE;
461 static ULONG STDMETHODCALLTYPE threadpool_factory_AddRef(IActivationFactory *iface)
463 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
464 ULONG refcount = InterlockedIncrement(&factory->refcount);
466 TRACE("iface %p, refcount %lu.\n", iface, refcount);
468 return refcount;
471 static ULONG STDMETHODCALLTYPE threadpool_factory_Release(IActivationFactory *iface)
473 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
474 ULONG refcount = InterlockedDecrement(&factory->refcount);
476 TRACE("iface %p, refcount %lu.\n", iface, refcount);
478 return refcount;
481 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetIids(
482 IActivationFactory *iface, ULONG *iid_count, IID **iids)
484 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
485 return E_NOTIMPL;
488 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetRuntimeClassName(
489 IActivationFactory *iface, HSTRING *class_name)
491 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
492 return E_NOTIMPL;
495 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetTrustLevel(
496 IActivationFactory *iface, TrustLevel *trust_level)
498 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
499 return E_NOTIMPL;
502 static HRESULT STDMETHODCALLTYPE threadpool_factory_ActivateInstance(
503 IActivationFactory *iface, IInspectable **instance)
505 FIXME("iface %p, instance %p stub!\n", iface, instance);
506 return E_NOTIMPL;
509 static const struct IActivationFactoryVtbl threadpool_factory_vtbl =
511 threadpool_factory_QueryInterface,
512 threadpool_factory_AddRef,
513 threadpool_factory_Release,
514 /* IInspectable methods */
515 threadpool_factory_GetIids,
516 threadpool_factory_GetRuntimeClassName,
517 threadpool_factory_GetTrustLevel,
518 /* IActivationFactory methods */
519 threadpool_factory_ActivateInstance,
522 static HRESULT STDMETHODCALLTYPE threadpool_statics_QueryInterface(
523 IThreadPoolStatics *iface, REFIID iid, void **object)
525 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
526 return IActivationFactory_QueryInterface(&factory->IActivationFactory_iface, iid, object);
529 static ULONG STDMETHODCALLTYPE threadpool_statics_AddRef(IThreadPoolStatics *iface)
531 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
532 return IActivationFactory_AddRef(&factory->IActivationFactory_iface);
535 static ULONG STDMETHODCALLTYPE threadpool_statics_Release(IThreadPoolStatics *iface)
537 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
538 return IActivationFactory_Release(&factory->IActivationFactory_iface);
541 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetIids(
542 IThreadPoolStatics *iface, ULONG *iid_count, IID **iids)
544 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
545 return E_NOTIMPL;
548 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetRuntimeClassName(
549 IThreadPoolStatics *iface, HSTRING *class_name)
551 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
552 return E_NOTIMPL;
555 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetTrustLevel(
556 IThreadPoolStatics *iface, TrustLevel *trust_level)
558 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
559 return E_NOTIMPL;
562 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunAsync(
563 IThreadPoolStatics *iface, IWorkItemHandler *handler, IAsyncAction **operation)
565 TRACE("iface %p, handler %p, operation %p.\n", iface, handler, operation);
567 return run_async(handler, WorkItemPriority_Normal, WorkItemOptions_None, operation);
570 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunWithPriorityAsync(
571 IThreadPoolStatics *iface, IWorkItemHandler *handler, WorkItemPriority priority, IAsyncAction **operation)
573 TRACE("iface %p, handler %p, priority %d, operation %p.\n", iface, handler, priority, operation);
575 return run_async(handler, priority, WorkItemOptions_None, operation);
578 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunWithPriorityAndOptionsAsync(
579 IThreadPoolStatics *iface, IWorkItemHandler *handler, WorkItemPriority priority,
580 WorkItemOptions options, IAsyncAction **operation)
582 TRACE("iface %p, handler %p, priority %d, options %d, operation %p.\n", iface, handler, priority, options, operation);
584 return run_async(handler, priority, options, operation);
587 static const struct IThreadPoolStaticsVtbl threadpool_statics_vtbl =
589 threadpool_statics_QueryInterface,
590 threadpool_statics_AddRef,
591 threadpool_statics_Release,
592 /* IInspectable methods */
593 threadpool_statics_GetIids,
594 threadpool_statics_GetRuntimeClassName,
595 threadpool_statics_GetTrustLevel,
596 /* IThreadPoolStatics methods */
597 threadpool_statics_RunAsync,
598 threadpool_statics_RunWithPriorityAsync,
599 threadpool_statics_RunWithPriorityAndOptionsAsync,
602 static struct threadpool_factory threadpool_factory =
604 .IActivationFactory_iface.lpVtbl = &threadpool_factory_vtbl,
605 .IThreadPoolStatics_iface.lpVtbl = &threadpool_statics_vtbl,
606 .refcount = 1,
609 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
611 FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out);
612 return CLASS_E_CLASSNOTAVAILABLE;
615 HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory)
617 const WCHAR *name = WindowsGetStringRawBuffer(classid, NULL);
619 TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
621 *factory = NULL;
623 if (!wcscmp(name, RuntimeClass_Windows_System_Threading_ThreadPool))
625 *factory = &threadpool_factory.IActivationFactory_iface;
626 IUnknown_AddRef(*factory);
629 if (*factory) return S_OK;
630 return CLASS_E_CLASSNOTAVAILABLE;