diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index ee9070507fb..10d36521bc1 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -972,6 +972,7 @@ @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @ stdcall TpAllocCleanupGroup(ptr) @ stdcall TpAllocPool(ptr ptr) +@ stdcall TpAllocTimer(ptr ptr ptr ptr) @ stdcall TpAllocWork(ptr ptr ptr ptr) @ stdcall TpCallbackLeaveCriticalSectionOnCompletion(ptr ptr) @ stdcall TpCallbackMayRunLong(ptr) @@ -984,6 +985,7 @@ @ stdcall TpReleaseCleanupGroup(ptr) @ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) @ stdcall TpReleasePool(ptr) +@ stdcall TpReleaseTimer(ptr) @ stdcall TpReleaseWork(ptr) @ stdcall TpSetPoolMaxThreads(ptr long) @ stdcall TpSetPoolMinThreads(ptr long) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index 33e2c8a5ff1..cf714a697f2 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -158,7 +158,8 @@ struct threadpool enum threadpool_objtype { TP_OBJECT_TYPE_SIMPLE, - TP_OBJECT_TYPE_WORK + TP_OBJECT_TYPE_WORK, + TP_OBJECT_TYPE_TIMER }; /* internal threadpool object representation */ @@ -196,6 +197,10 @@ struct threadpool_object { PTP_WORK_CALLBACK callback; } work; + struct + { + PTP_TIMER_CALLBACK callback; + } timer; } u; }; @@ -239,6 +244,13 @@ static inline struct threadpool_object *impl_from_TP_WORK( TP_WORK *work ) return object; } +static inline struct threadpool_object *impl_from_TP_TIMER( TP_TIMER *timer ) +{ + struct threadpool_object *object = (struct threadpool_object *)timer; + assert( object->type == TP_OBJECT_TYPE_TIMER ); + return object; +} + static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group ) { return (struct threadpool_group *)group; @@ -1683,6 +1695,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) break; } + case TP_OBJECT_TYPE_TIMER: + { + TRACE( "executing timer callback %p(%p, %p, %p)\n", + object->u.timer.callback, callback_instance, object->userdata, object ); + object->u.timer.callback( callback_instance, object->userdata, (TP_TIMER *)object ); + TRACE( "callback %p returned\n", object->u.timer.callback ); + break; + } + default: assert(0); break; @@ -1788,6 +1809,37 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) return tp_threadpool_alloc( (struct threadpool **)out ); } +/*********************************************************************** + * TpAllocTimer (NTDLL.@) + */ +NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID userdata, + TP_CALLBACK_ENVIRON *environment ) +{ + struct threadpool_object *object; + struct threadpool *pool; + NTSTATUS status; + + TRACE( "%p %p %p %p\n", out, callback, userdata, environment ); + + object = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*object) ); + if (!object) + return STATUS_NO_MEMORY; + + status = tp_threadpool_lock( &pool, environment ); + if (status) + { + RtlFreeHeap( GetProcessHeap(), 0, object ); + return status; + } + + object->type = TP_OBJECT_TYPE_TIMER; + object->u.timer.callback = callback; + tp_object_initialize( object, pool, userdata, environment ); + + *out = (TP_TIMER *)object; + return STATUS_SUCCESS; +} + /*********************************************************************** * TpAllocWork (NTDLL.@) */ @@ -2067,6 +2119,19 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) tp_threadpool_release( this ); } +/*********************************************************************** + * TpReleaseTimer (NTDLL.@) + */ +VOID WINAPI TpReleaseTimer( TP_TIMER *timer ) +{ + struct threadpool_object *this = impl_from_TP_TIMER( timer ); + + TRACE( "%p\n", timer ); + + tp_object_shutdown( this ); + tp_object_release( this ); +} + /*********************************************************************** * TpReleaseWork (NTDLL.@) */