Index: /trunk/include/iprt/nt/nt.h
===================================================================
--- /trunk/include/iprt/nt/nt.h	(revision 52948)
+++ /trunk/include/iprt/nt/nt.h	(revision 52949)
@@ -390,4 +390,176 @@
 typedef CLIENT_ID *PCLIENT_ID;
 #endif
+
+/** @name User Shared Data
+ * @{ */
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _KSYSTEM_TIME
+{
+    ULONG                   LowPart;
+    LONG                    High1Time;
+    LONG                    High2Time;
+} KSYSTEM_TIME;
+typedef KSYSTEM_TIME *PKSYSTEM_TIME;
+
+typedef enum _NT_PRODUCT_TYPE
+{
+    NtProductWinNt = 1,
+    NtProductLanManNt,
+    NtProductServer
+} NT_PRODUCT_TYPE;
+
+#define PROCESSOR_FEATURE_MAX       64
+
+typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
+{
+    StandardDesign = 0,
+    NEC98x86,
+    EndAlternatives
+} ALTERNATIVE_ARCHITECTURE_TYPE;
+
+# if 0
+typedef struct _XSTATE_FEATURE
+{
+    ULONG                   Offset;
+    ULONG                   Size;
+} XSTATE_FEATURE;
+typedef XSTATE_FEATURE *PXSTATE_FEATURE;
+
+#define MAXIMUM_XSTATE_FEATURES     64
+
+typedef struct _XSTATE_CONFIGURATION
+{
+    ULONG64                 EnabledFeatures;
+    ULONG                   Size;
+    ULONG                   OptimizedSave  : 1;
+    XSTATE_FEATURE          Features[MAXIMUM_XSTATE_FEATURES];
+} XSTATE_CONFIGURATION;
+typedef XSTATE_CONFIGURATION *PXSTATE_CONFIGURATION;
+# endif
+
+typedef struct _KUSER_SHARED_DATA
+{
+    ULONG                   TickCountLowDeprecated;
+    ULONG                   TickCountMultiplier;
+    KSYSTEM_TIME volatile   InterruptTime;
+    KSYSTEM_TIME volatile   SystemTime;
+    KSYSTEM_TIME volatile   TimeZoneBias;
+    USHORT                  ImageNumberLow;
+    USHORT                  ImageNumberHigh;
+    WCHAR                   NtSystemRoot[260];
+    ULONG                   MaxStackTraceDepth;
+    ULONG                   CryptoExponent;
+    ULONG                   TimeZoneId;
+    ULONG                   LargePageMinimum;
+    ULONG                   AitSamplingValue;
+    ULONG                   AppCompatFlag;
+    ULONGLONG               RNGSeedVersion;
+    ULONG                   GlobalValidationRunlevel;
+    LONG volatile           TimeZoneBiasStamp;
+    ULONG                   Reserved2;
+    NT_PRODUCT_TYPE         NtProductType;
+    BOOLEAN                 ProductTypeIsValid;
+    BOOLEAN                 Reserved0[1];
+    USHORT                  NativeProcessorArchitecture;
+    ULONG                   NtMajorVersion;
+    ULONG                   NtMinorVersion;
+    BOOLEAN                 ProcessorFeatures[PROCESSOR_FEATURE_MAX];
+    ULONG                   Reserved1;
+    ULONG                   Reserved3;
+    ULONG volatile          TimeSlip;
+    ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture;
+    ULONG                   AltArchitecturePad[1];
+    LARGE_INTEGER           SystemExpirationDate;
+    ULONG                   SuiteMask;
+    BOOLEAN                 KdDebuggerEnabled;
+    union
+    {
+        UCHAR               MitigationPolicies;
+        struct
+        {
+            UCHAR           NXSupportPolicy  : 2;
+            UCHAR           SEHValidationPolicy  : 2;
+            UCHAR           CurDirDevicesSkippedForDlls  : 2;
+            UCHAR           Reserved  : 2;
+        };
+    };
+    UCHAR                   Reserved6[2];
+    ULONG volatile          ActiveConsoleId;
+    ULONG volatile          DismountCount;
+    ULONG                   ComPlusPackage;
+    ULONG                   LastSystemRITEventTickCount;
+    ULONG                   NumberOfPhysicalPages;
+    BOOLEAN                 SafeBootMode;
+    UCHAR                   Reserved12[3];
+    union
+    {
+        ULONG               SharedDataFlags;
+        struct
+        {
+            ULONG           DbgErrorPortPresent  : 1;
+            ULONG           DbgElevationEnabled  : 1;
+            ULONG           DbgVirtEnabled  : 1;
+            ULONG           DbgInstallerDetectEnabled  : 1;
+            ULONG           DbgLkgEnabled  : 1;
+            ULONG           DbgDynProcessorEnabled  : 1;
+            ULONG           DbgConsoleBrokerEnabled  : 1;
+            ULONG           DbgSecureBootEnabled  : 1;
+            ULONG           SpareBits  : 24;
+        };
+    };
+    ULONG                   DataFlagsPad[1];
+    ULONGLONG               TestRetInstruction;
+    LONGLONG                QpcFrequency;
+    ULONGLONG               SystemCallPad[3];
+    union
+    {
+        ULONG64 volatile    TickCountQuad;
+        KSYSTEM_TIME volatile TickCount;
+        struct
+        {
+            ULONG           ReservedTickCountOverlay[3];
+            ULONG           TickCountPad[1];
+        };
+    };
+    ULONG                   Cookie;
+    ULONG                   CookiePad[1];
+    LONGLONG                ConsoleSessionForegroundProcessId;
+    ULONGLONG               TimeUpdateLock;
+    ULONGLONG               BaselineSystemTimeQpc;
+    ULONGLONG               BaselineInterruptTimeQpc;
+    ULONGLONG               QpcSystemTimeIncrement;
+    ULONGLONG               QpcInterruptTimeIncrement;
+    ULONG                   QpcSystemTimeIncrement32;
+    ULONG                   QpcInterruptTimeIncrement32;
+    UCHAR                   QpcSystemTimeIncrementShift;
+    UCHAR                   QpcInterruptTimeIncrementShift;
+    UCHAR                   Reserved8[14];
+    USHORT                  UserModeGlobalLogger[16];
+    ULONG                   ImageFileExecutionOptions;
+    ULONG                   LangGenerationCount;
+    ULONGLONG               Reserved4;
+    ULONGLONG volatile      InterruptTimeBias;
+    ULONGLONG volatile      QpcBias;
+    ULONG volatile          ActiveProcessorCount;
+    UCHAR volatile          ActiveGroupCount;
+    UCHAR                   Reserved9;
+    union
+    {
+        USHORT              QpcData;
+        struct
+        {
+            BOOLEAN volatile QpcBypassEnabled;
+            UCHAR           QpcShift;
+        };
+    };
+    LARGE_INTEGER           TimeZoneBiasEffectiveStart;
+    LARGE_INTEGER           TimeZoneBiasEffectiveEnd;
+    XSTATE_CONFIGURATION    XState;
+} KUSER_SHARED_DATA;
+typedef KUSER_SHARED_DATA *PKUSER_SHARED_DATA;
+#endif /* IPRT_NT_USE_WINTERNL */
+/** @} */
+
 
 /** @name Process And Thread Environment Blocks
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 52949)
@@ -313,5 +313,5 @@
 {
     SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED = 0,
-    SUPR3HARDENEDMAINSTATE_WIN_VM_INIT_CALLED,
+    SUPR3HARDENEDMAINSTATE_WIN_EARLY_INIT_CALLED,
     SUPR3HARDENEDMAINSTATE_WIN_EARLY_IMPORTS_RESOLVED,
     SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED,
@@ -342,5 +342,5 @@
 extern DECLHIDDEN(SUPR3HARDENEDMAINSTATE) g_enmSupR3HardenedMainState;
 #ifdef RT_OS_WINDOWS
-extern DECLHIDDEN(bool)                 g_fSupEarlyVmProcessInit;
+extern DECLHIDDEN(bool)                 g_fSupEarlyProcessInit;
 #endif
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 52949)
@@ -1713,5 +1713,5 @@
     g_SupPreInitData.u32EndMagic  = SUPPREINITDATA_MAGIC;
 #ifdef RT_OS_WINDOWS
-    if (!g_fSupEarlyVmProcessInit)
+    if (!g_fSupEarlyProcessInit)
 #endif
         g_SupPreInitData.Data.hDevice = SUP_HDEVICE_NIL;
@@ -1748,10 +1748,10 @@
      * at dropping compatibility layers and process "security" solutions.
      */
