Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 37590)
+++ /trunk/include/iprt/err.h	(revision 37591)
@@ -1640,4 +1640,10 @@
 /** @} */
 
+/** @name RTDvm status codes
+ * @{ */
+/** The internal logger revision did not match. */
+#define VERR_LOG_REVISION_MISMATCH                  (-22300)
+/** @} */
+
 /* SED-END */
 
Index: /trunk/include/iprt/log.h
===================================================================
--- /trunk/include/iprt/log.h	(revision 37590)
+++ /trunk/include/iprt/log.h	(revision 37591)
@@ -264,5 +264,6 @@
     uint32_t                offScratch;
     /** This is set if a prefix is pending. */
-    uint32_t                fPendingPrefix;
+    bool                    fPendingPrefix;
+    bool                    afAlignment[3];
     /** Pointer to the logger function.
      * This is actually pointer to a wrapper which will push a pointer to the
@@ -291,6 +292,6 @@
 #ifndef IN_RC
 
-/** Pointer to file logging bits for the logger. */
-typedef struct RTLOGGERFILE *PRTLOGGERFILE;
+/** Pointer to internal logger bits. */
+typedef struct RTLOGGERINTERNAL *PRTLOGGERINTERNAL;
 
 /**
@@ -301,23 +302,7 @@
     /** Pointer to temporary scratch buffer.
      * This is used to format the log messages. */
-    char                    achScratch[32768];
+    char                    achScratch[49152];
     /** Current scratch buffer position. */
     uint32_t                offScratch;
-    /** This is set if a prefix is pending. */
-    uint32_t                fPendingPrefix;
-    /** Pointer to the logger function.
-     * This is actually pointer to a wrapper which will push a pointer to the
-     * instance pointer onto the stack before jumping to the real logger function.
-     * A very unfortunate hack to work around the missing variadic macro support in C++.
-     * (The memory is (not R0) allocated using RTMemExecAlloc().) */
-    PFNRTLOGGER             pfnLogger;
-    /** Pointer to the flush function. */
-    PFNRTLOGFLUSH           pfnFlush;
-    /** Custom prefix callback. */
-    PFNRTLOGPREFIX          pfnPrefix;
-    /** Prefix callback argument. */
-    void                   *pvPrefixUserArg;
-    /** Spinning mutex semaphore. */
-    RTSEMSPINMUTEX          hSpinMtx;
     /** Magic number. */
     uint32_t                u32Magic;
@@ -326,15 +311,15 @@
     /** Destination flags - RTLOGDEST. */
     uint32_t                fDestFlags;
-    /** Currently unused field. */
-    uint32_t                uUnused;
-    /** Pointer to the file related logging information.
+    /** Pointer to the internal bits of the logger.
      * (The memory is allocated in the same block as RTLOGGER.) */
-    PRTLOGGERFILE           pFile;
-    /** Pointer to the group name array.
-     * (The data is readonly and provided by the user.) */
-    const char * const     *papszGroups;
-    /** The max number of groups that there is room for in afGroups and papszGroups.
-     * Used by RTLogCopyGroupAndFlags(). */
-    uint32_t                cMaxGroups;
+    PRTLOGGERINTERNAL       pInt;
+    /** Pointer to the logger function (used in non-C99 mode only).
+     *
+     * This is actually pointer to a wrapper which will push a pointer to the
+     * instance pointer onto the stack before jumping to the real logger function.
+     * A very unfortunate hack to work around the missing variadic macro
+     * support in older C++/C standards.  (The memory is allocated using
+     * RTMemExecAlloc(), except for agnostic R0 code.) */
+    PFNRTLOGGER             pfnLogger;
     /** Number of groups in the afGroups and papszGroups members. */
     uint32_t                cGroups;
@@ -346,5 +331,5 @@
 
 /** RTLOGGER::u32Magic value. (Avram Noam Chomsky) */
-#define RTLOGGER_MAGIC      0x19281207
+# define RTLOGGER_MAGIC     UINT32_C(0x19281207)
 
 #endif /* !IN_RC */
@@ -372,4 +357,6 @@
     /** Flush the file to disk when flushing the buffer. */
     RTLOGFLAGS_FLUSH                = 0x00000200,
+    /** Restrict the number of log entries per group. */
+    RTLOGFLAGS_RESTRICT_GROUPS      = 0x00000400,
     /** New lines should be prefixed with the write and read lock counts. */
     RTLOGFLAGS_PREFIX_LOCK_COUNTS   = 0x00008000,
@@ -427,29 +414,29 @@
     /** Flow logging. */
     RTLOGGRPFLAGS_FLOW         = 0x00000080,
+    /** Restrict the number of log entries. */
+    RTLOGGRPFLAGS_RESTRICT     = 0x00000100,
 
     /** Lelik logging. */
-    RTLOGGRPFLAGS_LELIK        = 0x00000100,
+    RTLOGGRPFLAGS_LELIK        = 0x00010000,
     /** Michael logging. */
-    RTLOGGRPFLAGS_MICHAEL      = 0x00000200,
-    /** dmik logging. */
-    RTLOGGRPFLAGS_DMIK         = 0x00000400,
+    RTLOGGRPFLAGS_MICHAEL      = 0x00020000,
     /** sunlover logging. */
-    RTLOGGRPFLAGS_SUNLOVER     = 0x00000800,
+    RTLOGGRPFLAGS_SUNLOVER     = 0x00040000,
     /** Achim logging. */
-    RTLOGGRPFLAGS_ACHIM        = 0x00001000,
+    RTLOGGRPFLAGS_ACHIM        = 0x00080000,
     /** Sander logging. */
-    RTLOGGRPFLAGS_SANDER       = 0x00002000,
+    RTLOGGRPFLAGS_SANDER       = 0x00100000,
     /** Klaus logging. */
-    RTLOGGRPFLAGS_KLAUS        = 0x00004000,
+    RTLOGGRPFLAGS_KLAUS        = 0x00200000,
     /** Frank logging. */
-    RTLOGGRPFLAGS_FRANK        = 0x00008000,
+    RTLOGGRPFLAGS_FRANK        = 0x00400000,
     /** bird logging. */
-    RTLOGGRPFLAGS_BIRD         = 0x00010000,
+    RTLOGGRPFLAGS_BIRD         = 0x00800000,
     /** aleksey logging. */
-    RTLOGGRPFLAGS_ALEKSEY      = 0x00020000,
+    RTLOGGRPFLAGS_ALEKSEY      = 0x01000000,
     /** dj logging. */
-    RTLOGGRPFLAGS_DJ           = 0x00040000,
+    RTLOGGRPFLAGS_DJ           = 0x02000000,
     /** NoName logging. */
-    RTLOGGRPFLAGS_NONAME       = 0x00080000
+    RTLOGGRPFLAGS_NONAME       = 0x04000000
 } RTLOGGRPFLAGS;
 
@@ -621,9 +608,4 @@
  */
 #define LogMichael(a)   LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_MICHAEL,  LOG_GROUP, a)
-
-/** @def LogDmik
- * dmik logging.
- */
-#define LogDmik(a)      LogIt(LOG_INSTANCE, RTLOGGRPFLAGS_DMIK,     LOG_GROUP, a)
 
 /** @def LogSunlover
@@ -1064,9 +1046,4 @@
 #define LogRelMichael(a)   LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_MICHAEL,  LOG_GROUP, a)
 
-/** @def LogRelDmik
- * dmik logging.
- */
-#define LogRelDmik(a)      LogRelIt(LOG_REL_INSTANCE, RTLOGGRPFLAGS_DMIK,     LOG_GROUP, a)
-
 /** @def LogRelSunlover
  * sunlover logging.
@@ -1532,10 +1509,22 @@
  * @param   pLogger             Where to create the logger instance.
  * @param   cbLogger            The amount of memory available for the logger instance.
- * @param   pfnLogger           Pointer to logger wrapper function for the clone.
- * @param   pfnFlush            Pointer to flush function for the clone.
- * @param   fFlags              Logger instance flags for the clone, a combination of the RTLOGFLAGS_* values.
+ * @param   pLoggerR0Ptr        The ring-0 address corresponding to @a pLogger.
+ * @param   pfnLoggerR0Ptr      Pointer to logger wrapper function.
+ * @param   pfnFlushR0Ptr       Pointer to flush function.
+ * @param   fFlags              Logger instance flags, a combination of the RTLOGFLAGS_* values.
  * @param   fDestFlags          The destination flags.
  */
-RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger, PFNRTLOGGER pfnLogger, PFNRTLOGFLUSH pfnFlush, uint32_t fFlags, uint32_t fDestFlags);
+RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger,
+                             RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr,
+                             uint32_t fFlags, uint32_t fDestFlags);
+
+/**
+ * Calculates the minimum size of a ring-0 logger instance.
+ *
+ * @returns The minimum size.
+ * @param   cGroups             The number of groups.
+ * @param   fFlags              Relevant flags.
+ */
+RTDECL(size_t) RTLogCalcSizeForR0(uint32_t cGroups, uint32_t fFlags);
 
 /**
@@ -1598,13 +1587,28 @@
 
 /**
+ * Same as RTLogSetCustomPrefixCallback for loggers created by
+ * RTLogCreateForR0.
+ *
+ * @returns IPRT status code.
+ * @param   pLogger             The logger instance.
+ * @param   pLoggerR0Ptr        The ring-0 address corresponding to @a pLogger.
+ * @param   pfnCallbackR0Ptr    The callback.
+ * @param   pvUserR0Ptr         The user argument for the callback.
+ *  */
+RTDECL(int) RTLogSetCustomPrefixCallbackForR0(PRTLOGGER pLogger, RTR0PTR pLoggerR0Ptr,
+                                              RTR0PTR pfnCallbackR0Ptr, RTR0PTR pvUserR0Ptr);
+
+/**
  * Copies the group settings and flags from logger instance to another.
  *
  * @returns IPRT status code.
  * @param   pDstLogger      The destination logger instance.
+ * @param   pDstLoggerR0Ptr The ring-0 address corresponding to @a pDstLogger.
  * @param   pSrcLogger      The source logger instance. If NULL the default one is used.
  * @param   fFlagsOr        OR mask for the flags.
  * @param   fFlagsAnd       AND mask for the flags.
  */
