Index: /trunk/include/VBox/VMMDevCoreTypes.h
===================================================================
--- /trunk/include/VBox/VMMDevCoreTypes.h	(revision 75547)
+++ /trunk/include/VBox/VMMDevCoreTypes.h	(revision 75548)
@@ -274,4 +274,5 @@
     VMMDevHGCMParmType_LinAddr_Locked_Out = 9,  /**< Locked Out (write; host->guest) */
     VMMDevHGCMParmType_PageList           = 10, /**< Physical addresses of locked pages for a buffer. */
+    VMMDevHGCMParmType_Embedded           = 11, /**< Small buffer embedded in request. */
     VMMDevHGCMParmType_SizeHack           = 0x7fffffff
 } HGCMFunctionParameterType;
@@ -304,7 +305,13 @@
         struct
         {
-            uint32_t size;   /**< Size of the buffer described by the page list. */
-            uint32_t offset; /**< Relative to the request header, valid if size != 0. */
+            uint32_t size;      /**< Size of the buffer described by the page list. */
+            uint32_t offset;    /**< Relative to the request header of a HGCMPageListInfo structure, valid if size != 0. */
         } PageList;
+        struct
+        {
+            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
+            uint32_t offData : 24;      /**< Relative to the request header, valid if cb != 0. */
+            uint32_t cbData;            /**< The buffer size. */
+        } Embedded;
     } u;
 #  ifdef __cplusplus
@@ -380,4 +387,10 @@
             uint32_t offset; /**< Relative to the request header, valid if size != 0. */
         } PageList;
+        struct
+        {
+            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
+            uint32_t offData : 24;      /**< Relative to the request header, valid if cb != 0. */
+            uint32_t cbData;            /**< The buffer size. */
+        } Embedded;
     } u;
 #  ifdef __cplusplus
@@ -468,4 +481,10 @@
             uint32_t offset; /**< Relative to the request header, valid if size != 0. */
         } PageList;
+        struct
+        {
+            uint32_t fFlags : 8;        /**< VBOX_HGCM_F_PARM_*. */
+            uint32_t offData : 24;      /**< Relative to the request header (must be a valid offset even if cbData is zero). */
+            uint32_t cbData;            /**< The buffer size. */
+        } Embedded;
     } u;
 #  ifdef __cplusplus
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp	(revision 75547)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCMInternal.cpp	(revision 75548)
@@ -56,4 +56,7 @@
 /** The max parameter buffer size for a kernel request. */
 #define VBGLR0_MAX_HGCM_KERNEL_PARM     (16*_1M)
