Index: trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 57266)
+++ trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 57303)
@@ -207,4 +207,6 @@
     /** The kind of process we're protecting. */
     SUPDRVNTPROTECTKIND volatile enmProcessKind;
+    /** Whether this structure is in the tree. */
+    bool                fInTree : 1;
     /** 7,: Hack to allow the supid themes service duplicate handle privileges to
      *  our process. */
@@ -2938,4 +2940,5 @@
             if (fSuccess)
             {
+                pNtChild->fInTree         = true;
                 pNtParent->u.pChild       = pNtChild; /* Parent keeps the initial reference. */
                 pNtParent->enmProcessKind = kSupDrvNtProtectKind_StubParent;
@@ -3268,4 +3271,6 @@
             else
             {
+                ACCESS_MASK const fDesiredAccess = pOpInfo->Parameters->CreateHandleInformation.DesiredAccess;
+
                 /* Special case 1 on Vista, 7 & 8:
                    The CreateProcess code passes the handle over to CSRSS.EXE
@@ -3284,5 +3289,5 @@
                 {
                     if (   !pOpInfo->KernelHandle
-                        && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
+                        && fDesiredAccess == s_fCsrssStupidDesires)
                     {
                         if (g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 3))
@@ -3313,5 +3318,5 @@
                 {
                     pNtProtect->fCsrssFirstProcessCreateHandle = false;
-                    if (pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == s_fCsrssStupidDesires)
+                    if (fDesiredAccess == s_fCsrssStupidDesires)
                     {
                         /* Not needed: PROCESS_CREATE_THREAD, PROCESS_SET_SESSIONID,
@@ -3333,5 +3338,5 @@
                 if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 0)
                     && g_uNtVerCombined  < SUP_MAKE_NT_VER_SIMPLE(6, 2)
-                    && pOpInfo->Parameters->CreateHandleInformation.DesiredAccess == 0x1478 /* 6.1.7600.16385 (win7_rtm.090713-1255) */
+                    && fDesiredAccess == 0x1478 /* 6.1.7600.16385 (win7_rtm.090713-1255) */
                     && pNtProtect->fThemesFirstProcessCreateHandle
                     && pOpInfo->KernelHandle == 0
@@ -3344,9 +3349,27 @@
                 }
 
+                /* Special case 6a, Windows 10+: AudioDG.exe opens the process with the
+                   PROCESS_SET_LIMITED_INFORMATION right.  It seems like it need it for
+                   some myserious and weirdly placed cpu set management of our process.
+                   I'd love to understand what that's all about...
+                   Currently playing safe and only grand this right, however limited, to
+                   audiodg.exe. */
+                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(10, 0)
+                    && (   fDesiredAccess == PROCESS_SET_LIMITED_INFORMATION
+                        || fDesiredAccess == (PROCESS_SET_LIMITED_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* expected fix #1 */
+                        || fDesiredAccess == (PROCESS_SET_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION)         /* expected fix #2 */
+                        )
+                    && pOpInfo->KernelHandle == 0
+                    && ExGetPreviousMode() == UserMode
+                    && supdrvNtProtectIsSystem32ProcessMatch(PsGetCurrentProcess(), "audiodg.exe") )
+                {
+                    fAllowedRights |= PROCESS_SET_LIMITED_INFORMATION;
+                    pOpInfo->CallContext = NULL; /* don't assert this. */
+                }
+
                 Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p wants %#x to %p/pid=%04zx [%d], allow %#x => %#x; %s [prev=%#x]\n",
                      pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
-                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess,
-                     pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind, fAllowedRights,
-                     pOpInfo->Parameters->CreateHandleInformation.DesiredAccess & fAllowedRights,
+                     fDesiredAccess, pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
+                     fAllowedRights, fDesiredAccess & fAllowedRights,
                      PsGetProcessImageFileName(PsGetCurrentProcess()), ExGetPreviousMode() ));
 
@@ -3373,4 +3396,6 @@
             else
             {
+                ACCESS_MASK const fDesiredAccess = pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess;
+
                 /* Special case 5 on Vista, 7 & 8:
                    This is the CSRSS.EXE end of special case #1. */
@@ -3379,5 +3404,5 @@
                     && pNtProtect->cCsrssFirstProcessDuplicateHandle > 0
                     && pOpInfo->KernelHandle == 0
-                    && pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess == s_fCsrssStupidDesires
+                    && fDesiredAccess == s_fCsrssStupidDesires
                     &&    pNtProtect->hParentPid
                        == PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess)
