Index: /trunk/include/iprt/nt/nt.h
===================================================================
--- /trunk/include/iprt/nt/nt.h	(revision 54997)
+++ /trunk/include/iprt/nt/nt.h	(revision 54998)
@@ -46,4 +46,5 @@
 # define NtReadFile                     ZwReadFile
 # define NtWriteFile                    ZwWriteFile
+# define NtFlushBuffersFile             ZwFlushBuffersFile
 /** @todo this is very incomplete! */
 #endif
@@ -226,4 +227,7 @@
 /** Initializes a IO_STATUS_BLOCK. */
 #define RTNT_IO_STATUS_BLOCK_INITIALIZER  { STATUS_FAILED_DRIVER_ENTRY, ~(uintptr_t)42 }
+/** Reinitializes a IO_STATUS_BLOCK. */
+#define RTNT_IO_STATUS_BLOCK_REINIT(a_pIos) \
+    do { (a_pIos)->Status = STATUS_FAILED_DRIVER_ENTRY; (a_pIos)->Information = ~(uintptr_t)42; } while (0)
 /** Similar to INVALID_HANDLE_VALUE in the Windows environment. */
 #define RTNT_INVALID_HANDLE_VALUE         ( (HANDLE)~(uintptr_t)0 )
@@ -1641,4 +1645,5 @@
 NTSYSAPI NTSTATUS NTAPI NtReadFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
 NTSYSAPI NTSTATUS NTAPI NtWriteFile(HANDLE, HANDLE, PIO_APC_ROUTINE, void const *, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
+NTSYSAPI NTSTATUS NTAPI NtFlushBuffersFile(HANDLE, PIO_STATUS_BLOCK);
 
 NTSYSAPI NTSTATUS NTAPI NtReadVirtualMemory(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 54997)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 54998)
@@ -92,4 +92,5 @@
 # define supR3HardenedLogV                 supR3HardenedStaticLogV
 # define supR3HardenedLog                  supR3HardenedStaticLog
+# define supR3HardenedLogFlush             supR3HardenedStaticLogFlush
 # define supR3HardenedVerifyAll            supR3HardenedStaticVerifyAll
 # define supR3HardenedVerifyFixedDir       supR3HardenedStaticVerifyFixedDir
@@ -433,4 +434,9 @@
  */
 DECLHIDDEN(void)    supR3HardenedLog(const char *pszFormat, ...);
+
+/**
+ * Flushes the log file.
+ */
+DECLHIDDEN(void)    supR3HardenedLogFlush(void);
 
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 54997)
+++ /trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp	(revision 54998)
@@ -169,4 +169,6 @@
  * release log at runtime. */
 static PFNRTLOGRELPRINTF g_pfnRTLogRelPrintf = NULL;
+/** Log volume name (for attempting volume flush). */
+static RTUTF16          g_wszStartupLogVol[16];
 #endif
 
@@ -1002,6 +1004,20 @@
                                       NULL);
                 if (RT_SUCCESS(rc))
+                {
                     SUP_DPRINTF(("Log file opened: " VBOX_VERSION_STRING "r%u g_hStartupLog=%p g_uNtVerCombined=%#x\n",
                                  VBOX_SVN_REV, g_hStartupLog, g_uNtVerCombined));
+
+                    /*
+                     * If the path contains a drive volume, save it so we can
+                     * use it to flush the volume containing the log file.
+                     */
+                    if (RT_C_IS_ALPHA(pszLogFile[0]) && pszLogFile[1] == ':')
+                    {
+                        RTUtf16CopyAscii(g_wszStartupLogVol, RT_ELEMENTS(g_wszStartupLogVol), "\\??\\");
+                        g_wszStartupLogVol[sizeof("\\??\\") - 1] = RT_C_TO_UPPER(pszLogFile[0]);
+                        g_wszStartupLogVol[sizeof("\\??\\") + 0] = ':';
+                        g_wszStartupLogVol[sizeof("\\??\\") + 1] = '\0';
+                    }
+                }
                 else
                     g_hStartupLog = NULL;
@@ -1051,4 +1067,72 @@
     supR3HardenedLogV(pszFormat, va);
     va_end(va);