-    if (   !g_fSupEarlyVmProcessInit
+    if (   !g_fSupEarlyProcessInit
         && !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)
         && supR3HardenedWinIsReSpawnNeeded(1 /*iWhich*/, argc, argv))
     {
         SUP_DPRINTF(("SUPR3HardenedMain: Respawn #1\n"));
-        supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV, true /*fAvastKludge*/);
+        supR3HardenedWinInit(SUPSECMAIN_FLAGS_DONT_OPEN_DEV, false /*fAvastKludge*/);
         supR3HardenedVerifyAll(true /* fFatal */, pszProgName);
         return supR3HardenedWinReSpawn(1 /*iWhich*/);
@@ -1764,5 +1764,5 @@
      * by early VM process init.)
      */
-    if (!g_fSupEarlyVmProcessInit)
+    if (!g_fSupEarlyProcessInit)
         supR3HardenedWinInit(fFlags, true /*fAvastKludge*/);
 #endif /* RT_OS_WINDOWS */
@@ -1777,33 +1777,34 @@
      * driver.  (Already done by early VM process init.)
      */
+    if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
+    {
 #ifdef RT_OS_WINDOWS
-    if (!g_fSupEarlyVmProcessInit)
-#endif
-        if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))
+        /*
+         * Windows: Verify the process (repeated by the kernel later).
+         */
+        if (!g_fSupEarlyProcessInit)
+            supR3HardenedWinVerifyProcess();
+
+        /*
+         * Windows: The second respawn.  This time we make a special arrangement
+         * with vboxdrv to monitor access to the new process from its inception.
+         */
+        if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv))
         {
+            SUP_DPRINTF(("SUPR3HardenedMain: Respawn #2\n"));
+            return supR3HardenedWinReSpawn(2 /* iWhich*/);
+        }
+        SUP_DPRINTF(("SUPR3HardenedMain: Final process, opening VBoxDrv...\n"));
+        supR3HardenedWinFlushLoaderCache();
+#endif /* RT_OS_WINDOWS */
+
+        /*
+         * Open the vboxdrv device.
+         */
 #ifdef RT_OS_WINDOWS
