Index: /trunk/include/iprt/memobj.h
===================================================================
--- /trunk/include/iprt/memobj.h	(revision 23609)
+++ /trunk/include/iprt/memobj.h	(revision 23610)
@@ -146,10 +146,16 @@
  * @returns IPRT status code.
  * @param   pMemObj         Where to store the ring-0 memory object handle.
- * @param   R3Ptr           User virtual address. This is rounded down to a page boundrary.
- * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundrary.
- * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an alias for the current one.
- *
- * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return the rounded
+ * @param   R3Ptr           User virtual address. This is rounded down to a page
+ *                          boundrary.
+ * @param   cb              Number of bytes to lock. This is rounded up to
+ *                          nearest page boundrary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an
+ *                          alias for the current one.
+ *
+ * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded
  *          down address.
+ *
  * @remarks Linux: This API requires that the memory begin locked is in a memory
  *          mapping that is not required in any forked off child process. This
@@ -157,5 +163,5 @@
  *          lifting it.
  */
-RTR0DECL(int) RTR0MemObjLockUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process);
+RTR0DECL(int) RTR0MemObjLockUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process);
 
 /**
@@ -166,8 +172,10 @@
  * @param   pv              Kernel virtual address. This is rounded down to a page boundrary.
  * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundrary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
  *
  * @remark  RTR0MemGetAddress() will return the rounded down address.
  */
-RTR0DECL(int) RTR0MemObjLockKernel(PRTR0MEMOBJ pMemObj, void *pv, size_t cb);
+RTR0DECL(int) RTR0MemObjLockKernel(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess);
 
 /**
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp	(revision 23609)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp	(revision 23610)
@@ -47,5 +47,5 @@
 /** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
  *  side effects. */
-# define USE_BOUNCH_BUFFERS
+# define USE_BOUNCE_BUFFERS
 #endif
 
@@ -64,5 +64,5 @@
         uint32_t    iParm;
         RTR0MEMOBJ  hObj;
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
         void       *pvSmallBuf;
 #endif
@@ -274,5 +274,5 @@
                 if (cb != 0)
                 {
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                     void       *pvSmallBuf = NULL;
 #endif
@@ -280,4 +280,8 @@
                     RTR0MEMOBJ  hObj;
                     int         rc;
+                    uint32_t    fAccess =    pSrcParm->type == VMMDevHGCMParmType_LinAddr_In
+                                          || pSrcParm->type == VMMDevHGCMParmType_LinAddr_Locked_In
+                                        ? RTMEM_PROT_READ
+                                        : RTMEM_PROT_READ | RTMEM_PROT_WRITE;
 
                     AssertReturn(iLockBuf < RT_ELEMENTS(pParmInfo->aLockBufs), VERR_INVALID_PARAMETER);
@@ -286,5 +290,5 @@
                         AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_KERNEL_PARM, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_KERNEL_PARM),
                                         VERR_OUT_OF_RANGE);
-                        rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb);
+                        rc = RTR0MemObjLockKernel(&hObj, (void *)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess);
                         if (RT_FAILURE(rc))
                         {
@@ -306,6 +310,6 @@
                         }
 
