Changeset 74205 in vbox for trunk/include/VBox
- Timestamp:
- Sep 12, 2018 9:22:06 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/HostServices/Service.h
r73942 r74205 24 24 */ 25 25 26 27 26 #ifndef ___VBox_HostService_Service_h 28 27 #define ___VBox_HostService_Service_h 29 28 29 #include <memory> /* for auto_ptr */ 30 30 31 #include <VBox/log.h> 31 32 #include <VBox/hgcmsvc.h> 33 32 34 #include <iprt/assert.h> 33 35 #include <iprt/alloc.h> 34 36 #include <iprt/cpp/utils.h> 35 37 36 #include <memory> /* for auto_ptr */ 37 38 /** @todo document the poor classes. */ 38 39 39 namespace HGCM 40 40 { 41 41 42 42 /** 43 * Message class encapsulating HGCM parameters. 43 * Structure for keeping a HGCM service context. 44 */ 45 typedef 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. 44 60 */ 45 61 class Message … … 47 63 public: 48 64 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 83 public: 84 171 85 static int CopyParms(PVBOXHGCMSVCPARM paParmsDst, uint32_t cParmsDst, 172 86 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 89 protected: 90 91 int initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]); 92 93 void reset(); 94 95 protected: 252 96 253 97 /** Stored message type. */ … … 257 101 /** Stored HGCM parameters. */ 258 102 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 else283 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 }312 103 }; 313 104 … … 319 110 public: 320 111 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 116 public: 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 140 public: 141 142 int SetDeferredMsgInfo(uint32_t uMsg, uint32_t cParms); 143 144 int SetDeferredMsgInfo(const Message *pMessage); 145 146 protected: 147 148 int completeInternal(VBOXHGCMCALLHANDLE hHandle, int rcOp); 149 150 void reset(void); 151 152 protected: 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; 379 178 }; 380 381 /**382 * Structure for keeping a HGCM service context.383 */384 typedef struct VBOXHGCMSVCTX385 {386 /** HGCM helper functions. */387 PVBOXHGCMSVCHELPERS pHelpers;388 /*389 * Callback function supplied by the host for notification of updates390 * to properties.391 */392 PFNHGCMSVCEXT pfnHostCallback;393 /** User data pointer to be supplied to the host callback function. */394 void *pvHostData;395 } VBOXHGCMSVCTX, *PVBOXHGCMSVCTX;396 179 397 180 template <class T> … … 588 371 589 372 } 590 591 373 #endif /* !___VBox_HostService_Service_h */ 592 374
Note:
See TracChangeset
for help on using the changeset viewer.