-            /*
-             * Windows: Verify the process (repeated by the kernel later.
-             */
-            supR3HardenedWinVerifyProcess();
-
-            /*
-             * Windows: The second respawn.  This time we make a special arrangement
-             * with vboxdrv to monitor access to the new process from its inception.
-             */
-            if (supR3HardenedWinIsReSpawnNeeded(2 /* iWhich*/, argc, argv))
-            {
-                SUP_DPRINTF(("SUPR3HardenedMain: Respawn #2\n"));
-                return supR3HardenedWinReSpawn(2 /* iWhich*/);
-            }
-            SUP_DPRINTF(("SUPR3HardenedMain: Final process, opening VBoxDrv...\n"));
-            supR3HardenedWinFlushLoaderCache();
-#endif /* RT_OS_WINDOWS */
-
-            /*
-             * Open the vboxdrv device.
-             */
+        if (!g_fSupEarlyProcessInit)
+#endif
             supR3HardenedMainOpenDevice();
-        }
+    }
 
 #ifdef RT_OS_WINDOWS
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 52949)
@@ -3578,5 +3578,5 @@
         if (pHandleInfo->Object == pProtectedProcess)
         {
-            /* Handles within the protected process is fine. */
+            /* Handles within the protected process are fine. */
             if (   !(pHandleInfo->GrantedAccess & SUPDRV_NT_EVIL_PROCESS_RIGHTS)
                 || pHandleInfo->UniqueProcessId == hProtectedPid)
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp	(revision 52949)
@@ -200,6 +200,8 @@
  *  supR3HardenedVmProcessInit. */
 static SUPR3WINPROCPARAMS   g_ProcParams = { NULL, NULL, 0, 0 };
-/** Set if supR3HardenedVmProcessInit was invoked. */
-bool                        g_fSupEarlyVmProcessInit = false;
+/** Set if supR3HardenedEarlyProcessInit was invoked. */
+bool                        g_fSupEarlyProcessInit = false;
+/** Set if the stub device has been opened (stub process only). */
+bool                        g_fSupStubOpened = false;
 
 /** @name Global variables initialized by suplibHardenedWindowsMain.
@@ -311,5 +313,5 @@
 #endif
 
-DECLASM(void) supR3HardenedVmProcessInitThunk(void);
+DECLASM(void) supR3HardenedEarlyProcessInitThunk(void);
 
 
@@ -351,4 +353,25 @@
     return pwszCur - pwsz;
 }
+
+
+/**
+ * Our version of GetTickCount.
+ * @returns Millisecond timestamp.
+ */
+static uint64_t supR3HardenedWinGetMilliTS(void)
+{
+    PKUSER_SHARED_DATA pUserSharedData = (PKUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
+
+    /* use interrupt time */
+    LARGE_INTEGER Time;
+    do
+    {
+        Time.HighPart = pUserSharedData->InterruptTime.High1Time;
+        Time.LowPart  = pUserSharedData->InterruptTime.LowPart;
+    } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
+
+    return (uint64_t)Time.QuadPart / 10000;
+}
+
 
 
@@ -3510,5 +3533,5 @@
      * process asynchronously.
      */
-    DWORD    dwStart = GetTickCount();
+    uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
     uint32_t cMsKludge = (g_fSupAdversaries & SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT) ? 256 : g_fSupAdversaries ? 64 : 16;
     do
@@ -3518,6 +3541,7 @@
         Time.QuadPart = -8000000 / 100; /* 8ms in 100ns units, relative time. */
         NtDelayExecution(FALSE, &Time);
-    } while (GetTickCount() - dwStart < cMsKludge);
-    SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Startup delay kludge #1: %u ms\n", GetTickCount() - dwStart));
+    } while (supR3HardenedWinGetMilliTS() - uMsTsStart < cMsKludge);
+    SUP_DPRINTF(("supR3HardNtPuChTriggerInitialImageEvents: Startup delay kludge #1: %u ms\n",
+                 supR3HardenedWinGetMilliTS() - uMsTsStart));
 
     /*
@@ -3778,5 +3802,5 @@
     {
         NTSTATUS rcNtWait;
-        DWORD dwStartTick = GetTickCount();
+        uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
         do
         {
@@ -3793,5 +3817,5 @@
                      || rcNtWait == STATUS_USER_APC
                      || rcNtWait == STATUS_ALERTED)
-                 && GetTickCount() - dwStartTick < 60 * 1000);
+                 && supR3HardenedWinGetMilliTS() - uMsTsStart < 60 * 1000);
         if (fExitOk)
             supR3HardenedError(rc, false /*fFatal*/,
