Changeset 58329 in vbox for trunk/src/VBox/HostServices/DragAndDrop
- Timestamp:
- Oct 20, 2015 10:05:12 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 103528
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r58257 r58329 30 30 #define LOG_GROUP LOG_GROUP_GUEST_DND 31 31 32 #include <algorithm> 33 #include <list> 32 34 #include <map> 33 35 … … 44 46 *********************************************************************************************************************************/ 45 47 46 /** Map holding pointers to HGCM clients. Key is the (unique) HGCM client ID. */ 47 typedef std::map<uint32_t, HGCM::Client*> DnDClientMap; 48 class DragAndDropClient : public HGCM::Client 49 { 50 public: 51 52 DragAndDropClient(uint32_t uClientId, VBOXHGCMCALLHANDLE hHandle = NULL, 53 uint32_t uMsg = 0, uint32_t cParms = 0, VBOXHGCMSVCPARM aParms[] = NULL) 54 : HGCM::Client(uClientId, hHandle, uMsg, cParms, aParms) 55 , m_fDeferred(false) 56 { 57 RT_ZERO(m_SvcCtx); 58 } 59 60 virtual ~DragAndDropClient(void) 61 { 62 disconnect(); 63 } 64 65 public: 66 67 void complete(VBOXHGCMCALLHANDLE hHandle, int rcOp); 68 void completeDeferred(int rcOp); 69 void disconnect(void); 70 bool isDeferred(void) const { return m_fDeferred; } 71 void setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 72 void setSvcContext(const HGCM::VBOXHGCMSVCTX &SvcCtx) { m_SvcCtx = SvcCtx; } 73 74 protected: 75 76 /** The HGCM service context this client is bound to. */ 77 HGCM::VBOXHGCMSVCTX m_SvcCtx; 78 /** Flag indicating whether this client currently is deferred mode, 79 * meaning that it did not return to the caller yet. */ 80 bool m_fDeferred; 81 }; 82 83 /** Map holding pointers to drag and drop clients. Key is the (unique) HGCM client ID. */ 84 typedef std::map<uint32_t, DragAndDropClient*> DnDClientMap; 85 86 /** Simple queue (list) which holds deferred (waiting) clients. */ 87 typedef std::list<uint32_t> DnDClientQueue; 48 88 49 89 /** … … 68 108 69 109 int modeSet(uint32_t u32Mode); 70 inline uint32_t modeGet( ){ return m_u32Mode; };110 inline uint32_t modeGet(void) const { return m_u32Mode; }; 71 111 72 112 protected: … … 76 116 protected: 77 117 78 DnDManager *m_pManager; 79 /** Map of all connected clients. */ 80 DnDClientMap m_clientMap; 118 /** Pointer to our DnD manager instance. */ 119 DnDManager *m_pManager; 120 /** Map of all connected clients. 121 * The primary key is the (unique) client ID, the secondary value 122 * an allocated pointer to the DragAndDropClient class, managed 123 * by this service class. */ 124 DnDClientMap m_clientMap; 81 125 /** List of all clients which are queued up (deferred return) and ready 82 * to process new commands. */ 83 RTCList<HGCM::Client*> m_clientQueue; 84 uint32_t m_u32Mode; 126 * to process new commands. The key is the (unique) client ID. */ 127 DnDClientQueue m_clientQueue; 128 /** Current drag and drop mode. */ 129 uint32_t m_u32Mode; 85 130 }; 86 131 132 133 /********************************************************************************************************************************* 134 * Client implementation * 135 *********************************************************************************************************************************/ 136 137 /** 138 * Completes the call by returning the control back to the guest 139 * side code. 140 */ 141 void DragAndDropClient::complete(VBOXHGCMCALLHANDLE hHandle, int rcOp) 142 { 143 LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId)); 144 145 if ( m_SvcCtx.pHelpers 146 && m_SvcCtx.pHelpers->pfnCallComplete) 147 { 148 m_SvcCtx.pHelpers->pfnCallComplete(hHandle, rcOp); 149 } 150 } 151 152 /** 153 * Completes a deferred call by returning the control back to the guest 154 * side code. 155 */ 156 void DragAndDropClient::completeDeferred(int rcOp) 157 { 158 AssertMsg(m_fDeferred, ("Client %RU32 is not in deferred mode\n", m_uClientId)); 159 Assert(m_hHandle != NULL); 160 161 LogFlowThisFunc(("uClientID=%RU32\n", m_uClientId)); 162 163 complete(m_hHandle, rcOp); 164 m_fDeferred = false; 165 } 166 167 /** 168 * Called when the HGCM client disconnected on the guest side. 169 * This function takes care of the client's data cleanup and also lets the host 170 * know that the client has been disconnected. 171 * 172 */ 173 void DragAndDropClient::disconnect(void) 174 { 175 LogFlowThisFunc(("uClient=%RU32\n", m_uClientId)); 176 177 if (isDeferred()) 178 completeDeferred(VERR_INTERRUPTED); 179 180 /* 181 * Let the host know. 182 */ 183 VBOXDNDCBDISCONNECTMSGDATA data; 184 RT_ZERO(data); 185 /** @todo Magic needed? */ 186 187 if (m_SvcCtx.pfnHostCallback) 188 { 189 int rc2 = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, GUEST_DND_DISCONNECT, &data, sizeof(data)); 190 if (RT_FAILURE(rc2)) 191 LogFlowFunc(("Warning: Unable to notify host about client %RU32 disconnect, rc=%Rrc\n", m_uClientId, rc2)); 192 /* Not fatal. */ 193 } 194 } 195 196 /** 197 * Set the client's status to deferred, meaning that it does not return to the caller 198 * on the guest side yet. 199 */ 200 void DragAndDropClient::setDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 201 { 202 LogFlowThisFunc(("uClient=%RU32\n", m_uClientId)); 203 204 AssertMsg(m_fDeferred == false, ("Client already in deferred mode\n")); 205 m_fDeferred = true; 206 207 m_hHandle = hHandle; 208 m_uMsg = u32Function; 209 m_cParms = cParms; 210 m_paParms = paParms; 211 } 87 212 88 213 /********************************************************************************************************************************* … … 118 243 int DragAndDropService::uninit(void) 119 244 { 245 LogFlowFuncEnter(); 246 120 247 if (m_pManager) 121 248 { … … 124 251 } 125 252 253 DnDClientMap::iterator itClient = m_clientMap.begin(); 254 while (itClient != m_clientMap.end()) 255 { 256 delete itClient->second; 257 m_clientMap.erase(itClient); 258 itClient = m_clientMap.begin(); 259 } 260 261 LogFlowFuncLeave(); 126 262 return VINF_SUCCESS; 127 263 } … … 147 283 try 148 284 { 149 m_clientMap[u32ClientID] = new HGCM::Client(u32ClientID); 285 DragAndDropClient *pClient = new DragAndDropClient(u32ClientID); 286 pClient->setSvcContext(m_SvcCtx); 287 m_clientMap[u32ClientID] = pClient; 150 288 } 151 289 catch(std::bad_alloc &) … … 179 317 * Remove from waiters queue. 180 318 */ 181 for (size_t i = 0; i < m_clientQueue.size(); i++) 182 { 183 HGCM::Client *pClient = m_clientQueue.at(i); 184 if (pClient->clientId() == u32ClientID) 185 { 186 if (m_pHelpers) 187 m_pHelpers->pfnCallComplete(pClient->handle(), VERR_INTERRUPTED); 188 189 m_clientQueue.removeAt(i); 190 delete pClient; 191 192 break; 193 } 194 } 319 m_clientQueue.remove(u32ClientID); 195 320 196 321 /* … … 208 333 int DragAndDropService::modeSet(uint32_t u32Mode) 209 334 { 210 /** @todo Validate mode. */ 335 #ifndef VBOX_WITH_DRAG_AND_DROP_GH 336 if ( u32Mode == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST 337 || u32Mode == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL) 338 { 339 m_u32Mode = VBOX_DRAG_AND_DROP_MODE_OFF; 340 return VERR_NOT_SUPPORTED; 341 } 342 #endif 343 211 344 switch (u32Mode) 212 345 { … … 308 441 #endif 309 442 310 #define DO_HOST_CALLBACK(); \ 311 if ( RT_SUCCESS(rc) \ 312 && m_pfnHostCallback) \ 313 { \ 314 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); \ 443 #define DO_HOST_CALLBACK(); \ 444 if ( RT_SUCCESS(rc) \ 445 && m_SvcCtx.pfnHostCallback) \ 446 { \ 447 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); \ 448 } 449 450 /* 451 * Lookup client. 452 */ 453 DragAndDropClient *pClient = NULL; 454 455 DnDClientMap::iterator itClient = m_clientMap.find(u32ClientID); 456 if (itClient != m_clientMap.end()) 457 { 458 pClient = itClient->second; 459 AssertPtr(pClient); 460 } 461 else 462 { 463 LogFunc(("Client %RU32 was not found\n", u32ClientID)); 464 rc = VERR_NOT_FOUND; 315 465 } 316 466 317 467 if (rc == VINF_SUCCESS) /* Note: rc might be VINF_HGCM_ASYNC_EXECUTE! */ 318 468 { 319 DnDClientMap::iterator itClient = m_clientMap.find(u32ClientID);320 Assert(itClient != m_clientMap.end());321 322 HGCM::Client *pClient = itClient->second;323 AssertPtr(pClient);324 325 469 LogFlowFunc(("Client %RU32: Protocol v%RU32\n", pClient->clientId(), pClient->protocol())); 326 470 … … 344 488 if (RT_FAILURE(rc)) /* No queued messages available? */ 345 489 { 346 if (m_ pfnHostCallback) /* Try asking the host. */490 if (m_SvcCtx.pfnHostCallback) /* Try asking the host. */ 347 491 { 348 492 VBOXDNDCBHGGETNEXTHOSTMSG data; 349 493 RT_ZERO(data); 350 494 data.hdr.uMagic = CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG; 351 rc = m_ pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));495 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); 352 496 if (RT_SUCCESS(rc)) 353 497 { … … 366 510 if (RT_FAILURE(rc)) 367 511 { 368 if (paParms[2].u.uint32) /* Blocking flag set? */ 512 uint32_t fFlags = 0; 513 int rc2 = paParms[2].getUInt32(&fFlags); 514 if ( RT_SUCCESS(rc2) 515 && fFlags) /* Blocking flag set? */ 369 516 { 370 517 /* Defer client returning. */ 371 518 rc = VINF_HGCM_ASYNC_EXECUTE; 372 519 } 520 else 521 rc = VERR_INVALID_PARAMETER; 373 522 374 523 LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc)); … … 390 539 if (cParms >= 3) 391 540 rc = paParms[0].getUInt32(&data.hdr.uContextID); 541 else /* Older protocols don't have a context ID. */ 542 rc = VINF_SUCCESS; 392 543 if (RT_SUCCESS(rc)) 393 544 rc = paParms[idxProto].getUInt32(&data.uProtocol); … … 660 811 rc = paParms[0].getUInt32(&data.hdr.uContextID); 661 812 if (RT_SUCCESS(rc)) 662 rc = paParms[ 0].getPointer((void**)&data.pszPath, &data.cbPath);663 if (RT_SUCCESS(rc)) 664 rc = paParms[ 1].getUInt32(&data.cbPath);665 if (RT_SUCCESS(rc)) 666 rc = paParms[ 2].getUInt32(&data.fMode);813 rc = paParms[1].getPointer((void**)&data.pszPath, &data.cbPath); 814 if (RT_SUCCESS(rc)) 815 rc = paParms[2].getUInt32(&data.cbPath); 816 if (RT_SUCCESS(rc)) 817 rc = paParms[3].getUInt32(&data.fMode); 667 818 } 668 819 break; … … 842 993 if (rc == VERR_NO_DATA) /* Manager has no new messsages? Try asking the host. */ 843 994 { 844 if (m_ pfnHostCallback)995 if (m_SvcCtx.pfnHostCallback) 845 996 { 846 997 VBOXDNDCBHGGETNEXTHOSTMSGDATA data; … … 851 1002 data.paParms = paParms; 852 1003 853 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 1004 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, 1005 &data, sizeof(data)); 854 1006 if (RT_SUCCESS(rc)) 855 1007 { … … 875 1027 try 876 1028 { 877 LogFlowFunc(("Deferring guest call completion of client ID=%RU32\n", u32ClientID));878 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle,879 u32Function, cParms, paParms));1029 AssertPtr(pClient); 1030 pClient->setDeferred(callHandle, u32Function, cParms, paParms); 1031 m_clientQueue.push_back(u32ClientID); 880 1032 } 881 1033 catch (std::bad_alloc) … … 885 1037 } 886 1038 } 887 else if (m_pHelpers) 888 { 889 /* Complete call on guest side. */ 890 m_pHelpers->pfnCallComplete(callHandle, rc); 891 } 1039 else if (pClient) 1040 pClient->complete(callHandle, rc); 892 1041 else 893 1042 rc = VERR_NOT_IMPLEMENTED; … … 921 1070 if (m_clientQueue.size()) /* Any clients in our queue ready for processing the next command? */ 922 1071 { 923 HGCM::Client *pClient = m_clientQueue.first(); 1072 uint32_t uClientNext = m_clientQueue.front(); 1073 DnDClientMap::iterator itClientNext = m_clientMap.find(uClientNext); 1074 Assert(itClientNext != m_clientMap.end()); 1075 1076 DragAndDropClient *pClient = itClientNext->second; 924 1077 AssertPtr(pClient); 925 1078 … … 939 1092 if (RT_SUCCESS(rc)) 940 1093 { 941 pClient->addMessageInfo(uMsg1, cParms1); 942 if ( m_pHelpers 943 && m_pHelpers->pfnCallComplete) 944 { 945 m_pHelpers->pfnCallComplete(pClient->handle(), rc); 946 } 947 948 m_clientQueue.removeFirst(); 949 950 delete pClient; 951 pClient = NULL; 952 } 953 else 954 AssertMsgFailed(("m_pManager::nextMessageInfo failed with rc=%Rrc\n", rc)); 1094 rc = pClient->addMessageInfo(uMsg1, cParms1); 1095 1096 /* Note: Report the current rc back to the guest. */ 1097 pClient->completeDeferred(rc); 1098 1099 m_clientQueue.pop_front(); 1100 } 955 1101 } 956 1102 else … … 992 1138 AssertPtr(pSelf); 993 1139 994 if (pSelf->m_ pfnHostCallback)1140 if (pSelf->m_SvcCtx.pfnHostCallback) 995 1141 { 996 1142 LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS: uStatus=%RU32, uPercentage=%RU32, rc=%Rrc\n", … … 1003 1149 data.rc = rc; /** @todo uin32_t vs. int. */ 1004 1150 1005 return pSelf->m_ pfnHostCallback(pSelf->m_pvHostData,1006 GUEST_DND_HG_EVT_PROGRESS,1007 &data, sizeof(data));1151 return pSelf->m_SvcCtx.pfnHostCallback(pSelf->m_SvcCtx.pvHostData, 1152 GUEST_DND_HG_EVT_PROGRESS, 1153 &data, sizeof(data)); 1008 1154 } 1009 1155
Note:
See TracChangeset
for help on using the changeset viewer.