-RTDECL(int) RTLogCopyGroupsAndFlags(PRTLOGGER pDstLogger, PCRTLOGGER pSrcLogger, unsigned fFlagsOr, unsigned fFlagsAnd);
+RTDECL(int) RTLogCopyGroupsAndFlagsForR0(PRTLOGGER pDstLogger, RTR0PTR pDstLoggerR0Ptr,
+                                         PCRTLOGGER pSrcLogger, uint32_t fFlagsOr, uint32_t fFlagsAnd);
 
 /**
@@ -1653,4 +1657,18 @@
  */
 RTDECL(bool) RTLogSetBuffering(PRTLOGGER pLogger, bool fBuffered);
+
+/**
+ * Sets the max number of entries per group.
+ *
+ * @returns Old restriction.
+ *
+ * @param   pLogger             The logger instance (NULL is an alias for the
+ *                              default logger).
+ * @param   cMaxEntriesPerGroup The max number of entries per group.
+ *
+ * @remarks Lowering the limit of an active logger may quietly mute groups.
+ *          Raising it may reactive already muted groups.
+ */
+RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup);
 
 #ifndef IN_RC
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 37590)
+++ /trunk/include/iprt/mangling.h	(revision 37591)
@@ -640,8 +640,9 @@
 # define RTLogBackdoorPrintf                            RT_MANGLER(RTLogBackdoorPrintf) /* r0drv-guest */
 # define RTLogBackdoorPrintfV                           RT_MANGLER(RTLogBackdoorPrintfV) /* r0drv-guest */
+# define RTLogCalcSizeForR0                             RT_MANGLER(RTLogCalcSizeForR0)
 # define RTLogCloneRC                                   RT_MANGLER(RTLogCloneRC)
 # define RTLogComPrintf                                 RT_MANGLER(RTLogComPrintf)
 # define RTLogComPrintfV                                RT_MANGLER(RTLogComPrintfV)
-# define RTLogCopyGroupsAndFlags                        RT_MANGLER(RTLogCopyGroupsAndFlags)
+# define RTLogCopyGroupsAndFlagsForR0                   RT_MANGLER(RTLogCopyGroupsAndFlagsForR0)
 # define RTLogCreate                                    RT_MANGLER(RTLogCreate)
 # define RTLogCreateEx                                  RT_MANGLER(RTLogCreateEx)
@@ -677,6 +678,8 @@
 # define RTLogSetBuffering                              RT_MANGLER(RTLogSetBuffering)
 # define RTLogSetCustomPrefixCallback                   RT_MANGLER(RTLogSetCustomPrefixCallback)
+# define RTLogSetCustomPrefixCallbackForR0              RT_MANGLER(RTLogSetCustomPrefixCallbackForR0)
 # define RTLogSetDefaultInstance                        RT_MANGLER(RTLogSetDefaultInstance)
 # define RTLogSetDefaultInstanceThread                  RT_MANGLER(RTLogSetDefaultInstanceThread) /* r0drv */
+# define RTLogSetGroupLimit                             RT_MANGLER(RTLogSetGroupLimit)
 # define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
 # define RTLogWriteCom                                  RT_MANGLER(RTLogWriteCom)
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 37590)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 37591)
@@ -190,11 +190,8 @@
  *  -# When increment the major number, execute all pending work.
  *
- * Skip versions:
- *  - 0x0018XXXX - Used by 4.0 for the >= 32/64 CPUs support.
- *
  * @todo Pending work on next major version change:
  *          - None.
  */
-#define SUPDRV_IOC_VERSION                              0x00170002
+#define SUPDRV_IOC_VERSION                              0x00190000
 
 /** SUP_IOCTL_COOKIE. */
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 37590)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 37591)
@@ -5993,12 +5993,12 @@
     }
 
-    PRTLOGGER loggerRelease;
-    static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
-    RTUINT fFlags = RTLOGFLAGS_PREFIX_TIME_PROG;
+    static const char * const   s_apszGroups[] = VBOX_LOGGROUP_NAMES;
+    char                        szError[RTPATH_MAX + 128] = "";
+    PRTLOGGER                   pReleaseLogger;
+    uint32_t                    fFlags = RTLOGFLAGS_PREFIX_TIME_PROG | RTLOGFLAGS_RESTRICT_GROUPS;
 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     fFlags |= RTLOGFLAGS_USECRLF;
 #endif
