ntdll: Implement RtlUpdateTimer for kernel32's ChangeTimerQueueTimer.
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index c739a5b..8bd4243 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c
@@ -1109,16 +1109,19 @@ * * RETURNS * nonzero on success or zero on failure - * - * BUGS - * Unimplemented */ BOOL WINAPI ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer, ULONG DueTime, ULONG Period ) { - FIXME("stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + NTSTATUS status = RtlUpdateTimer(TimerQueue, Timer, DueTime, Period); + + 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 d41bd79..19fc8e2 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c
@@ -583,7 +583,6 @@ /* Basically kill the timer since it won't have time to run again. */ BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 10000, 0); - todo_wine ok(ret, "ChangeTimerQueueTimer\n"); } } @@ -600,7 +599,6 @@ fail if the timer is already flagged. Hence we really run only once. Otherwise we will run multiple times. */ BOOL ret = pChangeTimerQueueTimer(d->q, d->t, 50, 50); - todo_wine ok(ret, "ChangeTimerQueueTimer\n"); ++d->num_calls; } @@ -707,6 +705,16 @@ q = pCreateTimerQueue(); ok(q != NULL, "CreateTimerQueue\n"); + /* Test changing a once-only timer before it fires (this is allowed, + whereas after it fires you cannot). */ + n1 = 0; + ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 10000, + 0, 0); + ok(ret, "CreateTimerQueueTimer\n"); + ok(t1 != NULL, "CreateTimerQueueTimer\n"); + ret = pChangeTimerQueueTimer(q, t1, 0, 0); + ok(ret, "ChangeTimerQueueTimer\n"); + d2.t = t2 = NULL; d2.num_calls = 0; d2.max_calls = 3; @@ -740,11 +748,12 @@ ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE); ok(ret, "DeleteTimerQueueEx\n"); + ok(n1 == 1, "ChangeTimerQueueTimer\n"); todo_wine { ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n"); - ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); } + ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n"); }
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 595a5f6..4d200eb 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec
@@ -895,7 +895,7 @@ @ stub RtlUpcaseUnicodeToCustomCPN @ stdcall RtlUpcaseUnicodeToMultiByteN(ptr long ptr ptr long) @ stdcall RtlUpcaseUnicodeToOemN(ptr long ptr ptr long) -# @ stub RtlUpdateTimer +@ stdcall RtlUpdateTimer(ptr ptr long long) @ stdcall RtlUpperChar(long) @ stdcall RtlUpperString(ptr ptr) @ stub RtlUsageHeap
diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index cbb97f4..f6e6c1e 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c
@@ -907,3 +907,39 @@ return status; } + +/*********************************************************************** + * RtlUpdateTimer (NTDLL.@) + * + * Changes the time at which a timer expires. + * + * PARAMS + * TimerQueue [I] The queue that holds the timer. + * Timer [I] The timer to update. + * DueTime [I] The delay, in milliseconds, before next firing the timer. + * Period [I] The period, in milliseconds, at which to fire the timer + * after the first callback. If zero, the timer will not + * refire once. It still needs to be deleted with + * RtlDeleteTimer. + * + * RETURNS + * Success: STATUS_SUCCESS. + * Failure: Any NTSTATUS code. + */ +NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, + DWORD DueTime, DWORD Period) +{ + struct timer_queue *q = TimerQueue; + struct queue_timer *t = Timer; + + RtlEnterCriticalSection(&q->cs); + /* Can't change a timer if it was once-only or destroyed. */ + if (t->expire != EXPIRE_NEVER) + { + t->period = Period; + queue_move_timer(t, queue_current_time() + DueTime, TRUE); + } + RtlLeaveCriticalSection(&q->cs); + + return STATUS_SUCCESS; +}
diff --git a/include/winternl.h b/include/winternl.h index 30bd0e5..cb9a6f7 100644 --- a/include/winternl.h +++ b/include/winternl.h
@@ -2340,6 +2340,7 @@ NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeStringToOemString(STRING*,const UNICODE_STRING*,BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeToMultiByteN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD); NTSYSAPI NTSTATUS WINAPI RtlUpcaseUnicodeToOemN(LPSTR,DWORD,LPDWORD,LPCWSTR,DWORD); +NTSYSAPI NTSTATUS WINAPI RtlUpdateTimer(HANDLE, HANDLE, DWORD, DWORD); NTSYSAPI CHAR WINAPI RtlUpperChar(CHAR); NTSYSAPI void WINAPI RtlUpperString(STRING *,const STRING *); NTSYSAPI NTSTATUS WINAPI RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR);