Changeset 85318 in vbox for trunk/src/VBox/HostServices/DragAndDrop
- Timestamp:
- Jul 13, 2020 9:07:41 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/DragAndDrop/VBoxDragAndDropSvc.cpp
r85145 r85318 50 50 { 51 51 public: 52 53 DragAndDropClient(uint32_t uClientID) 54 : HGCM::Client(uClientID) 52 DragAndDropClient(uint32_t idClient) 53 : HGCM::Client(idClient) 55 54 { 56 55 RT_ZERO(m_SvcCtx); … … 63 62 64 63 public: 65 66 void disconnect(void); 64 void disconnect(void) RT_NOEXCEPT; 67 65 }; 68 66 … … 79 77 { 80 78 public: 81 82 79 explicit DragAndDropService(PVBOXHGCMSVCHELPERS pHelpers) 83 80 : HGCM::AbstractService<DragAndDropService>(pHelpers) 84 , m_pManager(NULL) {} 81 , m_pManager(NULL) 82 , m_u32Mode(VBOX_DRAG_AND_DROP_MODE_OFF) 83 {} 85 84 86 85 protected: 87 88 int init(VBOXHGCMSVCFNTABLE *pTable);89 int uninit(void);90 int client Connect(uint32_t u32ClientID, void *pvClient);91 int clientDisconnect(uint32_t u32ClientID, void *pvClient);92 void guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);93 int hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) ;94 95 int modeSet(uint32_t u32Mode); 96 in line uint32_t modeGet(void) const { return m_u32Mode; };97 98 protected: 86 int init(VBOXHGCMSVCFNTABLE *pTable) RT_NOEXCEPT RT_OVERRIDE; 87 int uninit(void) RT_NOEXCEPT RT_OVERRIDE; 88 int clientConnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT RT_OVERRIDE; 89 int clientDisconnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT RT_OVERRIDE; 90 void guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient, uint32_t u32Function, 91 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT RT_OVERRIDE; 92 int hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT RT_OVERRIDE; 93 94 private: 95 int modeSet(uint32_t u32Mode) RT_NOEXCEPT; 96 inline uint32_t modeGet(void) const RT_NOEXCEPT 97 { return m_u32Mode; }; 99 98 100 99 static DECLCALLBACK(int) progressCallback(uint32_t uStatus, uint32_t uPercentage, int rc, void *pvUser); 101 100 102 protected: 103 101 private: 104 102 /** Pointer to our DnD manager instance. */ 105 103 DnDManager *m_pManager; … … 112 110 * to process new commands. The key is the (unique) client ID. */ 113 111 DnDClientQueue m_clientQueue; 114 /** Current drag and drop mode . */112 /** Current drag and drop mode, VBOX_DRAG_AND_DROP_MODE_XXX. */ 115 113 uint32_t m_u32Mode; 116 114 }; … … 123 121 /** 124 122 * Called when the HGCM client disconnected on the guest side. 123 * 125 124 * This function takes care of the client's data cleanup and also lets the host 126 125 * know that the client has been disconnected. 127 *128 126 */ 129 void DragAndDropClient::disconnect(void) 127 void DragAndDropClient::disconnect(void) RT_NOEXCEPT 130 128 { 131 LogFlowThisFunc(("uClient=%RU32\n", m_ uClientID));129 LogFlowThisFunc(("uClient=%RU32\n", m_idClient)); 132 130 133 131 if (IsDeferred()) … … 146 144 int rc2 = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, GUEST_DND_DISCONNECT, &data, sizeof(data)); 147 145 if (RT_FAILURE(rc2)) 148 LogFlowFunc(("Warning: Unable to notify host about client %RU32 disconnect, rc=%Rrc\n", m_ uClientID, rc2));146 LogFlowFunc(("Warning: Unable to notify host about client %RU32 disconnect, rc=%Rrc\n", m_idClient, rc2)); 149 147 /* Not fatal. */ 150 148 } … … 156 154 *********************************************************************************************************************************/ 157 155 158 int DragAndDropService::init(VBOXHGCMSVCFNTABLE *pTable) 156 int DragAndDropService::init(VBOXHGCMSVCFNTABLE *pTable) RT_NOEXCEPT 159 157 { 160 158 /* Register functions. */ … … 174 172 m_pManager = new DnDManager(&DragAndDropService::progressCallback, this); 175 173 } 176 catch (std::bad_alloc &)174 catch (std::bad_alloc &) 177 175 { 178 176 rc = VERR_NO_MEMORY; … … 183 181 } 184 182 185 int DragAndDropService::uninit(void) 183 int DragAndDropService::uninit(void) RT_NOEXCEPT 186 184 { 187 185 LogFlowFuncEnter(); … … 205 203 } 206 204 207 int DragAndDropService::clientConnect(uint32_t u32ClientID, void *pvClient)205 int DragAndDropService::clientConnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT 208 206 { 209 207 RT_NOREF1(pvClient); … … 214 212 } 215 213 216 int rc = VINF_SUCCESS;217 214 218 215 /* 219 216 * Add client to our client map. 220 217 */ 221 if (m_clientMap.find(u32ClientID) != m_clientMap.end()) 222 rc = VERR_ALREADY_EXISTS; 223 224 if (RT_SUCCESS(rc)) 225 { 226 try 227 { 228 DragAndDropClient *pClient = new DragAndDropClient(u32ClientID); 229 pClient->SetSvcContext(m_SvcCtx); 230 m_clientMap[u32ClientID] = pClient; 231 } 232 catch(std::bad_alloc &) 233 { 234 rc = VERR_NO_MEMORY; 235 } 236 237 if (RT_SUCCESS(rc)) 238 { 239 /* 240 * Reset the message queue as soon as a new clients connect 241 * to ensure that every client has the same state. 242 */ 243 if (m_pManager) 244 m_pManager->Reset(); 245 } 246 } 247 248 LogFlowFunc(("Client %RU32 connected, rc=%Rrc\n", u32ClientID, rc)); 249 return rc; 218 if (m_clientMap.find(idClient) != m_clientMap.end()) 219 { 220 LogFunc(("Client %RU32 is already connected!\n", idClient)); 221 return VERR_ALREADY_EXISTS; 222 } 223 224 try 225 { 226 DragAndDropClient *pClient = new DragAndDropClient(idClient); 227 pClient->SetSvcContext(m_SvcCtx); 228 m_clientMap[idClient] = pClient; 229 } 230 catch (std::bad_alloc &) 231 { 232 LogFunc(("Client %RU32 - VERR_NO_MEMORY!\n", idClient)); 233 return VERR_NO_MEMORY; 234 } 235 236 /* 237 * Reset the message queue as soon as a new clients connect 238 * to ensure that every client has the same state. 239 */ 240 if (m_pManager) 241 m_pManager->Reset(); 242 243 LogFlowFunc(("Client %RU32 connected (VINF_SUCCESS)\n", idClient)); 244 return VINF_SUCCESS; 250 245 } 251 246 252 int DragAndDropService::clientDisconnect(uint32_t u32ClientID, void *pvClient)247 int DragAndDropService::clientDisconnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT 253 248 { 254 249 RT_NOREF1(pvClient); 255 250 256 251 /* Client not found? Bail out early. */ 257 DnDClientMap::iterator itClient = m_clientMap.find( u32ClientID);252 DnDClientMap::iterator itClient = m_clientMap.find(idClient); 258 253 if (itClient == m_clientMap.end()) 254 { 255 LogFunc(("Client %RU32 not found!\n", idClient)); 259 256 return VERR_NOT_FOUND; 257 } 260 258 261 259 /* 262 260 * Remove from waiters queue. 263 261 */ 264 m_clientQueue.remove( u32ClientID);262 m_clientQueue.remove(idClient); 265 263 266 264 /* … … 272 270 m_clientMap.erase(itClient); 273 271 274 LogFlowFunc(("Client %RU32 disconnected\n", u32ClientID));272 LogFlowFunc(("Client %RU32 disconnected\n", idClient)); 275 273 return VINF_SUCCESS; 276 274 } 277 275 278 int DragAndDropService::modeSet(uint32_t u32Mode) 276 int DragAndDropService::modeSet(uint32_t u32Mode) RT_NOEXCEPT 279 277 { 280 278 #ifndef VBOX_WITH_DRAG_AND_DROP_GH … … 304 302 } 305 303 306 void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,304 void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, 307 305 void *pvClient, uint32_t u32Function, 308 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 306 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT 309 307 { 310 308 RT_NOREF1(pvClient); 311 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32\n", 312 u32ClientID, u32Function, cParms)); 309 LogFlowFunc(("idClient=%RU32, u32Function=%RU32, cParms=%RU32\n", idClient, u32Function, cParms)); 313 310 314 311 /* Check if we've the right mode set. */ … … 319 316 { 320 317 if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF) 321 {322 318 rc = VINF_SUCCESS; 323 }324 319 else 325 320 { … … 341 336 break; 342 337 } 338 343 339 case GUEST_DND_HG_ACK_OP: 344 340 case GUEST_DND_HG_REQ_DATA: … … 347 343 if ( modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 348 344 || modeGet() == VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST) 349 {350 345 rc = VINF_SUCCESS; 351 }352 346 else 353 LogFlowFunc(("Host -> Guest DnD mode disabled, ignoring request\n"));347 LogFlowFunc(("Host -> Guest DnD mode disabled, failing request\n")); 354 348 break; 355 349 } … … 366 360 if ( modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 367 361 || modeGet() == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 368 {369 362 rc = VINF_SUCCESS; 370 }371 363 else 372 364 #endif 373 LogFlowFunc(("Guest -> Host DnD mode disabled, ignoring request\n"));365 LogFlowFunc(("Guest -> Host DnD mode disabled, failing request\n")); 374 366 break; 375 367 } … … 397 389 DragAndDropClient *pClient = NULL; 398 390 399 DnDClientMap::iterator itClient = m_clientMap.find( u32ClientID);391 DnDClientMap::iterator itClient = m_clientMap.find(idClient); 400 392 if (itClient != m_clientMap.end()) 401 393 { … … 405 397 else 406 398 { 407 LogFunc(("Client %RU32 was not found\n", u32ClientID));399 LogFunc(("Client %RU32 was not found\n", idClient)); 408 400 rc = VERR_NOT_FOUND; 409 401 } … … 412 404 * Will set rc to VERR_INVALID_PARAMETER otherwise. See #9777. */ 413 405 #define VERIFY_BUFFER_SIZE_UINT32(a_ParmUInt32, a_SizeExpected) \ 414 { \406 do { \ 415 407 uint32_t cbTemp = 0; \ 416 408 rc = HGCMSvcGetU32(&a_ParmUInt32, &cbTemp); \ 417 409 ASSERT_GUEST_STMT(RT_SUCCESS(rc) && cbTemp == a_SizeExpected, rc = VERR_INVALID_PARAMETER); \ 418 } 410 } while (0) 419 411 420 412 if (rc == VINF_SUCCESS) /* Note: rc might be VINF_HGCM_ASYNC_EXECUTE! */ … … 990 982 AssertPtr(pClient); 991 983 pClient->SetDeferred(callHandle, u32Function, cParms, paParms); 992 m_clientQueue.push_back( u32ClientID);984 m_clientQueue.push_back(idClient); 993 985 } 994 986 catch (std::bad_alloc &) … … 1010 1002 1011 1003 int DragAndDropService::hostCall(uint32_t u32Function, 1012 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 1004 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT 1013 1005 { 1014 1006 LogFlowFunc(("u32Function=%RU32, cParms=%RU32, cClients=%zu, cQueue=%zu\n", … … 1016 1008 1017 1009 int rc; 1018 1019 do 1020 { 1021 bool fSendToGuest = false; /* Whether to send the message down to the guest side or not. */ 1022 1023 switch (u32Function) 1010 bool fSendToGuest = false; /* Whether to send the message down to the guest side or not. */ 1011 1012 switch (u32Function) 1013 { 1014 case HOST_DND_SET_MODE: 1024 1015 { 1025 case HOST_DND_SET_MODE: 1026 { 1027 if (cParms != 1) 1028 rc = VERR_INVALID_PARAMETER; 1029 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT) 1030 rc = VERR_INVALID_PARAMETER; 1031 else 1032 rc = modeSet(paParms[0].u.uint32); 1033 break; 1034 } 1035 1036 case HOST_DND_CANCEL: 1037 { 1038 LogFlowFunc(("Cancelling all waiting clients ...\n")); 1039 1040 /* Reset the message queue as the host cancelled the whole operation. */ 1041 m_pManager->Reset(); 1042 1043 rc = m_pManager->AddMsg(u32Function, cParms, paParms, true /* fAppend */); 1044 if (RT_FAILURE(rc)) 1045 { 1046 AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n", u32Function, rc)); 1047 break; 1048 } 1049 1050 /* 1051 * Wake up all deferred clients and tell them to process 1052 * the cancelling message next. 1053 */ 1054 DnDClientQueue::iterator itQueue = m_clientQueue.begin(); 1055 while (itQueue != m_clientQueue.end()) 1056 { 1057 DnDClientMap::iterator itClient = m_clientMap.find(*itQueue); 1058 Assert(itClient != m_clientMap.end()); 1059 1060 DragAndDropClient *pClient = itClient->second; 1061 AssertPtr(pClient); 1062 1063 int rc2 = pClient->SetDeferredMsgInfo(HOST_DND_CANCEL, 1064 /* Protocol v3+ also contains the context ID. */ 1065 pClient->GetProtocolVer() >= 3 ? 1 : 0); 1066 pClient->CompleteDeferred(rc2); 1067 1068 m_clientQueue.erase(itQueue); 1069 itQueue = m_clientQueue.begin(); 1070 } 1071 1072 Assert(m_clientQueue.empty()); 1073 1074 /* Tell the host that everything went well. */ 1075 rc = VINF_SUCCESS; 1076 break; 1077 } 1078 1079 case HOST_DND_HG_EVT_ENTER: 1080 { 1081 /* Reset the message queue as a new DnD operation just began. */ 1082 m_pManager->Reset(); 1083 1084 fSendToGuest = true; 1085 rc = VINF_SUCCESS; 1086 break; 1087 } 1088 1089 default: 1090 { 1091 fSendToGuest = true; 1092 rc = VINF_SUCCESS; 1093 break; 1094 } 1016 if (cParms != 1) 1017 rc = VERR_INVALID_PARAMETER; 1018 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT) 1019 rc = VERR_INVALID_PARAMETER; 1020 else 1021 rc = modeSet(paParms[0].u.uint32); 1022 break; 1095 1023 } 1096 1024 1025 case HOST_DND_CANCEL: 1026 { 1027 LogFlowFunc(("Cancelling all waiting clients ...\n")); 1028 1029 /* Reset the message queue as the host cancelled the whole operation. */ 1030 m_pManager->Reset(); 1031 1032 rc = m_pManager->AddMsg(u32Function, cParms, paParms, true /* fAppend */); 1033 if (RT_FAILURE(rc)) 1034 { 1035 AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n", u32Function, rc)); 1036 break; 1037 } 1038 1039 /* 1040 * Wake up all deferred clients and tell them to process 1041 * the cancelling message next. 1042 */ 1043 DnDClientQueue::iterator itQueue = m_clientQueue.begin(); 1044 while (itQueue != m_clientQueue.end()) 1045 { 1046 DnDClientMap::iterator itClient = m_clientMap.find(*itQueue); 1047 Assert(itClient != m_clientMap.end()); 1048 1049 DragAndDropClient *pClient = itClient->second; 1050 AssertPtr(pClient); 1051 1052 int rc2 = pClient->SetDeferredMsgInfo(HOST_DND_CANCEL, 1053 /* Protocol v3+ also contains the context ID. */ 1054 pClient->GetProtocolVer() >= 3 ? 1 : 0); 1055 pClient->CompleteDeferred(rc2); 1056 1057 m_clientQueue.erase(itQueue); 1058 itQueue = m_clientQueue.begin(); 1059 } 1060 1061 Assert(m_clientQueue.empty()); 1062 1063 /* Tell the host that everything went well. */ 1064 rc = VINF_SUCCESS; 1065 break; 1066 } 1067 1068 case HOST_DND_HG_EVT_ENTER: 1069 { 1070 /* Reset the message queue as a new DnD operation just began. */ 1071 m_pManager->Reset(); 1072 1073 fSendToGuest = true; 1074 rc = VINF_SUCCESS; 1075 break; 1076 } 1077 1078 default: 1079 { 1080 fSendToGuest = true; 1081 rc = VINF_SUCCESS; 1082 break; 1083 } 1084 } 1085 1086 do /* goto avoidance break-loop. */ 1087 { 1097 1088 if (fSendToGuest) 1098 1089 {
Note:
See TracChangeset
for help on using the changeset viewer.