Index: /trunk/include/iprt/timer.h
===================================================================
--- /trunk/include/iprt/timer.h	(revision 54511)
+++ /trunk/include/iprt/timer.h	(revision 54512)
@@ -145,4 +145,7 @@
  *
  * @returns iprt status code.
+ * @retval  VERR_WRONG_CONTEXT if executing at the wrong IRQL (windows), PIL
+ *          (solaris), or similar.  Portable code does not destroy timers with
+ *          preemption (or interrupts) disabled.
  * @param   pTimer      Timer to stop and destroy. NULL is ok.
  */
Index: /trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp	(revision 54511)
+++ /trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp	(revision 54512)
@@ -36,5 +36,6 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
-#include <iprt/alloc.h>
+#include <iprt/mem.h>
+#include <iprt/thread.h>
 
 #include "internal-r0drv-nt.h"
@@ -59,4 +60,6 @@
     /** Pointer to the parent timer. */
     PRTTIMER                pParent;
+    /** Thread active executing the worker function, NIL if inactive. */
+    RTNATIVETHREAD volatile hActiveThread;
     /** The NT DPC object. */
     KDPC                    NtDpc;
@@ -187,4 +190,6 @@
         &&  pTimer->u32Magic == RTTIMER_MAGIC)
     {
+        ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, RTThreadNativeSelf());
+
         if (!pTimer->u64NanoInterval)
             ASMAtomicWriteBool(&pTimer->fSuspended, true);
@@ -193,4 +198,6 @@
             rtTimerNtRearmInternval(pTimer, iTick, &pTimer->aSubTimers[0].NtDpc);
         pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick);
+
+        ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, NIL_RTNATIVETHREAD);
     }
 
@@ -227,4 +234,6 @@
         &&  pTimer->u32Magic == RTTIMER_MAGIC)
     {
+        ASMAtomicWriteHandle(&pSubTimer->hActiveThread, RTThreadNativeSelf());
+
         if (!pTimer->u64NanoInterval)
             if (ASMAtomicDecS32(&pTimer->cOmniSuspendCountDown) <= 0)
@@ -232,4 +241,6 @@
 
         pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick);
+
+        ASMAtomicWriteHandle(&pSubTimer->hActiveThread, NIL_RTNATIVETHREAD);
     }
 
@@ -272,4 +283,6 @@
         RTCPUSET    OnlineSet;
         RTMpGetOnlineSet(&OnlineSet);
+
+        ASMAtomicWriteHandle(&pSubTimer->hActiveThread, RTThreadNativeSelf());
 
         if (pTimer->u64NanoInterval)
@@ -309,4 +322,6 @@
             pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick);
         }
+
+        ASMAtomicWriteHandle(&pSubTimer->hActiveThread, NIL_RTNATIVETHREAD);
     }
 
@@ -379,16 +394,9 @@
      */
     ASMAtomicWriteBool(&pTimer->fSuspended, true);
+
     KeCancelTimer(&pTimer->NtTimer);
 
     for (RTCPUID iCpu = 0; iCpu < pTimer->cSubTimers; iCpu++)
         KeRemoveQueueDpc(&pTimer->aSubTimers[iCpu].NtDpc);
-
-    /*
-     * I'm a bit uncertain whether this should be done during RTTimerStop
-     * or only in RTTimerDestroy()... Linux and Solaris will wait AFAIK,
-     * which is why I'm keeping this here for now.
-     */
-    if (g_pfnrtNtKeFlushQueuedDpcs)
-        g_pfnrtNtKeFlushQueuedDpcs();
 }
 
@@ -431,4 +439,10 @@
 
     /*
+     * We do not support destroying a timer from the callback because it is
+     * not 101% safe since we cannot flush DPCs.  Solaris has the same restriction.
+     */
+    AssertReturn(KeGetCurrentIrql() == PASSIVE_LEVEL, VERR_INVALID_CONTEXT);
+
+    /*
      * Invalidate the timer, stop it if it's running and finally
      * free up the memory.
@@ -437,4 +451,11 @@
     if (!ASMAtomicUoReadBool(&pTimer->fSuspended))
         rtTimerNtStopWorker(pTimer);
+
+    /*
+     * Flush DPCs to be on the safe side.
+     */
+    if (g_pfnrtNtKeFlushQueuedDpcs)
+        g_pfnrtNtKeFlushQueuedDpcs();
+
     RTMemFree(pTimer);
 
Index: /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp	(revision 54511)
+++ /trunk/src/VBox/Runtime/testcase/tstRTR0Timer.cpp	(revision 54512)
@@ -520,5 +520,5 @@
 #endif
 
-#if !defined(RT_OS_SOLARIS) /* Not expected to work on all hosts. */
+#if !defined(RT_OS_SOLARIS) && !defined(RT_OS_WINDOWS) /* Not expected to work on all hosts. */
         case TSTRTR0TIMER_ONE_SHOT_DESTROY:
         case TSTRTR0TIMER_ONE_SHOT_DESTROY_HIRES:
