Dan Hipschman : ntdll: Implement RtlUpdateTimer for kernel32' s ChangeTimerQueueTimer.

Alexandre Julliard julliard at winehq.org
Fri Jul 25 08:15:35 CDT 2008


Module: wine
Branch: master
Commit: 396e47ef5c201ff01f2eef7fcb0339520db4e6fa
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=396e47ef5c201ff01f2eef7fcb0339520db4e6fa

Author: Dan Hipschman <dsh at linux.ucla.edu>
Date:   Thu Jul 24 16:27:03 2008 -0700

ntdll: Implement RtlUpdateTimer for kernel32's ChangeTimerQueueTimer.

---

 dlls/kernel32/sync.c       |   15 +++++++++------
 dlls/kernel32/tests/sync.c |   15 ++++++++++++---
 dlls/ntdll/ntdll.spec      |    2 +-
 dlls/ntdll/threadpool.c    |   36 ++++++++++++++++++++++++++++++++++++
 include/winternl.h         |    1 +
 5 files changed, 59 insertions(+), 10 deletions(-)

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 @@ BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
  *
  * 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 @@ static void CALLBACK timer_queue_cb3(PVOID p, BOOLEAN timedOut)
         /* 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 @@ static void CALLBACK timer_queue_cb4(PVOID p, BOOLEAN timedOut)
            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 @@ static void test_timer_queue(void)
     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 @@ static void test_timer_queue(void)
 
     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 @@ NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue,
 
     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 RtlUpcaseUnicodeStringToCountedOemString(STRING*,const
 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);




More information about the wine-cvs mailing list