[CMAKE]
[reactos.git] / subsystems / win32 / win32k / ntuser / timer.c
index e178241..b3a7fbd 100644 (file)
@@ -5,6 +5,7 @@
  * FILE:             subsystems/win32/win32k/ntuser/timer.c
  * PROGRAMER:        Gunnar
  *                   Thomas Weidenmueller (w3seek@users.sourceforge.net)
+ *                   Michael Martin (michael.martin@reactos.org)
  * REVISION HISTORY: 10/04/2003 Implemented System Timers
  *
  */
@@ -24,13 +25,14 @@ static LONG TimeLast = 0;
 #define MAX_ELAPSE_TIME 0x7FFFFFFF
 
 /* Windows 2000 has room for 32768 window-less timers */
-#define NUM_WINDOW_LESS_TIMERS   1024
+#define NUM_WINDOW_LESS_TIMERS   32768
 
 static FAST_MUTEX     Mutex;
 static RTL_BITMAP     WindowLessTimersBitMap;
 static PVOID          WindowLessTimersBitMapBuffer;
-static ULONG          HintIndex = 0;
+static ULONG          HintIndex = 1;
 
+ERESOURCE TimerLock;
 
 #define IntLockWindowlessTimerBitmap() \
   ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Mutex)
@@ -38,6 +40,19 @@ static ULONG          HintIndex = 0;
 #define IntUnlockWindowlessTimerBitmap() \
   ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Mutex)
 
+#define TimerEnterExclusive() \
+{ \
+  KeEnterCriticalRegion(); \
+  ExAcquireResourceExclusiveLite(&TimerLock, TRUE); \
+}
+
+#define TimerLeave() \
+{ \
+  ExReleaseResourceLite(&TimerLock); \
+  KeLeaveCriticalRegion(); \
+}
+
+
 /* FUNCTIONS *****************************************************************/
 static
 PTIMER
@@ -49,14 +64,23 @@ CreateTimer(VOID)
 
   if (!FirstpTmr)
   {
+      ExInitializeResourceLite(&TimerLock);
       FirstpTmr = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
-      if (FirstpTmr) InitializeListHead(&FirstpTmr->ptmrList);
+      if (FirstpTmr)
+      {
+         FirstpTmr->head.h = Handle;
+         InitializeListHead(&FirstpTmr->ptmrList);
+      }
       Ret = FirstpTmr;
   }
   else
   {
       Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
-      if (Ret) InsertTailList(&FirstpTmr->ptmrList, &Ret->ptmrList);
+      if (Ret)
+      {
+         Ret->head.h = Handle;
+         InsertTailList(&FirstpTmr->ptmrList, &Ret->ptmrList);
+      }
   }
   return Ret;
 }
@@ -66,25 +90,37 @@ BOOL
 FASTCALL
 RemoveTimer(PTIMER pTmr)
 {
+  BOOL Ret = FALSE;
   if (pTmr)
   {
      /* Set the flag, it will be removed when ready */
-     pTmr->flags |= TMRF_DELETEPENDING;
-     return TRUE;
+     RemoveEntryList(&pTmr->ptmrList);
+     if ((pTmr->pWnd == NULL) && (!(pTmr->flags & TMRF_SYSTEM)))
+     {
+        UINT_PTR IDEvent;
+
+        IDEvent = NUM_WINDOW_LESS_TIMERS - pTmr->nID;
+        IntLockWindowlessTimerBitmap();
+        RtlClearBit(&WindowLessTimersBitMap, IDEvent);
+        IntUnlockWindowlessTimerBitmap();
+     }
+     UserDereferenceObject(pTmr);
+     Ret = UserDeleteObject( UserHMGetHandle(pTmr), otTimer);
   }
-  return FALSE;
+  if (!Ret) DPRINT1("Warning: Unable to delete timer\n");
+
+  return Ret;
 }
 
 PTIMER
 FASTCALL