+}
+
+
+DECLHIDDEN(void) supR3HardenedLogFlush(void)
+{
+#ifdef RT_OS_WINDOWS
+    if (   g_hStartupLog != NULL
+        && g_cbStartupLog < 16*_1M)
+    {
+        IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
+        NTSTATUS rcNt = NtFlushBuffersFile(g_hStartupLog, &Ios);
+
+        /*
+         * Try flush the volume containing the log file too.
+         */
+        if (g_wszStartupLogVol[0])
+        {
+            HANDLE              hLogVol = RTNT_INVALID_HANDLE_VALUE;
+            UNICODE_STRING      NtName;
+            NtName.Buffer        = g_wszStartupLogVol;
+            NtName.Length        = (USHORT)(RTUtf16Len(g_wszStartupLogVol) * sizeof(RTUTF16));
+            NtName.MaximumLength = NtName.Length + 1;
+            OBJECT_ATTRIBUTES   ObjAttr;
+            InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
+            RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
+            rcNt = NtCreateFile(&hLogVol,
+                                GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+                                &ObjAttr,
+                                &Ios,
+                                NULL /* Allocation Size*/,
+                                0 /*FileAttributes*/,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                FILE_OPEN,
+                                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+                                NULL /*EaBuffer*/,
+                                0 /*EaLength*/);
+            if (NT_SUCCESS(rcNt))
+                rcNt = Ios.Status;
+            if (NT_SUCCESS(rcNt))
+            {
+                RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
+                rcNt = NtFlushBuffersFile(hLogVol, &Ios);
+                NtClose(hLogVol);
+            }
+            else
+            {
+                /* This may have sideeffects similar to what we want... */
+                hLogVol = RTNT_INVALID_HANDLE_VALUE;
+                RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
+                rcNt = NtCreateFile(&hLogVol,
+                                    GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
+                                    &ObjAttr,
+                                    &Ios,
+                                    NULL /* Allocation Size*/,
+                                    0 /*FileAttributes*/,
+                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                    FILE_OPEN,
+                                    FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
+                                    NULL /*EaBuffer*/,
+                                    0 /*EaLength*/);
+                if (NT_SUCCESS(rcNt) && NT_SUCCESS(Ios.Status))
+                    NtClose(hLogVol);
+            }
+        }
+    }
+#else
+    /* later */
+#endif
 }
 
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp	(revision 54997)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp	(revision 54998)
@@ -1545,5 +1545,6 @@
  * Frees (or replaces) executable memory of allocation type private.
  *
- * @returns VBox status code.
+ * @returns True if nothing really bad happen, false if to quit ASAP because we
+ *          killed the process being scanned.
  * @param   pThis               The process scanning state structure. Details
  *                              about images are added to this.
@@ -1552,5 +1553,5 @@
  *                              executable memory.
  */
-static void supHardNtVpFreeOrReplacePrivateExecMemory(PSUPHNTVPSTATE pThis, HANDLE hProcess,
+static bool supHardNtVpFreeOrReplacePrivateExecMemory(PSUPHNTVPSTATE pThis, HANDLE hProcess,
                                                       MEMORY_BASIC_INFORMATION const *pMemInfo)
 {
@@ -1596,5 +1597,5 @@
         {
             supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, "RTMemAllocZ(%#zx) failed", cbCopy);
-            return;
+            return true;
         }
 
@@ -1603,4 +1604,5 @@
             supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED,
                                 "Error reading data from original alloc: %#x (%p LB %#zx)", rcNt, uCopySrc, cbCopy, rcNt);
+        supR3HardenedLogFlush();
     }
 
@@ -1613,14 +1615,28 @@
         SIZE_T cbFreeInOut = 0;
         rcNt = NtFreeVirtualMemory(hProcess, &pvFreeInOut, &cbFreeInOut, MEM_RELEASE);
