VirtualBox

Changeset 74205 in vbox for trunk/include/VBox


Ignore:
Timestamp:
Sep 12, 2018 9:22:06 AM (6 years ago)
Author:
vboxsync
Message:

DnD/HostService: Refactored out more code to the common client and message classes, added documentation (also about deferred client states).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/Service.h

    r73942 r74205  
    2424 */
    2525
    26 
    2726#ifndef ___VBox_HostService_Service_h
    2827#define ___VBox_HostService_Service_h
    2928
     29#include <memory>  /* for auto_ptr */
     30
    3031#include <VBox/log.h>
    3132#include <VBox/hgcmsvc.h>
     33
    3234#include <iprt/assert.h>
    3335#include <iprt/alloc.h>
    3436#include <iprt/cpp/utils.h>
    3537
    36 #include <memory>  /* for auto_ptr */
    37 
    38 /** @todo  document the poor classes.   */
     38
    3939namespace HGCM
    4040{
    4141
    4242/**
    43  * Message class encapsulating HGCM parameters.
     43 * Structure for keeping a HGCM service context.
     44 */
     45typedef struct VBOXHGCMSVCTX
     46{
     47    /** HGCM helper functions. */
     48    PVBOXHGCMSVCHELPERS pHelpers;
     49    /*
     50     * Callback function supplied by the host for notification of updates
     51     * to properties.
     52     */
     53    PFNHGCMSVCEXT       pfnHostCallback;
     54    /** User data pointer to be supplied to the host callback function. */
     55    void               *pvHostData;
     56} VBOXHGCMSVCTX, *PVBOXHGCMSVCTX;
     57
     58/**
     59 * Base class encapsulating and working with a HGCM message.
    4460 */
    4561class Message
     
    4763public:
    4864
    49     Message(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
    50         : m_uMsg(0)
    51         , m_cParms(0)
    52         , m_paParms(0)
    53     {
    54         initData(uMsg, cParms, aParms);
    55     }
    56 
    57     virtual ~Message(void)
    58     {
    59         cleanup();
    60     }
    61 
    62     /**
    63      * Returns the type of this message.
    64      *
    65      * @returns Message type
    66      */
    67     uint32_t GetType(void) const { return m_uMsg; }
    68 
    69     /**
    70      * Returns the parameter count of this message.
    71      *
    72      * @returns Parameter count.
    73      */
    74     uint32_t GetParamCount(void) const { return m_cParms; }
    75 
    76     /**
    77      * Retrieves the raw HGCM parameter data
    78      *
    79      * @returns IPRT status code.
    80      * @param   uMsg            Message type to retrieve the parameter data for. Needed for sanity.
    81      * @param   cParms          Size (in parameters) of @a aParms array.
    82      * @param   aParms          Where to store the HGCM parameter data.
    83      */
    84     int GetData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) const
    85     {
    86         if (m_uMsg != uMsg)
    87         {
    88             LogFlowFunc(("Stored message type (%RU32) does not match request (%RU32)\n", m_uMsg, uMsg));
    89             return VERR_INVALID_PARAMETER;
    90         }
    91         if (m_cParms > cParms)
    92         {
    93             LogFlowFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", m_cParms, cParms));
    94             return VERR_INVALID_PARAMETER;
    95         }
    96 
    97         return Message::CopyParms(&aParms[0], cParms, m_paParms, m_cParms, false /* fDeepCopy */);
    98     }
    99 
    100     /**
    101      * Retrieves a specific parameter value as uint32_t.
    102      *
    103      * @returns IPRT status code.
    104      * @param   uParm           Index of parameter to retrieve.
    105      * @param   pu32Info        Where to store the parameter value.
    106      */
    107     int GetParmU32(uint32_t uParm, uint32_t *pu32Info) const
    108     {
    109         AssertPtrNullReturn(pu32Info, VERR_INVALID_PARAMETER);
    110         AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
    111         AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_32BIT, VERR_INVALID_PARAMETER);
    112 
    113         *pu32Info = m_paParms[uParm].u.uint32;
    114 
    115         return VINF_SUCCESS;
    116     }
    117 
    118     /**
    119      * Retrieves a specific parameter value as uint64_t.
    120      *
    121      * @returns IPRT status code.
    122      * @param   uParm           Index of parameter to retrieve.
    123      * @param   pu64Info        Where to store the parameter value.
    124      */
    125     int GetParmU64(uint32_t uParm, uint64_t *pu64Info) const
    126     {
    127         AssertPtrNullReturn(pu64Info, VERR_INVALID_PARAMETER);
    128         AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
    129         AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_INVALID_PARAMETER);
    130 
    131         *pu64Info = m_paParms[uParm].u.uint64;
    132 
    133         return VINF_SUCCESS;
    134     }
    135 
    136     /**
    137      * Retrieves a specific parameter value as a data address + size.
    138      *
    139      * @returns IPRT status code.
    140      * @param   uParm           Index of parameter to retrieve.
    141      * @param   ppvAddr         Where to store the data address.
    142      * @param   pcbSize         Where to store the data size (in bytes).
    143      *
    144      * @remarks Does not copy (store) the actual content of the pointer (deep copy).
    145      */
    146     int GetParmPtr(uint32_t uParm, void **ppvAddr, uint32_t *pcbSize) const
    147     {
    148         AssertPtrNullReturn(ppvAddr, VERR_INVALID_PARAMETER);
    149         AssertPtrNullReturn(pcbSize, VERR_INVALID_PARAMETER);
    150         AssertReturn(uParm < m_cParms, VERR_INVALID_PARAMETER);
    151         AssertReturn(m_paParms[uParm].type == VBOX_HGCM_SVC_PARM_PTR, VERR_INVALID_PARAMETER);
    152 
    153         *ppvAddr = m_paParms[uParm].u.pointer.addr;
    154         *pcbSize = m_paParms[uParm].u.pointer.size;
    155 
    156         return VINF_SUCCESS;
    157     }
    158 
    159     /**
    160      * Copies HGCM parameters from source to destination.
    161      *
    162      * @returns IPRT status code.
    163      * @param   paParmsDst      Destination array to copy parameters to.
    164      * @param   cParmsDst       Size (in parameters) of destination array.
    165      * @param   paParmsSrc      Source array to copy parameters from.
    166      * @param   cParmsSrc       Size (in parameters) of source array.
    167      * @param   fDeepCopy       Whether to perform a deep copy of pointer parameters or not.
    168      *
    169      * @remark Static convenience function.
    170      */
     65    Message(void);
     66
     67    Message(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
     68
     69    virtual ~Message(void);
     70
     71    uint32_t GetParamCount(void) const;
     72
     73    int GetData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) const;
     74
     75    int GetParmU32(uint32_t uParm, uint32_t *pu32Info) const;
     76
     77    int GetParmU64(uint32_t uParm, uint64_t *pu64Info) const;
     78
     79    int GetParmPtr(uint32_t uParm, void **ppvAddr, uint32_t *pcbSize) const;
     80
     81    uint32_t GetType(void) const;
     82
     83public:
     84
    17185    static int CopyParms(PVBOXHGCMSVCPARM paParmsDst, uint32_t cParmsDst,
    17286                         PVBOXHGCMSVCPARM paParmsSrc, uint32_t cParmsSrc,
    173                          bool fDeepCopy)
    174     {
    175         AssertPtrReturn(paParmsSrc, VERR_INVALID_POINTER);
    176         AssertPtrReturn(paParmsDst, VERR_INVALID_POINTER);
    177 
    178         if (cParmsSrc > cParmsDst)
    179             return VERR_BUFFER_OVERFLOW;
    180 
    181         int rc = VINF_SUCCESS;
    182         for (uint32_t i = 0; i < cParmsSrc; i++)
    183         {
    184             paParmsDst[i].type = paParmsSrc[i].type;
    185             switch (paParmsSrc[i].type)
    186             {
    187                 case VBOX_HGCM_SVC_PARM_32BIT:
    188                 {
    189                     paParmsDst[i].u.uint32 = paParmsSrc[i].u.uint32;
    190                     break;
    191                 }
    192                 case VBOX_HGCM_SVC_PARM_64BIT:
    193                 {
    194                     paParmsDst[i].u.uint64 = paParmsSrc[i].u.uint64;
    195                     break;
    196                 }
    197                 case VBOX_HGCM_SVC_PARM_PTR:
    198                 {
    199                     /* Do we have to perform a deep copy? */
    200                     if (fDeepCopy)
    201                     {
    202                         /* Yes, do so. */
    203                         paParmsDst[i].u.pointer.size = paParmsSrc[i].u.pointer.size;
    204                         if (paParmsDst[i].u.pointer.size > 0)
    205                         {
    206                             paParmsDst[i].u.pointer.addr = RTMemAlloc(paParmsDst[i].u.pointer.size);
    207                             if (!paParmsDst[i].u.pointer.addr)
    208                             {
    209                                 rc = VERR_NO_MEMORY;
    210                                 break;
    211                             }
    212                         }
    213                     }
    214                     else
    215                     {
    216                         /* No, but we have to check if there is enough room. */
    217                         if (paParmsDst[i].u.pointer.size < paParmsSrc[i].u.pointer.size)
    218                         {
    219                             rc = VERR_BUFFER_OVERFLOW;
    220                             break;
    221                         }
    222                     }
    223 
    224                     if (paParmsSrc[i].u.pointer.size)
    225                     {
    226                         if (   paParmsDst[i].u.pointer.addr
    227                             && paParmsDst[i].u.pointer.size)
    228                         {
    229                             memcpy(paParmsDst[i].u.pointer.addr,
    230                                    paParmsSrc[i].u.pointer.addr,
    231                                    RT_MIN(paParmsDst[i].u.pointer.size, paParmsSrc[i].u.pointer.size));
    232                         }
    233                         else
    234                             rc = VERR_INVALID_POINTER;
    235                     }
    236                     break;
    237                 }
    238                 default:
    239                 {
    240                     AssertMsgFailed(("Unknown HGCM type %u\n", paParmsSrc[i].type));
    241                     rc = VERR_INVALID_PARAMETER;
    242                     break;
    243                 }
    244             }
    245             if (RT_FAILURE(rc))
    246                 break;
    247         }
    248         return rc;
    249     }
    250 
    251 private:
     87                         bool fDeepCopy);
     88
     89protected:
     90
     91    int initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
     92
     93    void reset();
     94
     95protected:
    25296
    25397    /** Stored message type. */
     
    257101    /** Stored HGCM parameters. */
    258102    PVBOXHGCMSVCPARM m_paParms;
    259 
    260     int initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
    261     {
    262         AssertReturn(cParms < 256, VERR_INVALID_PARAMETER);
    263         AssertPtrNullReturn(aParms, VERR_INVALID_PARAMETER);
    264 
    265         /* Cleanup old messages. */
    266         cleanup();
    267 
    268         m_uMsg   = uMsg;
    269         m_cParms = cParms;
    270 
    271         int rc = VINF_SUCCESS;
    272 
    273         if (cParms)
    274         {
    275             m_paParms = (VBOXHGCMSVCPARM*)RTMemAllocZ(sizeof(VBOXHGCMSVCPARM) * m_cParms);
    276             if (m_paParms)
    277             {
    278                 rc = Message::CopyParms(m_paParms, m_cParms, &aParms[0], cParms, true /* fDeepCopy */);
    279                 if (RT_FAILURE(rc))
    280                     cleanup();
    281             }
    282             else
    283                 rc = VERR_NO_MEMORY;
    284         }
    285 
    286         return rc;
    287     }
    288 
    289     /**
    290      * Cleans up the message by free'ing all allocated parameters and resetting the rest.
    291      */
    292     void cleanup(void)
    293     {
    294         if (m_paParms)
    295         {
    296             for (uint32_t i = 0; i < m_cParms; ++i)
    297             {
    298                 switch (m_paParms[i].type)
    299                 {
    300                     case VBOX_HGCM_SVC_PARM_PTR:
    301                         if (m_paParms[i].u.pointer.size)
    302                             RTMemFree(m_paParms[i].u.pointer.addr);
    303                         break;
    304                 }
    305             }
    306             RTMemFree(m_paParms);
    307             m_paParms = 0;
    308         }
    309         m_cParms = 0;
    310         m_uMsg = 0;
    311     }
    312103};
    313104
     
    319110public:
    320111
    321     Client(uint32_t uClientId, VBOXHGCMCALLHANDLE hHandle = NULL,
    322            uint32_t uMsg = 0, uint32_t cParms = 0, VBOXHGCMSVCPARM aParms[] = NULL)
    323       : m_uClientId(uClientId)
    324       , m_uProtocol(0)
    325       , m_hHandle(hHandle)
    326       , m_uMsg(uMsg)
    327       , m_cParms(cParms)
    328       , m_paParms(aParms) {}
    329 
    330 public:
    331 
    332     VBOXHGCMCALLHANDLE GetHandle(void) const { return m_hHandle; }
    333     uint32_t GetMsgType(void) const { return m_uMsg; }
    334     uint32_t GetClientID(void) const { return m_uClientId; }
    335     uint32_t GetProtocolVer(void) const { return m_uProtocol; }
    336 
    337 public:
    338 
    339     int SetProtocolVer(uint32_t uProtocol) { m_uProtocol = uProtocol; return VINF_SUCCESS; }
    340 
    341 public:
    342 
    343     int addMessageInfo(uint32_t uMsg, uint32_t cParms)
    344     {
    345         if (m_cParms != 3)
    346             return VERR_INVALID_PARAMETER;
    347 
    348         m_paParms[0].setUInt32(uMsg);
    349         m_paParms[1].setUInt32(cParms);
    350 
    351         return VINF_SUCCESS;
    352     }
    353     int addMessageInfo(const Message *pMessage)
    354     {
    355         AssertPtrReturn(pMessage, VERR_INVALID_POINTER);
    356         if (m_cParms != 3)
    357             return VERR_INVALID_PARAMETER;
    358 
    359         m_paParms[0].setUInt32(pMessage->GetType());
    360         m_paParms[1].setUInt32(pMessage->GetParamCount());
    361 
    362         return VINF_SUCCESS;
    363     }
    364     int addMessage(const Message *pMessage)
    365     {
    366         AssertPtrReturn(pMessage, VERR_INVALID_POINTER);
    367         return pMessage->GetData(m_uMsg, m_cParms, m_paParms);
    368     }
    369 
    370 protected:
    371 
    372     uint32_t m_uClientId;
    373     /** Optional protocol version the client uses. */
    374     uint32_t m_uProtocol;
    375     VBOXHGCMCALLHANDLE m_hHandle;
    376     uint32_t m_uMsg;
    377     uint32_t m_cParms;
    378     PVBOXHGCMSVCPARM m_paParms;
     112    Client(uint32_t uClientID);
     113
     114    virtual ~Client(void);
     115
     116public:
     117
     118    int Complete(VBOXHGCMCALLHANDLE hHandle, int rcOp = VINF_SUCCESS);
     119
     120    int CompleteDeferred(int rcOp = VINF_SUCCESS);
     121
     122    uint32_t GetClientID(void) const;
     123
     124    VBOXHGCMCALLHANDLE GetHandle(void) const;
     125
     126    uint32_t GetMsgType(void) const;
     127
     128    uint32_t GetMsgParamCount(void) const;
     129
     130    uint32_t GetProtocolVer(void) const;
     131
     132    bool IsDeferred(void) const;
     133
     134    void SetDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     135
     136    void SetProtocolVer(uint32_t uVersion);
     137
     138    void SetSvcContext(const VBOXHGCMSVCTX &SvcCtx);
     139
     140public:
     141
     142    int SetDeferredMsgInfo(uint32_t uMsg, uint32_t cParms);
     143
     144    int SetDeferredMsgInfo(const Message *pMessage);
     145
     146protected:
     147
     148    int completeInternal(VBOXHGCMCALLHANDLE hHandle, int rcOp);
     149
     150    void reset(void);
     151
     152protected:
     153
     154    /** The client's HGCM client ID. */
     155    uint32_t           m_uClientID;
     156    /** Optional protocol version the client uses. Set to 0 by default. */
     157    uint32_t           m_uProtocolVer;
     158    /** The HGCM service context this client is bound to. */
     159    VBOXHGCMSVCTX      m_SvcCtx;
     160    /** Flag indicating whether this client currently is deferred mode,
     161     *  meaning that it did not return to the caller yet. */
     162    bool               m_fDeferred;
     163    /** Structure for keeping the client's deferred state.
     164     *  A client is in a deferred state when it asks for the next HGCM message,
     165     *  but the service can't provide it yet. That way a client will block (on the guest side, does not return)
     166     *  until the service can complete the call. */
     167    struct
     168    {
     169        /** The client's HGCM call handle. Needed for completing a deferred call. */
     170        VBOXHGCMCALLHANDLE hHandle;
     171        /** Message type (function number) to use when completing the deferred call. */
     172        uint32_t           uType;
     173        /** Parameter count to use when completing the deferred call. */
     174        uint32_t           cParms;
     175        /** Parameters to use when completing the deferred call. */
     176        PVBOXHGCMSVCPARM   paParms;
     177    } m_Deferred;
    379178};
    380 
    381 /**
    382  * Structure for keeping a HGCM service context.
    383  */
    384 typedef struct VBOXHGCMSVCTX
    385 {
    386     /** HGCM helper functions. */
    387     PVBOXHGCMSVCHELPERS pHelpers;
    388     /*
    389      * Callback function supplied by the host for notification of updates
    390      * to properties.
    391      */
    392     PFNHGCMSVCEXT       pfnHostCallback;
    393     /** User data pointer to be supplied to the host callback function. */
    394     void               *pvHostData;
    395 } VBOXHGCMSVCTX, *PVBOXHGCMSVCTX;
    396179
    397180template <class T>
     
    588371
    589372}
    590 
    591373#endif /* !___VBox_HostService_Service_h */
    592374
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