-#ifndef USE_BOUNCH_BUFFERS
-                        rc = RTR0MemObjLockUser(&hObj, (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, cb, NIL_RTR0PROCESS);
+#ifndef USE_BOUNCE_BUFFERS
+                        rc = RTR0MemObjLockUser(&hObj, (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, cb, fAccess, NIL_RTR0PROCESS);
                         if (RT_FAILURE(rc))
                         {
@@ -317,5 +321,5 @@
                               iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
 
-#else  /* USE_BOUNCH_BUFFERS */
+#else  /* USE_BOUNCE_BUFFERS */
                         /*
                          * This is a bit massive, but we don't want to waste a
@@ -347,5 +351,5 @@
                                 }
                             }
-                            rc = RTR0MemObjLockKernel(&hObj, pvSmallBuf, cb);
+                            rc = RTR0MemObjLockKernel(&hObj, pvSmallBuf, cb, fAccess);
                             if (RT_FAILURE(rc))
                             {
@@ -380,10 +384,10 @@
                                   iParm, pSrcParm->type, cb, pSrcParm->u.Pointer.u.linearAddr, hObj));
                         }
-#endif /* USE_BOUNCH_BUFFERS */
+#endif /* USE_BOUNCE_BUFFERS */
                     }
 
                     pParmInfo->aLockBufs[iLockBuf].iParm      = iParm;
                     pParmInfo->aLockBufs[iLockBuf].hObj       = hObj;
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                     pParmInfo->aLockBufs[iLockBuf].pvSmallBuf = pvSmallBuf;
 #endif
@@ -541,5 +545,5 @@
                 if (pSrcParm->u.Pointer.size != 0)
                 {
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                     void      *pvSmallBuf = pParmInfo->aLockBufs[iLockBuf].pvSmallBuf;
 #endif
@@ -557,5 +561,5 @@
                         pDstParm->u.PageList.offset = offExtra;
                         pDstPgLst->flags            = vbglR0HGCMInternalLinAddrTypeToPageListFlags(pSrcParm->type);
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                         if (fIsUser)
                             pDstPgLst->offFirstPage = (uintptr_t)pvSmallBuf & PAGE_OFFSET_MASK;
@@ -576,5 +580,5 @@
                         pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type);
                         pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size;
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                         if (fIsUser)
                             pDstParm->u.Pointer.u.linearAddr = pvSmallBuf
@@ -749,5 +753,5 @@
     HGCMFunctionParameter       *pDstParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     uint32_t    cParms   = pCallInfo->cParms;
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
     uint32_t    iLockBuf = 0;
 #endif
@@ -777,5 +781,5 @@
             case VMMDevHGCMParmType_LinAddr_Locked_In:
             case VMMDevHGCMParmType_LinAddr_In:
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                 if (    fIsUser
                     &&  iLockBuf < pParmInfo->cLockBufs
@@ -798,5 +802,5 @@
             case VMMDevHGCMParmType_LinAddr:
             {
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
                 if (fIsUser)
                 {
@@ -830,5 +834,5 @@
     }
 
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
     Assert(!fIsUser || pParmInfo->cLockBufs == iLockBuf);
 #endif
@@ -904,5 +908,5 @@
         {
             RTR0MemObjFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].hObj, false /*fFreeMappings*/);
-#ifdef USE_BOUNCH_BUFFERS
+#ifdef USE_BOUNCE_BUFFERS
             RTMemTmpFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].pvSmallBuf);
 #endif
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.cpp	(revision 23609)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.cpp	(revision 23610)
@@ -100,9 +100,10 @@
      *       know they aren't pagable.
      */
-    RTR0MEMOBJ MemObj = NIL_RTR0MEMOBJ;
+    RTR0MEMOBJ  MemObj = NIL_RTR0MEMOBJ;
+    uint32_t    fAccess = RTMEM_PROT_READ | (fWriteAccess ? RTMEM_PROT_WRITE : 0);
     if ((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER)
-        rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, NIL_RTR0PROCESS);
+        rc = RTR0MemObjLockUser(&MemObj, (RTR3PTR)pv, u32Size, fAccess, NIL_RTR0PROCESS);
     else
-        rc = RTR0MemObjLockKernel(&MemObj, pv, u32Size);
+        rc = RTR0MemObjLockKernel(&MemObj, pv, u32Size, fAccess);
     if (RT_SUCCESS(rc))
         *ppvCtx = MemObj;
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 23609)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 23610)
@@ -203,5 +203,5 @@
 DECLASM(int)    UNWIND_WRAP(RTR0MemObjAllocCont)(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable);
 DECLASM(int)    UNWIND_WRAP(RTR0MemObjEnterPhys)(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb);
-DECLASM(int)    UNWIND_WRAP(RTR0MemObjLockUser)(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process);
+DECLASM(int)    UNWIND_WRAP(RTR0MemObjLockUser)(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fFlags, RTR0PROCESS R0Process);
 DECLASM(int)    UNWIND_WRAP(RTR0MemObjMapKernel)(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, unsigned fProt);
 DECLASM(int)    UNWIND_WRAP(RTR0MemObjMapKernelEx)(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, unsigned fProt, size_t offSub, size_t cbSub);
@@ -2321,5 +2321,5 @@
      */
     Mem.eType = MEMREF_TYPE_LOCKED;
-    rc = RTR0MemObjLockUser(&Mem.MemObj, pvR3, cb, RTR0ProcHandleSelf());
+    rc = RTR0MemObjLockUser(&Mem.MemObj, pvR3, cb, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf());
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 23609)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 23610)
@@ -197,5 +197,5 @@
  *          - Nothing.
  */