-        if (!NT_SUCCESS(rcNt))
+        if (NT_SUCCESS(rcNt))
+        {
+            SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #1 succeeded: %#x [%p/%p LB 0/%#zx]\n",
+                         rcNt, pvFree, pvFreeInOut, cbFreeInOut));
+            supR3HardenedLogFlush();
+        }
+        else
         {
             SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #1 failed: %#x [%p LB 0]\n", rcNt, pvFree));
+            supR3HardenedLogFlush();
             pvFreeInOut = pvFree;
             cbFreeInOut = cbFree;
             rcNt = NtFreeVirtualMemory(hProcess, &pvFreeInOut, &cbFreeInOut, MEM_RELEASE);
-            if (!NT_SUCCESS(rcNt))
+            if (NT_SUCCESS(rcNt))
+            {
+                SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #2 succeeded: %#x [%p/%p LB %#zx/%#zx]\n",
+                             rcNt, pvFree, pvFreeInOut, cbFree, cbFreeInOut));
+                supR3HardenedLogFlush();
+            }
+            else
             {
                 SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #2 failed: %#x [%p LB %#zx]\n",
                              rcNt, pvFree, cbFree));
+                supR3HardenedLogFlush();
                 pvFreeInOut = pMemInfo->BaseAddress;
                 cbFreeInOut = pMemInfo->RegionSize;
@@ -1632,4 +1648,5 @@
                     SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Free attempt #3 succeeded [%p LB %#zx]\n",
                                  pvFree, cbFree));
+                    supR3HardenedLogFlush();
                 }
                 else
@@ -1643,5 +1660,5 @@
          * Query the region again, redo the free operation if there's still memory there.
          */
-        if (!NT_SUCCESS(rcNt) || (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW))
+        if (!NT_SUCCESS(rcNt) || !(pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW))
             break;
         SIZE_T                      cbActual = 0;
@@ -1654,7 +1671,10 @@
                      i, MemInfo3.AllocationBase, MemInfo3.BaseAddress, MemInfo3.RegionSize, MemInfo3.State,
                      MemInfo3.AllocationProtect, MemInfo3.Protect));
+        supR3HardenedLogFlush();
         if (pMemInfo->State == MEM_FREE)
             break;
+        NtYieldExecution();
         SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Retrying free...\n"));
+        supR3HardenedLogFlush();
     }
 
@@ -1669,4 +1689,5 @@
         rcNt = NtAllocateVirtualMemory(hProcess, &pvAlloc, 0, &cbAlloc, MEM_COMMIT, PAGE_READWRITE);
         if (!NT_SUCCESS(rcNt))
+        {
             supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED,
                                 "NtAllocateVirtualMemory (%p LB %#zx) failed with rcNt=%#x allocating "
@@ -1674,46 +1695,65 @@
                                 "See VBoxStartup.log for more details",
                                 pvAlloc, cbFree, rcNt);
-        else if (   (uintptr_t)pvFree < (uintptr_t)pvAlloc
-                 || (uintptr_t)pvFree + cbFree > (uintptr_t)pvAlloc + cbFree)
+            supR3HardenedLogFlush();
+            NtTerminateProcess(hProcess, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED);
+            return false;
+        }
+
+        if (   (uintptr_t)pvFree < (uintptr_t)pvAlloc
+            || (uintptr_t)pvFree + cbFree > (uintptr_t)pvAlloc + cbFree)
+        {
             supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED,
                                 "We wanted NtAllocateVirtualMemory to get us %p LB %#zx, but it returned %p LB %#zx.",
                                 pMemInfo->BaseAddress, pMemInfo->RegionSize, pvFree, cbFree, rcNt);