@@ -3822,5 +3846,5 @@
  *                          close the event semaphore and set it to NULL.
  */
-static void supR3HardenedWinCheckVmChild(HANDLE hProcWait, uintptr_t uChildExeAddr, HANDLE *phEvtParent, HANDLE *phEvtChild)
+static void supR3HardenedWinCheckChild(HANDLE hProcWait, uintptr_t uChildExeAddr, HANDLE *phEvtParent, HANDLE *phEvtChild)
 {
     /*
@@ -3828,10 +3852,10 @@
      */
     uintptr_t           uChildAddr = uChildExeAddr + ((uintptr_t)&g_ProcParams - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
-    SIZE_T              cbIgnored;
+    SIZE_T              cbIgnored = 0;
     SUPR3WINPROCPARAMS  ChildProcParams;
     RT_ZERO(ChildProcParams);
     NTSTATUS rcNt = NtReadVirtualMemory(hProcWait, (PVOID)uChildAddr, &ChildProcParams, sizeof(ChildProcParams), &cbIgnored);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt,
+        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckChild", rcNt,
                                   "NtReadVirtualMemory(,%p,) failed reading child process status: %#x\n", uChildAddr, rcNt);
 
@@ -3841,5 +3865,5 @@
     rcNt = NtSetEvent(*phEvtChild, NULL);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt, "NtSetEvent failed: %#x\n", rcNt);
+        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckChild", rcNt, "NtSetEvent failed: %#x\n", rcNt);
 
     /*
@@ -3850,5 +3874,5 @@
         rcNt = NtClose(*phEvtChild);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckVmChild", rcNt, "NtClose failed on event sem: %#x\n", rcNt);
+        supR3HardenedWinKillChild(hProcWait, "supR3HardenedWinCheckChild", rcNt, "NtClose failed on event sem: %#x\n", rcNt);
     *phEvtChild = NULL;
     *phEvtParent = NULL;
@@ -3862,10 +3886,10 @@
     /* An error occurred, report it. */
     ChildProcParams.szErrorMsg[sizeof(ChildProcParams.szErrorMsg) - 1] = '\0';
-    supR3HardenedFatalMsg("supR3HardenedWinCheckVmChild", kSupInitOp_Misc, ChildProcParams.rc, "%s", ChildProcParams.szErrorMsg);
-}
-
-
-static void supR3HardenedWinInitVmChild(HANDLE hProcess, HANDLE hThread, uintptr_t uChildNtDllAddr, uintptr_t uChildExeAddr,
-                                        HANDLE hEvtChild, HANDLE hEvtParent)
+    supR3HardenedFatalMsg("supR3HardenedWinCheckChild", kSupInitOp_Misc, ChildProcParams.rc, "%s", ChildProcParams.szErrorMsg);
+}
+
+
+static void supR3HardenedWinSetupChildInit(HANDLE hProcess, HANDLE hThread, uintptr_t uChildNtDllAddr, uintptr_t uChildExeAddr,
+                                           HANDLE hEvtChild, HANDLE hEvtParent)
 {
     /*
@@ -3884,5 +3908,5 @@
     NTSTATUS  rcNt = NtWriteVirtualMemory(hProcess, (PVOID)uChildAddr, &ChildProcParams, sizeof(ChildProcParams), &cbIgnored);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rcNt,
                                   "NtWriteVirtualMemory(,%p,) failed writing child process parameters: %#x\n", uChildAddr, rcNt);
 
@@ -3894,5 +3918,5 @@
     int rc = supHardNtLdrCacheOpen("ntdll.dll", &pLdrEntry);
     if (RT_FAILURE(rc))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rc,
                                   "supHardNtLdrCacheOpen failed on NTDLL: %Rrc\n", rc);
 
@@ -3900,5 +3924,5 @@
     rc = supHardNtLdrCacheEntryGetBits(pLdrEntry, &pbChildNtDllBits, uChildNtDllAddr, NULL, NULL, NULL /*pErrInfo*/);
     if (RT_FAILURE(rc))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rc,
                                   "supHardNtLdrCacheEntryGetBits failed on NTDLL: %Rrc\n", rc);
 