-#define SUPDRV_IOC_VERSION                              0x000f0000
+#define SUPDRV_IOC_VERSION                              0x00100000
 
 /** SUP_IOCTL_COOKIE. */
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 23609)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 23610)
@@ -272,8 +272,8 @@
         strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
-        const uint32_t MinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x000f0000
-                                  ?  0x000f0000
-                                  :  SUPDRV_IOC_VERSION & 0xffff0000;
-        CookieReq.u.In.u32MinVersion = MinVersion;
+        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x00100000
+                                   ?  0x00100000
+                                   :  SUPDRV_IOC_VERSION & 0xffff0000;
+        CookieReq.u.In.u32MinVersion = uMinVersion;
         rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);
         if (    RT_SUCCESS(rc)
@@ -281,5 +281,5 @@
         {
             if (    (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)
-                &&  CookieReq.u.Out.u32SessionVersion >= MinVersion)
+                &&  CookieReq.u.Out.u32SessionVersion >= uMinVersion)
             {
                 /*
@@ -348,5 +348,5 @@
             {
                 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
-                        CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, MinVersion));
+                        CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, uMinVersion));
                 rc = VERR_VM_DRIVER_VERSION_MISMATCH;
             }
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm	(revision 23609)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrvA-win.asm	(revision 23610)
@@ -99,5 +99,5 @@
 NtWrapDyn2DrvFunctionWithAllRegParams  supdrvNtWrap, RTR0MemObjAllocCont
 NtWrapDyn2DrvFunctionWithAllRegParams  supdrvNtWrap, RTR0MemObjEnterPhys
-NtWrapDyn2DrvFunctionWithAllRegParams  supdrvNtWrap, RTR0MemObjLockUser
+NtWrapDyn2DrvFunctionWith5Params       supdrvNtWrap, RTR0MemObjLockUser
 NtWrapDyn2DrvFunctionWith5Params       supdrvNtWrap, RTR0MemObjMapKernel
 NtWrapDyn2DrvFunctionWith7Params       supdrvNtWrap, RTR0MemObjMapKernelEx
Index: /trunk/src/VBox/Runtime/include/internal/memobj.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/memobj.h	(revision 23609)
+++ /trunk/src/VBox/Runtime/include/internal/memobj.h	(revision 23610)
@@ -335,7 +335,9 @@
  * @param   R3Ptr           User virtual address, page aligned.
  * @param   cb              Number of bytes to lock, page aligned.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
  * @param   R0Process       The process to lock pages in.
  */
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process);
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process);
 
 /**
@@ -346,6 +348,8 @@
  * @param   pv              Kernel virtual address, page aligned.
  * @param   cb              Number of bytes to lock, page aligned.
- */
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb);
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ */
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess);
 
 /**
Index: /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp	(revision 23610)
@@ -655,11 +655,14 @@
  * @return IPRT status code.
  *
- * @param ppMem     Where to store the memory object pointer.
- * @param pv        First page.
- * @param cb        Number of bytes.
- * @param Task      The task \a pv and \a cb refers to.
+ * @param   ppMem           Where to store the memory object pointer.
+ * @param   pv              First page.
+ * @param   cb              Number of bytes.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   Task            The task \a pv and \a cb refers to.
  */
