wow32: Use spec file imports.
[wine.git] / dlls / threadpoolwinrt / main.c
blobfb59a777e30e971b231ec43128c6a274ed2cd563
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 static const char *debugstr_hstring(HSTRING hstr)
42 const WCHAR *str;
43 UINT32 len;
44 if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)";
45 str = WindowsGetStringRawBuffer(hstr, &len);
46 return wine_dbgstr_wn(str, len);
49 struct threadpool_factory
51 IActivationFactory IActivationFactory_iface;
52 IThreadPoolStatics IThreadPoolStatics_iface;
53 LONG refcount;
56 struct async_action
58 IAsyncAction IAsyncAction_iface;
59 IAsyncInfo IAsyncInfo_iface;
60 LONG refcount;
63 static inline struct threadpool_factory *impl_from_IActivationFactory(IActivationFactory *iface)
65 return CONTAINING_RECORD(iface, struct threadpool_factory, IActivationFactory_iface);
68 static inline struct threadpool_factory *impl_from_IThreadPoolStatics(IThreadPoolStatics *iface)
70 return CONTAINING_RECORD(iface, struct threadpool_factory, IThreadPoolStatics_iface);
73 static inline struct async_action *impl_from_IAsyncAction(IAsyncAction *iface)
75 return CONTAINING_RECORD(iface, struct async_action, IAsyncAction_iface);
78 static inline struct async_action *impl_from_IAsyncInfo(IAsyncInfo *iface)
80 return CONTAINING_RECORD(iface, struct async_action, IAsyncInfo_iface);
83 static HRESULT STDMETHODCALLTYPE async_action_QueryInterface(IAsyncAction *iface, REFIID iid, void **out)
85 struct async_action *action = impl_from_IAsyncAction(iface);
87 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
89 if (IsEqualIID(iid, &IID_IAsyncAction)
90 || IsEqualIID(iid, &IID_IInspectable)
91 || IsEqualIID(iid, &IID_IUnknown))
93 *out = iface;
95 else if (IsEqualIID(iid, &IID_IAsyncInfo))
97 *out = &action->IAsyncInfo_iface;
99 else
101 *out = NULL;
102 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
105 IUnknown_AddRef((IUnknown *)*out);
106 return S_OK;
109 static ULONG STDMETHODCALLTYPE async_action_AddRef(IAsyncAction *iface)
111 struct async_action *action = impl_from_IAsyncAction(iface);
112 ULONG refcount = InterlockedIncrement(&action->refcount);
114 TRACE("iface %p, refcount %lu.\n", iface, refcount);
116 return refcount;
119 static ULONG STDMETHODCALLTYPE async_action_Release(IAsyncAction *iface)
121 struct async_action *action = impl_from_IAsyncAction(iface);
122 ULONG refcount = InterlockedDecrement(&action->refcount);
124 TRACE("iface %p, refcount %lu.\n", iface, refcount);
126 if (!refcount)
127 free(action);
129 return refcount;
132 static HRESULT STDMETHODCALLTYPE async_action_GetIids(
133 IAsyncAction *iface, ULONG *iid_count, IID **iids)
135 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
137 return E_NOTIMPL;
140 static HRESULT STDMETHODCALLTYPE async_action_GetRuntimeClassName(
141 IAsyncAction *iface, HSTRING *class_name)
143 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
145 return E_NOTIMPL;
148 static HRESULT STDMETHODCALLTYPE async_action_GetTrustLevel(
149 IAsyncAction *iface, TrustLevel *trust_level)
151 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
153 return E_NOTIMPL;
156 static HRESULT STDMETHODCALLTYPE async_action_put_Completed(IAsyncAction *iface, IAsyncActionCompletedHandler *handler)
158 FIXME("iface %p, handler %p stub!\n", iface, handler);
160 return E_NOTIMPL;
163 static HRESULT STDMETHODCALLTYPE async_action_get_Completed(IAsyncAction *iface, IAsyncActionCompletedHandler **handler)
165 FIXME("iface %p, handler %p stub!\n", iface, handler);
167 return E_NOTIMPL;
170 static HRESULT STDMETHODCALLTYPE async_action_GetResults(IAsyncAction *iface)
172 FIXME("iface %p stub!\n", iface);
174 return E_NOTIMPL;
177 static const IAsyncActionVtbl async_action_vtbl =
179 async_action_QueryInterface,
180 async_action_AddRef,
181 async_action_Release,
182 async_action_GetIids,
183 async_action_GetRuntimeClassName,
184 async_action_GetTrustLevel,
185 async_action_put_Completed,
186 async_action_get_Completed,
187 async_action_GetResults,
190 static HRESULT STDMETHODCALLTYPE async_info_QueryInterface(IAsyncInfo *iface, REFIID iid, void **out)
192 struct async_action *action = impl_from_IAsyncInfo(iface);
193 return IAsyncAction_QueryInterface(&action->IAsyncAction_iface, iid, out);
196 static ULONG STDMETHODCALLTYPE async_info_AddRef(IAsyncInfo *iface)
198 struct async_action *action = impl_from_IAsyncInfo(iface);
199 return IAsyncAction_AddRef(&action->IAsyncAction_iface);
202 static ULONG STDMETHODCALLTYPE async_info_Release(IAsyncInfo *iface)
204 struct async_action *action = impl_from_IAsyncInfo(iface);
205 return IAsyncAction_Release(&action->IAsyncAction_iface);
208 static HRESULT STDMETHODCALLTYPE async_info_GetIids(IAsyncInfo *iface, ULONG *iid_count, IID **iids)
210 struct async_action *action = impl_from_IAsyncInfo(iface);
211 return IAsyncAction_GetIids(&action->IAsyncAction_iface, iid_count, iids);
214 static HRESULT STDMETHODCALLTYPE async_info_GetRuntimeClassName(IAsyncInfo *iface, HSTRING *class_name)
216 struct async_action *action = impl_from_IAsyncInfo(iface);
217 return IAsyncAction_GetRuntimeClassName(&action->IAsyncAction_iface, class_name);
220 static HRESULT STDMETHODCALLTYPE async_info_GetTrustLevel(IAsyncInfo *iface, TrustLevel *trust_level)
222 struct async_action *action = impl_from_IAsyncInfo(iface);
223 return IAsyncAction_GetTrustLevel(&action->IAsyncAction_iface, trust_level);
226 static HRESULT STDMETHODCALLTYPE async_info_get_Id(IAsyncInfo *iface, UINT32 *id)
228 FIXME("iface %p, id %p stub!\n", iface, id);
230 return E_NOTIMPL;
233 static HRESULT STDMETHODCALLTYPE async_info_get_Status(IAsyncInfo *iface, AsyncStatus *status)
235 FIXME("iface %p, status %p stub!\n", iface, status);
237 return E_NOTIMPL;
240 static HRESULT STDMETHODCALLTYPE async_info_get_ErrorCode(IAsyncInfo *iface, HRESULT *error_code)
242 FIXME("iface %p, error_code %p stub!\n", iface, error_code);
244 return E_NOTIMPL;
247 static HRESULT STDMETHODCALLTYPE async_info_Cancel(IAsyncInfo *iface)
249 FIXME("iface %p stub!\n", iface);
251 return E_NOTIMPL;
254 static HRESULT STDMETHODCALLTYPE async_info_Close(IAsyncInfo *iface)
256 FIXME("iface %p stub!\n", iface);
258 return E_NOTIMPL;
261 static const IAsyncInfoVtbl async_info_vtbl =
263 async_info_QueryInterface,
264 async_info_AddRef,
265 async_info_Release,
266 async_info_GetIids,
267 async_info_GetRuntimeClassName,
268 async_info_GetTrustLevel,
269 async_info_get_Id,
270 async_info_get_Status,
271 async_info_get_ErrorCode,
272 async_info_Cancel,
273 async_info_Close,
276 static HRESULT async_action_create(IAsyncAction **ret)
278 struct async_action *object;
280 *ret = NULL;
282 if (!(object = calloc(1, sizeof(*object))))
283 return E_OUTOFMEMORY;
285 object->IAsyncAction_iface.lpVtbl = &async_action_vtbl;
286 object->IAsyncInfo_iface.lpVtbl = &async_info_vtbl;
287 object->refcount = 1;
289 *ret = &object->IAsyncAction_iface;
291 return S_OK;
294 struct work_item
296 IWorkItemHandler *handler;
297 IAsyncAction *action;
300 static void release_work_item(struct work_item *item)
302 IWorkItemHandler_Release(item->handler);
303 IAsyncAction_Release(item->action);
304 free(item);
307 static HRESULT alloc_work_item(IWorkItemHandler *handler, struct work_item **ret)
309 struct work_item *object;
310 HRESULT hr;
312 *ret = NULL;
314 if (!(object = calloc(1, sizeof(*object))))
315 return E_OUTOFMEMORY;
317 if (FAILED(hr = async_action_create(&object->action)))
319 free(object);
320 return hr;
323 IWorkItemHandler_AddRef((object->handler = handler));
325 *ret = object;
327 return S_OK;
330 static void work_item_invoke_release(struct work_item *item)
332 IWorkItemHandler_Invoke(item->handler, item->action);
333 release_work_item(item);
336 static DWORD WINAPI sliced_thread_proc(void *arg)
338 struct work_item *item = arg;
339 work_item_invoke_release(item);
340 return 0;
343 struct thread_pool
345 INIT_ONCE init_once;
346 TP_POOL *pool;
349 static struct thread_pool pools[3];
351 static BOOL CALLBACK pool_init_once(INIT_ONCE *init_once, void *param, void **context)
353 struct thread_pool *pool = param;
355 if (!(pool->pool = CreateThreadpool(NULL))) return FALSE;
357 SetThreadpoolThreadMaximum(pool->pool, 10);
359 return TRUE;
362 static void CALLBACK pool_work_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_WORK *work)
364 struct work_item *item = context;
365 work_item_invoke_release(item);
368 static HRESULT submit_threadpool_work(struct work_item *item, WorkItemPriority priority, IAsyncAction **action)
370 struct thread_pool *pool;
371 TP_WORK *work;
373 assert(priority == WorkItemPriority_Low
374 || priority == WorkItemPriority_Normal
375 || priority == WorkItemPriority_High);
377 pool = &pools[priority + 1];
379 if (!InitOnceExecuteOnce(&pool->init_once, pool_init_once, pool, NULL))
380 return E_FAIL;
382 if (!(work = CreateThreadpoolWork(pool_work_callback, item, NULL)))
383 return E_FAIL;
385 IAsyncAction_AddRef((*action = item->action));
386 SubmitThreadpoolWork(work);
388 return S_OK;
391 static HRESULT submit_standalone_thread_work(struct work_item *item, WorkItemPriority priority, IAsyncAction **action)
393 HANDLE thread;
395 if (!(thread = CreateThread(NULL, 0, sliced_thread_proc, item, priority == WorkItemPriority_Normal ?
396 0 : CREATE_SUSPENDED, NULL)))
398 WARN("Failed to create a thread, error %ld.\n", GetLastError());
399 return HRESULT_FROM_WIN32(GetLastError());
402 IAsyncAction_AddRef((*action = item->action));
403 if (priority != WorkItemPriority_Normal)
405 SetThreadPriority(thread, priority == WorkItemPriority_High ? THREAD_PRIORITY_HIGHEST : THREAD_PRIORITY_LOWEST);
406 ResumeThread(thread);
408 CloseHandle(thread);
410 return S_OK;
413 static HRESULT run_async(IWorkItemHandler *handler, WorkItemPriority priority, WorkItemOptions options,
414 IAsyncAction **action)
416 struct work_item *item;
417 HRESULT hr;
419 *action = NULL;
421 if (!handler)
422 return E_INVALIDARG;
424 if (priority < WorkItemPriority_Low || priority > WorkItemPriority_High)
425 return E_INVALIDARG;
427 if (FAILED(hr = alloc_work_item(handler, &item)))
428 return hr;
430 if (options == WorkItemOptions_TimeSliced)
431 hr = submit_standalone_thread_work(item, priority, action);
432 else
433 hr = submit_threadpool_work(item, priority, action);
435 if (FAILED(hr))
436 release_work_item(item);
438 return hr;
441 static HRESULT STDMETHODCALLTYPE threadpool_factory_QueryInterface(
442 IActivationFactory *iface, REFIID iid, void **out)
444 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
446 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
448 if (IsEqualGUID(iid, &IID_IUnknown) ||
449 IsEqualGUID(iid, &IID_IInspectable) ||
450 IsEqualGUID(iid, &IID_IAgileObject) ||
451 IsEqualGUID(iid, &IID_IActivationFactory))
453 IUnknown_AddRef(iface);
454 *out = &factory->IActivationFactory_iface;
455 return S_OK;
458 if (IsEqualGUID(iid, &IID_IThreadPoolStatics))
460 IUnknown_AddRef(iface);
461 *out = &factory->IThreadPoolStatics_iface;
462 return S_OK;
465 FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
466 *out = NULL;
467 return E_NOINTERFACE;
470 static ULONG STDMETHODCALLTYPE threadpool_factory_AddRef(IActivationFactory *iface)
472 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
473 ULONG refcount = InterlockedIncrement(&factory->refcount);
475 TRACE("iface %p, refcount %lu.\n", iface, refcount);
477 return refcount;
480 static ULONG STDMETHODCALLTYPE threadpool_factory_Release(IActivationFactory *iface)
482 struct threadpool_factory *factory = impl_from_IActivationFactory(iface);
483 ULONG refcount = InterlockedDecrement(&factory->refcount);
485 TRACE("iface %p, refcount %lu.\n", iface, refcount);
487 return refcount;
490 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetIids(
491 IActivationFactory *iface, ULONG *iid_count, IID **iids)
493 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
494 return E_NOTIMPL;
497 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetRuntimeClassName(
498 IActivationFactory *iface, HSTRING *class_name)
500 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
501 return E_NOTIMPL;
504 static HRESULT STDMETHODCALLTYPE threadpool_factory_GetTrustLevel(
505 IActivationFactory *iface, TrustLevel *trust_level)
507 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
508 return E_NOTIMPL;
511 static HRESULT STDMETHODCALLTYPE threadpool_factory_ActivateInstance(
512 IActivationFactory *iface, IInspectable **instance)
514 FIXME("iface %p, instance %p stub!\n", iface, instance);
515 return E_NOTIMPL;
518 static const struct IActivationFactoryVtbl threadpool_factory_vtbl =
520 threadpool_factory_QueryInterface,
521 threadpool_factory_AddRef,
522 threadpool_factory_Release,
523 /* IInspectable methods */
524 threadpool_factory_GetIids,
525 threadpool_factory_GetRuntimeClassName,
526 threadpool_factory_GetTrustLevel,
527 /* IActivationFactory methods */
528 threadpool_factory_ActivateInstance,
531 static HRESULT STDMETHODCALLTYPE threadpool_statics_QueryInterface(
532 IThreadPoolStatics *iface, REFIID iid, void **object)
534 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
535 return IActivationFactory_QueryInterface(&factory->IActivationFactory_iface, iid, object);
538 static ULONG STDMETHODCALLTYPE threadpool_statics_AddRef(IThreadPoolStatics *iface)
540 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
541 return IActivationFactory_AddRef(&factory->IActivationFactory_iface);
544 static ULONG STDMETHODCALLTYPE threadpool_statics_Release(IThreadPoolStatics *iface)
546 struct threadpool_factory *factory = impl_from_IThreadPoolStatics(iface);
547 return IActivationFactory_Release(&factory->IActivationFactory_iface);
550 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetIids(
551 IThreadPoolStatics *iface, ULONG *iid_count, IID **iids)
553 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
554 return E_NOTIMPL;
557 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetRuntimeClassName(
558 IThreadPoolStatics *iface, HSTRING *class_name)
560 FIXME("iface %p, class_name %p stub!\n", iface, class_name);
561 return E_NOTIMPL;
564 static HRESULT STDMETHODCALLTYPE threadpool_statics_GetTrustLevel(
565 IThreadPoolStatics *iface, TrustLevel *trust_level)
567 FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
568 return E_NOTIMPL;
571 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunAsync(
572 IThreadPoolStatics *iface, IWorkItemHandler *handler, IAsyncAction **operation)
574 TRACE("iface %p, handler %p, operation %p.\n", iface, handler, operation);
576 return run_async(handler, WorkItemPriority_Normal, WorkItemOptions_None, operation);
579 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunWithPriorityAsync(
580 IThreadPoolStatics *iface, IWorkItemHandler *handler, WorkItemPriority priority, IAsyncAction **operation)
582 TRACE("iface %p, handler %p, priority %d, operation %p.\n", iface, handler, priority, operation);
584 return run_async(handler, priority, WorkItemOptions_None, operation);
587 static HRESULT STDMETHODCALLTYPE threadpool_statics_RunWithPriorityAndOptionsAsync(
588 IThreadPoolStatics *iface, IWorkItemHandler *handler, WorkItemPriority priority,
589 WorkItemOptions options, IAsyncAction **operation)
591 TRACE("iface %p, handler %p, priority %d, options %d, operation %p.\n", iface, handler, priority, options, operation);
593 return run_async(handler, priority, options, operation);
596 static const struct IThreadPoolStaticsVtbl threadpool_statics_vtbl =
598 threadpool_statics_QueryInterface,
599 threadpool_statics_AddRef,
600 threadpool_statics_Release,
601 /* IInspectable methods */
602 threadpool_statics_GetIids,
603 threadpool_statics_GetRuntimeClassName,
604 threadpool_statics_GetTrustLevel,
605 /* IThreadPoolStatics methods */
606 threadpool_statics_RunAsync,
607 threadpool_statics_RunWithPriorityAsync,
608 threadpool_statics_RunWithPriorityAndOptionsAsync,
611 static struct threadpool_factory threadpool_factory =
613 .IActivationFactory_iface.lpVtbl = &threadpool_factory_vtbl,
614 .IThreadPoolStatics_iface.lpVtbl = &threadpool_statics_vtbl,
615 .refcount = 1,
618 HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
620 FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out);
621 return CLASS_E_CLASSNOTAVAILABLE;
624 HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory)
626 const WCHAR *name = WindowsGetStringRawBuffer(classid, NULL);
628 TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
630 *factory = NULL;
632 if (!wcscmp(name, RuntimeClass_Windows_System_Threading_ThreadPool))
634 *factory = &threadpool_factory.IActivationFactory_iface;
635 IUnknown_AddRef(*factory);
638 if (*factory) return S_OK;
639 return CLASS_E_CLASSNOTAVAILABLE;