@@ -3907,17 +3931,19 @@
                           "LdrInitializeThunk", &uLdrInitThunk);
     if (RT_FAILURE(rc))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rc,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rc,
                                   "Error locating LdrInitializeThunk in NTDLL: %Rrc", rc);
     PVOID pvLdrInitThunk = (PVOID)(uintptr_t)uLdrInitThunk;
-    SUP_DPRINTF(("supR3HardenedWinInitVmChild: uLdrInitThunk=%p\n", (uintptr_t)uLdrInitThunk));
+    SUP_DPRINTF(("supR3HardenedWinSetupChildInit: uLdrInitThunk=%p\n", (uintptr_t)uLdrInitThunk));
 
     /*
      * Calculate the address of our code in the child process.
      */
-    uintptr_t uEarlyVmProcInitEP = uChildExeAddr + (  (uintptr_t)&supR3HardenedVmProcessInitThunk
-                                                    - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
+    uintptr_t uEarlyProcInitEP = uChildExeAddr + (  (uintptr_t)&supR3HardenedEarlyProcessInitThunk
+                                                  - (uintptr_t)NtCurrentPeb()->ImageBaseAddress);
 
     /*
      * Compose the LdrInitializeThunk replacement bytes.
+     * Note! The amount of code we replace here must be less or equal to what
+     *       the process verification code ignores.
      */
     uint8_t abNew[16];
@@ -3927,8 +3953,8 @@
     abNew[1] = 0x25;
     *(uint32_t *)&abNew[2] = 0;
-    *(uint64_t *)&abNew[6] = uEarlyVmProcInitEP;
+    *(uint64_t *)&abNew[6] = uEarlyProcInitEP;
 #elif defined(RT_ARCH_X86)
     abNew[0] = 0xe9;
-    *(uint32_t *)&abNew[1] = uEarlyVmProcInitEP - ((uint32_t)uLdrInitThunk + 5);
+    *(uint32_t *)&abNew[1] = uEarlyProcInitEP - ((uint32_t)uLdrInitThunk + 5);
 #else
 # error "Unsupported arch."
@@ -3943,10 +3969,10 @@
     rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, PAGE_EXECUTE_READWRITE, &fOldProt);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rcNt,
                                   "NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
 
     rcNt = NtWriteVirtualMemory(hProcess, pvLdrInitThunk, abNew, sizeof(abNew), &cbIgnored);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rcNt,
                                   "NtWriteVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);
 
@@ -3955,9 +3981,9 @@
     rcNt = NtProtectVirtualMemory(hProcess, &pvProt, &cbProt, fOldProt, &fOldProt);
     if (!NT_SUCCESS(rcNt))
-        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinInitVmChild", rcNt,
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinSetupChildInit", rcNt,
                                   "NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", rcNt);
 
     /* Caller starts child execution. */
-    SUP_DPRINTF(("supR3HardenedWinInitVmChild: Start child.\n"));
+    SUP_DPRINTF(("supR3HardenedWinSetupChildInit: Start child.\n"));
 }
 
@@ -3983,14 +4009,12 @@
      * Set up VM child communication event semaphores.
      */
+    OBJECT_ATTRIBUTES ObjAttrs;
     HANDLE hEvtChild = NULL;
+    InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
+    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtChild, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE));
+
     HANDLE hEvtParent = NULL;
-    if (iWhich >= 2)
-    {
-        OBJECT_ATTRIBUTES ObjAttrs;
-        InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
-        SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtChild, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE));
-        InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
-        SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtParent, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE));
-    }
+    InitializeObjectAttributes(&ObjAttrs, NULL /*pName*/, OBJ_INHERIT, NULL /*hRootDir*/, NULL /*pSecDesc*/);
+    SUPR3HARDENED_ASSERT_NT_SUCCESS(NtCreateEvent(&hEvtParent, EVENT_ALL_ACCESS, &ObjAttrs, NotificationEvent, FALSE));
 
     /*
@@ -4140,6 +4164,5 @@
      * Start the process execution.
      */
-    if (iWhich >= 2)
-        supR3HardenedWinInitVmChild(hProcess, hThread, uChildNtDllAddr, uChildExeAddr, hEvtChild, hEvtParent);
+    supR3HardenedWinSetupChildInit(hProcess, hThread, uChildNtDllAddr, uChildExeAddr, hEvtChild, hEvtParent);
 
     ULONG cSuspendCount = 0;
@@ -4155,18 +4178,21 @@
     PROCESS_BASIC_INFORMATION BasicInfo;
     HANDLE hProcWait;
