Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 67978)
+++ /trunk/include/iprt/mangling.h	(revision 67979)
@@ -3485,4 +3485,5 @@
 # define RTUtf16End                                     RT_MANGLER(RTUtf16End)
 # define RTUtf16ICmpAscii                               RT_MANGLER(RTUtf16ICmpAscii)
+# define RTUtf16NICmpAscii                              RT_MANGLER(RTUtf16NICmpAscii)
 # define RTUtf16NLen                                    RT_MANGLER(RTUtf16NLen)
 # define RTUtf16NLenEx                                  RT_MANGLER(RTUtf16NLenEx)
Index: /trunk/include/iprt/nt/nt.h
===================================================================
--- /trunk/include/iprt/nt/nt.h	(revision 67978)
+++ /trunk/include/iprt/nt/nt.h	(revision 67979)
@@ -2664,4 +2664,10 @@
                                                                  IN PSIZE_T pcbFilename OPTIONAL,
                                                                  IN PSIZE_T pcbNeeded OPTIONAL);
+/** @since Windows 8.
+ * @note Status code is always zero in windows 10 build 14393. */
+NTSYSAPI NTSTATUS ApiSetQueryApiSetPresence(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+/** @copydoc ApiSetQueryApiSetPresence */
+typedef NTSTATUS (NTAPI *PFNAPISETQUERYAPISETPRESENCE)(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+
 
 # ifdef IPRT_NT_USE_WINTERNL
Index: /trunk/include/iprt/utf16.h
===================================================================
--- /trunk/include/iprt/utf16.h	(revision 67978)
+++ /trunk/include/iprt/utf16.h	(revision 67979)
@@ -462,5 +462,5 @@
 
 /**
- * Performs a case insensitive string compare between an UTF-16 string and an
+ * Performs a case insensitive string compare between an UTF-16 string and a
  * pure ASCII string.
  *
@@ -525,4 +525,21 @@
  */
 RTDECL(int) RTUtf16BigNICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2, size_t cwcMax);
+
+/**
+ * Performs a case insensitive string compare between a UTF-16 string and a pure
+ * ASCII string, stopping after N characters.
+ *
+ * Since this compare only takes cares about the first 128 codepoints in
+ * unicode, no tables are needed and there aren't any real complications.
+ *
+ * @returns < 0 if the first string less than the second string.
+ * @returns 0 if the first string identical to the second string.
+ * @returns > 0 if the first string greater than the second string.
+ * @param   pwsz1       The UTF-16 first string. Null is allowed.
+ * @param   psz2        The pure ASCII second string. Null is allowed.
+ * @param   cwcMax      Maximum number of UTF-16 characters to compare.
+ */
+RTDECL(int) RTUtf16NICmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax);
+
 
 /**
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 67978)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 67979)
@@ -313,4 +313,5 @@
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16PrintHexBytes.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16ICmpAscii.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16NICmpAscii.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16CatAscii.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/string/RTUtf16CopyAscii.cpp \
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp	(revision 67978)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp	(revision 67979)
@@ -1672,4 +1672,141 @@
 
 /**
+ * Checks if the given name is a valid ApiSet name.
+ *
+ * This is only called on likely looking names.
+ *
+ * @returns true if ApiSet name, false if not.
+ * @param   pName               The name to check out.
+ */
+static bool supR3HardenedIsApiSetDll(PUNICODE_STRING pName)
+{
+    /*
+     * API added in Windows 8, or so they say.
+     */
+    if (ApiSetQueryApiSetPresence != NULL)
+    {
+        BOOLEAN fPresent = FALSE;
+        NTSTATUS rcNt = ApiSetQueryApiSetPresence(pName, &fPresent);
+        SUP_DPRINTF(("supR3HardenedIsApiSetDll: ApiSetQueryApiSetPresence(%.*ls) -> %#x, fPresent=%d\n",
+                     pName->Length / sizeof(WCHAR), pName->Buffer, rcNt, fPresent));
+        return fPresent != 0;
+    }
+
+    /*
+     * Fallback needed for Windows 7.  Fortunately, there aren't too many fake DLLs here.
+     */
+    if (   supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
+                                          L"api-ms-win-", 11, false /*fCheckSlash*/)
+        || supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
+                                          L"ext-ms-win-", 11, false /*fCheckSlash*/) )
+    {
+#define MY_ENTRY(a) { a, sizeof(a) - 1 }
+        static const struct { const char *psz; size_t cch; } s_aKnownSets[] =
+        {
+            MY_ENTRY("api-ms-win-core-console-l1-1-0 "),
+            MY_ENTRY("api-ms-win-core-datetime-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-debug-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-delayload-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-errorhandling-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-fibers-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-file-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-handle-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-heap-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-interlocked-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-io-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-libraryloader-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-localization-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-localregistry-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-memory-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-misc-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-namedpipe-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-processenvironment-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-processthreads-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-profile-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-rtlsupport-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-string-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-synch-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-sysinfo-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-threadpool-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-ums-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-util-l1-1-0"),
+            MY_ENTRY("api-ms-win-core-xstate-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-base-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-lsalookup-l1-1-0"),
+            MY_ENTRY("api-ms-win-security-sddl-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-core-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-management-l1-1-0"),
+            MY_ENTRY("api-ms-win-service-management-l2-1-0"),
+            MY_ENTRY("api-ms-win-service-winsvc-l1-1-0"),
+        };
+#undef MY_ENTRY
+
+        /* drop the dll suffix if present. */
+        PCRTUTF16 pawcName = pName->Buffer;
+        size_t    cwcName  = pName->Length / sizeof(WCHAR);
+        if (   cwcName > 5
+            && (pawcName[cwcName - 1] == 'l' || pawcName[cwcName - 1] == 'L')
+            && (pawcName[cwcName - 2] == 'l' || pawcName[cwcName - 2] == 'L')
+            && (pawcName[cwcName - 3] == 'd' || pawcName[cwcName - 3] == 'D')
+            &&  pawcName[cwcName - 4] == '.')
+            cwcName -= 4;
+
+        /* Search the table. */
+        for (size_t i = 0; i < RT_ELEMENTS(s_aKnownSets); i++)
+            if (   cwcName == s_aKnownSets[i].cch
+                && RTUtf16NICmpAscii(pawcName, s_aKnownSets[i].psz, cwcName) == 0)
+            {
+                SUP_DPRINTF(("supR3HardenedIsApiSetDll: '%.*ls' -> true\n", pName->Length / sizeof(WCHAR)));
+                return true;
+            }
+
+        SUP_DPRINTF(("supR3HardenedIsApiSetDll: Warning! '%.*ls' looks like an API set, but it's not in the list!\n",
+                     pName->Length / sizeof(WCHAR), pName->Buffer));
+    }
+
+    SUP_DPRINTF(("supR3HardenedIsApiSetDll: '%.*ls' -> false\n", pName->Length / sizeof(WCHAR)));
+    return false;
+}
+
+
+/**
+ * Checks whether the given unicode string contains a path separator and at
+ * least one dash.
+ *
+ * This is used to check for likely ApiSet name.  So far, all the pseudo DLL
+ * names include multiple dashes, so we use that as a criteria for recognizing
+ * them.  By happy coincident, most regular DLLs doesn't include dashes.
+ *
+ * @returns true if it contains path separator, false if only a name.
+ * @param   pPath               The path to check.
+ */
+static bool supR3HardenedHasDashButNoPath(PUNICODE_STRING pPath)
+{
+    size_t    cDashes = 0;
+    size_t    cwcLeft = pPath->Length / sizeof(WCHAR);
+    PCRTUTF16 pwc     = pPath->Buffer;
+    while (cwcLeft-- > 0)
+    {
+        RTUTF16 wc = *pwc++;
+        switch (wc)
+        {
+            default:
+                break;
+
+            case '-':
+                cDashes++;
+                break;
+
+            case '\\':
+            case '/':
+            case ':':
+                return false;
+        }
+    }
+    return cDashes > 0;
+}
+
+
+/**
  * Helper for supR3HardenedMonitor_LdrLoadDll.
  *
@@ -1724,30 +1861,4 @@
         return false;
     return RTUtf16ICmpAscii(pwszTmp, pszName) == 0;
-}
-
-/**
- * Checks whether the given unicode string contains a path separator.
- *
- * @returns true if it contains path separator, false if only a name.
- * @param   pPath               The path to check.
- */
-static bool supR3HardenedContainsPathSep(PUNICODE_STRING pPath)
-{
-    size_t    cwcLeft = pPath->Length / sizeof(WCHAR);
-    PCRTUTF16 pwc     = pPath->Buffer;
-    while (cwcLeft-- > 0)
-    {
-        RTUTF16 wc = *pwc++;
-        switch (wc)
-        {
-            default:
-                break;
-            case '\\':
-            case '/':
-            case ':':
-                return true;
-        }
-    }
-    return false;
 }
 