-    char szError[RTPATH_MAX + 128] = "";
-    int vrc = RTLogCreateEx(&loggerRelease, fFlags, "all",
+    int vrc = RTLogCreateEx(&pReleaseLogger, fFlags, "all all.restrict default.unrestricted",
                             "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_FILE,
                             NULL /* pfnBeginEnd */, 0 /* cHistory */, 0 /* cbHistoryFileMax */, 0 /* uHistoryTimeMax */,
@@ -6006,9 +6006,11 @@
     if (RT_SUCCESS(vrc))
     {
+        RTLogSetGroupLimit(pReleaseLogger, 32768);
+
         /* some introductory information */
         RTTIMESPEC timeSpec;
         char szTmp[256];
         RTTimeSpecToString(RTTimeNow(&timeSpec), szTmp, sizeof(szTmp));
-        RTLogRelLogger(loggerRelease, 0, ~0U,
+        RTLogRelLogger(pReleaseLogger, 0, ~0U,
                        "VirtualBox %s r%u %s (%s %s) release log\n"
 #ifdef VBOX_BLEEDING_EDGE
@@ -6021,20 +6023,20 @@
         vrc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "OS Product: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Product: %s\n", szTmp);
         vrc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "OS Release: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Release: %s\n", szTmp);
         vrc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "OS Version: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Version: %s\n", szTmp);
         vrc = RTSystemQueryOSInfo(RTSYSOSINFO_SERVICE_PACK, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "OS Service Pack: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "OS Service Pack: %s\n", szTmp);
         vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "DMI Product Name: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "DMI Product Name: %s\n", szTmp);
         vrc = RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_VERSION, szTmp, sizeof(szTmp));
         if (RT_SUCCESS(vrc) || vrc == VERR_BUFFER_OVERFLOW)
-            RTLogRelLogger(loggerRelease, 0, ~0U, "DMI Product Version: %s\n", szTmp);
+            RTLogRelLogger(pReleaseLogger, 0, ~0U, "DMI Product Version: %s\n", szTmp);
 
         ComPtr<IHost> pHost;
@@ -6044,5 +6046,5 @@
         pHost->COMGETTER(MemorySize)(&cMbHostRam);
         pHost->COMGETTER(MemoryAvailable)(&cMbHostRamAvail);
-        RTLogRelLogger(loggerRelease, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n",
+        RTLogRelLogger(pReleaseLogger, 0, ~0U, "Host RAM: %uMB RAM, available: %uMB\n",
                        cMbHostRam, cMbHostRamAvail);
 
@@ -6050,5 +6052,5 @@
         char szExecName[RTPATH_MAX];
         char *pszExecName = RTProcGetExecutablePath(szExecName, sizeof(szExecName));
-        RTLogRelLogger(loggerRelease, 0, ~0U,
+        RTLogRelLogger(pReleaseLogger, 0, ~0U,
                        "Executable: %s\n"
                        "Process ID: %u\n"
@@ -6063,9 +6065,9 @@
 
         /* register this logger as the release logger */
-        RTLogRelSetDefaultInstance(loggerRelease);
+        RTLogRelSetDefaultInstance(pReleaseLogger);
         hrc = S_OK;
 
         /* Explicitly flush the log in case of VBOX_RELEASE_LOG=buffered. */
-        RTLogFlush(loggerRelease);
+        RTLogFlush(pReleaseLogger);
     }
     else
Index: /trunk/src/VBox/Runtime/common/log/log.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/log/log.cpp	(revision 37590)
+++ /trunk/src/VBox/Runtime/common/log/log.cpp	(revision 37591)
@@ -72,29 +72,70 @@
 {
     /** The logger instance. */
-    PRTLOGGER   pLogger;
+    PRTLOGGER               pLogger;
     /** The flags. (used for prefixing.) */
-    unsigned    fFlags;
+    unsigned                fFlags;
     /** The group. (used for prefixing.) */
-    unsigned    iGroup;
+    unsigned                iGroup;
 } RTLOGOUTPUTPREFIXEDARGS, *PRTLOGOUTPUTPREFIXEDARGS;
 
-#ifdef IN_RING3
-/**
- * File logging bits for the logger.
- */
-typedef struct RTLOGGERFILE
-{
+/**
+ * Internal logger data.
+ *
+ * @remarks Don't make casual changes to this structure.
+ */
+typedef struct RTLOGGERINTERNAL
+{
+    /** The structure revision (RTLOGGERINTERNAL_REV). */
+    uint32_t                uRevision;
+    /** The size of the internal logger structure. */
+    uint32_t                cbSelf;
+
+    /** Spinning mutex semaphore.  Can be NIL. */
+    RTSEMSPINMUTEX          hSpinMtx;
+    /** Pointer to the flush function. */
+    PFNRTLOGFLUSH           pfnFlush;
+
+    /** Custom prefix callback. */
+    PFNRTLOGPREFIX          pfnPrefix;
+    /** Prefix callback argument. */
+    void                   *pvPrefixUserArg;
+    /** This is set if a prefix is pending. */
+    bool                    fPendingPrefix;
+    /** Alignment padding. */
+    bool                    afPadding1[3];
+
+    /** The max number of groups that there is room for in afGroups and papszGroups.
+     * Used by RTLogCopyGroupAndFlags(). */
+    uint32_t                cMaxGroups;
+    /** Pointer to the group name array.
+     * (The data is readonly and provided by the user.) */
+    const char * const     *papszGroups;
+
+    /** The number of log entries per group.  NULL if
+     * RTLOGFLAGS_RESTRICT_GROUPS is not specified. */
+    uint32_t               *pacEntriesPerGroup;
+    /** The max number of entries per group. */
+    uint32_t                cMaxEntriesPerGroup;
+    /** Padding.  */
+    uint32_t                u32Padding2;
+
+#ifdef IN_RING3 /* Note! Must be at the end! */
+    /** @name File logging bits for the logger.
+     * @{ */
     /** Pointer to the function called when starting logging, and when
      * ending or starting a new log file as part of history rotation.
      * This can be NULL. */
     PFNRTLOGPHASE           pfnPhase;
+
     /** Handle to log file (if open). */
-    RTFILE                  File;
-    /** Pointer to filename.
-     * (The memory is allocated in the same block as RTLOGGER.) */
-    char                   *pszFilename;
-    /** Log file history settings: number of older files to keep.
-     * 0 means no history. */
-    uint32_t                cHistory;
+    union
+    {
+        RTFILE              hFile;
+        RTHCUINTPTR         uPaddingForNewRTFILE;
+    } u;
+# if ARCH_BITS == 32
+    /** Alignment padding.  */
+    uint32_t                u32Padding;
+# endif
     /** Log file history settings: maximum amount of data to put in a file. */
     uint64_t                cbHistoryFileMax;
@@ -105,7 +146,22 @@
     /** Log file history settings: in what time slot was the file created. */
     uint32_t                uHistoryTimeSlotStart;
-} RTLOGGERFILE;
+    /** Log file history settings: number of older files to keep.
+     * 0 means no history. */
+    uint32_t                cHistory;
+    /** Pointer to filename. */
+    char                    szFilename[RTPATH_MAX];
+    /** @} */
 #endif /* IN_RING3 */
-
+} RTLOGGERINTERNAL;
+
+/** The revision of the internal logger structure. */
+#define RTLOGGERINTERNAL_REV    UINT32_C(9)
+
+#ifdef IN_RING3
+/** The size of the RTLOGGERINTERNAL structure in ring-0.  */
+# define RTLOGGERINTERNAL_R0_SIZE       RT_OFFSETOF(RTLOGGERINTERNAL, pfnPhase)
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, u.hFile, sizeof(void *));
+AssertCompileMemberAlignment(RTLOGGERINTERNAL, cbHistoryFileMax, sizeof(uint64_t));
+#endif
 
 /*******************************************************************************
@@ -126,4 +182,5 @@
 static DECLCALLBACK(size_t) rtLogOutputPrefixed(void *pv, const char *pachChars, size_t cbChars);
 static void rtlogLoggerExVLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, va_list args);
+static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...);
 
 
@@ -142,4 +199,5 @@
 static uint32_t volatile            g_cLoggerLockCount;
 #endif
+
 #ifdef IN_RING0
 /** Number of per-thread loggers. */
@@ -210,4 +268,5 @@
     { "tsc",          sizeof("tsc"         ) - 1,   RTLOGFLAGS_PREFIX_TSC,          false }, /* before ts! */
     { "ts",           sizeof("ts"          ) - 1,   RTLOGFLAGS_PREFIX_TS,           false },
+    /* We intentionally omit RTLOGFLAGS_RESTRICT_GROUPS. */
 };
 
@@ -244,7 +303,12 @@
 {
 #ifndef IN_RC
-    if (pLogger->hSpinMtx != NIL_RTSEMSPINMUTEX)
-    {
-        int rc = RTSemSpinMutexRequest(pLogger->hSpinMtx);
+    PRTLOGGERINTERNAL pInt = pLogger->pInt;
+    AssertMsgReturn(pInt->uRevision == RTLOGGERINTERNAL_REV, ("%#x != %#x\n", pInt->uRevision, RTLOGGERINTERNAL_REV),
+                    VERR_LOG_REVISION_MISMATCH);
+    AssertMsgReturn(pInt->cbSelf == sizeof(*pInt), ("%#x != %#x\n", pInt->cbSelf, sizeof(*pInt)),
+                    VERR_LOG_REVISION_MISMATCH);
+    if (pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+    {
+        int rc = RTSemSpinMutexRequest(pInt->hSpinMtx);
         if (RT_FAILURE(rc))
             return rc;
@@ -262,6 +326,6 @@
 {
 #ifndef IN_RC
-    if (pLogger->hSpinMtx != NIL_RTSEMSPINMUTEX)
-        RTSemSpinMutexRelease(pLogger->hSpinMtx);
+    if (pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX)
+        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
 #endif
     return;
@@ -281,5 +345,5 @@
 {
     PRTLOGGER pLogger = (PRTLOGGER)pvArg;
-    RTFileWrite(pLogger->pFile->File, pachChars, cbChars, NULL);
+    RTFileWrite(pLogger->pInt->u.hFile, pachChars, cbChars, NULL);
     return cbChars;
 }
@@ -325,6 +389,6 @@
     va_list args;
     AssertPtrReturnVoid(pLogger);
-    AssertPtrReturnVoid(pLogger->pFile);
-    Assert(pLogger->hSpinMtx != NIL_RTSEMSPINMUTEX);
+    AssertPtrReturnVoid(pLogger->pInt);
+    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
 
     va_start(args, pszFormat);
@@ -345,6 +409,6 @@
     va_list args;
     AssertPtrReturnVoid(pLogger);
-    AssertPtrReturnVoid(pLogger->pFile);
-    Assert(pLogger->hSpinMtx != NIL_RTSEMSPINMUTEX);
+    AssertPtrReturnVoid(pLogger->pInt);
+    Assert(pLogger->pInt->hSpinMtx != NIL_RTSEMSPINMUTEX);
 
     va_start(args, pszFormat);
@@ -356,12 +420,13 @@
 
 RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, uint32_t fFlags, const char *pszGroupSettings,
-                           const char *pszEnvVarBase, unsigned cGroups, const char * const * papszGroups,
+                           const char *pszEnvVarBase, unsigned cGroups, const char * const *papszGroups,
                            uint32_t fDestFlags, PFNRTLOGPHASE pfnPhase, uint32_t cHistory,
                            uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
                            char *pszErrorMsg, size_t cchErrorMsg, const char *pszFilenameFmt, va_list args)
 {
-    int        rc;
-    size_t     cb;
-    PRTLOGGER  pLogger;
+    int         rc;
+    size_t      offInternal;
+    size_t      cbLogger;
+    PRTLOGGER   pLogger;
 
     /*
@@ -384,43 +449,53 @@
      * Allocate a logger instance.
      */
-    cb = RT_OFFSETOF(RTLOGGER, afGroups[cGroups + 1]) + RTPATH_MAX;
-#ifdef IN_RING3
-    cb += sizeof(RTLOGGERFILE);
-#endif
-    pLogger = (PRTLOGGER)RTMemAllocZVar(cb);
+    offInternal = RT_OFFSETOF(RTLOGGER, afGroups[cGroups]);
+    offInternal = RT_ALIGN_Z(offInternal, sizeof(uint64_t));
+    cbLogger = offInternal;
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cbLogger += cGroups * sizeof(uint32_t);
+    pLogger = (PRTLOGGER)RTMemAllocZVar(offInternal + sizeof(RTLOGGERINTERNAL));
     if (pLogger)
     {
-#if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
+# if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
         uint8_t *pu8Code;
-#endif
-
-        pLogger->u32Magic    = RTLOGGER_MAGIC;
-        pLogger->papszGroups = papszGroups;
-        pLogger->cMaxGroups  = cGroups;
-        pLogger->cGroups     = cGroups;
-#ifdef IN_RING3
-        pLogger->pFile       = (PRTLOGGERFILE)((char *)&pLogger->afGroups[cGroups + 1] + RTPATH_MAX);
-        pLogger->pFile->File        = NIL_RTFILE;
-        pLogger->pFile->pszFilename = (char *)&pLogger->afGroups[cGroups + 1];
-        pLogger->pFile->pfnPhase    = pfnPhase;
-        pLogger->pFile->cHistory    = cHistory;
+# endif
+        pLogger->u32Magic       = RTLOGGER_MAGIC;
+        pLogger->cGroups        = cGroups;
+        pLogger->fFlags         = fFlags;
+        pLogger->fDestFlags     = fDestFlags;
+        pLogger->pInt           = (PRTLOGGERINTERNAL)((uintptr_t)pLogger + offInternal);
+        pLogger->pInt->uRevision                = RTLOGGERINTERNAL_REV;
+        pLogger->pInt->cbSelf                   = sizeof(RTLOGGERINTERNAL);
+        pLogger->pInt->hSpinMtx                 = NIL_RTSEMSPINMUTEX;
+        pLogger->pInt->pfnFlush                 = NULL;
+        pLogger->pInt->pfnPrefix                = NULL;
+        pLogger->pInt->pvPrefixUserArg          = NULL;
+        pLogger->pInt->afPadding1[0]            = false;
+        pLogger->pInt->afPadding1[1]            = false;
+        pLogger->pInt->afPadding1[2]            = false;
+        pLogger->pInt->cMaxGroups               = cGroups;
+        pLogger->pInt->papszGroups              = papszGroups;
+        if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+            pLogger->pInt->pacEntriesPerGroup   = (uint32_t *)(pLogger->pInt + 1);
+        else
+            pLogger->pInt->pacEntriesPerGroup   = NULL;
+        pLogger->pInt->cMaxEntriesPerGroup      = UINT32_MAX;
+# ifdef IN_RING3
+        pLogger->pInt->pfnPhase                 = pfnPhase;
+        pLogger->pInt->u.hFile                  = NIL_RTFILE;
+        pLogger->pInt->cHistory                 = cHistory;
         if (cbHistoryFileMax == 0)
-            pLogger->pFile->cbHistoryFileMax = UINT64_MAX;
+            pLogger->pInt->cbHistoryFileMax     = UINT64_MAX;
         else
-            pLogger->pFile->cbHistoryFileMax = cbHistoryFileMax;
+            pLogger->pInt->cbHistoryFileMax     = cbHistoryFileMax;
         if (cSecsHistoryTimeSlot == 0)
-            pLogger->pFile->cSecsHistoryTimeSlot = UINT32_MAX;
+            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
         else
-            pLogger->pFile->cSecsHistoryTimeSlot = cSecsHistoryTimeSlot;
-#else  /* !IN_RING3 */
-        pLogger->pFile       = NULL;
-#endif /* !IN_RING3 */
-        pLogger->fFlags      = fFlags;
-        pLogger->fDestFlags  = fDestFlags;
-        pLogger->fPendingPrefix = true;
+            pLogger->pInt->cSecsHistoryTimeSlot = cSecsHistoryTimeSlot;
+# endif  /* IN_RING3 */
         if (pszGroupSettings)
             RTLogGroupSettings(pLogger, pszGroupSettings);
 
-#if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
+# if defined(RT_ARCH_X86) && (!defined(LOG_USE_C99) || !defined(RT_WITHOUT_EXEC_ALLOC))
         /*
          * Emit wrapper code.
@@ -447,14 +522,14 @@
         else
         {
-# ifdef RT_OS_LINUX
+#  ifdef RT_OS_LINUX
             if (pszErrorMsg) /* Most probably SELinux causing trouble since the larger RTMemAlloc succeeded. */
                 RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("mmap(PROT_WRITE | PROT_EXEC) failed -- SELinux?"));
-# endif
+#  endif
             rc = VERR_NO_MEMORY;
         }
         if (RT_SUCCESS(rc))
-#endif /* X86 wrapper code*/
-        {
-#ifdef IN_RING3 /* files and env.vars. are only accessible when in R3 at the present time. */
+# endif /* X86 wrapper code*/
+        {
+# ifdef IN_RING3 /* files and env.vars. are only accessible when in R3 at the present time. */
             /*
              * Format the filename.
@@ -463,5 +538,5 @@
             {
                 /** @todo validate the length, fail on overflow. */
-                RTStrPrintfV(pLogger->pFile->pszFilename, RTPATH_MAX, pszFilenameFmt, args);
+                RTStrPrintfV(pLogger->pInt->szFilename, sizeof(pLogger->pInt->szFilename), pszFilenameFmt, args);
                 pLogger->fDestFlags |= RTLOGDEST_FILE;
             }
@@ -501,5 +576,5 @@
                     RTLogGroupSettings(pLogger, pszVar);
             }
-#endif /* IN_RING3 */
+# endif /* IN_RING3 */
 
             /*
@@ -507,5 +582,5 @@
              */
             rc = VINF_SUCCESS;
-#ifdef IN_RING3
+# ifdef IN_RING3
             if (pLogger->fDestFlags & RTLOGDEST_FILE)
             {
@@ -521,16 +596,16 @@
                 {
                     /* Force rotation if it is configured. */
-                    pLogger->pFile->cbHistoryFileWritten = UINT64_MAX;
+                    pLogger->pInt->cbHistoryFileWritten = UINT64_MAX;
                     rtlogRotate(pLogger, 0, true /* fFirst */);
 
                     /* If the file is not open then rotation is not set up. */
-                    if (pLogger->pFile->File == NIL_RTFILE)
+                    if (pLogger->pInt->u.hFile == NIL_RTFILE)
                     {
-                        pLogger->pFile->cbHistoryFileWritten = 0;
+                        pLogger->pInt->cbHistoryFileWritten = 0;
                         rc = rtlogFileOpen(pLogger, pszErrorMsg, cchErrorMsg);
                     }
                 }
             }
-#endif  /* IN_RING3 */
+# endif  /* IN_RING3 */
 
             /*
@@ -540,23 +615,23 @@
             if (RT_SUCCESS(rc))
             {
-                rc = RTSemSpinMutexCreate(&pLogger->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
+                rc = RTSemSpinMutexCreate(&pLogger->pInt->hSpinMtx, RTSEMSPINMUTEX_FLAGS_IRQ_SAFE);
                 if (RT_SUCCESS(rc))
                 {
-#ifdef IN_RING3 /** @todo do counters in ring-0 too? */
+# ifdef IN_RING3 /** @todo do counters in ring-0 too? */
                     RTTHREAD Thread = RTThreadSelf();
                     if (Thread != NIL_RTTHREAD)
                     {
                         int32_t c = RTLockValidatorWriteLockGetCount(Thread);
-                        RTSemSpinMutexRequest(pLogger->hSpinMtx);
+                        RTSemSpinMutexRequest(pLogger->pInt->hSpinMtx);
                         c = RTLockValidatorWriteLockGetCount(Thread) - c;
-                        RTSemSpinMutexRelease(pLogger->hSpinMtx);
+                        RTSemSpinMutexRelease(pLogger->pInt->hSpinMtx);
                         ASMAtomicWriteU32(&g_cLoggerLockCount, c);
                     }
 
                     /* Use the callback to generate some initial log contents. */
-                    Assert(VALID_PTR(pLogger->pFile->pfnPhase) || pLogger->pFile->pfnPhase == NULL);
-                    if (pLogger->pFile->pfnPhase)
-                        pLogger->pFile->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
-#endif
+                    Assert(VALID_PTR(pLogger->pInt->pfnPhase) || pLogger->pInt->pfnPhase == NULL);
+                    if (pLogger->pInt->pfnPhase)
+                        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_BEGIN, rtlogPhaseMsgNormal);
+# endif
                     *ppLogger = pLogger;
                     return VINF_SUCCESS;
@@ -566,12 +641,12 @@
                     RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("failed to create semaphore"));
             }
-#ifdef IN_RING3
-            RTFileClose(pLogger->pFile->File);
-#endif
-#if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
+# ifdef IN_RING3
+            RTFileClose(pLogger->pInt->u.hFile);
+# endif
+# if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
             RTMemFree(*(void **)&pLogger->pfnLogger);
-#else
+# else
             RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
-#endif
+# endif
         }
         RTMemFree(pLogger);
@@ -640,6 +715,7 @@
     if (!pLogger)
         return VINF_SUCCESS;
-    AssertReturn(VALID_PTR(pLogger), VERR_INVALID_POINTER);
+    AssertPtrReturn(pLogger, VERR_INVALID_POINTER);
     AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+    AssertPtrReturn(pLogger->pInt, VERR_INVALID_POINTER);
 
     /*
@@ -659,30 +735,30 @@
     rtlogFlush(pLogger);
 
-#ifdef IN_RING3
+# ifdef IN_RING3
     /*
      * Add end of logging message.
      */
     if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
-        && pLogger->pFile->File != NIL_RTFILE)
-        pLogger->pFile->pfnPhase(pLogger, RTLOGPHASE_END, rtlogPhaseMsgLocked);
+        && pLogger->pInt->u.hFile != NIL_RTFILE)
+        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_END, rtlogPhaseMsgLocked);
 
     /*
      * Close output stuffs.
      */