-    ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE;
+    ULONG fRights = SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_VM_READ;
     if (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)) /* Introduced in Vista. */
         fRights |= PROCESS_QUERY_LIMITED_INFORMATION;
     else
         fRights |= PROCESS_QUERY_INFORMATION;
-    if (iWhich == 2)
-        fRights |= PROCESS_VM_READ;
     rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
                              NtCurrentProcess(), &hProcWait,
                              fRights, 0 /*HandleAttributes*/, 0);
     if (rcNt == STATUS_ACCESS_DENIED)
+    {
+        supR3HardenedError(rcNt, false /*fFatal*/,
+                           "supR3HardenedWinDoReSpawn: NtDuplicateObject(,,,,%#x,,) -> %#x, retrying with only %#x...\n",
+                           fRights, rcNt, SYNCHRONIZE);
         rcNt = NtDuplicateObject(NtCurrentProcess(), hProcess,
                                  NtCurrentProcess(), &hProcWait,
                                  SYNCHRONIZE, 0 /*HandleAttributes*/, 0);
+    }
     if (!NT_SUCCESS(rcNt))
         supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
@@ -4177,13 +4203,10 @@
 
     /*
-     * Signal the VM child that we've closed the unrestricted handles.
-     */
-    if (iWhich >= 2)
-    {
-        rcNt = NtSetEvent(hEvtChild, NULL);
-        if (!NT_SUCCESS(rcNt))
-            supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
-                                      "NtSetEvent failed on child process handle: %#x\n", rcNt);
-    }
+     * Signal the child that we've closed the unrestricted handles.
+     */
+    rcNt = NtSetEvent(hEvtChild, NULL);
+    if (!NT_SUCCESS(rcNt))
+        supR3HardenedWinKillChild(hProcess, "supR3HardenedWinReSpawn", VERR_INVALID_NAME,
+                                  "NtSetEvent failed on child process handle: %#x\n", rcNt);
 
     /*
@@ -4233,5 +4256,5 @@
         rcNt = NtWaitForMultipleObjects(cHandles, &ahHandles[0], WaitAnyObject, TRUE /*Alertable*/, NULL /*pTimeout*/);
         if (rcNt == STATUS_WAIT_0 + 1 && hEvtParent != NULL)
-            supR3HardenedWinCheckVmChild(hProcWait, uChildExeAddr, &hEvtParent, &hEvtChild);
+            supR3HardenedWinCheckChild(hProcWait, uChildExeAddr, &hEvtParent, &hEvtChild);
         else if (   (ULONG)rcNt - (ULONG)STATUS_WAIT_0           < cHandles
                  || (ULONG)rcNt - (ULONG)STATUS_ABANDONED_WAIT_0 < cHandles)
@@ -4418,9 +4441,12 @@
 static void supR3HardenedWinOpenStubDevice(void)
 {
+    if (g_fSupStubOpened)
+        return;
+
     /*
      * Retry if we think driver might still be initializing (STATUS_NO_SUCH_DEVICE + \Drivers\VBoxDrv).
      */
     static const WCHAR  s_wszName[] = L"\\Device\\VBoxDrvStub";
-    DWORD const         uStartTick = GetTickCount();
+    uint64_t const      uMsTsStart = supR3HardenedWinGetMilliTS();
     NTSTATUS            rcNt;
     uint32_t            iTry;
@@ -4457,5 +4483,5 @@
         if (rcNt != STATUS_NO_SUCH_DEVICE)
             break;
-        if (iTry > 0 && GetTickCount() - uStartTick > 5000)  /* 5 sec, at least two tries */
+        if (iTry > 0 && supR3HardenedWinGetMilliTS() - uMsTsStart > 5000)  /* 5 sec, at least two tries */
             break;
         if (!supR3HardenedWinDriverExists("VBoxDrv"))
@@ -4476,5 +4502,7 @@
     }
 
-    if (!NT_SUCCESS(rcNt))
+    if (NT_SUCCESS(rcNt))
+        g_fSupStubOpened = true;
+    else
     {
         /*
@@ -4542,4 +4570,5 @@
              * suggestions accordingly.
              */
+/** @todo don't fail during early init, wait till later and try load the driver if missing or at least query the service manager for additional information. */
             if (   rcNt == STATUS_NO_SUCH_DEVICE
                 || rcNt == STATUS_OBJECT_NAME_NOT_FOUND)
@@ -4579,5 +4608,8 @@
     /*
      * Before the 2nd respawn we set up a child protection deal with the
-     * support driver via /Devices/VBoxDrvStub.
+     * support driver via /Devices/VBoxDrvStub.  (We tried to do this
+     * during the early init, but in case we had trouble accessing vboxdrv we
+     * retry it here where we have kernel32.dll and others to pull in for
+     * better diagnostics.)
      */
     if (iWhich == 2)
@@ -4687,6 +4719,6 @@
             for (uint32_t iLoop = 0; iLoop < 16; iLoop++)
             {
-                uint32_t    cSleeps = 0;
-                DWORD       dwStart = GetTickCount();
+                uint32_t cSleeps = 0;
+                uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
                 do
                 {
@@ -4696,8 +4728,8 @@
                     NtDelayExecution(FALSE, &Time);
                     cSleeps++;
-                } while (   GetTickCount() - dwStart <= cMsFudge
+                } while (   supR3HardenedWinGetMilliTS() - uMsTsStart <= cMsFudge
                          || cSleeps < 8);
                 SUP_DPRINTF(("supR3HardenedWinInit: Startup delay kludge #2/%u: %u ms, %u sleeps\n",
-                             iLoop, GetTickCount() - dwStart, cSleeps));
+                             iLoop, supR3HardenedWinGetMilliTS() - uMsTsStart, cSleeps));
 
                 cFixes = 0;
