[10/11] kernel32: Implement DeleteTimerQueueTimer.

Dan Hipschman dsh at linux.ucla.edu
Fri Jul 18 19:20:20 CDT 2008


This removes the last todo_wine from the timer queue tests.  The tests
are by no means comprehensive, but the basics are covered, so this is a
good start.

---
 dlls/kernel32/sync.c       |   64 +++++++++++++++++++++++++++++++++++++++++--
 dlls/kernel32/tests/sync.c |    6 ----
 2 files changed, 61 insertions(+), 9 deletions(-)

diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index 4076859..eb6c979 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -1044,6 +1044,12 @@ BOOL WINAPI CancelWaitableTimer( HANDLE handle )
 }
 
 
+struct event_entry
+{
+    struct list entry;
+    HANDLE event;
+};
+
 struct timer_queue;
 struct queue_timer
 {
@@ -1056,6 +1062,7 @@ struct queue_timer
     ULONG flags;
     DWORD expire;
     BOOL die;          /* timer should be deleted; once set, never unset */
+    struct list events;
 };
 
 struct timer_queue
@@ -1074,11 +1081,21 @@ static void queue_remove_timer(struct timer_queue *q, struct queue_timer *t)
     /* We MUST hold the queue cs while calling this function.  This ensures
        that we cannot queue another callback for this timer.  The runcount
        being zero makes sure we don't have any already queued.  */
+    struct event_entry *e, *temp;
     assert(t->runcount == 0);
     assert(t->die);
+
     list_remove(&t->entry);
     if (q->next == t)
         q->next = NULL;
+
+    LIST_FOR_EACH_ENTRY_SAFE(e, temp, &t->events, struct event_entry, entry)
+    {
+        SetEvent(e->event);
+        list_remove(&e->entry);
+        HeapFree(GetProcessHeap(), 0, e);
+    }
+
     HeapFree(GetProcessHeap(), 0, t);
 }
 
@@ -1297,6 +1314,7 @@ BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
             ERR("due time wrapped\n");
     }
     t->die = FALSE;
+    list_init(&t->events);
 
     ret = TRUE;
     RtlEnterCriticalSection(&q->cs);
@@ -1366,9 +1384,49 @@ BOOL WINAPI ChangeTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
                                    HANDLE CompletionEvent )
 {
-    FIXME("stub\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return TRUE;
+    struct queue_timer *t = Timer;
+    struct timer_queue *q = t->q;
+    struct event_entry *e = NULL;
+    BOOL ret = FALSE;
+
+    if (CompletionEvent == INVALID_HANDLE_VALUE)
+    {
+        CompletionEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+        if (!CompletionEvent)
+        {
+            SetLastError(ERROR_IO_PENDING);
+            ret = FALSE;
+        }
+        else
+            ret = TRUE;
+    }
+
+    if (CompletionEvent)
+    {
+        e = HeapAlloc(GetProcessHeap(), 0, sizeof *e);
+        if (!e)
+        {
+            SetLastError(ERROR_OUTOFMEMORY);
+            ret = FALSE;
+        }
+    }
+
+    RtlEnterCriticalSection(&q->cs);
+    if (e)
+        list_add_tail(&t->events, &e->entry);
+    t->die = TRUE;
+    SetEvent(q->event);
+    RtlLeaveCriticalSection(&q->cs);
+
+    if (ret)
+    {
+        WaitForSingleObject(CompletionEvent, INFINITE);
+        CloseHandle(CompletionEvent);
+    }
+    else
+        SetLastError(ERROR_IO_PENDING);
+
+    return ret;
 }
 
 
diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c
index b77d57f..2cc9041 100644
--- a/dlls/kernel32/tests/sync.c
+++ b/dlls/kernel32/tests/sync.c
@@ -572,11 +572,8 @@ static void CALLBACK timer_queue_cb2(PVOID p, BOOLEAN timedOut)
             /* Note, XP SP2 does *not* do any deadlock checking, so passing
                INVALID_HANDLE_VALUE here will just hang.  */
             ret = pDeleteTimerQueueTimer(d->q, d->t, NULL);
-            todo_wine
-            {
             ok(!ret, "DeleteTimerQueueTimer\n");
             ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n");
-            }
         }
 }
 
@@ -749,10 +746,7 @@ static void test_timer_queue(void)
 
     ret = pDeleteTimerQueueEx(q, INVALID_HANDLE_VALUE);
     ok(ret, "DeleteTimerQueueEx\n");
-    todo_wine
-    {
     ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n");
-    }
     ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n");
     ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n");
 }



More information about the wine-patches mailing list