@@ -3399,4 +3424,18 @@
                 }
 
+                /* Special case 6b, Windows 10+: AudioDG.exe duplicates the handle it opened above. */
+                if (   g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(10, 0)
+                    && (   fDesiredAccess == PROCESS_SET_LIMITED_INFORMATION
+                        || fDesiredAccess == (PROCESS_SET_LIMITED_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION) /* expected fix #1 */
+                        || fDesiredAccess == (PROCESS_SET_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION)         /* expected fix #2 */
+                        )
+                    && pOpInfo->KernelHandle == 0
+                    && ExGetPreviousMode() == UserMode
+                    && supdrvNtProtectIsSystem32ProcessMatch(PsGetCurrentProcess(), "audiodg.exe") )
+                {
+                    fAllowedRights |= PROCESS_SET_LIMITED_INFORMATION;
+                    pOpInfo->CallContext = NULL; /* don't assert this. */
+                }
+
                 Log(("vboxdrv/ProcessHandlePre: %sctx=%04zx/%p[%p] dup from %04zx/%p with %#x to %p in pid=%04zx [%d] %s\n",
                      pOpInfo->KernelHandle ? "k" : "", PsGetProcessId(PsGetCurrentProcess()), PsGetCurrentProcess(),
@@ -3404,5 +3443,5 @@
                      PsGetProcessId((PEPROCESS)pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess),
                      pOpInfo->Parameters->DuplicateHandleInformation.SourceProcess,
-                     pOpInfo->Parameters->DuplicateHandleInformation.DesiredAccess,
+                     fDesiredAccess,
                      pOpInfo->Object, pNtProtect->AvlCore.Key, pNtProtect->enmProcessKind,
                      PsGetProcessImageFileName(PsGetCurrentProcess()) ));
@@ -3685,4 +3724,5 @@
         RTSpinlockAcquire(g_hNtProtectLock);
         bool fSuccess = RTAvlPVInsert(&g_NtProtectTree, &pNtProtect->AvlCore);
+        pNtProtect->fInTree = fSuccess;
         RTSpinlockRelease(g_hNtProtectLock);
 
@@ -3725,7 +3765,11 @@
          */
         ASMAtomicWriteU32(&pNtProtect->u32Magic, SUPDRVNTPROTECT_MAGIC_DEAD);
-        PSUPDRVNTPROTECT pRemoved = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pNtProtect->AvlCore.Key);
-
-        PSUPDRVNTPROTECT pRemovedChild = NULL;
+        if (pNtProtect->fInTree)
+        {
+            PSUPDRVNTPROTECT pRemoved = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pNtProtect->AvlCore.Key);
+            Assert(pRemoved == pNtProtect);
+            pNtProtect->fInTree = false;
+        }
+
         PSUPDRVNTPROTECT pChild = NULL;
         if (pNtProtect->enmProcessKind == kSupDrvNtProtectKind_StubParent)
@@ -3739,5 +3783,13 @@
                 uint32_t cChildRefs = ASMAtomicDecU32(&pChild->cRefs);
                 if (!cChildRefs)
-                    pRemovedChild = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pChild->AvlCore.Key);
+                {
+                    Assert(pChild->fInTree);
+                    if (pChild->fInTree)
+                    {
+                        PSUPDRVNTPROTECT pRemovedChild = (PSUPDRVNTPROTECT)RTAvlPVRemove(&g_NtProtectTree, pChild->AvlCore.Key);
+                        Assert(pRemovedChild == pChild);
+                        pChild->fInTree = false;
+                    }
+                }
                 else
                     pChild = NULL;
@@ -3748,6 +3800,4 @@
 
         RTSpinlockRelease(g_hNtProtectLock);
-        Assert(pRemoved == pNtProtect);
-        Assert(pRemovedChild == pChild);
 
         if (pNtProtect->pCsrssProcess)
@@ -3977,5 +4027,5 @@
                little overly paranoid as I think we can safely trust the
                system process... */
-            if (   cSystemProcessHandles < (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3) ? 2 : 1)
+            if (   cSystemProcessHandles < (g_uNtVerCombined >= SUP_MAKE_NT_VER_SIMPLE(6, 3) ? UINT32_C(2) : UINT32_C(1))
                 && pHandleInfo->UniqueProcessId == PsGetProcessId(PsInitialSystemProcess))
             {