@@ -1955,9 +2066,6 @@
      * or something we're known to use but should be taken from WinSxS.
      */
-    else if (   (   supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
-                                                  L"api-ms-win-", 11, false /*fCheckSlash*/)
-                 || supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
-                                                  L"ext-ms-win-", 11, false /*fCheckSlash*/) )
-             && !supR3HardenedContainsPathSep(pName))
+    else if (   supR3HardenedHasDashButNoPath(pName)
+             && supR3HardenedIsApiSetDll(pName))
     {
         memcpy(wszPath, pName->Buffer, pName->Length);
Index: /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 67978)
+++ /trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h	(revision 67979)
@@ -63,4 +63,5 @@
 SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(LdrRegisterDllNotification, 16)
 SUPHARNT_IMPORT_STDCALL_EARLY(LdrGetDllHandle, 16)
+SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(ApiSetQueryApiSetPresence, 8)
 
 SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16)
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 67978)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 67979)
@@ -2096,4 +2096,5 @@
 	common/string/RTStrNLenEx.cpp \
 	common/string/RTUtf16ICmpAscii.cpp \
+	common/string/RTUtf16NICmpAscii.cpp \
 	common/string/straprintf.cpp \
 	common/string/strformat.cpp \
Index: /trunk/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp	(revision 67979)
+++ /trunk/src/VBox/Runtime/common/string/RTUtf16NICmpAscii.cpp	(revision 67979)
@@ -0,0 +1,61 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTUtf16ICmpAscii.
+ */
+
+/*
+ * Copyright (C) 2010-2016 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/string.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+
+
+RTDECL(int) RTUtf16NICmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax)
+{
+    for (;;)
+    {
+        if (cwcMax == 0)
+            return 0;
+
+        RTUTF16         wc1  = *pwsz1++;
+        unsigned char   uch2 = *psz2++; Assert(uch2 < 0x80);
+        if (wc1 != uch2)
+        {
+            if (wc1 >= 0x80)
+                return 1;
+            if (RT_C_TO_LOWER(wc1) != RT_C_TO_LOWER(uch2))
+                return wc1 < uch2 ? -1 : 1;
+        }
+
+        if (!uch2)
+            return 0;
+        cwcMax--;
+    }
+}
+RT_EXPORT_SYMBOL(RTUtf16NICmpAscii);
+