@@ -5364,5 +5396,5 @@
     if (g_ProcParams.hEvtParent || g_ProcParams.hEvtChild)
     {
-        SUPR3HARDENED_ASSERT(g_fSupEarlyVmProcessInit);
+        SUPR3HARDENED_ASSERT(g_fSupEarlyProcessInit);
         NtSetEvent(g_ProcParams.hEvtParent, NULL);
         NtClose(g_ProcParams.hEvtParent);
@@ -5372,5 +5404,5 @@
     }
     else
-        SUPR3HARDENED_ASSERT(!g_fSupEarlyVmProcessInit);
+        SUPR3HARDENED_ASSERT(!g_fSupEarlyProcessInit);
 
     /*
@@ -5479,17 +5511,18 @@
 
 /**
- * Routine called by the supR3HardenedVmProcessInitThunk assembly routine when
- * LdrInitializeThunk is executed in during process initialization.
- *
- * This initializes the VM process, hooking NTDLL APIs and opening the device
- * driver before any other DLLs gets loaded into the process.  This greately
- * reduces and controls the trusted code base of the process compared to the
- * opening it from SUPR3HardenedMain, avoid issues with so call protection
- * software that is in the habit of patching half of the ntdll and kernel32
- * APIs in the process, making it almost indistinguishable from software that is
- * up to no good.  Once we've opened vboxdrv, the process should be locked down
- * so thighly that only kernel software and csrss can mess with the process.
- */
-DECLASM(uintptr_t) supR3HardenedVmProcessInit(void)
+ * Routine called by the supR3HardenedEarlyProcessInitThunk assembly routine
+ * when LdrInitializeThunk is executed in during process initialization.
+ *
+ * This initializes the Stub and VM processes, hooking NTDLL APIs and opening
+ * the device driver before any other DLLs gets loaded into the process.  This
+ * greately reduces and controls the trusted code base of the process compared
+ * to opening the driver from SUPR3HardenedMain.  It also avoids issues with so
+ * call protection software that is in the habit of patching half of the ntdll
+ * and kernel32 APIs in the process, making it almost indistinguishable from
+ * software that is up to no good.  Once we've opened vboxdrv, the process
+ * should be locked down so thighly that only kernel software and csrss can mess
+ * with the process.
+ */
+DECLASM(uintptr_t) supR3HardenedEarlyProcessInit(void)
 {
     /*
@@ -5497,5 +5530,5 @@
      */
     if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&g_enmSupR3HardenedMainState,
-                             SUPR3HARDENEDMAINSTATE_WIN_VM_INIT_CALLED,
+                             SUPR3HARDENEDMAINSTATE_WIN_EARLY_INIT_CALLED,
                              SUPR3HARDENEDMAINSTATE_NOT_YET_CALLED))
     {
@@ -5503,5 +5536,5 @@
         return 0x22;  /* crash */
     }
-    g_fSupEarlyVmProcessInit = true;
+    g_fSupEarlyProcessInit = true;
 
     /*
@@ -5524,5 +5557,5 @@
     Timeout.QuadPart = -600000000; /* 60 second */
     NTSTATUS rcNt = NtWaitForSingleObject(g_ProcParams.hEvtChild, FALSE /*Alertable*/, &Timeout);
-    if (NT_SUCCESS(rcNt))
+    if (rcNt != STATUS_SUCCESS)
         rcNt = NtClearEvent(g_ProcParams.hEvtChild);
     if (!NT_SUCCESS(rcNt))
@@ -5568,6 +5601,16 @@
      * Open the driver.
      */
-    SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n"));
-    supR3HardenedMainOpenDevice();
+    if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_1_ARG0) == 0)
+    {
+        SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv stub...\n"));
+        supR3HardenedWinOpenStubDevice();
+    }
+    else if (cArgs >= 1 && suplibHardenedStrCmp(papszArgs[0], SUPR3_RESPAWN_2_ARG0) == 0)
+    {
+        SUP_DPRINTF(("supR3HardenedVmProcessInit: Opening vboxdrv...\n"));
+        supR3HardenedMainOpenDevice();
+    }
+    else
+        supR3HardenedFatal("Unexpected first argument '%s'!\n", papszArgs[0]);
     g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_EARLY_DEVICE_OPENED;
 
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm	(revision 52949)
@@ -36,5 +36,5 @@
 
 ; External code.