-static int rtR0MemObjNativeLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, task_t Task)
-{
+static int rtR0MemObjNativeLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess, task_t Task)
+{
+    NOREF(fAccess);
 #ifdef USE_VM_MAP_WIRE
     vm_map_t Map = get_task_map(Task);
@@ -729,13 +732,13 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
-{
-    return rtR0MemObjNativeLock(ppMem, (void *)R3Ptr, cb, (task_t)R0Process);
-}
-
-
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
-{
-    return rtR0MemObjNativeLock(ppMem, pv, cb, kernel_task);
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
+{
+    return rtR0MemObjNativeLock(ppMem, (void *)R3Ptr, cb, fAccess, (task_t)R0Process);
+}
+
+
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    return rtR0MemObjNativeLock(ppMem, pv, cb, fAccess, kernel_task);
 }
 
Index: /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/freebsd/memobj-r0drv-freebsd.c	(revision 23610)
@@ -378,7 +378,8 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     int rc;
+    NOREF(fAccess);
 
     /* create the object. */
@@ -406,7 +407,8 @@
 
 
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
 {
     int rc;
+    NOREF(fAccess);
 
     /* create the object. */
Index: /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c	(revision 23610)
@@ -734,5 +734,5 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     const int cPages = cb >> PAGE_SHIFT;
@@ -741,4 +741,5 @@
     PRTR0MEMOBJLNX pMemLnx;
     int rc = VERR_NO_MEMORY;
+    NOREF(fAccess);
 
     /*
@@ -830,5 +831,5 @@
 
 
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fFlags)
 {
     void           *pvLast = (uint8_t *)pv + cb - 1;
@@ -839,4 +840,5 @@
     uint8_t        *pbPage;
     size_t          iPage;
+    NOREF(fAccess);
 
     /*
Index: /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/memobj-r0drv.cpp	(revision 23610)
@@ -492,7 +492,12 @@
  * @returns IPRT status code.
  * @param   pMemObj         Where to store the ring-0 memory object handle.
- * @param   R3Ptr           User virtual address. This is rounded down to a page boundrary.
- * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundrary.
- * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an alias for the current one.
+ * @param   R3Ptr           User virtual address. This is rounded down to a page
+ *                          boundrary.
+ * @param   cb              Number of bytes to lock. This is rounded up to
+ *                          nearest page boundrary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process to lock pages in. NIL_R0PROCESS is an
+ *                          alias for the current one.
  *
  * @remarks RTR0MemGetAddressR3() and RTR0MemGetAddress() will return therounded
@@ -504,5 +509,5 @@
  *          lifting it.
  */
-RTR0DECL(int) RTR0MemObjLockUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+RTR0DECL(int) RTR0MemObjLockUser(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     /* sanity checks. */
@@ -515,8 +520,10 @@
     if (R0Process == NIL_RTR0PROCESS)
         R0Process = RTR0ProcHandleSelf();
+    AssertReturn(!(fAccess & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE)), VERR_INVALID_PARAMETER);
+    AssertReturn(fAccess, VERR_INVALID_PARAMETER);
     RT_ASSERT_PREEMPTIBLE();
 
     /* do the locking. */
-    return rtR0MemObjNativeLockUser(pMemObj, R3PtrAligned, cbAligned, R0Process);
+    return rtR0MemObjNativeLockUser(pMemObj, R3PtrAligned, cbAligned, fAccess, R0Process);
 }
 RT_EXPORT_SYMBOL(RTR0MemObjLockUser);
@@ -530,8 +537,10 @@
  * @param   pv              Kernel virtual address. This is rounded down to a page boundrary.
  * @param   cb              Number of bytes to lock. This is rounded up to nearest page boundrary.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
  *
  * @remark  RTR0MemGetAddress() will return the rounded down address.
  */
-RTR0DECL(int) RTR0MemObjLockKernel(PRTR0MEMOBJ pMemObj, void *pv, size_t cb)
+RTR0DECL(int) RTR0MemObjLockKernel(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess)
 {
     /* sanity checks. */
@@ -543,8 +552,10 @@
     AssertReturn(cb <= cbAligned, VERR_INVALID_PARAMETER);
     AssertPtrReturn(pvAligned, VERR_INVALID_POINTER);
+    AssertReturn(!(fAccess & ~(RTMEM_PROT_READ | RTMEM_PROT_WRITE)), VERR_INVALID_PARAMETER);
+    AssertReturn(fAccess, VERR_INVALID_PARAMETER);
     RT_ASSERT_PREEMPTIBLE();
 
     /* do the allocation. */
-    return rtR0MemObjNativeLockKernel(pMemObj, pvAligned, cbAligned);
+    return rtR0MemObjNativeLockKernel(pMemObj, pvAligned, cbAligned, fAccess);
 }
 RT_EXPORT_SYMBOL(RTR0MemObjLockKernel);
Index: /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/nt/memobj-r0drv-nt.cpp	(revision 23610)
@@ -501,10 +501,12 @@
  * @return IPRT status code.
  *
- * @param ppMem     Where to store the memory object pointer.
- * @param pv        First page.
- * @param cb        Number of bytes.
- * @param R0Process The process \a pv and \a cb refers to.
+ * @param   ppMem           Where to store the memory object pointer.
+ * @param   pv              First page.
+ * @param   cb              Number of bytes.
+ * @param   fAccess         The desired access, a combination of RTMEM_PROT_READ
+ *                          and RTMEM_PROT_WRITE.
+ * @param   R0Process       The process \a pv and \a cb refers to.
  */
-static int rtR0MemObjNtLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, RTR0PROCESS R0Process)
+static int rtR0MemObjNtLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     /*
@@ -549,5 +551,11 @@
         __try
         {
-            MmProbeAndLockPages(pMdl, R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode, IoModifyAccess);
+            MmProbeAndLockPages(pMdl,
+                                R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode,
+                                fAccess == RTMEM_PROT_READ
+                                ? IoReadAccess
+                                : fAccess == RTMEM_PROT_WRITE
+                                ? IoWriteAccess
+                                : IoModifyAccess);
 
             pMemNt->apMdls[iMdl] = pMdl;
@@ -561,8 +569,11 @@
         }
 
-        if (R0Process != NIL_RTR0PROCESS )
+        if (R0Process != NIL_RTR0PROCESS)
         {
             /* Make sure the user process can't change the allocation. */
