VirtualBox

Ignore:
Timestamp:
Jun 11, 2007 1:16:07 PM (18 years ago)
Author:
vboxsync
Message:

Lock user buffers in a HGCM call (Windows guest only)

Location:
trunk/src/VBox/Additions/common/VBoxGuestLib
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp

    r2981 r3090  
    2828#include <iprt/string.h>
    2929#include <iprt/assert.h>
     30#include <iprt/alloca.h>
    3031
    3132/* These functions can be only used by VBoxGuest. */
     
    129130    int rc;
    130131
    131     if (!pCallInfo || !pAsyncCallback)
     132    if (!pCallInfo || !pAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS)
    132133        return VERR_INVALID_PARAMETER;
    133134
     
    145146    if (VBOX_SUCCESS(rc))
    146147    {
     148        void **papvCtx = NULL;
     149
    147150        /* Initialize request memory */
    148151        pHGCMCall->header.fu32Flags = 0;
     
    156159        {
    157160            memcpy (VMMDEV_HGCM_CALL_PARMS(pHGCMCall), VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), cbParms);
    158         }
    159 
    160         dprintf (("calling VbglGRPerform\n"));
    161 
    162         /* Issue request */
    163         rc = VbglGRPerform (&pHGCMCall->header.header);
    164 
    165         dprintf (("VbglGRPerform rc = %Vrc (header rc=%d)\n", rc, pHGCMCall->header.result));
    166 
    167         /** If the call failed, but as a result of the request itself, then pretend success 
    168          *  Upper layers will interpret the result code in the packet.
    169          */
    170         if (VBOX_FAILURE(rc) && rc == pHGCMCall->header.result)
    171         {
    172             Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
    173             rc = VINF_SUCCESS;
    174         }
    175 
     161           
     162            /* Lock user buffers. */
     163            if (pCallInfo->cParms > 0)
     164            {
     165                papvCtx = (void **)alloca(pCallInfo->cParms * sizeof (papvCtx[0]));
     166                memset (papvCtx, 0, pCallInfo->cParms * sizeof (papvCtx[0]));
     167            }
     168           
     169            HGCMFunctionParameter *pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     170           
     171            unsigned iParm = 0;
     172            for (; iParm < pCallInfo->cParms; iParm++, pParm++)
     173            {
     174                if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
     175                    || pParm->type == VMMDevHGCMParmType_LinAddr_Out
     176                    || pParm->type == VMMDevHGCMParmType_LinAddr)
     177                {
     178                    rc = vbglLockLinear (&papvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
     179                   
     180                    if (VBOX_FAILURE (rc))
     181                    {
     182                        break;
     183                    }
     184                }
     185            }
     186        }
     187
     188        /* Check that the parameter locking was ok. */
    176189        if (VBOX_SUCCESS(rc))
    177190        {
    178             /* Check if host decides to process the request asynchronously. */
    179             if (rc == VINF_HGCM_ASYNC_EXECUTE)
    180             {
    181                 /* Wait for request completion interrupt notification from host */
    182                 pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
    183             }
    184 
    185             if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
    186             {
    187                 if (cbParms)
    188                 {
    189                     memcpy (VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), VMMDEV_HGCM_CALL_PARMS(pHGCMCall), cbParms);
    190                 }
    191                 pCallInfo->result = pHGCMCall->header.result;
    192             }
    193             else
    194             {
    195                 /* The callback returns without completing the request,
    196                  * that means the wait was interrrupted. That can happen
    197                  * if system reboots or the VBoxService ended abnormally.
    198                  * In both cases it is OK to just leave the allocated memory
    199                  * in the physical heap. The memory leak does not affect normal
    200                  * operations.
    201                  * @todo VbglGRCancel (&pHGCMCall->header.header) need to be implemented.
    202                  *       The host will not write to the cancelled memory.
    203                  */
    204                 pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     191            dprintf (("calling VbglGRPerform\n"));
     192
     193            /* Issue request */
     194            rc = VbglGRPerform (&pHGCMCall->header.header);
     195
     196            dprintf (("VbglGRPerform rc = %Vrc (header rc=%d)\n", rc, pHGCMCall->header.result));
     197
     198            /** If the call failed, but as a result of the request itself, then pretend success 
     199             *  Upper layers will interpret the result code in the packet.
     200             */
     201            if (VBOX_FAILURE(rc) && rc == pHGCMCall->header.result)
     202            {
     203                Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE);
     204                rc = VINF_SUCCESS;
     205            }
     206
     207            if (VBOX_SUCCESS(rc))
     208            {
     209                /* Check if host decides to process the request asynchronously. */
     210                if (rc == VINF_HGCM_ASYNC_EXECUTE)
     211                {
     212                    /* Wait for request completion interrupt notification from host */
     213                    pAsyncCallback (&pHGCMCall->header, pvAsyncData, u32AsyncData);
     214                }
     215
     216                if (pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)
     217                {
     218                    if (cbParms)
     219                    {
     220                        memcpy (VBOXGUEST_HGCM_CALL_PARMS(pCallInfo), VMMDEV_HGCM_CALL_PARMS(pHGCMCall), cbParms);
     221                    }
     222                    pCallInfo->result = pHGCMCall->header.result;
     223                }
     224                else
     225                {
     226                    /* The callback returns without completing the request,
     227                     * that means the wait was interrrupted. That can happen
     228                     * if system reboots or the VBoxService ended abnormally.
     229                     * In both cases it is OK to just leave the allocated memory
     230                     * in the physical heap. The memory leak does not affect normal
     231                     * operations.
     232                     * @todo VbglGRCancel (&pHGCMCall->header.header) need to be implemented.
     233                     *       The host will not write to the cancelled memory.
     234                     */
     235                    pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED;
     236                }
     237            }
     238        }
     239           
     240        /* Unlock user buffers. */
     241        if (papvCtx != NULL)
     242        {
     243            HGCMFunctionParameter *pParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo);
     244           
     245            unsigned iParm = 0;
     246            for (; iParm < pCallInfo->cParms; iParm++, pParm++)
     247            {
     248                if (   pParm->type == VMMDevHGCMParmType_LinAddr_In
     249                    || pParm->type == VMMDevHGCMParmType_LinAddr_Out
     250                    || pParm->type == VMMDevHGCMParmType_LinAddr)
     251                {
     252                    if (papvCtx[iParm] != NULL)
     253                    {
     254                        vbglUnlockLinear (papvCtx[iParm], (void *)pParm->u.Pointer.u.linearAddr, pParm->u.Pointer.size);
     255                    }
     256                }
    205257            }
    206258        }
  • trunk/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk

    r2981 r3090  
    4444SOURCES_GUESTLIBBASE = \
    4545        GenericRequest.cpp \
     46        SysHlp.cpp \
    4647        PhysHeap.cpp \
    4748        Init.cpp \
  • trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.cpp

    r2981 r3090  
    2828#include <iprt/assert.h>
    2929
     30int vbglLockLinear (void **ppvCtx, void *pv, uint32_t u32Size)
     31{
     32    int rc = VINF_SUCCESS;
     33   
     34#ifdef __WIN__
     35    PMDL pMdl = IoAllocateMdl (pv, u32Size, FALSE, FALSE, NULL);
     36
     37    if (pMdl == NULL)
     38    {
     39        rc = VERR_NOT_SUPPORTED;
     40    }
     41    else
     42    {
     43        __try {
     44            /* Calls to MmProbeAndLockPages must be enclosed in a try/except block. */
     45            MmProbeAndLockPages (pMdl,
     46                                 KernelMode,
     47                                 IoModifyAccess);
     48                                 
     49            *ppvCtx = pMdl;
     50
     51        } __except(EXCEPTION_EXECUTE_HANDLER) {
     52
     53            IoFreeMdl (pMdl);
     54            rc = VERR_INVALID_PARAMETER;
     55        }
     56    }
     57#else
     58    NOREF(ppvCtx);
     59    NOREF(pv);
     60    NOREF(u32Size);
     61#endif /* __WIN__ */
     62   
     63    return rc;
     64}
     65
     66void vbglUnlockLinear (void *pvCtx, void *pv, uint32_t u32Size)
     67{
     68    NOREF(pv);
     69    NOREF(u32Size);
     70
     71#ifdef __WIN__
     72    PMDL pMdl = (PMDL)pvCtx;
     73
     74    if (pMdl != NULL)
     75    {
     76        MmUnlockPages (pMdl);
     77        IoFreeMdl (pMdl);
     78    }
     79#else
     80    NOREF(pvCtx);
     81#endif /* __WIN__ */
     82}
     83
    3084#ifndef VBGL_VBOXGUEST
    3185
  • trunk/src/VBox/Additions/common/VBoxGuestLib/SysHlp.h

    r2981 r3090  
    5757} VBGLDRIVER;
    5858
     59int vbglLockLinear (void **ppvCtx, void *pv, uint32_t u32Size);
     60void vbglUnlockLinear (void *pvCtx, void *pv, uint32_t u32Size);
     61
    5962
    6063#ifndef VBGL_VBOXGUEST
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette