Index: /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 78277)
+++ /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 78278)
@@ -70,4 +70,6 @@
     /** Used MmAllocatePagesForMdl(). */
     bool                fAllocatedPagesForMdl;
+    /** Set if this is sub-section of the parent. */
+    bool                fSubMapping;
     /** Pointer returned by MmSecureVirtualMemory */
     PVOID               pvSecureMem;
@@ -184,7 +186,8 @@
         case RTR0MEMOBJTYPE_MAPPING:
         {
-            Assert(pMemNt->cMdls == 0 && pMemNt->Core.pv);
             PRTR0MEMOBJNT pMemNtParent = (PRTR0MEMOBJNT)pMemNt->Core.uRel.Child.pParent;
             Assert(pMemNtParent);
+            Assert(pMemNt->Core.pv);
+            Assert((pMemNt->cMdls == 0 && !pMemNt->fSubMapping) || (pMemNt->cMdls == 1 && pMemNt->fSubMapping));
             if (pMemNtParent->cMdls)
             {
@@ -192,5 +195,12 @@
                 Assert(     pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS
                        ||   pMemNt->Core.u.Mapping.R0Process == RTR0ProcHandleSelf());
-                MmUnmapLockedPages(pMemNt->Core.pv, pMemNtParent->apMdls[0]);
+                if (!pMemNt->cMdls)
+                    MmUnmapLockedPages(pMemNt->Core.pv, pMemNtParent->apMdls[0]);
+                else
+                {
+                    MmUnmapLockedPages(pMemNt->Core.pv, pMemNt->apMdls[0]);
+                    IoFreeMdl(pMemNt->apMdls[0]);
+                    pMemNt->apMdls[0] = NULL;
+                }
             }
             else
@@ -199,4 +209,5 @@
                        &&   !pMemNtParent->Core.u.Phys.fAllocated);
                 Assert(pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS);
+                Assert(!pMemNt->fSubMapping);
                 MmUnmapIoSpace(pMemNt->Core.pv, pMemNt->Core.cb);
             }
@@ -701,5 +712,5 @@
  */
 static int rtR0MemObjNtMap(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
-                           unsigned fProt, RTR0PROCESS R0Process)
+                           unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     int rc = VERR_MAP_FAILED;
@@ -747,4 +758,21 @@
         }
 
+        /* Create a partial MDL if this is a sub-range request. */
+        PMDL pMdl;
+        if (!offSub && !cbSub)
+            pMdl = pMemNtToMap->apMdls[0];
+        else
+        {
+            pMdl = IoAllocateMdl(NULL, (ULONG)cbSub, FALSE, FALSE, NULL);
+            if (pMdl)
+                IoBuildPartialMdl(pMemNtToMap->apMdls[0], pMdl,
+                                  (uint8_t *)MmGetMdlVirtualAddress(pMemNtToMap->apMdls[0]) + offSub, (ULONG)cbSub);
+            else
+            {
+                IoFreeMdl(pMdl);
+                return VERR_NO_MEMORY;
+            }
+        }
+
         __try
         {
@@ -753,5 +781,5 @@
             void *pv;
             if (g_pfnrtMmMapLockedPagesSpecifyCache)
-                pv = g_pfnrtMmMapLockedPagesSpecifyCache(pMemNtToMap->apMdls[0],
+                pv = g_pfnrtMmMapLockedPagesSpecifyCache(pMdl,
                                                          R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode,
                                                          MmCached,
@@ -760,15 +788,24 @@
                                                          NormalPagePriority);
             else
-                pv = MmMapLockedPages(pMemNtToMap->apMdls[0],
-                                      R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode);
+                pv = MmMapLockedPages(pMdl, R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode);
             if (pv)
             {
                 NOREF(fProt);
 
-                PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_MAPPING, pv,
-                                                                    pMemNtToMap->Core.cb);
+                PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(  !offSub && !cbSub
+                                                                    ? sizeof(*pMemNt) : RT_UOFFSETOF_DYN(RTR0MEMOBJNT, apMdls[1]),
+                                                                    RTR0MEMOBJTYPE_MAPPING, pv, pMemNtToMap->Core.cb);
                 if (pMemNt)
                 {
                     pMemNt->Core.u.Mapping.R0Process = R0Process;
+                    if (!offSub && !cbSub)
+                        pMemNt->fSubMapping = false;
+                    else
+                    {
+                        pMemNt->apMdls[0]   = pMdl;
+                        pMemNt->cMdls       = 1;
+                        pMemNt->fSubMapping = true;
+                    }
+
                     *ppMem = &pMemNt->Core;
                     return VINF_SUCCESS;
@@ -776,5 +813,5 @@
 
                 rc = VERR_NO_MEMORY;
-                MmUnmapLockedPages(pv, pMemNtToMap->apMdls[0]);
+                MmUnmapLockedPages(pv, pMdl);
             }
         }
@@ -799,4 +836,8 @@
         if (R0Process != NIL_RTR0PROCESS)
             return VERR_NOT_SUPPORTED;
+
+        /* Cannot sub-mak these (yet). */
+        AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED);
+
 
         /** @todo uAlignment */
@@ -830,6 +871,5 @@
                                           unsigned fProt, size_t offSub, size_t cbSub)
 {
-    AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
-    return rtR0MemObjNtMap(ppMem, pMemToMap, pvFixed, uAlignment, fProt, NIL_RTR0PROCESS);
+    return rtR0MemObjNtMap(ppMem, pMemToMap, pvFixed, uAlignment, fProt, NIL_RTR0PROCESS, offSub, cbSub);
 }
 
@@ -839,6 +879,5 @@
 {
     AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_NOT_SUPPORTED);
-    AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
-    return rtR0MemObjNtMap(ppMem, pMemToMap, (void *)R3PtrFixed, uAlignment, fProt, R0Process);
+    return rtR0MemObjNtMap(ppMem, pMemToMap, (void *)R3PtrFixed, uAlignment, fProt, R0Process, offSub, cbSub);
 }
 