-    if (pLogger->pFile->File != NIL_RTFILE)
-    {
-        int rc2 = RTFileClose(pLogger->pFile->File);
+    if (pLogger->pInt->u.hFile != NIL_RTFILE)
+    {
+        int rc2 = RTFileClose(pLogger->pInt->u.hFile);
         AssertRC(rc2);
         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
             rc = rc2;
-        pLogger->pFile->File = NIL_RTFILE;
-    }
-#endif
+        pLogger->pInt->u.hFile = NIL_RTFILE;
+    }
+# endif
 
     /*
      * Free the mutex, the wrapper and the instance memory.
      */
-    hSpinMtx = pLogger->hSpinMtx;
-    pLogger->hSpinMtx = NIL_RTSEMSPINMUTEX;
+    hSpinMtx = pLogger->pInt->hSpinMtx;
+    pLogger->pInt->hSpinMtx = NIL_RTSEMSPINMUTEX;
     if (hSpinMtx != NIL_RTSEMSPINMUTEX)
     {
@@ -697,9 +773,9 @@
     if (pLogger->pfnLogger)
     {
-#if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
+# if defined(LOG_USE_C99) && defined(RT_WITHOUT_EXEC_ALLOC)
         RTMemFree(*(void **)&pLogger->pfnLogger);
-#else
+# else
         RTMemExecFree(*(void **)&pLogger->pfnLogger, 64);
-#endif
+# endif
         pLogger->pfnLogger = NULL;
     }
@@ -772,5 +848,5 @@
     {
         AssertMsgFailed(("%d req=%d cGroups=%d\n", cbLoggerRC, RT_OFFSETOF(RTLOGGERRC, afGroups[pLogger->cGroups]), pLogger->cGroups));
-        return VERR_INVALID_PARAMETER;
+        return VERR_BUFFER_OVERFLOW;
     }
     memcpy(&pLoggerRC->afGroups[0], &pLogger->afGroups[0], pLogger->cGroups * sizeof(pLoggerRC->afGroups[0]));
@@ -780,5 +856,5 @@
      * Copy bits from the HC instance.
      */
-    pLoggerRC->fPendingPrefix = pLogger->fPendingPrefix;
+    pLoggerRC->fPendingPrefix = pLogger->pInt->fPendingPrefix;
     pLoggerRC->fFlags |= pLogger->fFlags;
 
@@ -851,19 +927,8 @@
 RT_EXPORT_SYMBOL(RTLogFlushRC);
 
-
-#ifdef IN_RING3
-/**
- * Create a logger instance for singled threaded ring-0 usage.
- *
- * @returns iprt status code.
- *
- * @param   pLogger             Where to create the logger instance.
- * @param   cbLogger            The amount of memory available for the logger instance.
- * @param   pfnLogger           Pointer to logger wrapper function for the clone.
- * @param   pfnFlush            Pointer to flush function for the clone.
- * @param   fFlags              Logger instance flags for the clone, a combination of the RTLOGFLAGS_* values.
- * @param   fDestFlags          The destination flags.
- */
-RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger, PFNRTLOGGER pfnLogger, PFNRTLOGFLUSH pfnFlush,
+# ifdef IN_RING3
+
+RTDECL(int) RTLogCreateForR0(PRTLOGGER pLogger, size_t cbLogger,
+                             RTR0PTR pLoggerR0Ptr, RTR0PTR pfnLoggerR0Ptr, RTR0PTR pfnFlushR0Ptr,
                              uint32_t fFlags, uint32_t fDestFlags)
 {
@@ -872,44 +937,73 @@
      */
     AssertPtrReturn(pLogger, VERR_INVALID_PARAMETER);
-    AssertReturn(cbLogger >= sizeof(*pLogger), VERR_INVALID_PARAMETER);
-    AssertReturn(pfnLogger, VERR_INVALID_PARAMETER);
-    AssertReturn(pfnFlush, VERR_INVALID_PARAMETER);
+    size_t const cbRequired = sizeof(*pLogger) + RTLOGGERINTERNAL_R0_SIZE;
+    AssertReturn(cbLogger >= cbRequired, VERR_BUFFER_OVERFLOW);
+    AssertReturn(pLoggerR0Ptr != NIL_RTR0PTR, VERR_INVALID_PARAMETER);
+    AssertReturn(pfnLoggerR0Ptr != NIL_RTR0PTR, VERR_INVALID_PARAMETER);
 
     /*
      * Initialize the ring-0 instance.
      */
-    pLogger->offScratch   = 0;
-    pLogger->fPendingPrefix = false;
-    pLogger->pfnLogger    = pfnLogger;
-    pLogger->pfnFlush     = pfnFlush;
-    pLogger->hSpinMtx     = NIL_RTSEMSPINMUTEX; /* Not serialized. */
-    pLogger->u32Magic     = RTLOGGER_MAGIC;
-    pLogger->fFlags       = fFlags;
-    pLogger->fDestFlags   = fDestFlags & ~RTLOGDEST_FILE;
-    pLogger->pFile        = NULL;
-    pLogger->papszGroups  = NULL;
-    pLogger->cMaxGroups   = (uint32_t)((cbLogger - RT_OFFSETOF(RTLOGGER, afGroups[0])) / sizeof(pLogger->afGroups[0]));
-    pLogger->cGroups      = 1;
-    pLogger->afGroups[0]  = 0;
+    pLogger->achScratch[0]  = 0;
+    pLogger->offScratch     = 0;
+    pLogger->pfnLogger      = (PFNRTLOGGER)pfnLoggerR0Ptr;
+    pLogger->fFlags         = fFlags;
+    pLogger->fDestFlags     = fDestFlags & ~RTLOGDEST_FILE;
+    pLogger->pInt           = NULL;
+    pLogger->cGroups        = 1;
+    pLogger->afGroups[0]    = 0;
+
+    uint32_t cMaxGroups     = (uint32_t)((cbLogger - cbRequired) / sizeof(pLogger->afGroups[0]));
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cMaxGroups /= 2;
+    PRTLOGGERINTERNAL pInt;
+    for (;;)
+    {
+        AssertReturn(cMaxGroups > 0, VERR_BUFFER_OVERFLOW);
+        pInt = (PRTLOGGERINTERNAL)&pLogger->afGroups[cMaxGroups];
+        if (!((uintptr_t)pInt & (sizeof(uint64_t) - 1)))
+            break;
+        cMaxGroups--;
+    }
+    pLogger->pInt               = (PRTLOGGERINTERNAL)(pLoggerR0Ptr + (uintptr_t)pInt - (uintptr_t)pLogger);
+    pInt->uRevision             = RTLOGGERINTERNAL_REV;
+    pInt->cbSelf                = RTLOGGERINTERNAL_R0_SIZE;
+    pInt->hSpinMtx              = NIL_RTSEMSPINMUTEX; /* Not serialized. */
+    pInt->pfnFlush              = (PFNRTLOGFLUSH)pfnFlushR0Ptr;
+    pInt->pfnPrefix             = NULL;
+    pInt->pvPrefixUserArg       = NULL;
+    pInt->fPendingPrefix        = false;
+    pInt->cMaxGroups            = cMaxGroups;
+    pInt->papszGroups           = NULL;
+    pInt->cMaxEntriesPerGroup   = UINT32_MAX;
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+    {
+        memset(pInt + 1, 0, sizeof(uint32_t) * cMaxGroups);
+        pInt->pacEntriesPerGroup= (uint32_t *)(pLogger->pInt + 1);
+    }
+    else
+        pInt->pacEntriesPerGroup= NULL;
+
+    pLogger->u32Magic           = RTLOGGER_MAGIC;
     return VINF_SUCCESS;
 }
 RT_EXPORT_SYMBOL(RTLogCreateForR0);
-#endif /* IN_RING3 */
-
-
-/**
- * Copies the group settings and flags from logger instance to another.
- *
- * @returns IPRT status code.
- * @param   pDstLogger      The destination logger instance.
- * @param   pSrcLogger      The source logger instance. If NULL the default one is used.
- * @param   fFlagsOr        OR mask for the flags.
- * @param   fFlagsAnd       AND mask for the flags.
- */
-RTDECL(int) RTLogCopyGroupsAndFlags(PRTLOGGER pDstLogger, PCRTLOGGER pSrcLogger, unsigned fFlagsOr, unsigned fFlagsAnd)
-{
-    int      rc;
-    unsigned cGroups;
-
+
+
+RTDECL(size_t) RTLogCalcSizeForR0(uint32_t cGroups, uint32_t fFlags)
+{
+    size_t cb = RT_OFFSETOF(RTLOGGER, afGroups[cGroups]);
+    cb = RT_ALIGN_Z(cb, sizeof(uint64_t));
+    cb += sizeof(RTLOGGERINTERNAL);
+    if (fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+        cb += sizeof(uint32_t) * cGroups;
+    return cb;
+}
+RT_EXPORT_SYMBOL(RTLogCalcSizeForR0);
+
+
+RTDECL(int) RTLogCopyGroupsAndFlagsForR0(PRTLOGGER pDstLogger, RTR0PTR pDstLoggerR0Ptr,
+                                         PCRTLOGGER pSrcLogger, uint32_t fFlagsOr, uint32_t fFlagsAnd)
+{
     /*
      * Validate input.
@@ -926,5 +1020,5 @@
         if (!pSrcLogger)
         {
-            pDstLogger->fFlags |= RTLOGFLAGS_DISABLED;
+            pDstLogger->fFlags |= RTLOGFLAGS_DISABLED | fFlagsOr;
             pDstLogger->cGroups = 1;
             pDstLogger->afGroups[0] = 0;
@@ -936,14 +1030,15 @@
      * Copy flags and group settings.
      */
-    pDstLogger->fFlags = (pSrcLogger->fFlags & fFlagsAnd) | fFlagsOr;
-
-    rc = VINF_SUCCESS;
-    cGroups = pSrcLogger->cGroups;
-    if (cGroups < pDstLogger->cMaxGroups)
-    {
-        AssertMsgFailed(("cMaxGroups=%zd cGroups=%zd (min size %d)\n", pDstLogger->cMaxGroups,
-                         pSrcLogger->cGroups, RT_OFFSETOF(RTLOGGER, afGroups[pSrcLogger->cGroups])));
+    pDstLogger->fFlags = (pSrcLogger->fFlags & fFlagsAnd & ~RTLOGFLAGS_RESTRICT_GROUPS) | fFlagsOr;
+
+    PRTLOGGERINTERNAL   pDstInt = (PRTLOGGERINTERNAL)((uintptr_t)pDstLogger->pInt - pDstLoggerR0Ptr + (uintptr_t)pDstLogger);
+    int                 rc      = VINF_SUCCESS;
+    uint32_t            cGroups = pSrcLogger->cGroups;
+    if (cGroups > pDstInt->cMaxGroups)
+    {
+        AssertMsgFailed(("cMaxGroups=%zd cGroups=%zd (min size %d)\n", pDstInt->cMaxGroups,
+                         pSrcLogger->cGroups, RT_OFFSETOF(RTLOGGER, afGroups[pSrcLogger->cGroups]) + RTLOGGERINTERNAL_R0_SIZE));
         rc = VERR_INVALID_PARAMETER;
-        cGroups = pDstLogger->cMaxGroups;
+        cGroups = pDstInt->cMaxGroups;
     }
     memcpy(&pDstLogger->afGroups[0], &pSrcLogger->afGroups[0], cGroups * sizeof(pDstLogger->afGroups[0]));
@@ -952,5 +1047,26 @@
     return rc;
 }
-RT_EXPORT_SYMBOL(RTLogCopyGroupsAndFlags);
+RT_EXPORT_SYMBOL(RTLogCopyGroupsAndFlagsForR0);
+
+
+RTDECL(int) RTLogSetCustomPrefixCallbackForR0(PRTLOGGER pLogger, RTR0PTR pLoggerR0Ptr,
+                                              RTR0PTR pfnCallbackR0Ptr, RTR0PTR pvUserR0Ptr)
+{
+    AssertPtrReturn(pLogger, VERR_INVALID_POINTER);
+    AssertReturn(pLogger->u32Magic == RTLOGGER_MAGIC, VERR_INVALID_MAGIC);
+
+    /*
+     * Do the work.
+     */
+    PRTLOGGERINTERNAL pInt = (PRTLOGGERINTERNAL)((uintptr_t)pLogger->pInt - pLoggerR0Ptr + (uintptr_t)pLogger);
+    AssertReturn(pInt->uRevision == RTLOGGERINTERNAL_REV, VERR_LOG_REVISION_MISMATCH);
+    pInt->pvPrefixUserArg = (void *)pvUserR0Ptr;
+    pInt->pfnPrefix       = (PFNRTLOGPREFIX)pfnCallbackR0Ptr;
+
+    return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTLogSetCustomPrefixCallbackForR0);
+
+# endif /* IN_RING3 */
 
 
@@ -1050,6 +1166,6 @@
      */
     rtlogLock(pLogger);
-    pLogger->pvPrefixUserArg = pvUser;
-    pLogger->pfnPrefix       = pfnCallback;
+    pLogger->pInt->pvPrefixUserArg = pvUser;
+    pLogger->pInt->pfnPrefix       = pfnCallback;
     rtlogUnlock(pLogger);
 
@@ -1219,5 +1335,5 @@
             {
                 const char *psz2 = (const char*)pszStart;
-                if (rtlogIsGroupMatching(pLogger->papszGroups[i], &psz2, cch))
+                if (rtlogIsGroupMatching(pLogger->pInt->papszGroups[i], &psz2, cch))
                 {
                     unsigned fFlags = RTLOGGRPFLAGS_ENABLED | RTLOGGRPFLAGS_LEVEL_1;
@@ -1279,8 +1395,8 @@
             { "f",          RTLOGGRPFLAGS_FLOW },
             { "flow",       RTLOGGRPFLAGS_FLOW },
+            { "restrict",   RTLOGGRPFLAGS_RESTRICT },
 
             { "lelik",      RTLOGGRPFLAGS_LELIK },
             { "michael",    RTLOGGRPFLAGS_MICHAEL },
-            { "dmik",       RTLOGGRPFLAGS_DMIK },
             { "sunlover",   RTLOGGRPFLAGS_SUNLOVER },
             { "achim",      RTLOGGRPFLAGS_ACHIM },
@@ -1344,7 +1460,7 @@
 static int rtLogGetGroupSettingsAddOne(const char *pszName, uint32_t fGroup, char **ppszBuf, size_t *pcchBuf, bool *pfNotFirst)
 {
-#define APPEND_PSZ(psz,cch) do { memcpy(*ppszBuf, (psz), (cch)); *ppszBuf += (cch); *pcchBuf -= (cch); } while (0)
-#define APPEND_SZ(sz)       APPEND_PSZ(sz, sizeof(sz) - 1)
-#define APPEND_CH(ch)       do { **ppszBuf = (ch); *ppszBuf += 1; *pcchBuf -= 1; } while (0)
+# define APPEND_PSZ(psz,cch) do { memcpy(*ppszBuf, (psz), (cch)); *ppszBuf += (cch); *pcchBuf -= (cch); } while (0)
+# define APPEND_SZ(sz)       APPEND_PSZ(sz, sizeof(sz) - 1)
+# define APPEND_CH(ch)       do { **ppszBuf = (ch); *ppszBuf += 1; *pcchBuf -= 1; } while (0)
 
     /*
@@ -1382,7 +1498,7 @@
         return VERR_BUFFER_OVERFLOW;
 
-#undef APPEND_PSZ
-#undef APPEND_SZ
-#undef APPEND_CH
+# undef APPEND_PSZ
+# undef APPEND_SZ
+# undef APPEND_CH
     return VINF_SUCCESS;
 }
@@ -1443,5 +1559,5 @@
             if (fGroup)
             {
-                const char *pszName = pLogger->papszGroups[i];
+                const char *pszName = pLogger->pInt->papszGroups[i];
                 if (pszName)
                 {
@@ -1458,6 +1574,6 @@
 }
 RT_EXPORT_SYMBOL(RTLogGetGroupSettings);
+
 #endif /* !IN_RC */
-
 
 /**
@@ -1588,4 +1704,27 @@
 RT_EXPORT_SYMBOL(RTLogSetBuffering);
 
+
+#ifdef IN_RING3
+RTDECL(uint32_t) RTLogSetGroupLimit(PRTLOGGER pLogger, uint32_t cMaxEntriesPerGroup)
+{
+    /*
+     * Resolve the logger instance.
+     */
+    if (!pLogger)
+    {
+        pLogger = RTLogDefaultInstance();
+        if (!pLogger)
+            return UINT32_MAX;
+    }
+
+    rtlogLock(pLogger);
+    uint32_t cOld = pLogger->pInt->cMaxEntriesPerGroup;
+    pLogger->pInt->cMaxEntriesPerGroup = cMaxEntriesPerGroup;
+    rtlogUnlock(pLogger);
+
+    return cOld;
+}
+#endif
+
 #ifndef IN_RC
 
@@ -1722,25 +1861,25 @@
                     if (i == 0 /* file */ && !fNo)
                     {
-                        AssertReturn(cch < RTPATH_MAX, VERR_OUT_OF_RANGE);
-                        memcpy(pLogger->pFile->pszFilename, pszVar, cch);
-                        pLogger->pFile->pszFilename[cch] = '\0';
+                        AssertReturn(cch < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
+                        memcpy(pLogger->pInt->szFilename, pszVar, cch);
+                        pLogger->pInt->szFilename[cch] = '\0';
                     }
                     /* log directory */
                     else if (i == 1 /* dir */ && !fNo)
                     {
-                        char        szTmp[RTPATH_MAX];
-                        const char *pszFile = RTPathFilename(pLogger->pFile->pszFilename);
+                        char        szTmp[sizeof(pLogger->pInt->szFilename)];
+                        const char *pszFile = RTPathFilename(pLogger->pInt->szFilename);
                         size_t      cchFile = pszFile ? strlen(pszFile) : 0;
-                        AssertReturn(cchFile + cch + 1 < RTPATH_MAX, VERR_OUT_OF_RANGE);
+                        AssertReturn(cchFile + cch + 1 < sizeof(pLogger->pInt->szFilename), VERR_OUT_OF_RANGE);
                         memcpy(szTmp, cchFile ? pszFile : "", cchFile + 1);
 
-                        memcpy(pLogger->pFile->pszFilename, pszVar, cch);
-                        pLogger->pFile->pszFilename[cch] = '\0';
-                        RTPathStripTrailingSlash(pLogger->pFile->pszFilename);
-
-                        cch = strlen(pLogger->pFile->pszFilename);
-                        pLogger->pFile->pszFilename[cch++] = '/';
-                        memcpy(&pLogger->pFile->pszFilename[cch], szTmp, cchFile);
-                        pLogger->pFile->pszFilename[cch+cchFile] = '\0';
+                        memcpy(pLogger->pInt->szFilename, pszVar, cch);
+                        pLogger->pInt->szFilename[cch] = '\0';
+                        RTPathStripTrailingSlash(pLogger->pInt->szFilename);
+
+                        cch = strlen(pLogger->pInt->szFilename);
+                        pLogger->pInt->szFilename[cch++] = '/';
+                        memcpy(&pLogger->pInt->szFilename[cch], szTmp, cchFile);
+                        pLogger->pInt->szFilename[cch + cchFile] = '\0';
                     }
                     else if (i == 2 /* history */)
@@ -1754,8 +1893,8 @@
                                 rc = RTStrToUInt32Full(szTmp, 0, &cHistory);
                             AssertMsgReturn(RT_SUCCESS(rc) && cHistory < _1M, ("Invalid history value %s (%Rrc)!\n", szTmp, rc), rc);
-                            pLogger->pFile->cHistory = cHistory;
+                            pLogger->pInt->cHistory = cHistory;
                         }
                         else
-                            pLogger->pFile->cHistory = 0;
+                            pLogger->pInt->cHistory = 0;
                     }
                     else if (i == 3 /* histsize */)
@@ -1766,11 +1905,11 @@
                             int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszVar, cch);
                             if (RT_SUCCESS(rc))
-                                rc = RTStrToUInt64Full(szTmp, 0, &pLogger->pFile->cbHistoryFileMax);
+                                rc = RTStrToUInt64Full(szTmp, 0, &pLogger->pInt->cbHistoryFileMax);
                             AssertMsgRCReturn(rc, ("Invalid history file size value %s (%Rrc)!\n", szTmp, rc), rc);
-                            if (pLogger->pFile->cbHistoryFileMax == 0)
-                                pLogger->pFile->cbHistoryFileMax = UINT64_MAX;
+                            if (pLogger->pInt->cbHistoryFileMax == 0)
+                                pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
                         }
                         else
-                            pLogger->pFile->cbHistoryFileMax = UINT64_MAX;
+                            pLogger->pInt->cbHistoryFileMax = UINT64_MAX;
                     }
                     else if (i == 4 /* histtime */)
@@ -1781,11 +1920,11 @@
                             int rc = RTStrCopyEx(szTmp, sizeof(szTmp), pszVar, cch);
                             if (RT_SUCCESS(rc))
-                                rc = RTStrToUInt32Full(szTmp, 0, &pLogger->pFile->cSecsHistoryTimeSlot);
+                                rc = RTStrToUInt32Full(szTmp, 0, &pLogger->pInt->cSecsHistoryTimeSlot);
                             AssertMsgRCReturn(rc, ("Invalid history time slot value %s (%Rrc)!\n", szTmp, rc), rc);
-                            if (pLogger->pFile->cSecsHistoryTimeSlot == 0)
-                                pLogger->pFile->cSecsHistoryTimeSlot = UINT32_MAX;
+                            if (pLogger->pInt->cSecsHistoryTimeSlot == 0)
+                                pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
                         }
                         else
-                            pLogger->pFile->cSecsHistoryTimeSlot = UINT32_MAX;
+                            pLogger->pInt->cSecsHistoryTimeSlot = UINT32_MAX;
                     }
                     else
