Changeset 97788 in vbox for trunk/src/VBox/HostServices/DragAndDrop
- Timestamp:
- Dec 12, 2022 6:36:50 PM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 154859
- Location:
- trunk/src/VBox/HostServices/DragAndDrop
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/DragAndDrop/VBoxDragAndDropSvc.cpp
r97763 r97788 285 285 286 286 /* 287 * Reset the message queue as soon as a new client s connect287 * Reset the message queue as soon as a new client connects 288 288 * to ensure that every client has the same state. 289 289 */ 290 290 if (m_pManager) 291 m_pManager->Reset( );291 m_pManager->Reset(true /* fForce */); 292 292 293 293 LogFlowFunc(("Client %RU32 connected (VINF_SUCCESS)\n", idClient)); … … 574 574 if (cParms == 3) 575 575 { 576 rc = m_pManager->GetNextMsgInfo(&paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */); 576 /* Make sure to increase the reference count so that the next message doesn't get removed between 577 * the guest's GUEST_DND_FN_GET_NEXT_HOST_MSG call and the actual message retrieval call. */ 578 rc = m_pManager->GetNextMsgInfo(true /* fAddRef */, 579 &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */); 577 580 if (RT_FAILURE(rc)) /* No queued messages available? */ 578 581 { … … 589 592 /* Note: paParms[2] was set by the guest as blocking flag. */ 590 593 } 594 595 LogFlowFunc(("Host callback returned %Rrc\n", rc)); 591 596 } 592 597 else /* No host callback in place, so drag and drop is not supported by the host. */ … … 1001 1006 data.paParms = paParms; 1002 1007 1003 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, 1004 &data, sizeof(data)); 1008 rc = m_SvcCtx.pfnHostCallback(m_SvcCtx.pvHostData, u32Function, &data, sizeof(data)); 1005 1009 if (RT_SUCCESS(rc)) 1006 1010 { … … 1010 1014 else 1011 1015 { 1012 /* 1013 * In case the guest is too fast asking for the next message 1014 * and the host did not supply it yet, just defer the client's 1015 * return until a response from the host available. 1016 */ 1017 LogFlowFunc(("No new messages from the host (yet), deferring request: %Rrc\n", rc)); 1018 rc = VINF_HGCM_ASYNC_EXECUTE; 1016 if (rc == VERR_CANCELLED) 1017 { 1018 /* Host indicated that the current operation was cancelled. Tell the guest. */ 1019 LogFunc(("Host indicated that operation was cancelled\n", rc)); 1020 } 1021 else 1022 { 1023 /* 1024 * In case the guest is too fast asking for the next message 1025 * and the host did not supply it yet, just defer the client's 1026 * return until a response from the host available. 1027 */ 1028 LogFunc(("No new messages from the host (%Rrc), deferring request\n", rc)); 1029 rc = VINF_HGCM_ASYNC_EXECUTE; 1030 } 1019 1031 } 1020 1032 } … … 1036 1048 if (rc == VINF_HGCM_ASYNC_EXECUTE) 1037 1049 { 1038 LogF lowFunc(("Deferring client %RU32\n", idClient));1050 LogFunc(("Deferring client %RU32\n", idClient)); 1039 1051 1040 1052 try … … 1061 1073 } 1062 1074 1063 LogF lowFunc(("Returning rc=%Rrc\n", rc));1075 LogFunc(("Returning %Rrc to guest\n", rc)); 1064 1076 } 1065 1077 … … 1170 1182 LogFlowFunc(("Cancelling all waiting clients ...\n")); 1171 1183 1172 /* Reset the message queue as the host cancelled the whole operation. */ 1173 m_pManager->Reset(); 1174 1175 rc = m_pManager->AddMsg(u32Function, cParms, paParms, true /* fAppend */); 1176 if (RT_FAILURE(rc)) 1177 { 1178 AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n", u32Function, rc)); 1179 break; 1180 } 1184 /* Forcefully reset the message queue, as the host has cancelled the current operation. */ 1185 m_pManager->Reset(true /* fForce */); 1181 1186 1182 1187 /* … … 1196 1201 /* Protocol v3+ also contains the context ID. */ 1197 1202 pClient->uProtocolVerDeprecated >= 3 ? 1 : 0); 1198 pClient->CompleteDeferred(rc2); 1203 AssertRC(rc2); 1204 1205 /* Return VERR_CANCELLED when waking up the guest side. */ 1206 pClient->CompleteDeferred(VERR_CANCELLED); 1199 1207 1200 1208 m_clientQueue.erase(itQueue); … … 1212 1220 { 1213 1221 /* Reset the message queue as a new DnD operation just began. */ 1214 m_pManager->Reset( );1222 m_pManager->Reset(false /* fForce */); 1215 1223 1216 1224 fSendToGuest = true; … … 1272 1280 uint32_t uMsgNext = 0; 1273 1281 uint32_t cParmsNext = 0; 1274 int rcNext = m_pManager->GetNextMsgInfo(&uMsgNext, &cParmsNext); 1282 /* Note: We only want to peek for the next message, hence fAddRef is false. */ 1283 int rcNext = m_pManager->GetNextMsgInfo(false /* fAddRef */, &uMsgNext, &cParmsNext); 1275 1284 1276 1285 LogFlowFunc(("uMsgClient=%s (%#x), uMsgNext=%s (%#x), cParmsNext=%RU32, rcNext=%Rrc\n", -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r97747 r97788 112 112 if (i > 0) 113 113 Log((" - ")); 114 uint32_t const uType = m_queueMsg[i]->GetType(); 115 Log(("%s (%d / %#x)", DnDHostMsgToStr(uType), uType, uType)); 114 DnDMessage const *pMsg = m_queueMsg[i]; 115 uint32_t const uType = pMsg->GetType(); 116 Log(("%s (%d / %#x) cRefS=%RU32", DnDHostMsgToStr(uType), uType, uType, pMsg->RefCount())); 116 117 } 117 118 Log(("\n")); … … 123 124 * 124 125 * @returns IPRT status code. VERR_NO_DATA if no next message is available. 126 * @param fAddRef Set to \c true to increase the message's reference count, or \c false if not. 125 127 * @param puType Where to store the message type. 126 128 * @param pcParms Where to store the message parameter count. 127 129 */ 128 int DnDManager::GetNextMsgInfo( uint32_t *puType, uint32_t *pcParms)130 int DnDManager::GetNextMsgInfo(bool fAddRef, uint32_t *puType, uint32_t *pcParms) 129 131 { 130 132 AssertPtrReturn(puType, VERR_INVALID_POINTER); … … 133 135 int rc; 134 136 135 #ifdef DEBUG136 DumpQueue();137 #endif138 139 137 if (m_queueMsg.isEmpty()) 140 138 { … … 149 147 *pcParms = pMsg->GetParamCount(); 150 148 149 if (fAddRef) 150 pMsg->AddRef(); 151 151 152 rc = VINF_SUCCESS; 152 153 } 153 154 154 LogFlowFunc(("Returning uMsg=%s (%#x), cParms=%RU32, rc=%Rrc\n", DnDHostMsgToStr(*puType), *puType, *pcParms, rc)); 155 #ifdef DEBUG 156 DumpQueue(); 157 #endif 158 159 LogFlowFunc(("Returning uMsg=%s (%#x), cParms=%RU32, fAddRef=%RTbool, rc=%Rrc\n", 160 DnDHostMsgToStr(*puType), *puType, *pcParms, fAddRef, rc)); 155 161 return rc; 156 162 } … … 158 164 /** 159 165 * Retrieves the next queued up message and removes it from the queue on success. 160 * Will return VERR_NO_DATA if no next message is available.161 * 162 * @ret urns IPRT status code.166 * 167 * @returns VBox status code. 168 * @retval VERR_NO_DATA if no next message is available. 163 169 * @param uMsg Message type to retrieve. 164 170 * @param cParms Number of parameters the \@a paParms array can store. … … 173 179 return VERR_NO_DATA; 174 180 181 #ifdef DEBUG 182 DumpQueue(); 183 #endif 184 175 185 /* Get the current message. */ 176 186 DnDMessage *pMsg = m_queueMsg.first(); 177 187 AssertPtr(pMsg); 178 188 179 m_queueMsg.removeFirst(); /* Remove the current message from the queue. */ 189 if (pMsg->Release() == 0) /* Not referenced by any client anymore? */ 190 m_queueMsg.removeFirst(); /* Remove the current message from the queue. */ 180 191 181 192 /* Fetch the current message info. */ … … 184 195 /* 185 196 * If there was an error handling the current message or the user has canceled 186 * the operation, we need to cleanup all pending events and inform the progress 187 * callback about our exit. 197 * the operation, we need to cleanup all pending events. 188 198 */ 189 199 if (RT_FAILURE(rc)) 190 200 { 191 201 /* Clear any pending messages. */ 192 Reset(); 193 194 /* Create a new cancel message to inform the guest + call 195 * the host whether the current transfer was canceled or aborted 196 * due to an error. */ 197 try 198 { 199 if (rc == VERR_CANCELLED) 200 LogFlowFunc(("Operation was cancelled\n")); 201 202 DnDHGCancelMessage *pMsgCancel = new DnDHGCancelMessage(); 203 204 int rc2 = AddMsg(pMsgCancel, false /* Prepend */); 205 AssertRC(rc2); 206 207 if (m_pfnProgressCallback) 208 { 209 LogFlowFunc(("Notifying host about aborting operation (%Rrc) ...\n", rc)); 210 m_pfnProgressCallback( rc == VERR_CANCELLED 211 ? DragAndDropSvc::DND_PROGRESS_CANCELLED 212 : DragAndDropSvc::DND_PROGRESS_ERROR, 213 100 /* Percent */, rc, 214 m_pvProgressUser); 215 } 216 } 217 catch(std::bad_alloc &) 218 { 219 rc = VERR_NO_MEMORY; 220 } 202 Reset(true /* fForce */); 221 203 } 222 204 … … 227 209 /** 228 210 * Resets the manager by clearing the message queue and internal state. 229 */ 230 void DnDManager::Reset(void) 211 * 212 * @param fForce Set to \c true to forcefully also remove still referenced messages, or \c false to only 213 * remove non-referenced messages. 214 */ 215 void DnDManager::Reset(bool fForce) 231 216 { 232 217 LogFlowFuncEnter(); 233 218 234 while (!m_queueMsg.isEmpty()) 235 { 236 delete m_queueMsg.last(); 237 m_queueMsg.removeLast(); 238 } 239 } 240 219 #ifdef DEBUG 220 DumpQueue(); 221 #endif 222 223 for (size_t i = 0; i < m_queueMsg.size(); i++) 224 { 225 if ( fForce 226 || m_queueMsg[i]->RefCount() == 0) 227 { 228 m_queueMsg.removeAt(i); 229 i = i > 0 ? i - 1 : 0; 230 } 231 } 232 } 233 -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h
r97731 r97788 50 50 51 51 DnDMessage(void) 52 { 53 } 52 : m_cRefs(0) { } 54 53 55 54 DnDMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) 56 : Message(uMsg, cParms, aParms) { } 55 : Message(uMsg, cParms, aParms) 56 , m_cRefs(0) { } 57 57 58 58 virtual ~DnDMessage(void) { } 59 60 uint32_t AddRef(void) { Assert(m_cRefs < 32); return ++m_cRefs; } 61 uint32_t Release(void) { if (m_cRefs) return --m_cRefs; return m_cRefs; } 62 uint32_t RefCount(void) const { return m_cRefs; } 63 64 protected: 65 66 /** The message's current reference count. */ 67 uint32_t m_cRefs; 59 68 }; 60 69 … … 100 109 virtual ~DnDManager(void) 101 110 { 102 Reset( );111 Reset(true /* fForce */); 103 112 } 104 113 … … 110 119 #endif 111 120 112 int GetNextMsgInfo( uint32_t *puType, uint32_t *pcParms);121 int GetNextMsgInfo(bool fAddRef, uint32_t *puType, uint32_t *pcParms); 113 122 int GetNextMsg(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 114 123 115 void Reset( void);124 void Reset(bool fForce); 116 125 117 126 protected:
Note:
See TracChangeset
for help on using the changeset viewer.