-extern NAME(supR3HardenedVmProcessInit)
+extern NAME(supR3HardenedEarlyProcessInit)
 
 
@@ -83,5 +83,6 @@
 
 ;;
-; Alternative code for LdrInitializeThunk that performs the VM process startup.
+; Alternative code for LdrInitializeThunk that performs the early process startup
+; for the Stub and VM processes.
 ;
 ; This does not concern itself with any arguments on stack or in registers that
@@ -89,5 +90,7 @@
 ; them all before we restart the restored LdrInitializeThunk routine.
 ;
-BEGINPROC supR3HardenedVmProcessInitThunk
+; @sa supR3HardenedEarlyProcessInit
+;
+BEGINPROC supR3HardenedEarlyProcessInitThunk
         ;
         ; Prologue.
@@ -123,5 +126,5 @@
         ; resume address in xAX, which we put in the "return" stack position.
         ;
-        call    NAME(supR3HardenedVmProcessInit)
+        call    NAME(supR3HardenedEarlyProcessInit)
         mov     [xBP + xCB], xAX
 
@@ -145,5 +148,5 @@
         leave
         ret
-ENDPROC   supR3HardenedVmProcessInitThunk
+ENDPROC   supR3HardenedEarlyProcessInitThunk
 
 
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedNoCrt-win.cpp	(revision 52949)
@@ -269,5 +269,5 @@
     if (!hHeap)
     {
-        if (   g_fSupEarlyVmProcessInit
+        if (   g_fSupEarlyProcessInit
             && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
             return supR3HardenedEarlyAlloc(cb, false /*fZero*/);
@@ -287,5 +287,5 @@
     if (!hHeap)
     {
-        if (   g_fSupEarlyVmProcessInit
+        if (   g_fSupEarlyProcessInit
             && g_enmSupR3HardenedMainState <= SUPR3HARDENEDMAINSTATE_WIN_EP_CALLED)
             return supR3HardenedEarlyAlloc(cb, true /*fZero*/);
@@ -328,5 +328,5 @@
 
     void *pv;
-    if (g_fSupEarlyVmProcessInit)
+    if (g_fSupEarlyProcessInit)
     {
         uint32_t iHeap = supR3HardenedEarlyFind(pvOld);
@@ -387,5 +387,5 @@
     if (pv)
     {
-        if (g_fSupEarlyVmProcessInit)
+        if (g_fSupEarlyProcessInit)
         {
             uint32_t iHeap = supR3HardenedEarlyFind(pv);
Index: /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 52948)
+++ /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 52949)
@@ -64,9 +64,9 @@
 SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16)
 SUPHARNT_IMPORT_STDCALL(RtlAddAccessDeniedAce, 16)
-SUPHARNT_IMPORT_STDCALL_EARLY(RtlAllocateHeap, 12)
+SUPHARNT_IMPORT_STDCALL(RtlAllocateHeap, 12)
 SUPHARNT_IMPORT_STDCALL(RtlCompactHeap, 8)
 SUPHARNT_IMPORT_STDCALL(RtlCopySid, 12)
 SUPHARNT_IMPORT_STDCALL(RtlCreateAcl, 12)
-SUPHARNT_IMPORT_STDCALL_EARLY(RtlCreateHeap, 24)
+SUPHARNT_IMPORT_STDCALL(RtlCreateHeap, 24)
 SUPHARNT_IMPORT_STDCALL(RtlCreateProcessParameters, 40)
 SUPHARNT_IMPORT_STDCALL(RtlCreateSecurityDescriptor, 8)
@@ -79,5 +79,5 @@
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlExitUserThread, 4)
 SUPHARNT_IMPORT_STDCALL(RtlExpandEnvironmentStrings_U, 16)
-SUPHARNT_IMPORT_STDCALL_EARLY(RtlFreeHeap, 12)
+SUPHARNT_IMPORT_STDCALL(RtlFreeHeap, 12)
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlFreeUnicodeString, 4)
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlGetLastNtStatus, 0)
@@ -91,5 +91,5 @@
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSetLastWin32Error, 4)
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSetLastWin32ErrorAndNtStatusFromNtStatus, 4)
-SUPHARNT_IMPORT_STDCALL_EARLY(RtlSizeHeap, 12)
+SUPHARNT_IMPORT_STDCALL(RtlSizeHeap, 12)
 SUPHARNT_IMPORT_STDCALL_EARLY(RtlSubAuthoritySid, 8)
 