+/** The max embedded buffer size. */
+#define VBGLR0_MAX_HGCM_EMBEDDED_BUFFER _64K
+
 #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
 /** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted
@@ -258,4 +261,30 @@
                     Log4(("GstHGCMCall: parm=%u type=pglst: cb=0\n", iParm));
                 break;
+
+            case VMMDevHGCMParmType_Embedded:
+                if (fIsUser) /// @todo relax this.
+                    return VERR_INVALID_PARAMETER;
+                cb = pSrcParm->u.Embedded.cbData;
+                if (cb)
+                {
+                    uint32_t off = pSrcParm->u.Embedded.offData;
+                    AssertMsgReturn(cb <= VBGLR0_MAX_HGCM_EMBEDDED_BUFFER, ("%#x > %#x\n", cb, VBGLR0_MAX_HGCM_EMBEDDED_BUFFER),
+                                    VERR_INVALID_PARAMETER);
+                    AssertMsgReturn(cb <= cbCallInfo - cParms * sizeof(HGCMFunctionParameter),
+                                    ("cb=%#x cParms=%#x cbCallInfo=%3x\n", cb, cParms, cbCallInfo),
+                                    VERR_INVALID_PARAMETER);
+                    AssertMsgReturn(   off >= cParms * sizeof(HGCMFunctionParameter)
+                                    && off <= cbCallInfo - cb,
+                                    ("offData=%#x cParms=%#x cbCallInfo=%#x\n", off, cParms, cbCallInfo),
+                                    VERR_INVALID_PARAMETER);
+                    AssertMsgReturn(VBOX_HGCM_F_PARM_ARE_VALID(pSrcParm->u.Embedded.fFlags),
+                                    ("%#x\n", pSrcParm->u.Embedded.fFlags), VERR_INVALID_PARAMETER);
+
+                    *pcbExtra += RT_ALIGN_32(cb, 8);
+                }
+                else
+                    Log4(("GstHGCMCall: parm=%u type=embed: cb=0\n", iParm));
+                break;
+
 
             case VMMDevHGCMParmType_LinAddr_Locked_In:
@@ -543,6 +572,28 @@
                 }
                 else
-                    pDstParm->u.PageList.offset = 0;
-                break;
+                    pDstParm->u.PageList.offset = 0; /** @todo will fail on the host side now */
+                break;
+
+            case VMMDevHGCMParmType_Embedded:
+            {
+                uint32_t const cb = pSrcParm->u.Embedded.cbData;
+                pDstParm->type = VMMDevHGCMParmType_Embedded;
+                pDstParm->u.Embedded.cbData  = cb;
+                pDstParm->u.Embedded.offData = offExtra;
+                if (cb > 0)
+                {
+                    uint8_t *pbDst = (uint8_t *)pHGCMCall + offExtra;
+                    if (pSrcParm->u.Embedded.fFlags & VBOX_HGCM_F_PARM_DIRECTION_TO_HOST)
+                    {
+                        memcpy(pbDst, (uint8_t const *)pCallInfo + pSrcParm->u.Embedded.offData, cb);
+                        if (RT_ALIGN(cb, 8) != cb)
+                            memset(pbDst + cb, 0, RT_ALIGN(cb, 8) - cb);
+                    }
+                    else
+                        RT_BZERO(pbDst, RT_ALIGN(cb, 8));
+                    offExtra += RT_ALIGN(cb, 8);
+                }
+                break;
+            }
 
             case VMMDevHGCMParmType_LinAddr_Locked_In:
@@ -762,5 +813,7 @@
  * @returns rc, unless RTR0MemUserCopyTo fails.
  * @param   pCallInfo           Call info structure to update.
+ * @param   cbCallInfo          The size of the client request.
  * @param   pHGCMCall           HGCM call request.
+ * @param   cbHGCMCall          The size of the HGCM call request.
  * @param   pParmInfo           Parameter locking/buffering info.
  * @param   fIsUser             Is it a user (true) or kernel request.
@@ -768,5 +821,6 @@
  *                              preserve informational status codes.
  */
