Paul Gofman : ntoskrnl.exe: Avoid leaking events on multipe KeSetTimerEx() calls.

Alexandre Julliard julliard at winehq.org
Thu May 28 17:11:11 CDT 2020


Module: wine
Branch: master
Commit: 4584ffaddae059ae2308d6f1f81fe143608763d8
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4584ffaddae059ae2308d6f1f81fe143608763d8

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Thu May 28 12:15:17 2020 +0300

ntoskrnl.exe: Avoid leaking events on multipe KeSetTimerEx() calls.

As the consequent testing shows we can't just close the events on timer
reset. That would result in wrong wait results for current waiters.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntoskrnl.exe/sync.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 1954b8befb..912dc046ba 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -83,9 +83,11 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
         {
             switch (objs[i]->Type)
             {
+            case TYPE_MANUAL_TIMER:
             case TYPE_MANUAL_EVENT:
                 objs[i]->WaitListHead.Blink = CreateEventW( NULL, TRUE, objs[i]->SignalState, NULL );
                 break;
+            case TYPE_AUTO_TIMER:
             case TYPE_AUTO_EVENT:
                 objs[i]->WaitListHead.Blink = CreateEventW( NULL, FALSE, objs[i]->SignalState, NULL );
                 break;
@@ -99,9 +101,6 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
                     semaphore->Header.SignalState, semaphore->Limit, NULL );
                 break;
             }
-            case TYPE_MANUAL_TIMER:
-            case TYPE_AUTO_TIMER:
-                break;
             }
         }
 
@@ -137,6 +136,8 @@ NTSTATUS WINAPI KeWaitForMultipleObjects(ULONG count, void *pobjs[],
         {
             switch (objs[i]->Type)
             {
+            case TYPE_AUTO_TIMER:
+            case TYPE_MANUAL_TIMER:
             case TYPE_MANUAL_EVENT:
             case TYPE_AUTO_EVENT:
             case TYPE_SEMAPHORE:
@@ -394,7 +395,11 @@ static void CALLBACK ke_timer_complete_proc(PTP_CALLBACK_INSTANCE instance, void
 
     TRACE("instance %p, timer %p, tp_timer %p.\n", instance, timer, tp_timer);
 
-    SetEvent(timer->Header.WaitListHead.Blink);
+    EnterCriticalSection( &sync_cs );
+    timer->Header.SignalState = TRUE;
+    if (timer->Header.WaitListHead.Blink)
+        SetEvent(timer->Header.WaitListHead.Blink);
+    LeaveCriticalSection( &sync_cs );
 }
 
 /***********************************************************************
@@ -440,7 +445,6 @@ BOOLEAN WINAPI KeSetTimerEx( KTIMER *timer, LARGE_INTEGER duetime, LONG period,
 
     ret = timer->Header.Inserted;
     timer->Header.Inserted = TRUE;
-    timer->Header.WaitListHead.Blink = CreateEventW( NULL, timer->Header.Type == TYPE_MANUAL_TIMER, FALSE, NULL );
 
     if (!timer->TimerListEntry.Blink)
         timer->TimerListEntry.Blink = (void *)CreateThreadpoolTimer(ke_timer_complete_proc, timer, NULL);
@@ -478,11 +482,15 @@ BOOLEAN WINAPI KeCancelTimer( KTIMER *timer )
             timer->TimerListEntry.Blink = NULL;
         }
     }
+    timer->Header.SignalState = FALSE;
+    if (timer->Header.WaitListHead.Blink && !*((ULONG_PTR *)&timer->Header.WaitListHead.Flink))
+    {
+        CloseHandle(timer->Header.WaitListHead.Blink);
+        timer->Header.WaitListHead.Blink = NULL;
+    }
 
     ret = timer->Header.Inserted;
     timer->Header.Inserted = FALSE;
-    CloseHandle(timer->Header.WaitListHead.Blink);
-    timer->Header.WaitListHead.Blink = NULL;
     LeaveCriticalSection( &sync_cs );
 
     return ret;




More information about the wine-cvs mailing list