-FindTimer(PWINDOW_OBJECT Window,
+FindTimer(PWND Window,
           UINT_PTR nID,
-          UINT flags,
-          BOOL Distroy)
+          UINT flags)
 {
   PLIST_ENTRY pLE;
   PTIMER pTmr = FirstpTmr, RetTmr = NULL;
-  KeEnterCriticalRegion();
+  TimerEnterExclusive();
   do
   {
     if (!pTmr) break;
@@ -93,10 +129,6 @@ FindTimer(PWINDOW_OBJECT Window,
          pTmr->pWnd == Window &&
         (pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) == (flags & (TMRF_SYSTEM|TMRF_RIT)))
     {
-       if (Distroy)
-       {
-          RemoveTimer(pTmr);
-       }
        RetTmr = pTmr;
        break;
     }
@@ -104,7 +136,7 @@ FindTimer(PWINDOW_OBJECT Window,
     pLE = pTmr->ptmrList.Flink;
     pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
   } while (pTmr != FirstpTmr);
-  KeLeaveCriticalRegion();
+  TimerLeave();
 
   return RetTmr;
 }
@@ -115,7 +147,7 @@ FindSystemTimer(PMSG pMsg)
 {
   PLIST_ENTRY pLE;
   PTIMER pTmr = FirstpTmr;
-  KeEnterCriticalRegion();
+  TimerEnterExclusive();
   do
   {
     if (!pTmr) break;
@@ -125,9 +157,9 @@ FindSystemTimer(PMSG pMsg)
        break;
 
     pLE = pTmr->ptmrList.Flink;
-    pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);    
+    pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
   } while (pTmr != FirstpTmr);
-  KeLeaveCriticalRegion();
+  TimerLeave();
 
   return pTmr;
 }
@@ -135,44 +167,43 @@ FindSystemTimer(PMSG pMsg)
 BOOL
 FASTCALL
 ValidateTimerCallback(PTHREADINFO pti,
-                      PWINDOW_OBJECT Window,
-                      WPARAM wParam,
                       LPARAM lParam)
 {
   PLIST_ENTRY pLE;
+  BOOL Ret = FALSE;
   PTIMER pTmr = FirstpTmr;
 
   if (!pTmr) return FALSE;
 
-  KeEnterCriticalRegion();
+  TimerEnterExclusive();
   do
   {
     if ( (lParam == (LPARAM)pTmr->pfn) &&
-         (pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) &&
+        !(pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) &&
          (pTmr->pti->ppi == pti->ppi) )
+    {
+       Ret = TRUE;
        break;
-
+    }
     pLE = pTmr->ptmrList.Flink;
     pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
   } while (pTmr != FirstpTmr);
-  KeLeaveCriticalRegion();
-
-  if (!pTmr) return FALSE;
+  TimerLeave();
 
-  return TRUE;
+  return Ret;
 }
 
 UINT_PTR FASTCALL