@@ -1863,15 +2002,14 @@
         }
 
-#ifdef IN_RING3
+# ifdef IN_RING3
     /*
      * Add the filename.
      */
-    if (    (fDestFlags & RTLOGDEST_FILE)
-        &&  VALID_PTR(pLogger->pFile->pszFilename))
+    if (fDestFlags & RTLOGDEST_FILE)
     {
         rc = RTStrCopyP(&pszBuf, &cchBuf, fNotFirst ? " file=" : "file=");
         if (RT_FAILURE(rc))
             return rc;
-        rc = RTStrCopyP(&pszBuf, &cchBuf, pLogger->pFile->pszFilename);
+        rc = RTStrCopyP(&pszBuf, &cchBuf, pLogger->pInt->szFilename);
         if (RT_FAILURE(rc))
             return rc;
@@ -1882,21 +2020,21 @@
     {
         char szNum[32];
-        if (pLogger->pFile->cHistory)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "history=%u" : " history=%u", pLogger->pFile->cHistory);
+        if (pLogger->pInt->cHistory)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "history=%u" : " history=%u", pLogger->pInt->cHistory);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
                 return rc;
         }
-        if (pLogger->pFile->cbHistoryFileMax != UINT64_MAX)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "histsize=%llu" : " histsize=%llu", pLogger->pFile->cbHistoryFileMax);
+        if (pLogger->pInt->cbHistoryFileMax != UINT64_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "histsize=%llu" : " histsize=%llu", pLogger->pInt->cbHistoryFileMax);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
                 return rc;
         }
