diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 7bce44566f8..c739a5bc433 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -1085,16 +1085,20 @@ BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) * * RETURNS * nonzero on success or zero on failure - * - * BUGS - * Unimplemented */ BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue, WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, DWORD Period, ULONG Flags ) { - FIXME("stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + NTSTATUS status = RtlCreateTimer(phNewTimer, TimerQueue, Callback, + Parameter, DueTime, Period, Flags); + + if (status != STATUS_SUCCESS) + { + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; + } + return TRUE; } diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index 697f90553c1..05f67dce4c5 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -622,7 +622,6 @@ static void test_timer_queue(void) ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 0, 0, 0); ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t1 != NULL, "CreateTimerQueueTimer\n"); /* A slow one. */ @@ -631,7 +630,6 @@ static void test_timer_queue(void) ret = pCreateTimerQueueTimer(&t2, q, timer_queue_cb1, &n2, 0, 100, 0); ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t2 != NULL, "CreateTimerQueueTimer\n"); /* A fast one. */ @@ -640,7 +638,6 @@ static void test_timer_queue(void) ret = pCreateTimerQueueTimer(&t3, q, timer_queue_cb1, &n3, 0, 10, 0); ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t3 != NULL, "CreateTimerQueueTimer\n"); /* Start really late (it won't start). */ @@ -649,7 +646,6 @@ static void test_timer_queue(void) ret = pCreateTimerQueueTimer(&t4, q, timer_queue_cb1, &n4, 10000, 10, 0); ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t4 != NULL, "CreateTimerQueueTimer\n"); /* Start soon, but delay so long it won't run again. */ @@ -658,7 +654,6 @@ static void test_timer_queue(void) ret = pCreateTimerQueueTimer(&t5, q, timer_queue_cb1, &n5, 0, 10000, 0); ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t5 != NULL, "CreateTimerQueueTimer\n"); /* Give them a chance to do some work. */ @@ -706,7 +701,6 @@ static void test_timer_queue(void) 10, 0); d2.t = t2; ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t2 != NULL, "CreateTimerQueueTimer\n"); d3.t = t3 = NULL; @@ -717,7 +711,6 @@ static void test_timer_queue(void) 10, 0); d3.t = t3; ok(ret, "CreateTimerQueueTimer\n"); - todo_wine ok(t3 != NULL, "CreateTimerQueueTimer\n"); Sleep(200); diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 0be408ef4d8..595a5f64d91 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -488,7 +488,7 @@ @ stdcall RtlCreateSecurityDescriptor(ptr long) # @ stub RtlCreateSystemVolumeInformationFolder @ stub RtlCreateTagHeap -# @ stub RtlCreateTimer +@ stdcall RtlCreateTimer(ptr ptr ptr ptr long long long) @ stdcall RtlCreateTimerQueue(ptr) @ stdcall RtlCreateUnicodeString(ptr wstr) @ stdcall RtlCreateUnicodeStringFromAsciiz(ptr str) diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index aa03959008e..c698cb713ef 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -543,6 +543,12 @@ struct timer_queue struct list timers; }; +static void queue_remove_timer(struct queue_timer *t) +{ + list_remove(&t->entry); + RtlFreeHeap(GetProcessHeap(), 0, t); +} + /*********************************************************************** * RtlCreateTimerQueue (NTDLL.@) * @@ -587,6 +593,12 @@ NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE NewTimerQueue) NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { struct timer_queue *q = TimerQueue; + struct queue_timer *t, *temp; + + RtlEnterCriticalSection(&q->cs); + LIST_FOR_EACH_ENTRY_SAFE(t, temp, &q->timers, struct queue_timer, entry) + queue_remove_timer(t); + RtlLeaveCriticalSection(&q->cs); RtlDeleteCriticalSection(&q->cs); RtlFreeHeap(GetProcessHeap(), 0, q); @@ -600,3 +612,48 @@ NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) return STATUS_PENDING; } } + +/*********************************************************************** + * RtlCreateTimer (NTDLL.@) + * + * Creates a new timer associated with the given queue. + * + * PARAMS + * NewTimer [O] The newly created timer. + * TimerQueue [I] The queue to hold the timer. + * Callback [I] The callback to fire. + * Parameter [I] The argument for the callback. + * DueTime [I] The delay, in milliseconds, before first firing the + * timer. + * Period [I] The period, in milliseconds, at which to fire the timer + * after the first callback. If zero, the timer will only + * fire once. It still needs to be deleted with + * RtlDeleteTimer. + * Flags [I] Flags controling the execution of the callback. In + * addition to the WT_* thread pool flags (see + * RtlQueueWorkItem), WT_EXECUTEINTIMERTHREAD and + * WT_EXECUTEONLYONCE are supported. + * + * RETURNS + * Success: STATUS_SUCCESS. + * Failure: Any NTSTATUS code. + */ +NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue, + RTL_WAITORTIMERCALLBACKFUNC Callback, + PVOID Parameter, DWORD DueTime, DWORD Period, + ULONG Flags) +{ + struct timer_queue *q = TimerQueue; + struct queue_timer *t = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *t); + if (!t) + return STATUS_NO_MEMORY; + + FIXME("timer expiration unimplemented\n"); + + RtlEnterCriticalSection(&q->cs); + list_add_tail(&q->timers, &t->entry); + RtlLeaveCriticalSection(&q->cs); + + *NewTimer = t; + return STATUS_SUCCESS; +} diff --git a/include/winternl.h b/include/winternl.h index 7b8e0551b17..30bd0e54283 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2118,6 +2118,7 @@ NTSYSAPI HANDLE WINAPI RtlCreateHeap(ULONG,PVOID,SIZE_T,SIZE_T,PVOID,PRTL_HEA NTSYSAPI NTSTATUS WINAPI RtlCreateProcessParameters(RTL_USER_PROCESS_PARAMETERS**,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,PWSTR,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*,const UNICODE_STRING*); NTSYSAPI NTSTATUS WINAPI RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD); NTSYSAPI NTSTATUS WINAPI RtlCreateTimerQueue(PHANDLE); +NTSYSAPI NTSTATUS WINAPI RtlCreateTimer(PHANDLE, HANDLE, RTL_WAITORTIMERCALLBACKFUNC, PVOID, DWORD, DWORD, ULONG); NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR); NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR); NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,const SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*);