Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 51940)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 51941)
@@ -577,4 +577,5 @@
 #endif
         }
+        RTTermRunCallbacks(RTTERMREASON_UNLOAD, 0);
         RTR0Term();
     }
@@ -614,4 +615,5 @@
     supdrvNtProtectTerm();
 #endif
+    RTTermRunCallbacks(RTTERMREASON_UNLOAD, 0);
     RTR0Term();
     vboxdrvNtDestroyDevices();
Index: /trunk/src/VBox/Runtime/common/misc/once.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/once.cpp	(revision 51940)
+++ /trunk/src/VBox/Runtime/common/misc/once.cpp	(revision 51941)
@@ -34,5 +34,13 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
-#include <iprt/critsect.h>
+#ifdef IN_RING3
+# include <iprt/critsect.h>
+# define RTONCE_USE_CRITSECT_FOR_TERM
+#elif defined(IN_RING0)
+# include <iprt/spinlock.h>
+# define RTONCE_USE_SPINLOCK_FOR_TERM
+#else
+# define RTONCE_NO_TERM
+#endif
 #include <iprt/err.h>
 #include <iprt/initterm.h>
@@ -44,12 +52,30 @@
 *   Global Variables                                                           *
 *******************************************************************************/
-#ifdef IN_RING3
-
+#ifndef RTONCE_NO_TERM
 /** For initializing the clean-up list code. */
 static RTONCE           g_OnceCleanUp = RTONCE_INITIALIZER;
-/** Critical section protecting the clean-up list. */
+/** Lock protecting the clean-up list. */
+#ifdef RTONCE_USE_CRITSECT_FOR_TERM
 static RTCRITSECT       g_CleanUpCritSect;
+#else
+static RTSEMFASTMUTEX   g_hCleanUpLock;
+#endif
 /** The clean-up list. */
 static RTLISTANCHOR     g_CleanUpList;
+
+/** Locks the clean-up list. */
+#ifdef RTONCE_USE_CRITSECT_FOR_TERM
+# define RTONCE_CLEANUP_LOCK()      RTCritSectEnter(&g_CleanUpCritSect)
+#else
+# define RTONCE_CLEANUP_LOCK()      RTSemFastMutexRequest(g_hCleanUpLock);
+#endif
+
+/** Unlocks the clean-up list. */
+#ifdef RTONCE_USE_CRITSECT_FOR_TERM
+# define RTONCE_CLEANUP_UNLOCK()    RTCritSectLeave(&g_CleanUpCritSect);
+#else
+# define RTONCE_CLEANUP_UNLOCK()    RTSemFastMutexRelease(g_hCleanUpLock);
+#endif
+
 
 
@@ -58,5 +84,5 @@
 {
     bool const fLazyCleanUpOk = RTTERMREASON_IS_LAZY_CLEANUP_OK(enmReason);
-    RTCritSectEnter(&g_CleanUpCritSect); /* Potentially dangerous. */
+    RTONCE_CLEANUP_LOCK();      /* Potentially dangerous. */
 
     PRTONCE pCur, pPrev;
@@ -87,6 +113,23 @@
     }
 
-    RTCritSectLeave(&g_CleanUpCritSect);
-    NOREF(pvUser); NOREF(enmReason); NOREF(iStatus);
+    RTONCE_CLEANUP_UNLOCK();
+
+    /*
+     * Reset our own structure and the critsect / mutex.
+     */
+    if (!fLazyCleanUpOk)
+    {
+# ifdef RTONCE_USE_CRITSECT_FOR_TERM
+        RTCritSectDelete(&g_CleanUpCritSect);
+# else
+        RTSemFastMutexDestroy(g_hCleanUpLock);
+        g_hCleanUpLock = NIL_RTSEMFASTMUTEX;
+# endif
+
+        ASMAtomicWriteS32(&g_OnceCleanUp.rc, VERR_INTERNAL_ERROR);
+        ASMAtomicWriteS32(&g_OnceCleanUp.iState, RTONCESTATE_UNINITIALIZED);
+    }
+
+    NOREF(pvUser); NOREF(iStatus);
 }
 
@@ -103,5 +146,9 @@
     NOREF(pvUser);
     RTListInit(&g_CleanUpList);
+# ifdef RTONCE_USE_CRITSECT_FOR_TERM
     int rc = RTCritSectInit(&g_CleanUpCritSect);
+# else
+    int rc = RTSemFastMutexCreate(&g_hCleanUpLock);
+# endif
     if (RT_SUCCESS(rc))
     {
@@ -110,12 +157,15 @@
             return rc;
 
+# ifdef RTONCE_USE_CRITSECT_FOR_TERM
         RTCritSectDelete(&g_CleanUpCritSect);
+# else
+        RTSemFastMutexDestroy(g_hCleanUpLock);
+        g_hCleanUpLock = NIL_RTSEMFASTMUTEX;
+# endif
     }
     return rc;
 }
 