-        if (pLogger->pFile->cSecsHistoryTimeSlot != UINT32_MAX)
-        {
-            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "histtime=%llu" : " histtime=%llu", pLogger->pFile->cSecsHistoryTimeSlot);
+        if (pLogger->pInt->cSecsHistoryTimeSlot != UINT32_MAX)
+        {
+            RTStrPrintf(szNum, sizeof(szNum), fNotFirst ? "histtime=%llu" : " histtime=%llu", pLogger->pInt->cSecsHistoryTimeSlot);
             rc = RTStrCopyP(&pszBuf, &cchBuf, szNum);
             if (RT_FAILURE(rc))
@@ -1904,5 +2042,5 @@
         }
     }
-#endif /* IN_RING3 */
+# endif /* IN_RING3 */
 
     return VINF_SUCCESS;
@@ -2131,5 +2269,5 @@
 }
 RT_EXPORT_SYMBOL(RTLogSetDefaultInstanceThread);
-#endif
+#endif /* IN_RING0 */
 
 
@@ -2209,7 +2347,30 @@
 
     /*
-     * Call worker.
-     */
-    rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
+     * Check restrictions and call worker.
+     */
+#ifndef IN_RC
+    if (RT_UNLIKELY(   (pLogger->fFlags & RTLOGFLAGS_RESTRICT_GROUPS)
+                    && iGroup < pLogger->cGroups
+                    && (pLogger->afGroups[iGroup] & RTLOGGRPFLAGS_RESTRICT)
+                    && ++pLogger->pInt->pacEntriesPerGroup[iGroup] >= pLogger->pInt->cMaxEntriesPerGroup ))
+    {
+        uint32_t cEntries = pLogger->pInt->pacEntriesPerGroup[iGroup];
+        if (cEntries > pLogger->pInt->cMaxEntriesPerGroup)
+            pLogger->pInt->pacEntriesPerGroup[iGroup] = cEntries - 1;
+        else
+        {
+            rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
+            if (   pLogger->pInt->papszGroups
+                && pLogger->pInt->papszGroups[iGroup])
+                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group %s (#%u), muting it.\n",
+                                     cEntries, pLogger->pInt->papszGroups[iGroup], iGroup);
+            else
+                rtlogLoggerExFLocked(pLogger, fFlags, iGroup, "%u messages from group #%u, muting it.\n",
+                                     cEntries, iGroup);
+        }
+    }
+    else
+#endif
+        rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, args);
 
     /*
@@ -2261,8 +2422,8 @@
         RTLogWriteStdErr(pThis->achScratch, pThis->offScratch);
 
-#ifndef LOG_NO_COM
+# ifndef LOG_NO_COM
     if (pThis->fDestFlags & RTLOGDEST_COM)
         RTLogWriteCom(pThis->achScratch, pThis->offScratch);
-#endif
+# endif
 
     /* empty the buffer. */
