Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 78119)
+++ /trunk/include/iprt/mangling.h	(revision 78120)
@@ -1739,4 +1739,5 @@
 # define RTR0MemObjMapKernelTag                         RT_MANGLER(RTR0MemObjMapKernelTag)     /* r0drv */
 # define RTR0MemObjMapUserTag                           RT_MANGLER(RTR0MemObjMapUserTag)       /* r0drv */
+# define RTR0MemObjMapUserExTag                         RT_MANGLER(RTR0MemObjMapUserExTag)     /* r0drv */
 # define RTR0MemObjProtect                              RT_MANGLER(RTR0MemObjProtect)          /* r0drv */
 # define RTR0MemObjReserveKernelTag                     RT_MANGLER(RTR0MemObjReserveKernelTag) /* r0drv */
Index: /trunk/include/iprt/memobj.h
===================================================================
--- /trunk/include/iprt/memobj.h	(revision 78119)
+++ /trunk/include/iprt/memobj.h	(revision 78120)
@@ -607,4 +607,50 @@
 
 /**
+ * Maps a memory object into user virtual address space in the current process
+ * (default tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   R0Process       The process to map the memory into. NIL_R0PROCESS is an alias for the current one.
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ */
+#define RTR0MemObjMapUserEx(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process, offSub, cbSub) \
+    RTR0MemObjMapUserExTag((pMemObj), (MemObjToMap), (R3PtrFixed), (uAlignment), (fProt), (R0Process), \
+                           (offSub), (cbSub), RTMEM_TAG)
+
+/**
+ * Maps a memory object into user virtual address space in the current process
+ * (custom tag).
+ *
+ * @returns IPRT status code.
+ * @param   pMemObj         Where to store the ring-0 memory object handle of the mapping object.
+ * @param   MemObjToMap     The object to be map.
+ * @param   R3PtrFixed      Requested address. (RTR3PTR)-1 means any address. This must match the alignment.
+ * @param   uAlignment      The alignment of the reserved memory.
+ *                          Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M and _4M.
+ * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
+ * @param   R0Process       The process to map the memory into. NIL_R0PROCESS is an alias for the current one.
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ * @param   pszTag          Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjMapUserExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+                                     unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub, const char *pszTag);
+
+/**
  * Change the page level protection of one or more pages in a memory object.
  *
Index: /trunk/src/VBox/Runtime/include/internal/memobj.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/memobj.h	(revision 78119)
+++ /trunk/src/VBox/Runtime/include/internal/memobj.h	(revision 78120)
@@ -447,6 +447,13 @@
  * @param   fProt           Combination of RTMEM_PROT_* flags (except RTMEM_PROT_NONE).
  * @param   R0Process       The process to map the memory into.
- */
-DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process);
+ * @param   offSub          Where in the object to start mapping. If non-zero
+ *                          the value must be page aligned and cbSub must be
+ *                          non-zero as well.
+ * @param   cbSub           The size of the part of the object to be mapped. If
+ *                          zero the entire object is mapped. The value must be
+ *                          page aligned.
+ */
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
+                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub);
 
 /**
Index: /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp	(revision 78120)
@@ -893,4 +893,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    Assert(!offSub || cbSub);
 
     IPRT_DARWIN_SAVE_EFL_AC();
@@ -959,5 +960,5 @@
                          */
                         PRTR0MEMOBJDARWIN pMemDarwin = (PRTR0MEMOBJDARWIN)rtR0MemObjNew(sizeof(*pMemDarwin), RTR0MEMOBJTYPE_MAPPING,
-                                                                                        pv, cbSub);
+                                                                                        pv, cbSub ? cbSub : pMemToMap->cb);
                         if (pMemDarwin)
                         {
@@ -995,5 +996,5 @@
 
 DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
-                                        unsigned fProt, RTR0PROCESS R0Process)
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     RT_NOREF(fProt);
@@ -1005,4 +1006,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    Assert(!offSub || cbSub);
 
     IPRT_DARWIN_SAVE_EFL_AC();
@@ -1019,10 +1021,12 @@
                                                                               0,
                                                                               kIOMapAnywhere | kIOMapDefaultCache,
-                                                                              0 /* offset */,
-                                                                              0 /* length */);
+                                                                              offSub,
+                                                                              cbSub);
 #else
         IOMemoryMap *pMemMap = pMemToMapDarwin->pMemDesc->map((task_t)R0Process,
                                                               0,
-                                                              kIOMapAnywhere | kIOMapDefaultCache);
+                                                              kIOMapAnywhere | kIOMapDefaultCache,
+                                                              offSub,
+                                                              cbSub);
 #endif
         if (pMemMap)