-            pMemNt->pvSecureMem = MmSecureVirtualMemory(pv, cb, PAGE_READWRITE);
+            pMemNt->pvSecureMem = MmSecureVirtualMemory(pv, cb,
+                                                        fAccess & RTMEM_PROT_WRITE
+                                                        ? PAGE_READWRITE
+                                                        : PAGE_READONLY);
             if (!pMemNt->pvSecureMem)
             {
@@ -604,15 +615,15 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
     /* (Can use MmProbeAndLockProcessPages if we need to mess with other processes later.) */
-    return rtR0MemObjNtLock(ppMem, (void *)R3Ptr, cb, R0Process);
-}
-
-
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
-{
-    return rtR0MemObjNtLock(ppMem, pv, cb, NIL_RTR0PROCESS);
+    return rtR0MemObjNtLock(ppMem, (void *)R3Ptr, cb, fAccess, R0Process);
+}
+
+
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    return rtR0MemObjNtLock(ppMem, pv, cb, fAccess, NIL_RTR0PROCESS);
 }
 
Index: /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/os2/memobj-r0drv-os2.cpp	(revision 23610)
@@ -242,5 +242,5 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
@@ -254,5 +254,6 @@
     /* lock it. */
     ULONG cPagesRet = cPages;
-    int rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, (void *)R3Ptr, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
+    int rc = KernVMLock(VMDHL_LONG | (fAccess & RTMEM_PROT_WRITE ? VMDHL_WRITE : 0),
+                        (void *)R3Ptr, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
     if (!rc)
     {
@@ -269,5 +270,5 @@
 
 
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
 {
     /* create the object. */
@@ -279,5 +280,6 @@
     /* lock it. */
     ULONG cPagesRet = cPages;
-    int rc = KernVMLock(VMDHL_LONG | VMDHL_WRITE, pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
+    int rc = KernVMLock(VMDHL_LONG | (fAccess & RTMEM_PROT_WRITE ? VMDHL_WRITE : 0),
+                        pv, cb, &pMemOs2->Lock, &pMemOs2->aPages[0], &cPagesRet);
     if (!rc)
     {
Index: /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 23610)
@@ -272,7 +272,8 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
+    NOREF(fAccess);
 
     /* Create the locking object */
@@ -306,6 +307,8 @@
 
 
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
-{
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    NOREF(fAccess);
+
     /* Create the locking object */
     PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
Index: /trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c	(revision 23609)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c	(revision 23610)
@@ -213,7 +213,8 @@
 
 
-int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
+int rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
 {
     AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
+    NOREF(fAccess);
 
     /* Create the locking object */
@@ -239,6 +240,8 @@
 
 
-int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
-{
+int rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    NOREF(fAccess);
+
     PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
     if (!pMemSolaris)
Index: /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 23609)
+++ /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 23610)
@@ -3105,5 +3105,5 @@
      */
     RTR0MEMOBJ MemObj;
-    rc = RTR0MemObjLockUser(&MemObj, pvR3, GMM_CHUNK_SIZE, NIL_RTR0PROCESS);
+    rc = RTR0MemObjLockUser(&MemObj, pvR3, GMM_CHUNK_SIZE, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
     if (RT_SUCCESS(rc))
     {