@@ -2401,18 +2562,18 @@
         fOpen |= RTFILE_O_WRITE_THROUGH;
 
-    int rc = RTFileOpen(&pLogger->pFile->File, pLogger->pFile->pszFilename, fOpen);
+    int rc = RTFileOpen(&pLogger->pInt->u.hFile, pLogger->pInt->szFilename, fOpen);
     if (RT_FAILURE(rc))
     {
-        pLogger->pFile->File = NIL_RTFILE;
+        pLogger->pInt->u.hFile = NIL_RTFILE;
         if (pszErrorMsg)
-            RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pFile->pszFilename, fOpen);
+            RTStrPrintf(pszErrorMsg, cchErrorMsg, N_("could not open file '%s' (fOpen=%#x)"), pLogger->pInt->szFilename, fOpen);
     }
     else
     {
-        rc = RTFileGetSize(pLogger->pFile->File, &pLogger->pFile->cbHistoryFileWritten);
+        rc = RTFileGetSize(pLogger->pInt->u.hFile, &pLogger->pInt->cbHistoryFileWritten);
         if (RT_FAILURE(rc))
         {
             /* Don't complain if this fails, assume the file is empty. */
-            pLogger->pFile->cbHistoryFileWritten = 0;
+            pLogger->pInt->cbHistoryFileWritten = 0;
             rc = VINF_SUCCESS;
         }
@@ -2436,10 +2597,10 @@
 {
     /* Suppress rotating empty log files simply because the time elapsed. */
-    if (RT_UNLIKELY(!pLogger->pFile->cbHistoryFileWritten))
-        pLogger->pFile->uHistoryTimeSlotStart = uTimeSlot;
+    if (RT_UNLIKELY(!pLogger->pInt->cbHistoryFileWritten))
+        pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
 
     /* Check rotation condition: file still small enough and not too old? */
-    if (RT_LIKELY(   pLogger->pFile->cbHistoryFileWritten < pLogger->pFile->cbHistoryFileMax
-                  && uTimeSlot == pLogger->pFile->uHistoryTimeSlotStart))
+    if (RT_LIKELY(   pLogger->pInt->cbHistoryFileWritten < pLogger->pInt->cbHistoryFileMax
+                  && uTimeSlot == pLogger->pInt->uHistoryTimeSlotStart))
         return;
 
@@ -2456,24 +2617,24 @@
      * chatty phase logging we could run into endless rotation.
      */
-    uint32_t const cSavedHistory = pLogger->pFile->cHistory;
-    pLogger->pFile->cHistory = 0;
+    uint32_t const cSavedHistory = pLogger->pInt->cHistory;
+    pLogger->pInt->cHistory = 0;
 
     /*
      * Close the old log file.
      */
-    if (pLogger->pFile->File != NIL_RTFILE)
+    if (pLogger->pInt->u.hFile != NIL_RTFILE)
     {
         /* Use the callback to generate some final log contents, but only if
          * this is a rotation with a fully set up logger. Leave the other case
          * to the RTLogCreateExV function. */
-        if (pLogger->pFile->pfnPhase && !fFirst)
+        if (pLogger->pInt->pfnPhase && !fFirst)
         {
             uint32_t fODestFlags = pLogger->fDestFlags;
             pLogger->fDestFlags &= RTLOGDEST_FILE;
-            pLogger->pFile->pfnPhase(pLogger, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
+            pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_PREROTATE, rtlogPhaseMsgLocked);
             pLogger->fDestFlags = fODestFlags;
         }
-        RTFileClose(pLogger->pFile->File);
-        pLogger->pFile->File = NIL_RTFILE;
+        RTFileClose(pLogger->pInt->u.hFile);
+        pLogger->pInt->u.hFile = NIL_RTFILE;
     }
 
@@ -2485,13 +2646,14 @@
         for (uint32_t i = cSavedHistory - 1; i + 1 > 0; i--)
         {
-            char szOldName[RTPATH_MAX];
+            char szOldName[sizeof(pLogger->pInt->szFilename) + 32];
             if (i > 0)
-                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLogger->pFile->pszFilename, i);
+                RTStrPrintf(szOldName, sizeof(szOldName), "%s.%u", pLogger->pInt->szFilename, i);
             else
-                RTStrCopy(szOldName, sizeof(szOldName), pLogger->pFile->pszFilename);
-            char szNewName[RTPATH_MAX];
-            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pFile->pszFilename, i + 1);
-            if (RTFileRename(szOldName, szNewName,
-                             RTFILEMOVE_FLAGS_REPLACE) == VERR_FILE_NOT_FOUND)
+                RTStrCopy(szOldName, sizeof(szOldName), pLogger->pInt->szFilename);
+
+            char szNewName[sizeof(pLogger->pInt->szFilename) + 32];
+            RTStrPrintf(szNewName, sizeof(szNewName), "%s.%u", pLogger->pInt->szFilename, i + 1);
+            if (   RTFileRename(szOldName, szNewName, RTFILEMOVE_FLAGS_REPLACE)
+                == VERR_FILE_NOT_FOUND)
                 RTFileDelete(szNewName);
         }
@@ -2502,6 +2664,6 @@
         for (uint32_t i = cSavedHistory + 1; ; i++)
         {
-            char szExcessName[RTPATH_MAX];
-            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLogger->pFile->pszFilename, i);
+            char szExcessName[sizeof(pLogger->pInt->szFilename) + 32];
+            RTStrPrintf(szExcessName, sizeof(szExcessName), "%s.%u", pLogger->pInt->szFilename, i);
             int rc = RTFileDelete(szExcessName);
             if (RT_FAILURE(rc))
@@ -2513,6 +2675,6 @@
      * Update logger state and create new log file.
      */
-    pLogger->pFile->cbHistoryFileWritten = 0;
-    pLogger->pFile->uHistoryTimeSlotStart = uTimeSlot;
+    pLogger->pInt->cbHistoryFileWritten = 0;
+    pLogger->pInt->uHistoryTimeSlotStart = uTimeSlot;
     rtlogFileOpen(pLogger, NULL, 0);
 
@@ -2522,14 +2684,14 @@
      * RTLogCreateExV function.
      */
-    if (pLogger->pFile->pfnPhase && !fFirst)
+    if (pLogger->pInt->pfnPhase && !fFirst)
     {
         uint32_t const fSavedDestFlags = pLogger->fDestFlags;
         pLogger->fDestFlags &= RTLOGDEST_FILE;
-        pLogger->pFile->pfnPhase(pLogger, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
+        pLogger->pInt->pfnPhase(pLogger, RTLOGPHASE_POSTROTATE, rtlogPhaseMsgLocked);
         pLogger->fDestFlags = fSavedDestFlags;
     }
 
     /* Restore saved values. */
-    pLogger->pFile->cHistory = cSavedHistory;
+    pLogger->pInt->cHistory = cSavedHistory;
     pLogger->fFlags          = fSavedFlags;
 }
@@ -2559,12 +2721,12 @@
     if (pLogger->fDestFlags & RTLOGDEST_FILE)
     {
-        if (pLogger->pFile->File != NIL_RTFILE)
-        {
-            RTFileWrite(pLogger->pFile->File, pLogger->achScratch, pLogger->offScratch, NULL);
+        if (pLogger->pInt->u.hFile != NIL_RTFILE)
+        {
+            RTFileWrite(pLogger->pInt->u.hFile, pLogger->achScratch, pLogger->offScratch, NULL);
             if (pLogger->fFlags & RTLOGFLAGS_FLUSH)
-                RTFileFlush(pLogger->pFile->File);
-        }
-        if (pLogger->pFile->cHistory)
-            pLogger->pFile->cbHistoryFileWritten += pLogger->offScratch;
+                RTFileFlush(pLogger->pInt->u.hFile);
+        }
+        if (pLogger->pInt->cHistory)
+            pLogger->pInt->cbHistoryFileWritten += pLogger->offScratch;
     }
 # endif
@@ -2582,6 +2744,11 @@
 #endif /* !IN_RC */
 
+#ifdef IN_RC
     if (pLogger->pfnFlush)
         pLogger->pfnFlush(pLogger);