@@ -1036,5 +1040,5 @@
                  */
                 PRTR0MEMOBJDARWIN pMemDarwin = (PRTR0MEMOBJDARWIN)rtR0MemObjNew(sizeof(*pMemDarwin), RTR0MEMOBJTYPE_MAPPING,
-                                                                                pv, pMemToMapDarwin->Core.cb);
+                                                                                pv, cbSub ? cbSub : pMemToMap->cb);
                 if (pMemDarwin)
                 {
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c	(revision 78120)
@@ -651,4 +651,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    Assert(!offSub || cbSub);
 
     int                rc;
@@ -711,5 +712,5 @@
 
 DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
-                                        unsigned fProt, RTR0PROCESS R0Process)
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     /*
@@ -719,4 +720,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    Assert(!offSub || cbSub);
 
     int                rc;
@@ -748,11 +750,14 @@
         AddrR3 = (vm_offset_t)R3PtrFixed;
 
+    if (cbSub == 0)
+        cbSub = pMemToMap->cb - offSub;
+
     /* Insert the pObject in the map. */
     vm_object_reference(pMemToMapFreeBSD->pObject);
     rc = vm_map_find(pProcMap,              /* Map to insert the object in */
                      pMemToMapFreeBSD->pObject, /* Object to map */
-                     0,                     /* Start offset in the object */
+                     offSub,                /* Start offset in the object */
                      &AddrR3,               /* Start address IN/OUT */
-                     pMemToMap->cb,         /* Size of the mapping */
+                     cbSub,                 /* Size of the mapping */
 #if __FreeBSD_version >= 1000055
                      0,                     /* Upper bound of the mapping */
Index: /trunk/src/VBox/Runtime/r0drv/haiku/memobj-r0drv-haiku.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/haiku/memobj-r0drv-haiku.c	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/haiku/memobj-r0drv-haiku.c	(revision 78120)
@@ -478,5 +478,5 @@
 
 int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
-                            unsigned fProt, RTR0PROCESS R0Process)
+                            unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
 #if 0
@@ -487,5 +487,6 @@
     AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
     if (uAlignment > PAGE_SIZE)
-    return VERR_NOT_SUPPORTED;
+        return VERR_NOT_SUPPORTED;
+    AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
 
     int                rc;
Index: /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 78120)
@@ -1530,6 +1530,6 @@
 
 
-DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed,
-                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     struct task_struct *pTask        = rtR0ProcessToLinuxTask(R0Process);
@@ -1550,4 +1550,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
 
 #ifdef VBOX_USE_PAE_HACK
Index: /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp	(revision 78120)
@@ -730,4 +730,12 @@
                                    size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag)
 {
+    return RTR0MemObjMapUserExTag(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process, 0, 0, pszTag);
+}
+RT_EXPORT_SYMBOL(RTR0MemObjMapUserTag);
+
+
+RTR0DECL(int) RTR0MemObjMapUserExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+                                     unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub, const char *pszTag)
+{
     /* sanity checks. */
     PRTR0MEMOBJINTERNAL pMemToMap;
@@ -749,4 +757,9 @@
     AssertReturn(fProt != RTMEM_PROT_NONE, VERR_INVALID_PARAMETER);
     AssertReturn(!(fProt & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
+    AssertReturn(!(offSub & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(offSub < pMemToMap->cb, VERR_INVALID_PARAMETER);
+    AssertReturn(!(cbSub & PAGE_OFFSET_MASK), VERR_INVALID_PARAMETER);
+    AssertReturn(cbSub <= pMemToMap->cb, VERR_INVALID_PARAMETER);
+    AssertReturn((!offSub && !cbSub) || (offSub + cbSub) <= pMemToMap->cb, VERR_INVALID_PARAMETER);
     if (R0Process == NIL_RTR0PROCESS)
         R0Process = RTR0ProcHandleSelf();
@@ -755,6 +768,10 @@
     RT_NOREF_PV(pszTag);
 
+    /* adjust the request to simplify the native code. */
+    if (offSub == 0 && cbSub == pMemToMap->cb)
+        cbSub = 0;
+
     /* do the mapping. */
-    rc = rtR0MemObjNativeMapUser(&pNew, pMemToMap, R3PtrFixed, uAlignment, fProt, R0Process);
+    rc = rtR0MemObjNativeMapUser(&pNew, pMemToMap, R3PtrFixed, uAlignment, fProt, R0Process, offSub, cbSub);
     if (RT_SUCCESS(rc))
     {
@@ -776,5 +793,5 @@
     return rc;
 }
-RT_EXPORT_SYMBOL(RTR0MemObjMapUserTag);
+RT_EXPORT_SYMBOL(RTR0MemObjMapUserExTag);
 
 
Index: /trunk/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/netbsd/memobj-r0drv-netbsd.c	(revision 78120)
@@ -499,5 +499,5 @@
 
 DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
-                                        unsigned fProt, RTR0PROCESS R0Process)
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     printf("NativeMapUser\n");
Index: /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 78120)
@@ -835,8 +835,9 @@
 
 
-DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed,
-                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     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);
 }
Index: /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp	(revision 78120)
@@ -428,5 +428,6 @@
 
 
-DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+                                        unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
@@ -434,4 +435,5 @@
     if (uAlignment > PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
 
     int rc;
Index: /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 78119)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 78120)
@@ -1012,5 +1012,5 @@
 
 DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
-                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub)
 {
     /*
@@ -1021,4 +1021,5 @@
     if (uAlignment != PAGE_SIZE)
         return VERR_NOT_SUPPORTED;
+    AssertMsgReturn(!offSub && !cbSub, ("%#zx %#zx\n", offSub, cbSub), VERR_NOT_SUPPORTED); /** @todo implement sub maps */
 
     /*