+            supR3HardenedLogFlush();
+            NtTerminateProcess(hProcess, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED);
+            return false;
+        }
+
+        /*
+         * Copy what we can, considering the 2nd free attempt.
+         */
+        uint8_t *pbDst = (uint8_t *)pvFree;
+        size_t   cbDst = cbFree;
+        uint8_t *pbSrc = (uint8_t *)pvCopy;
+        size_t   cbSrc = cbCopy;
+        if ((uintptr_t)pbDst != uCopySrc)
+        {
+            if ((uintptr_t)pbDst > uCopySrc)
+            {
+                uintptr_t cbAdj = (uintptr_t)pbDst - uCopySrc;
+                pbSrc += cbAdj;
+                cbSrc -= cbSrc;
+            }
+            else
+            {
+                uintptr_t cbAdj = uCopySrc - (uintptr_t)pbDst;
+                pbDst += cbAdj;
+                cbDst -= cbAdj;
+            }
+        }
+        if (cbSrc > cbDst)
+            cbSrc = cbDst;
+
+        SIZE_T cbWritten;
+        rcNt = NtWriteVirtualMemory(hProcess, pbDst, pbSrc, cbSrc, &cbWritten);
+        if (NT_SUCCESS(rcNt))
+        {
+            SUP_DPRINTF(("supHardNtVpFreeOrReplacePrivateExecMemory: Restored the exec memory as non-exec.\n"));
+            supR3HardenedLogFlush();
+        }
         else
         {
-            /*
-             * Copy what we can, considering the 2nd free attempt.
-             */
-            uint8_t *pbDst = (uint8_t *)pvFree;
-            size_t   cbDst = cbFree;
-            uint8_t *pbSrc = (uint8_t *)pvCopy;
-            size_t   cbSrc = cbCopy;
-            if ((uintptr_t)pbDst != uCopySrc)
-            {
-                if ((uintptr_t)pbDst > uCopySrc)
-                {
-                    uintptr_t cbAdj = (uintptr_t)pbDst - uCopySrc;
-                    pbSrc += cbAdj;
-                    cbSrc -= cbSrc;
-                }
-                else
-                {
-                    uintptr_t cbAdj = uCopySrc - (uintptr_t)pbDst;
-                    pbDst += cbAdj;
-                    cbDst -= cbAdj;
-                }
-            }
-            if (cbSrc > cbDst)
-                cbSrc = cbDst;
-
-            SIZE_T cbWritten;
-            rcNt = NtWriteVirtualMemory(hProcess, pbDst, pbSrc, cbSrc, &cbWritten);
-            if (!NT_SUCCESS(rcNt))
-                supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED,
-                                    "NtWriteVirtualMemory (%p LB %#zx) failed: %#x",
-                                    pMemInfo->BaseAddress, pMemInfo->RegionSize, rcNt);
+            supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED,
+                                "NtWriteVirtualMemory (%p LB %#zx) failed: %#x",
+                                pMemInfo->BaseAddress, pMemInfo->RegionSize, rcNt);
+            supR3HardenedLogFlush();
+            NtTerminateProcess(hProcess, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED);
+            return false;
         }
     }
     if (pvCopy)
         RTMemFree(pvCopy);
+    return true;
 }
 #endif /* IN_RING3 */
@@ -1857,5 +1897,8 @@
                  */
                 if (MemInfo.Type == MEM_PRIVATE)
-                    supHardNtVpFreeOrReplacePrivateExecMemory(pThis, hProcess, &MemInfo);
+                {
+                    if (!supHardNtVpFreeOrReplacePrivateExecMemory(pThis, hProcess, &MemInfo))
+                        break;
+                }
                 /*
                  * Unmap mapped memory, failing that, drop exec privileges.
Index: /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 54997)
+++ /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 54998)
@@ -8,4 +8,5 @@
 SUPHARNT_IMPORT_SYSCALL(NtDeviceIoControlFile, 40)
 SUPHARNT_IMPORT_SYSCALL(NtDuplicateObject, 28)
+SUPHARNT_IMPORT_SYSCALL(NtFlushBuffersFile, 8)
 SUPHARNT_IMPORT_SYSCALL(NtFreeVirtualMemory, 16)
 SUPHARNT_IMPORT_SYSCALL(NtGetContextThread, 8)
Index: /trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def	(revision 54997)
+++ /trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def	(revision 54998)
@@ -5,5 +5,5 @@
 
 ;
-; Copyright (C) 2010-2014 Oracle Corporation
+; Copyright (C) 2010-2015 Oracle Corporation
 ;
 ; This file is part of VirtualBox Open Source Edition (OSE), as
@@ -42,4 +42,5 @@
     NtDeviceIoControlFile                 ;;= _NtDeviceIoControlFile@40
     NtDuplicateObject                     ;;= _NtDuplicateObject@28
+    NtFlushBuffersFile                    ;;= _NtFlushBuffersFile@8
     NtFreeVirtualMemory                   ;;= _NtFreeVirtualMemory@16
     NtGetContextThread                    ;;= _NtGetContextThread@8