-#endif /* IN_RING3 */
-
-
+#endif /* !RTONCE_NO_TERM */
 
 /**
@@ -262,7 +312,7 @@
                  , VERR_INTERNAL_ERROR);
 
-#ifndef IN_RING3
+#ifdef RTONCE_NO_TERM
     AssertReturn(!pfnCleanUp, VERR_NOT_SUPPORTED);
-#else /* IN_RING3 */
+#else /* !RTONCE_NO_TERM */
 
     /*
@@ -275,5 +325,5 @@
             return rc;
     }
-#endif /* IN_RING3 */
+#endif /* !RTONCE_NO_TERM */
 
     /*
@@ -290,5 +340,5 @@
         ASMAtomicWriteS32(&pOnce->rc, rcOnce);
 
-#ifdef IN_RING3
+#ifndef RTONCE_NO_TERM
         /*
          * Register clean-up if requested and we were successful.
@@ -296,11 +346,13 @@
         if (pfnCleanUp && RT_SUCCESS(rcOnce))
         {
-            RTCritSectEnter(&g_CleanUpCritSect);
+            RTONCE_CLEANUP_LOCK();
+
             pOnce->pfnCleanUp = pfnCleanUp;
             pOnce->pvUser     = pvUser;
             RTListAppend(&g_CleanUpList, &pOnce->CleanUpNode);
-            RTCritSectLeave(&g_CleanUpCritSect);
+
+            RTONCE_CLEANUP_UNLOCK();
         }
-#endif
+#endif /* !RTONCE_NO_TERM */
 
         /*
@@ -367,15 +419,17 @@
     NOREF(iState);
 
-#ifdef IN_RING3
+#ifndef RTONCE_NO_TERM
     /* Unregister clean-up. */
     if (pOnce->pfnCleanUp)
     {
-        RTCritSectEnter(&g_CleanUpCritSect);
+        RTONCE_CLEANUP_LOCK();
+
         RTListNodeRemove(&pOnce->CleanUpNode);
         pOnce->pfnCleanUp = NULL;
         pOnce->pvUser     = NULL;
-        RTCritSectLeave(&g_CleanUpCritSect);
-    }
-#endif /* IN_RING3 */
+
+        RTONCE_CLEANUP_UNLOCK();
+    }
+#endif /* !RTONCE_NO_TERM */
 
     /* Do the same as RTONCE_INITIALIZER does. */
Index: /trunk/src/VBox/Runtime/common/rand/rand.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/rand/rand.cpp	(revision 51940)
+++ /trunk/src/VBox/Runtime/common/rand/rand.cpp	(revision 51941)
@@ -81,7 +81,30 @@
 
 
+/**
+ * Termination counterpart to rtRandInitOnce.
+ *
+ * @returns IPRT status code.
+ * @param   pvUser          Ignored.
+ * @param   fLazyCleanUpOk  Set if we're terminating the process.
+ */
+static DECLCALLBACK(void) rtRandTermOnce(void *pvUser, bool fLazyCleanUpOk)
+{
+    if (!fLazyCleanUpOk)
+    {
+        RTRAND hRand = g_hRand;
+        g_hRand = NIL_RTRAND;
+        if (hRand != NIL_RTRAND)
+        {
+            int rc = RTRandAdvDestroy(hRand);
+            AssertRC(rc);
+        }
+    }
+    NOREF(pvUser);
+}
+
+
 RTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     RTRandAdvBytes(g_hRand, pv, cb);
 }
@@ -91,5 +114,5 @@
 RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvU32Ex(g_hRand, u32First, u32Last);
 }
@@ -99,5 +122,5 @@
 RTDECL(uint32_t) RTRandU32(void) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvU32(g_hRand);
 }
@@ -107,5 +130,5 @@
 RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvS32Ex(g_hRand, i32First, i32Last);
 }
@@ -115,5 +138,5 @@
 RTDECL(int32_t) RTRandS32(void) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvS32(g_hRand);
 }
@@ -123,5 +146,5 @@
 RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvU64Ex(g_hRand, u64First, u64Last);
 }
@@ -131,5 +154,5 @@
 RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvU64(g_hRand);
 }
@@ -139,5 +162,5 @@
 RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvS64Ex(g_hRand, i64First, i64Last);
 }
@@ -147,5 +170,5 @@
 RTDECL(int64_t) RTRandS64(void) RT_NO_THROW
 {
-    RTOnce(&g_rtRandOnce, rtRandInitOnce, NULL);
+    RTOnceEx(&g_rtRandOnce, rtRandInitOnce, rtRandTermOnce, NULL);
     return RTRandAdvS32(g_hRand);
 }