+#else
+    if (pLogger->pInt->pfnFlush)
+        pLogger->pInt->pfnFlush(pLogger);
+#endif
 
     /* empty the buffer. */
@@ -2595,8 +2762,6 @@
      */
     if (   (pLogger->fDestFlags & RTLOGDEST_FILE)
-        && pLogger->pFile->cHistory)
-        rtlogRotate(pLogger,
-                    RTTimeProgramSecTS() / pLogger->pFile->cSecsHistoryTimeSlot,
-                    false /* fFirst */);
+        && pLogger->pInt->cHistory)
+        rtlogRotate(pLogger, RTTimeProgramSecTS() / pLogger->pInt->cSecsHistoryTimeSlot, false /* fFirst */);
 #endif
 }
@@ -2678,14 +2843,19 @@
         for (;;)
         {
-            size_t cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
-            char *psz;
+            size_t      cb = sizeof(pLogger->achScratch) - pLogger->offScratch - 1;
             const char *pszNewLine;
+            char       *psz;
+#ifdef IN_RC
+            bool       *pfPendingPrefix = &pLogger->fPendingPrefix;
+#else
+            bool       *pfPendingPrefix = &pLogger->pInt->fPendingPrefix;
+#endif
 
             /*
              * Pending prefix?
              */
-            if (pLogger->fPendingPrefix)
+            if (*pfPendingPrefix)
             {
-                pLogger->fPendingPrefix = false;
+                *pfPendingPrefix = false;
 
 #if defined(DEBUG) && defined(IN_RING3)
@@ -2880,7 +3050,7 @@
 #ifndef IN_RC
                 if (    (pLogger->fFlags & RTLOGFLAGS_PREFIX_CUSTOM)
-                    &&  pLogger->pfnPrefix)
+                    &&  pLogger->pInt->pfnPrefix)
                 {
-                    psz += pLogger->pfnPrefix(pLogger, psz, 31, pLogger->pvPrefixUserArg);
+                    psz += pLogger->pInt->pfnPrefix(pLogger, psz, 31, pLogger->pInt->pvPrefixUserArg);
                     *psz++ = ' ';                                                               /* +32 */
                 }
@@ -2917,5 +3087,5 @@
                 {
 #ifdef IN_RING3
-                    const char *pszGroup = pArgs->iGroup != ~0U ? pLogger->papszGroups[pArgs->iGroup] : NULL;
+                    const char *pszGroup = pArgs->iGroup != ~0U ? pLogger->pInt->papszGroups[pArgs->iGroup] : NULL;
 #else
                     const char *pszGroup = NULL;
@@ -2966,5 +3136,4 @@
                         case RTLOGGRPFLAGS_LELIK:       pszGroup = "lelik"   ;  cch = sizeof("lelik"   ) - 1; break;
                         case RTLOGGRPFLAGS_MICHAEL:     pszGroup = "Michael" ;  cch = sizeof("Michael" ) - 1; break;
-                        case RTLOGGRPFLAGS_DMIK:        pszGroup = "dmik"    ;  cch = sizeof("dmik"    ) - 1; break;
                         case RTLOGGRPFLAGS_SUNLOVER:    pszGroup = "sunlover";  cch = sizeof("sunlover") - 1; break;
                         case RTLOGGRPFLAGS_ACHIM:       pszGroup = "Achim"   ;  cch = sizeof("Achim"   ) - 1; break;
@@ -3024,5 +3193,5 @@
                 {
                     cb = pszNewLine - pachChars + 1;
-                    pLogger->fPendingPrefix = true;
+                    *pfPendingPrefix = true;
                 }
             }
@@ -3045,5 +3214,5 @@
                 cbChars--;
                 cb++;
-                pLogger->fPendingPrefix = true;
+                *pfPendingPrefix = true;
             }
 
@@ -3102,2 +3271,22 @@
 }
 
+
+/**
+ * For calling rtlogLoggerExVLocked.
+ *
+ * @param   pLogger     The logger.
+ * @param   fFlags      The logging flags.
+ * @param   iGroup      The group.
+ *                      The value ~0U is reserved for compatibility with RTLogLogger[V] and is
+ *                      only for internal usage!
+ * @param   pszFormat   Format string.
+ * @param   ...         Format arguments.
+ */
+static void rtlogLoggerExFLocked(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup, const char *pszFormat, ...)
+{
+    va_list va;
+    va_start(va, pszFormat);
+    rtlogLoggerExVLocked(pLogger, fFlags, iGroup, pszFormat, va);
+    va_end(va);
+}
+
Index: /trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 37590)
+++ /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 37591)
@@ -339,4 +339,5 @@
 {
     int rc;
+#define RTLogCalcSizeForR0(cGroups, fFlags) (RT_OFFSETOF(VMMR0LOGGER, Logger.afGroups[cGroups]) + PAGE_SIZE)
 
     /*
@@ -354,16 +355,15 @@
 
 # ifdef VBOX_WITH_R0_LOGGING
+        size_t const cbLogger = RTLogCalcSizeForR0(pLogger->cGroups, 0);
         for (VMCPUID i = 0; i < pVM->cCpus; i++)
         {
             PVMCPU pVCpu = &pVM->aCpus[i];
-
-            rc = MMR3HyperAllocOnceNoRelEx(pVM, RT_OFFSETOF(VMMR0LOGGER, Logger.afGroups[pLogger->cGroups]),
-                                           0, MM_TAG_VMM, MMHYPER_AONR_FLAGS_KERNEL_MAPPING,
+            rc = MMR3HyperAllocOnceNoRelEx(pVM, cbLogger, PAGE_SIZE, MM_TAG_VMM, MMHYPER_AONR_FLAGS_KERNEL_MAPPING,
                                            (void **)&pVCpu->vmm.s.pR0LoggerR3);
             if (RT_FAILURE(rc))
                 return rc;
-            pVCpu->vmm.s.pR0LoggerR3->pVM = pVM->pVMR0;
+            pVCpu->vmm.s.pR0LoggerR3->pVM        = pVM->pVMR0;
             //pVCpu->vmm.s.pR0LoggerR3->fCreated = false;
-            pVCpu->vmm.s.pR0LoggerR3->cbLogger = RT_OFFSETOF(RTLOGGER, afGroups[pLogger->cGroups]);
+            pVCpu->vmm.s.pR0LoggerR3->cbLogger   = cbLogger;
             pVCpu->vmm.s.pR0LoggerR0 = MMHyperR3ToR0(pVM, pVCpu->vmm.s.pR0LoggerR3);
         }
@@ -861,5 +861,5 @@
         pVM->vmm.s.pRCLoggerRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pRCLoggerR3);
         rc = RTLogCloneRC(NULL /* default */, pVM->vmm.s.pRCLoggerR3, pVM->vmm.s.cbRCLogger,
-                          RCPtrLoggerWrapper,  RCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
+                          RCPtrLoggerWrapper, RCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
         AssertReleaseMsgRC(rc, ("RTLogCloneRC failed! rc=%Rra\n", rc));
     }
@@ -874,5 +874,5 @@
         pVM->vmm.s.pRCRelLoggerRC = MMHyperR3ToRC(pVM, pVM->vmm.s.pRCRelLoggerR3);
         rc = RTLogCloneRC(RTLogRelDefaultInstance(), pVM->vmm.s.pRCRelLoggerR3, pVM->vmm.s.cbRCRelLogger,
-                          RCPtrLoggerWrapper,  RCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
+                          RCPtrLoggerWrapper, RCPtrLoggerFlush, RTLOGFLAGS_BUFFERED);
         AssertReleaseMsgRC(rc, ("RTLogCloneRC failed! rc=%Rra\n", rc));
     }
@@ -884,4 +884,5 @@
      * in ring-0. Only initialize it once.
      */
+    PRTLOGGER const pDefault = RTLogRelDefaultInstance();
     for (VMCPUID i = 0; i < pVM->cCpus; i++)
     {
@@ -900,6 +901,6 @@
                 AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerFlush not found! rc=%Rra\n", rc), rc);
 
-                rc = RTLogCreateForR0(&pR0LoggerR3->Logger, pR0LoggerR3->cbLogger,
-                                      *(PFNRTLOGGER *)&pfnLoggerWrapper, *(PFNRTLOGFLUSH *)&pfnLoggerFlush,
+                rc = RTLogCreateForR0(&pR0LoggerR3->Logger, pR0LoggerR3->cbLogger, pVCpu->vmm.s.pR0LoggerR0,
+                                      pfnLoggerWrapper, pfnLoggerFlush,
                                       RTLOGFLAGS_BUFFERED, RTLOGDEST_DUMMY);
                 AssertReleaseMsgRCReturn(rc, ("RTLogCreateForR0 failed! rc=%Rra\n", rc), rc);
@@ -908,5 +909,5 @@
                 rc = PDMR3LdrGetSymbolR0(pVM, VMMR0_MAIN_MODULE_NAME, "vmmR0LoggerPrefix", &pfnLoggerPrefix);
                 AssertReleaseMsgRCReturn(rc, ("vmmR0LoggerPrefix not found! rc=%Rra\n", rc), rc);
-                rc = RTLogSetCustomPrefixCallback(&pR0LoggerR3->Logger, *(PFNRTLOGPREFIX *)&pfnLoggerPrefix, NULL);
+                rc = RTLogSetCustomPrefixCallbackForR0(&pR0LoggerR3->Logger, pVCpu->vmm.s.pR0LoggerR0, pfnLoggerPrefix, NULL);
                 AssertReleaseMsgRCReturn(rc, ("RTLogSetCustomPrefixCallback failed! rc=%Rra\n", rc), rc);
 
@@ -917,5 +918,6 @@
             }
 
-            rc = RTLogCopyGroupsAndFlags(&pR0LoggerR3->Logger, NULL /* default */, pVM->vmm.s.pRCLoggerR3->fFlags, RTLOGFLAGS_BUFFERED);
+            rc = RTLogCopyGroupsAndFlagsForR0(&pR0LoggerR3->Logger, pVCpu->vmm.s.pR0LoggerR0, pDefault,
+                                              UINT32_MAX, RTLOGFLAGS_BUFFERED);
             AssertRC(rc);
         }