-static int vbglR0HGCMInternalCopyBackResult(PVBGLIOCHGCMCALL pCallInfo, VMMDevHGCMCall const *pHGCMCall,
+static int vbglR0HGCMInternalCopyBackResult(PVBGLIOCHGCMCALL pCallInfo, uint32_t cbCallInfo,
+                                            VMMDevHGCMCall const *pHGCMCall, uint32_t cbHGCMCall,
                                             struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc)
 {
@@ -791,4 +845,6 @@
      * Copy back parameters.
      */
+    /** @todo This is assuming user data (pDstParm) is buffered.  Not true
+     *        on OS/2, though I'm not sure we care... */
     for (iParm = 0; iParm < cParms; iParm++, pSrcParm++, pDstParm++)
     {
@@ -803,4 +859,25 @@
                 pDstParm->u.PageList.size = pSrcParm->u.PageList.size;
                 break;
+
+            case VMMDevHGCMParmType_Embedded:
+            {
+                uint32_t cb;
+                pDstParm->u.Embedded.cbData = cb = pSrcParm->u.Embedded.cbData;
+                if (    cb > 0
+                    && (pDstParm->u.Embedded.fFlags & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
+                {
+                    uint32_t const offDst = pDstParm->u.Embedded.offData;
+                    uint32_t const offSrc = pDstParm->u.Embedded.offData;
+                    AssertReturn(offDst < cbCallInfo, VERR_INTERNAL_ERROR_2);
+                    AssertReturn(offDst >= sizeof(*pCallInfo) + cParms * sizeof(*pDstParm), VERR_INTERNAL_ERROR_2);
+                    AssertReturn(cb <= cbCallInfo - offDst , VERR_INTERNAL_ERROR_2);
+                    AssertReturn(offSrc < cbCallInfo, VERR_INTERNAL_ERROR_2);
+                    AssertReturn(offSrc >= sizeof(*pHGCMCall) + cParms * sizeof(*pSrcParm), VERR_INTERNAL_ERROR_2);
+                    AssertReturn(cb <= cbHGCMCall - offSrc, VERR_INTERNAL_ERROR_2);
+
+                    memcpy((uint8_t *)pCallInfo + offDst, (uint8_t const *)pHGCMCall + offSrc, cb);
+                }
+                break;
+            }
 
             case VMMDevHGCMParmType_LinAddr_Locked_In:
@@ -902,7 +979,6 @@
          */
         VMMDevHGCMCall *pHGCMCall;
-        rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pHGCMCall,
-                           sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra,
-                           VMMDevReq_HGCMCall);
+        uint32_t const  cbHGCMCall = sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra;
+        rc = VbglR0GRAlloc((VMMDevRequestHeader **)&pHGCMCall, cbHGCMCall, VMMDevReq_HGCMCall);
         if (RT_SUCCESS(rc))
         {
@@ -919,5 +995,5 @@
                  * Copy back the result (parameters and buffers that changed).
                  */
-                rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc);
+                rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, cbCallInfo, pHGCMCall, cbHGCMCall, &ParmInfo, fIsUser, rc);
             }
             else
Index: /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp
===================================================================
--- /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 75547)
+++ /trunk/src/VBox/Devices/VMMDev/VMMDevHGCM.cpp	(revision 75548)
@@ -621,6 +621,7 @@
  * @param   pThis           The VMMDev instance data.
  * @param   pCmd            Command structure where host parameters needs initialization.
- */
-static int vmmdevHGCMInitHostParameters(PVMMDEV pThis, PVBOXHGCMCMD pCmd)
+ * @param   pbReq           The request buffer.
+ */
+static int vmmdevHGCMInitHostParameters(PVMMDEV pThis, PVBOXHGCMCMD pCmd, uint8_t const *pbReq)
 {
     AssertReturn(pCmd->enmCmdType == VBOXHGCMCMDTYPE_CALL, VERR_INTERNAL_ERROR);
@@ -653,4 +654,5 @@
             case VMMDevHGCMParmType_LinAddr:
             case VMMDevHGCMParmType_PageList:
+            case VMMDevHGCMParmType_Embedded:
             {
                 const uint32_t cbData = pGuestParm->u.ptr.cbData;
@@ -668,7 +670,15 @@
                     if (pGuestParm->u.ptr.fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_TO_HOST)
                     {
-                        int rc = vmmdevHGCMGuestBufferRead(pThis->pDevIns, pv, cbData, &pGuestParm->u.ptr);
-                        ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
-                        RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                        if (pGuestParm->enmType != VMMDevHGCMParmType_Embedded)
+                        {
+                            int rc = vmmdevHGCMGuestBufferRead(pThis->pDevIns, pv, cbData, &pGuestParm->u.ptr);
+                            ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
+                            RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                        }
+                        else
+                        {
+                            memcpy(pv, &pbReq[pGuestParm->u.ptr.offFirstPage], cbData);
+                            RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
+                        }
                     }
                 }
@@ -889,4 +899,5 @@
                 cbTotalData += cbData;
 
+/** @todo respect zero byte page lists...    */
                 /* Check that the page list info is within the request. */
                 ASSERT_GUEST_RETURN(   offPageListInfo >= offExtra
@@ -935,4 +946,40 @@
             }
 
+            case VMMDevHGCMParmType_Embedded:
+            {
+#ifdef VBOX_WITH_64_BITS_GUESTS
+                AssertCompileMembersSameSizeAndOffset(HGCMFunctionParameter64, u.Embedded.cbData, HGCMFunctionParameter32, u.Embedded.cbData);
+                uint32_t const cbData    = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.cbData;
+                uint32_t const offData   = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.offData;
+                uint32_t const fFlags    = ((HGCMFunctionParameter64 *)pu8HGCMParm)->u.Embedded.fFlags;
+#else
+                uint32_t const cbData    = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.cbData;
+                uint32_t const offData   = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.offData;
+                uint32_t const fFlags    = ((HGCMFunctionParameter   *)pu8HGCMParm)->u.Embedded.fFlags;
+#endif
+                LogFunc(("Embedded guest parameter cb %u, offset %u, flags %#x\n", cbData, offData, fFlags));
+
+                ASSERT_GUEST_RETURN(cbData <= VMMDEV_MAX_HGCM_DATA_SIZE - cbTotalData, VERR_INVALID_PARAMETER);
+                cbTotalData += cbData;
+
+                /* Check flags and buffer range. */
+                ASSERT_GUEST_MSG_RETURN(VBOX_HGCM_F_PARM_ARE_VALID(fFlags), ("%#x\n", fFlags), VERR_INVALID_FLAGS);
+                ASSERT_GUEST_MSG_RETURN(   offData >= offExtra
+                                        && offData <= cbHGCMCall
+                                        && cbData  <= cbHGCMCall - offData,
+                                        ("offData=%#x cbData=%#x cbHGCMCall=%#x offExtra=%#x\n", offData, cbData, cbHGCMCall, offExtra),
+                                        VERR_INVALID_PARAMETER);
+                RT_UNTRUSTED_VALIDATED_FENCE();
+
+                /* We use part of the ptr member. */
+                pGuestParm->u.ptr.fu32Direction     = fFlags;
+                pGuestParm->u.ptr.cbData            = cbData;
+                pGuestParm->u.ptr.offFirstPage      = offData;
+                pGuestParm->u.ptr.GCPhysSinglePage  = pCmd->GCPhys + offData;
+                pGuestParm->u.ptr.cPages            = 1;
+                pGuestParm->u.ptr.paPages           = &pGuestParm->u.ptr.GCPhysSinglePage;
+                break;
+            }
+
             default:
                 ASSERT_GUEST_FAILED_RETURN(VERR_INVALID_PARAMETER);
@@ -995,5 +1042,5 @@
         {
             /* Copy guest data to host parameters, so HGCM services can use the data. */
-            rc = vmmdevHGCMInitHostParameters(pThis, pCmd);
+            rc = vmmdevHGCMInitHostParameters(pThis, pCmd, (uint8_t const *)pHGCMCall);
             if (RT_SUCCESS(rc))
             {
@@ -1003,11 +1050,36 @@
                 vmmdevHGCMAddCommand(pThis, pCmd);
 
+#if 1
+                if (    pCmd->u.call.u32Function == 9
+                    &&  pCmd->u.call.cParms      == 5)
+                {
+                    vmmdevHGCMRemoveCommand(pThis, pCmd);
+
+                    if (pCmd->pvReqLocked)
+                    {
+                        VMMDevHGCMRequestHeader volatile *pHeader = (VMMDevHGCMRequestHeader volatile *)pCmd->pvReqLocked;
+                        pHeader->header.rc = VINF_SUCCESS;
+                        pHeader->result    = VINF_SUCCESS;
+                        pHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
+                    }
+                    else
+                    {
+                        VMMDevHGCMRequestHeader *pHeader = (VMMDevHGCMRequestHeader *)pHGCMCall;
+                        pHeader->header.rc = VINF_SUCCESS;
+                        pHeader->result    = VINF_SUCCESS;
+                        pHeader->fu32Flags |= VBOX_HGCM_REQ_DONE;
+                        PDMDevHlpPhysWrite(pThis->pDevIns, GCPhys, pHeader,  sizeof(*pHeader));
+                    }
+                    vmmdevHGCMCmdFree(pThis, pCmd);
+                    return VINF_HGCM_ASYNC_EXECUTE; /* ignored, but avoids assertions. */
+                }
+#endif
+
                 rc = pThis->pHGCMDrv->pfnCall(pThis->pHGCMDrv, pCmd,
                                               pCmd->u.call.u32ClientID, pCmd->u.call.u32Function,
                                               pCmd->u.call.cParms, pCmd->u.call.paHostParms, tsArrival);
-                if (RT_SUCCESS(rc))
+
+                if (rc == VINF_HGCM_ASYNC_EXECUTE)
                 {
-                    Assert(rc == VINF_HGCM_ASYNC_EXECUTE);
-
                     /*
                      * Done.  Just update statistics and return.
@@ -1139,4 +1211,20 @@
                     uint32_t cbSrc = pHostParm->u.pointer.size;
                     rc = vmmdevHGCMGuestBufferWrite(pThis->pDevIns, pPtr, pvSrc, cbSrc);
+                }
+                break;
+            }
+
+            case VMMDevHGCMParmType_Embedded:
+            {
+                const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
+                if (   pPtr->cbData > 0
+                    && (pPtr->fu32Direction & VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST))
+                {
+                    const void *pvSrc = pHostParm->u.pointer.addr;
+                    uint32_t    cbSrc = pHostParm->u.pointer.size;
+                    if (pCmd->pvReqLocked)
+                        memcpy((uint8_t *)pCmd->pvReqLocked + pPtr->offFirstPage, pvSrc, cbSrc);
+                    else
+                        rc = PDMDevHlpPhysWrite(pThis->pDevIns, pGuestParm->u.ptr.GCPhysSinglePage, pvSrc, cbSrc);
                 }
                 break;
@@ -1487,5 +1575,6 @@
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr_Out
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
-                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList)
+                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList
+                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
                     {
                         const VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
@@ -1619,5 +1708,6 @@
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr_Out
                              || pGuestParm->enmType == VMMDevHGCMParmType_LinAddr
-                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList)
+                             || pGuestParm->enmType == VMMDevHGCMParmType_PageList
+                             || pGuestParm->enmType == VMMDevHGCMParmType_Embedded)
                     {
                         VBOXHGCMPARMPTR * const pPtr = &pGuestParm->u.ptr;
@@ -1628,6 +1718,12 @@
                         if (RT_SUCCESS(rc))
                         {
-                            pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
-                            AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
+                            if (pPtr->cPages == 1)
+                                pPtr->paPages = &pPtr->GCPhysSinglePage;
+                            else
+                            {
+                                AssertReturn(pGuestParm->enmType != VMMDevHGCMParmType_Embedded, VERR_INTERNAL_ERROR_3);
+                                pPtr->paPages = (RTGCPHYS *)RTMemAlloc(pPtr->cPages * sizeof(RTGCPHYS));
+                                AssertStmt(pPtr->paPages, rc = VERR_NO_MEMORY);
+                            }
 
                             if (RT_SUCCESS(rc))
@@ -2092,5 +2188,5 @@
                     case VBOXHGCMCMDTYPE_CALL:
                     {
-                        rcCmd = vmmdevHGCMInitHostParameters(pThis, pCmd);
+                        rcCmd = vmmdevHGCMInitHostParameters(pThis, pCmd, (uint8_t const *)pReqHdr);
                         if (RT_SUCCESS(rcCmd))
                         {