-IntSetTimer( PWINDOW_OBJECT Window,
+IntSetTimer( PWND Window,
                   UINT_PTR IDEvent,
                   UINT Elapse,
                   TIMERPROC TimerFunc,
                   INT Type)
 {
   PTIMER pTmr;
-  UINT Ret= IDEvent;
+  UINT Ret = IDEvent;
   LARGE_INTEGER DueTime;
-  DueTime.QuadPart = (LONGLONG)(-10000000);
+  DueTime.QuadPart = (LONGLONG)(-5000000);
 
 #if 0
   /* Windows NT/2k/XP behaviour */
@@ -197,9 +228,17 @@ IntSetTimer( PWINDOW_OBJECT Window,
      Elapse = 10;
   }
 
-  if ((Window == NULL) && (!(Type & TMRF_SYSTEM)))
+  /* Passing an IDEvent of 0 and the SetTimer returns 1.
+     It will create the timer with an ID of 0 */
+  if ((Window) && (IDEvent == 0))
+     Ret = 1;
+
+  pTmr = FindTimer(Window, IDEvent, Type);
+
+  if ((!pTmr) && (Window == NULL) && (!(Type & TMRF_SYSTEM)))
   {
       IntLockWindowlessTimerBitmap();
+
       IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex);
 
       if (IDEvent == (UINT_PTR) -1)
@@ -207,39 +246,43 @@ IntSetTimer( PWINDOW_OBJECT Window,
          IntUnlockWindowlessTimerBitmap();
          DPRINT1("Unable to find a free window-less timer id\n");
          SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
+         ASSERT(FALSE);
          return 0;
       }
 
-      HintIndex = ++IDEvent;
-      IntUnlockWindowlessTimerBitmap();
+      IDEvent = NUM_WINDOW_LESS_TIMERS - IDEvent;
       Ret = IDEvent;
+
+      IntUnlockWindowlessTimerBitmap();
   }
 
-  pTmr = FindTimer(Window, IDEvent, Type, FALSE);
-  if ((!pTmr) || (pTmr->flags & TMRF_DELETEPENDING))
+  if (!pTmr)
   {
      pTmr = CreateTimer();
      if (!pTmr) return 0;
 
-    if (Window && (Type & TMRF_TIFROMWND))
-       pTmr->pti = Window->pti->pEThread->Tcb.Win32Thread;
-    else
-    {
-       if (Type & TMRF_RIT)
-          pTmr->pti = ptiRawInput;
-       else
-          pTmr->pti = PsGetCurrentThreadWin32Thread();
+     if (Window && (Type & TMRF_TIFROMWND))
+        pTmr->pti = Window->head.pti->pEThread->Tcb.Win32Thread;
+     else
+     {
+        if (Type & TMRF_RIT)
+           pTmr->pti = ptiRawInput;
+        else
+           pTmr->pti = PsGetCurrentThreadWin32Thread();
      }
+
      pTmr->pWnd    = Window;
      pTmr->cmsCountdown = Elapse;
      pTmr->cmsRate = Elapse;
      pTmr->pfn     = TimerFunc;
      pTmr->nID     = IDEvent;
-     pTmr->flags   = Type|TMRF_INIT; // Set timer to Init mode.
+     pTmr->flags   = Type|TMRF_INIT;
+  }
+  else
+  {
+     pTmr->cmsCountdown = Elapse;
+     pTmr->cmsRate = Elapse;
   }
-
-  pTmr->cmsCountdown = Elapse;
-  pTmr->cmsRate = Elapse;
 
   ASSERT(MasterTimer != NULL);
   // Start the timer thread!
@@ -273,14 +316,15 @@ StartTheTimers(VOID)
 
 UINT_PTR
 FASTCALL
-SystemTimerSet( PWINDOW_OBJECT Window,
+SystemTimerSet( PWND Window,
                 UINT_PTR nIDEvent,
                 UINT uElapse,
                 TIMERPROC lpTimerFunc)
 {
-  if (Window && Window->pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
+  if (Window && Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
   {
      SetLastWin32Error(ERROR_ACCESS_DENIED);
+     DPRINT("SysemTimerSet: Access Denied!\n");
      return 0;
   }
   return IntSetTimer( Window, nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM);
@@ -288,7 +332,7 @@ SystemTimerSet( PWINDOW_OBJECT Window,
 
 BOOL
 FASTCALL
-PostTimerMessages(PWINDOW_OBJECT Window)
+PostTimerMessages(PWND Window)
 {
   PLIST_ENTRY pLE;
   PUSER_MESSAGE_QUEUE ThreadQueue;
@@ -302,15 +346,15 @@ PostTimerMessages(PWINDOW_OBJECT Window)
   pti = PsGetCurrentThreadWin32Thread();
   ThreadQueue = pti->MessageQueue;
 
-  KeEnterCriticalRegion();
+  TimerEnterExclusive();
 
   do
   {
      if ( (pTmr->flags & TMRF_READY) &&
           (pTmr->pti == pti) &&
-          ((pTmr->pWnd == Window) || (Window == NULL) ) )
+          ((pTmr->pWnd == Window) || (Window == NULL)) )
         {
-           Msg.hwnd    = (pTmr->pWnd) ? pTmr->pWnd->hSelf : 0;
+           Msg.hwnd    = (pTmr->pWnd) ? pTmr->pWnd->head.h : 0;
            Msg.message = (pTmr->flags & TMRF_SYSTEM) ? WM_SYSTIMER : WM_TIMER;
            Msg.wParam  = (WPARAM) pTmr->nID;
            Msg.lParam  = (LPARAM) pTmr->pfn;
@@ -319,13 +363,14 @@ PostTimerMessages(PWINDOW_OBJECT Window)
            pTmr->flags &= ~TMRF_READY;
            ThreadQueue->WakeMask = ~QS_TIMER;
            Hit = TRUE;
+           break;
         }
 
      pLE = pTmr->ptmrList.Flink;
      pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
   } while (pTmr != FirstpTmr);
 
-  KeLeaveCriticalRegion();
+  TimerLeave();
 
   return Hit;
 }
@@ -342,12 +387,12 @@ ProcessTimers(VOID)
 
   if (!pTmr) return;
 
-  UserEnterExclusive();
+  TimerEnterExclusive();
 
   KeQueryTickCount(&TickCount);
   Time = MsqCalculateMessageTime(&TickCount);
 
-  DueTime.QuadPart = (LONGLONG)(-1000000);
+  DueTime.QuadPart = (LONGLONG)(-500000);
 
   do
   {
@@ -389,25 +434,7 @@ ProcessTimers(VOID)
                 }
              }
           }
-          if (pTmr->flags & TMRF_DELETEPENDING)
-          {
-             DPRINT("Removing Timer %x from List\n", pTmr);
-
-             /* FIXME: Fix this!!!! */
-/*
-             if (!pTmr->pWnd)
-             {
-                DPRINT1("Clearing Bits for WindowLess Timer\n");
-                IntLockWindowlessTimerBitmap();
-                RtlSetBits(&WindowLessTimersBitMap, pTmr->nID, 1);
-                IntUnlockWindowlessTimerBitmap();
-             }
-*/
-             RemoveEntryList(&pTmr->ptmrList);
-             UserDeleteObject( UserHMGetHandle(pTmr), otTimer);
-          }
-           else
-             pTmr->cmsCountdown = pTmr->cmsRate;
+          pTmr->cmsCountdown = pTmr->cmsRate;
        }
        else
           pTmr->cmsCountdown -= Time - TimeLast;
@@ -423,108 +450,12 @@ ProcessTimers(VOID)
 
   TimeLast = Time;
 
-  UserLeave();
+  TimerLeave();
   DPRINT("TimerCount = %d\n", TimerCount);
 }
 
-//
-//
-// Old Timer Queueing
-//
-//
-UINT_PTR FASTCALL
-InternalSetTimer(HWND Wnd, UINT_PTR IDEvent, UINT Elapse, TIMERPROC TimerFunc, BOOL SystemTimer)
-{
-   PWINDOW_OBJECT Window;
-   UINT_PTR Ret = 0;
-   PTHREADINFO pti;
-   PUSER_MESSAGE_QUEUE MessageQueue;
-
-   DPRINT("IntSetTimer wnd %x id %p elapse %u timerproc %p systemtimer %s\n",
-          Wnd, IDEvent, Elapse, TimerFunc, SystemTimer ? "TRUE" : "FALSE");
-
-   if ((Wnd == NULL) && ! SystemTimer)
-   {
-      DPRINT("Window-less timer\n");
-      /* find a free, window-less timer id */
-      IntLockWindowlessTimerBitmap();
-      IDEvent = RtlFindClearBitsAndSet(&WindowLessTimersBitMap, 1, HintIndex);
-
-      if (IDEvent == (UINT_PTR) -1)
-      {
-         IntUnlockWindowlessTimerBitmap();
-         DPRINT1("Unable to find a free window-less timer id\n");
-         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-         return 0;
-      }
-
-      HintIndex = ++IDEvent;
-      IntUnlockWindowlessTimerBitmap();
-      Ret = IDEvent;
-      pti = PsGetCurrentThreadWin32Thread();
-      MessageQueue = pti->MessageQueue;
-   }
-   else
-   {
-      if (!(Window = UserGetWindowObject(Wnd)))
-      {
-         DPRINT1("Invalid window handle\n");
-         return 0;
-      }
-
-      if (Window->pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
-      {
-         DPRINT1("Trying to set timer for window in another process (shatter attack?)\n");
-         SetLastWin32Error(ERROR_ACCESS_DENIED);
-         return 0;
-      }
-
-      Ret = IDEvent;
-      MessageQueue = Window->pti->MessageQueue;
-   }
-
-#if 0
-
-   /* Windows NT/2k/XP behaviour */
-   if (Elapse > 0x7fffffff)
-   {
-      DPRINT("Adjusting uElapse\n");
-      Elapse = 1;
-   }
-
-#else
-
-   /* Windows XP SP2 and Windows Server 2003 behaviour */
-   if (Elapse > 0x7fffffff)
-   {
-      DPRINT("Adjusting uElapse\n");
-      Elapse = 0x7fffffff;
-   }
-
-#endif
-
-   /* Windows 2k/XP and Windows Server 2003 SP1 behaviour */
-   if (Elapse < 10)
-   {
-      DPRINT("Adjusting uElapse\n");
-      Elapse = 10;
-   }
-
-   if (! MsqSetTimer(MessageQueue, Wnd,
-                     IDEvent, Elapse, TimerFunc,
-                     SystemTimer ? WM_SYSTIMER : WM_TIMER))
-   {
-      DPRINT1("Failed to set timer in message queue\n");
-      SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-      return 0;
-   }
-
-if (Ret == 0) ASSERT(FALSE);
-   return Ret;
-}
-
 BOOL FASTCALL
-DestroyTimersForWindow(PTHREADINFO pti, PWINDOW_OBJECT Window)
+DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
 {
    PLIST_ENTRY pLE;
    PTIMER pTmr = FirstpTmr;
@@ -533,21 +464,19 @@ DestroyTimersForWindow(PTHREADINFO pti, PWINDOW_OBJECT Window)
    if ((FirstpTmr == NULL) || (Window == NULL))
       return FALSE;
 
-   KeEnterCriticalRegion();
+   TimerEnterExclusive();
 
    do
    {
       if ((pTmr) && (pTmr->pti == pti) && (pTmr->pWnd == Window))
       {
-         pTmr->flags &= ~TMRF_READY;
-         pTmr->flags |= TMRF_DELETEPENDING;
-         TimersRemoved = TRUE;
+         TimersRemoved = RemoveTimer(pTmr);
       }
       pLE = pTmr->ptmrList.Flink;
       pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
    } while (pTmr != FirstpTmr);
 
-   KeLeaveCriticalRegion();
+   TimerLeave();
 
    return TimersRemoved;
 }
@@ -562,98 +491,45 @@ DestroyTimersForThread(PTHREADINFO pti)
    if (FirstpTmr == NULL)
       return FALSE;
 
-   KeEnterCriticalRegion();
+   TimerEnterExclusive();
 
    do
    {
       if ((pTmr) && (pTmr->pti == pti))
       {
-         pTmr->flags &= ~TMRF_READY;
-         pTmr->flags |= TMRF_DELETEPENDING;
-         TimersRemoved = TRUE;
+         TimersRemoved = RemoveTimer(pTmr);
       }
       pLE = pTmr->ptmrList.Flink;
       pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
    } while (pTmr != FirstpTmr);
 
-   KeLeaveCriticalRegion();
+   TimerLeave();
 
    return TimersRemoved;
 }
 
 BOOL FASTCALL
-IntKillTimer(PWINDOW_OBJECT Window, UINT_PTR IDEvent, BOOL SystemTimer)
+IntKillTimer(PWND Window, UINT_PTR IDEvent, BOOL SystemTimer)
 {
    PTIMER pTmr = NULL;
    DPRINT("IntKillTimer Window %x id %p systemtimer %s\n",
           Window, IDEvent, SystemTimer ? "TRUE" : "FALSE");
 
-   if (IDEvent == 0)
-      return FALSE;
+   pTmr = FindTimer(Window, IDEvent, SystemTimer ? TMRF_SYSTEM : 0);
 
-   pTmr = FindTimer(Window, IDEvent, SystemTimer ? TMRF_SYSTEM : 0, TRUE);
-   return pTmr ? TRUE :  FALSE;
-}
-
-//
-//
-// Old Kill Timer
-//
-//
-BOOL FASTCALL
-InternalKillTimer(HWND Wnd, UINT_PTR IDEvent, BOOL SystemTimer)
-{
-   PTHREADINFO pti;
-   PWINDOW_OBJECT Window = NULL;
-
-   DPRINT("IntKillTimer wnd %x id %p systemtimer %s\n",
-          Wnd, IDEvent, SystemTimer ? "TRUE" : "FALSE");
-
-   pti = PsGetCurrentThreadWin32Thread();
-   if (Wnd)
+   if (pTmr)
    {
-      Window = UserGetWindowObject(Wnd);
-
-      if (! MsqKillTimer(pti->MessageQueue, Wnd,
-                                IDEvent, SystemTimer ? WM_SYSTIMER : WM_TIMER))
-      {
-         // Give it another chance to find the timer.
-         if (Window && !( MsqKillTimer(Window->pti->MessageQueue, Wnd,
-                            IDEvent, SystemTimer ? WM_SYSTIMER : WM_TIMER)))
-         {
-            DPRINT1("Unable to locate timer in message queue for Window.\n");
-            SetLastWin32Error(ERROR_INVALID_PARAMETER);
-            return FALSE;
-         }
-      }
+      TimerEnterExclusive();
+      RemoveTimer(pTmr);
+      TimerLeave();
    }
 
-   /* window-less timer? */
-   if ((Wnd == NULL) && ! SystemTimer)
-   {
-      if (! MsqKillTimer(pti->MessageQueue, Wnd,
-                                IDEvent, SystemTimer ? WM_SYSTIMER : WM_TIMER))
-      {
-         DPRINT1("Unable to locate timer in message queue for Window-less timer.\n");
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return FALSE;
-      }
-
-      /* Release the id */
-      IntLockWindowlessTimerBitmap();
-
-      ASSERT(RtlAreBitsSet(&WindowLessTimersBitMap, IDEvent - 1, 1));
-      RtlClearBits(&WindowLessTimersBitMap, IDEvent - 1, 1);
-
-      HintIndex = IDEvent - 1;
-
-      IntUnlockWindowlessTimerBitmap();
-   }
-
-   return TRUE;
+   return pTmr ? TRUE :  FALSE;
 }
 
-NTSTATUS FASTCALL
+INIT_FUNCTION
+NTSTATUS
+NTAPI
 InitTimerImpl(VOID)
 {
    ULONG BitmapBytes;
@@ -661,7 +537,7 @@ InitTimerImpl(VOID)
    ExInitializeFastMutex(&Mutex);
 
    BitmapBytes = ROUND_UP(NUM_WINDOW_LESS_TIMERS, sizeof(ULONG) * 8) / 8;
-   WindowLessTimersBitMapBuffer = ExAllocatePoolWithTag(PagedPool, BitmapBytes, TAG_TIMERBMP);
+   WindowLessTimersBitMapBuffer = ExAllocatePoolWithTag(NonPagedPool, BitmapBytes, TAG_TIMERBMP);
    if (WindowLessTimersBitMapBuffer == NULL)
    {
       return STATUS_UNSUCCESSFUL;
@@ -671,7 +547,7 @@ InitTimerImpl(VOID)
                        WindowLessTimersBitMapBuffer,
                        BitmapBytes * 8);
 
-   /* yes we need this, since ExAllocatePool isn't supposed to zero out allocated memory */
+   /* yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */
    RtlClearAllBits(&WindowLessTimersBitMap);
 
    return STATUS_SUCCESS;
@@ -687,16 +563,19 @@ NtUserSetTimer
    TIMERPROC lpTimerFunc
 )
 {
+   PWND Window;
    DECLARE_RETURN(UINT_PTR);
 
    DPRINT("Enter NtUserSetTimer\n");
    UserEnterExclusive();
+   Window = UserGetWindowObject(hWnd);
+   UserLeave();
 
-   RETURN(IntSetTimer(UserGetWindowObject(hWnd), nIDEvent, uElapse, lpTimerFunc, 0));
+   RETURN(IntSetTimer(Window, nIDEvent, uElapse, lpTimerFunc, TMRF_TIFROMWND));
 
 CLEANUP:
    DPRINT("Leave NtUserSetTimer, ret=%i\n", _ret_);
-   UserLeave();
+
    END_CLEANUP;
 }
 
@@ -709,19 +588,18 @@ NtUserKillTimer
    UINT_PTR uIDEvent
 )
 {
-   PWINDOW_OBJECT Window;
+   PWND Window;
    DECLARE_RETURN(BOOL);
 
    DPRINT("Enter NtUserKillTimer\n");
    UserEnterExclusive();
-
    Window = UserGetWindowObject(hWnd);
+   UserLeave();
 
    RETURN(IntKillTimer(Window, uIDEvent, FALSE));
 
 CLEANUP:
    DPRINT("Leave NtUserKillTimer, ret=%i\n", _ret_);
-   UserLeave();
    END_CLEANUP;
 }
 
@@ -738,14 +616,11 @@ NtUserSetSystemTimer(
    DECLARE_RETURN(UINT_PTR);
 
    DPRINT("Enter NtUserSetSystemTimer\n");
-   UserEnterExclusive();
 
-   // This is wrong, lpTimerFunc is NULL!
-   RETURN(IntSetTimer(UserGetWindowObject(hWnd), nIDEvent, uElapse, lpTimerFunc, TMRF_SYSTEM));
+   RETURN(IntSetTimer(UserGetWindowObject(hWnd), nIDEvent, uElapse, NULL, TMRF_SYSTEM));
 
 CLEANUP:
    DPRINT("Leave NtUserSetSystemTimer, ret=%i\n", _ret_);
-   UserLeave();
    END_CLEANUP;
 }