Changeset 50460 in vbox for trunk/src/VBox/HostServices/DragAndDrop
- Timestamp:
- Feb 14, 2014 9:46:58 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 92295
- Location:
- trunk/src/VBox/HostServices/DragAndDrop
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/DragAndDrop/Makefile.kmk
r42261 r50460 43 43 $(LIB_VMM) \ 44 44 $(LIB_RUNTIME) \ 45 $(LIB_REM) 45 $(LIB_REM) \ 46 $(PATH_STAGE_LIB)/VBoxDnDHostR3Lib$(VBOX_SUFF_LIB) 46 47 47 48 VBoxDragAndDropSvc_LDFLAGS.darwin = \ -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r50316 r50460 5 5 6 6 /* 7 * Copyright (C) 2011-201 3Oracle Corporation7 * Copyright (C) 2011-2014 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 48 48 { 49 49 public: 50 DnDHGSendDirPrivate(const RTCString &strPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 51 : m_strPath(strPath) 52 , m_cbSize(cbSize) 53 , m_pfnProgressCallback(pfnProgressCallback) 54 , m_pvProgressUser(pvProgressUser) 50 51 DnDHGSendDirPrivate(const RTCString &strPath, 52 uint32_t fMode, uint64_t cbSize, 53 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 54 : m_strPath(strPath) 55 , m_cbSize(cbSize) 56 , m_pfnProgressCallback(pfnProgressCallback) 57 , m_pvProgressUser(pvProgressUser) 55 58 { 56 59 VBOXHGCMSVCPARM paTmpParms[3]; 57 60 paTmpParms[0].setString(m_strPath.c_str()); 58 paTmpParms[1].setUInt32( m_strPath.length() + 1);61 paTmpParms[1].setUInt32((uint32_t)(m_strPath.length() + 1)); 59 62 paTmpParms[2].setUInt32(fMode); 60 63 … … 74 77 75 78 protected: 76 RTCString m_strPath;79 RTCString m_strPath; 77 80 78 81 /* Progress stuff */ … … 90 93 { 91 94 public: 92 DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize, PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 93 virtual ~DnDHGSendFilePrivate(); 95 96 DnDHGSendFilePrivate(const RTCString &strHostPath, 97 const RTCString &strGuestPath, 98 uint32_t fMode, uint64_t cbSize, 99 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 100 virtual ~DnDHGSendFilePrivate(void); 94 101 95 102 int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); … … 117 124 { 118 125 public: 119 DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 126 127 DnDHGSendDataMessagePrivate(uint32_t uMsg, uint32_t cParms, 128 VBOXHGCMSVCPARM paParms[], 129 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 120 130 int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 121 131 … … 149 159 { 150 160 m_paSkelParms[0].setString(m_strGuestPath.c_str()); 151 m_paSkelParms[1].setUInt32( m_strGuestPath.length() + 1);161 m_paSkelParms[1].setUInt32((uint32_t)(m_strGuestPath.length() + 1)); 152 162 m_paSkelParms[2].setPointer(NULL, 0); 153 163 m_paSkelParms[3].setUInt32(0); … … 198 208 199 209 /* Tell the guest the actual size. */ 200 paParms[3].setUInt32( cbRead);210 paParms[3].setUInt32((uint32_t)cbRead); 201 211 } 202 212 } … … 205 215 { 206 216 /* Check if we are done. */ 217 Assert(m_cbFileProcessed <= m_cbFileSize); 207 218 bool fDone = m_cbFileSize == m_cbFileProcessed; 208 219 if (!fDone) … … 231 242 { 232 243 RTFileClose(m_hCurFile); 233 m_hCurFile = 0;244 m_hCurFile = NIL_RTFILE; 234 245 } 235 246 } … … 325 336 PFNDNDPROGRESS pfnProgressCallback, 326 337 void *pvProgressUser) 327 : m_cb All(0)338 : m_cbTotal(0) 328 339 , m_cbTransfered(0) 329 340 , m_pfnProgressCallback(pfnProgressCallback) 330 341 , m_pvProgressUser(pvProgressUser) 331 342 { 343 if (cParms < 5) /* Paranoia. */ 344 return; 345 346 const char *pszFormat = static_cast<const char*>(paParms[1].u.pointer.addr); 347 uint32_t cbFormat = paParms[1].u.pointer.size; 348 349 int rc = VINF_SUCCESS; 332 350 RTCString strNewURIs; 333 351 334 /* Check the format for any uri type. */ 335 if (hasFileUrls(static_cast<const char*>(paParms[1].u.pointer.addr), 336 paParms[1].u.pointer.size)) 337 { 338 LogFlowFunc(("Old data: '%s'\n", (char*)paParms[3].u.pointer.addr)); 352 /* Do we need to build up a file tree? */ 353 if (DnDMIMEHasFileURLs(pszFormat, cbFormat)) 354 { 355 const char *pszList = static_cast<const char*>(paParms[3].u.pointer.addr); 356 AssertPtr(pszList); 357 uint32_t cbList = paParms[3].u.pointer.size; 358 Assert(cbList); 359 360 LogFlowFunc(("Old data: '%s'\n", pszList)); 339 361 340 362 /* The list is separated by newline (even if only one file is listed). */ 341 RTCList<RTCString> lstURIOrg = RTCString(static_cast<const char*>(paParms[3].u.pointer.addr),342 paParms[3].u.pointer.size).split("\r\n");363 RTCList<RTCString> lstURIOrg 364 = RTCString(pszList, cbList).split("\r\n"); 343 365 if (!lstURIOrg.isEmpty()) 344 366 { 345 RTCList<RTCString> lstURINew; 346 for (size_t i = 0; i < lstURIOrg.size(); ++i) 347 { 348 const RTCString &strURI = lstURIOrg.at(i); 349 350 /* Query the path component of a file URI. If this hasn't a 351 * file scheme NULL is returned. */ 352 char *pszFilePath; 353 if ((pszFilePath = RTUriFilePath(strURI.c_str(), URI_FILE_FORMAT_AUTO))) 354 { 355 /* Add the path to our internal file list (recursive in 356 * the case of a directory). */ 357 char *pszFilename; 358 if ((pszFilename = RTPathFilename(pszFilePath))) 359 { 360 char *pszNewURI = RTUriFileCreate(pszFilename); 361 if (pszNewURI) 362 { 363 lstURINew.append(pszNewURI); 364 RTStrFree(pszNewURI); 365 366 buildFileTree(pszFilePath, pszFilename - pszFilePath); 367 } 368 } 369 370 RTStrFree(pszFilePath); 371 } 372 else /* Just append the raw data. */ 373 lstURINew.append(strURI); 374 } 375 376 /* We have to change the actual DnD data. Remove any host paths and 377 * just decode the filename into the new data. The guest tools will 378 * add the correct path again, before sending the DnD drop event to 379 * some window. */ 380 strNewURIs = RTCString::join(lstURINew, "\r\n") + "\r\n"; 381 382 /* Note: We don't delete the old pointer here, cause this is done 383 * by the caller. We just use the RTString data, which has the 384 * scope of this ctor. This is enough cause the data is copied in 385 * the DnDHGSendDataMessagePrivate anyway. */ 386 paParms[3].u.pointer.addr = (void*)strNewURIs.c_str(); 387 paParms[3].u.pointer.size = strNewURIs.length() + 1; 388 paParms[4].u.uint32 = strNewURIs.length() + 1; 367 rc = m_lstURI.AppendPathsFromList(lstURIOrg, 0 /* fFlags */); 368 if (RT_SUCCESS(rc)) 369 { 370 /* Add the total size of all meta data + files transferred to 371 * the message's total count. */ 372 m_cbTotal += m_lstURI.TotalBytes(); 373 374 /* We have to change the actual DnD data. Remove any host paths and 375 * just decode the filename into the new data. The guest tools will 376 * add the correct path again, before sending the DnD drop event to 377 * some window. */ 378 strNewURIs = m_lstURI.RootToString(); 379 380 /* Note: We don't delete the old pointer here, cause this is done 381 * by the caller. We just use the RTString data, which has the 382 * scope of this ctor. This is enough cause the data is copied in 383 * the DnDHGSendDataMessagePrivate anyway. */ 384 paParms[3].u.pointer.addr = (void *)strNewURIs.c_str(); 385 paParms[3].u.pointer.size = (uint32_t)(strNewURIs.length() + 1); 386 paParms[4].u.uint32 = (uint32_t)(strNewURIs.length() + 1); 387 388 LogFlowFunc(("Set new data: '%s'\n", (char*)paParms[3].u.pointer.addr)); 389 } 389 390 } 390 391 } 391 392 392 393 /* Add the size of the data to the todo list. */ 393 m_cbAll += paParms[4].u.uint32; 394 m_cbTotal += paParms[4].u.uint32; 395 LogFlowFunc(("cbTotal=%zu\n", m_cbTotal)); 394 396 395 397 /* The first message is the meta info for the data and the data itself. */ 396 398 m_pNextPathMsg = new DnDHGSendDataMessagePrivate(uMsg, cParms, paParms, 397 399 &DnDHGSendDataMessage::progressCallback, this); 398 #ifdef DEBUG399 LogFlowFunc(("new data '%s'\n", (char*)paParms[3].u.pointer.addr));400 LogFlowFunc(("cbAll: %zu\n", m_cbAll));401 LogFlowFunc(("cbData: %RU32\n", paParms[4].u.uint32));402 403 for (size_t i = 0; i < m_uriList.size(); ++i)404 LogFlowFunc(("file: %s : %s - %o - %ld\n",405 m_uriList.at(i).m_strHostPath.c_str(), m_uriList.at(i).m_strGuestPath.c_str(),406 m_uriList.at(i).m_fMode, m_uriList.at(i).m_cbSize));407 #endif408 400 } 409 401 … … 430 422 } 431 423 432 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 424 int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, 425 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 433 426 { 434 427 if (!m_pNextPathMsg) … … 444 437 } 445 438 446 /* File data to send? */439 /* File/directory data to send? */ 447 440 if (!m_pNextPathMsg) 448 441 { 449 if (m_ uriList.isEmpty())442 if (m_lstURI.IsEmpty()) 450 443 return rc; 444 451 445 /* Create new messages based on our internal path list. Currently 452 446 * this could be directories or regular files. */ 453 PathEntry nextPath = m_uriList.first();447 const DnDURIPath &nextPath = m_lstURI.First(); 454 448 try 455 449 { 450 LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n", 451 nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath.c_str(), 452 nextPath.m_fMode, nextPath.m_cbSize, 453 RTFS_IS_DIRECTORY(nextPath.m_fMode), RTFS_IS_FILE(nextPath.m_fMode))); 454 456 455 if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) 457 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_str GuestPath,456 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strDstPath, 458 457 nextPath.m_fMode, nextPath.m_cbSize, 459 &DnDHGSendDataMessage::progressCallback, this); 458 &DnDHGSendDataMessage::progressCallback, 459 this /* pvProgressUser */); 460 460 else if (RTFS_IS_FILE(nextPath.m_fMode)) 461 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_str HostPath, nextPath.m_strGuestPath,461 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strSrcPath, nextPath.m_strDstPath, 462 462 nextPath.m_fMode, nextPath.m_cbSize, 463 &DnDHGSendDataMessage::progressCallback, this); 463 &DnDHGSendDataMessage::progressCallback, 464 this /* pvProgressUser */); 464 465 else 465 AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", 466 nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); 467 468 m_uriList.removeFirst(); 466 AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n", 467 nextPath.m_fMode, nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath), 468 VERR_NO_DATA); 469 470 m_lstURI.RemoveFirst(); 469 471 } 470 472 catch(std::bad_alloc &) … … 473 475 } 474 476 } 475 476 return rc;477 }478 479 bool DnDHGSendDataMessage::hasFileUrls(const char *pcszFormat, size_t cbMax) const480 {481 LogFlowFunc(("format %s\n", pcszFormat));482 483 /** @todo text/uri also an official variant? */484 return ( RTStrNICmp(pcszFormat, "text/uri-list", cbMax) == 0485 || RTStrNICmp(pcszFormat, "x-special/gnome-icon-list", cbMax) == 0);486 }487 488 int DnDHGSendDataMessage::buildFileTree(const char *pcszPath, size_t cbBaseLen)489 {490 RTFSOBJINFO objInfo;491 int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);492 if (RT_FAILURE(rc))493 return rc;494 495 /*496 * These are the types we currently support. Symlinks are not directly497 * supported. First the guest could be an OS which doesn't support it and498 * second the symlink could point to a file which is out of the base tree.499 * Both things are hard to support. For now we just copy the target file in500 * this case.501 */502 if (!( RTFS_IS_DIRECTORY(objInfo.Attr.fMode)503 || RTFS_IS_FILE(objInfo.Attr.fMode)504 || RTFS_IS_SYMLINK(objInfo.Attr.fMode)))505 return VINF_SUCCESS;506 507 uint64_t cbSize = 0;508 rc = RTFileQuerySize(pcszPath, &cbSize);509 if (rc == VERR_IS_A_DIRECTORY)510 rc = VINF_SUCCESS;511 512 if (RT_FAILURE(rc))513 return rc;514 515 m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize));516 m_cbAll += cbSize;517 LogFlowFunc(("cbFile: %RU64\n", cbSize));518 519 PRTDIR hDir;520 /* We have to try to open even symlinks, cause they could be symlinks521 * to directories. */522 rc = RTDirOpen(&hDir, pcszPath);523 /* The following error happens when this was a symlink to an file or a524 * regular file. */525 if (rc == VERR_PATH_NOT_FOUND)526 return VINF_SUCCESS;527 if (RT_FAILURE(rc))528 return rc;529 530 while (RT_SUCCESS(rc))531 {532 RTDIRENTRY DirEntry;533 rc = RTDirRead(hDir, &DirEntry, NULL);534 if (RT_FAILURE(rc))535 {536 if (rc == VERR_NO_MORE_FILES)537 rc = VINF_SUCCESS;538 break;539 }540 switch (DirEntry.enmType)541 {542 case RTDIRENTRYTYPE_DIRECTORY:543 {544 /* Skip "." and ".." entries. */545 if ( RTStrCmp(DirEntry.szName, ".") == 0546 || RTStrCmp(DirEntry.szName, "..") == 0)547 break;548 if (char *pszRecDir = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName))549 {550 rc = buildFileTree(pszRecDir, cbBaseLen);551 RTStrFree(pszRecDir);552 }553 else554 rc = VERR_NO_MEMORY;555 break;556 }557 case RTDIRENTRYTYPE_SYMLINK:558 case RTDIRENTRYTYPE_FILE:559 {560 char *pszNewFile;561 if ((pszNewFile = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName)))562 {563 /* We need the size and the mode of the file. */564 RTFSOBJINFO objInfo1;565 rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING);566 if (RT_FAILURE(rc))567 return rc;568 rc = RTFileQuerySize(pszNewFile, &cbSize);569 if (RT_FAILURE(rc))570 break;571 572 m_uriList.append(PathEntry(pszNewFile, &pszNewFile[cbBaseLen],573 objInfo1.Attr.fMode, cbSize));574 m_cbAll += cbSize;575 576 RTStrFree(pszNewFile);577 }578 else579 rc = VERR_NO_MEMORY;580 break;581 }582 583 default:584 break;585 }586 }587 588 RTDirClose(hDir);589 477 590 478 return rc; … … 601 489 pSelf->m_cbTransfered += cbDone; 602 490 603 /* Advance progress info */491 /* Advance progress info. */ 604 492 int rc = VINF_SUCCESS; 605 493 if ( pSelf->m_pfnProgressCallback 606 && pSelf->m_cbAll) 607 { 608 rc = pSelf->m_pfnProgressCallback((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbAll, 494 && pSelf->m_cbTotal) 495 { 496 AssertMsg(pSelf->m_cbTransfered <= pSelf->m_cbTotal, 497 ("More bytes transferred (%zu) than expected (%zu), cbDone=%zu\n", 498 pSelf->m_cbTransfered, pSelf->m_cbTotal, cbDone)); 499 500 unsigned uPercentage = (unsigned)((uint64_t)pSelf->m_cbTransfered * 100 / pSelf->m_cbTotal); 501 rc = pSelf->m_pfnProgressCallback(RT_CLAMP(uPercentage, 0, 100), 609 502 DragAndDropSvc::DND_PROGRESS_RUNNING, 610 503 VINF_SUCCESS /* rc */, pSelf->m_pvProgressUser); -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.h
r50308 r50460 4 4 5 5 /* 6 * Copyright (C) 2011-201 2Oracle Corporation6 * Copyright (C) 2011-2014 Oracle Corporation 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 18 18 #define ___VBox_HostService_DnD_dndmanager_h 19 19 20 #include <VBox/GuestHost/DragAndDrop.h> 20 21 #include <VBox/HostServices/Service.h> 21 22 #include <VBox/HostServices/DragAndDropSvc.h> … … 34 35 { 35 36 public: 36 DnDMessage() 37 : m_pNextMsg(NULL) 38 { 39 } 40 virtual ~DnDMessage() 37 38 DnDMessage(void) 39 : m_pNextMsg(NULL) 40 { 41 } 42 43 virtual ~DnDMessage(void) 41 44 { 42 45 clearNextMsg(); 43 46 } 44 47 45 virtual HGCM::Message* nextHGCMMessage( )48 virtual HGCM::Message* nextHGCMMessage(void) 46 49 { 47 50 return m_pNextMsg; 48 51 } 52 49 53 virtual int currentMessageInfo(uint32_t *puMsg, uint32_t *pcParms) 50 54 { … … 60 64 return VINF_SUCCESS; 61 65 } 62 virtual int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 66 67 virtual int currentMessage(uint32_t uMsg, uint32_t cParms, 68 VBOXHGCMSVCPARM paParms[]) 63 69 { 64 70 if (!m_pNextMsg) … … 71 77 return rc; 72 78 } 73 virtual void clearNextMsg() 79 80 virtual void clearNextMsg(void) 74 81 { 75 82 if (m_pNextMsg) … … 80 87 } 81 88 82 virtual bool isMessageWaiting( ) const { return m_pNextMsg != NULL; }89 virtual bool isMessageWaiting(void) const { return m_pNextMsg != NULL; } 83 90 84 91 protected: 92 85 93 HGCM::Message *m_pNextMsg; 86 94 }; … … 106 114 public: 107 115 108 DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[], PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser); 116 DnDHGSendDataMessage(uint32_t uMsg, uint32_t cParms, 117 VBOXHGCMSVCPARM paParms[], 118 PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser); 119 109 120 virtual ~DnDHGSendDataMessage(void); 110 121 … … 117 128 protected: 118 129 119 struct PathEntry120 {121 PathEntry(const RTCString &strHostPath, const RTCString &strGuestPath, uint32_t fMode, uint64_t cbSize)122 : m_strHostPath(strHostPath)123 , m_strGuestPath(strGuestPath)124 , m_fMode(fMode)125 , m_cbSize(cbSize) {}126 RTCString m_strHostPath;127 RTCString m_strGuestPath;128 uint32_t m_fMode;129 uint64_t m_cbSize;130 };131 132 bool hasFileUrls(const char *pcszFormat, size_t cbMax) const;133 int buildFileTree(const char *pcszPath, size_t cbBaseLen);134 130 static DECLCALLBACK(int) progressCallback(size_t cbDone, void *pvUser); 135 131 136 RTCList<PathEntry> m_uriList;137 132 DnDMessage *m_pNextPathMsg; 138 133 139 /* Total size (in bytes). */ 140 size_t m_cbAll; 141 /* Transferred size (in bytes). */ 134 DnDURIList m_lstURI; 135 /* Total message size (in bytes). */ 136 size_t m_cbTotal; 137 /* Transferred message size (in bytes). */ 142 138 size_t m_cbTransfered; 139 143 140 PFNDNDPROGRESS m_pfnProgressCallback; 144 141 void *m_pvProgressUser; … … 152 149 { 153 150 public: 154 DnDHGCancelMessage() 155 { 156 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 0, 0); 151 152 DnDHGCancelMessage(void) 153 { 154 m_pNextMsg 155 = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 156 0 /* cParms */, 0 /* aParms */); 157 157 } 158 158 }; … … 165 165 { 166 166 public: 167 167 168 DnDManager(PFNDNDPROGRESS pfnProgressCallback, void *pvProgressUser) 168 : m_pCurMsg(0)169 , m_fOpInProcess(false)170 , m_pfnProgressCallback(pfnProgressCallback)171 , m_pvProgressUser(pvProgressUser)169 : m_pCurMsg(0) 170 , m_fOpInProcess(false) 171 , m_pfnProgressCallback(pfnProgressCallback) 172 , m_pvProgressUser(pvProgressUser) 172 173 {} 173 virtual ~DnDManager() 174 175 virtual ~DnDManager(void) 174 176 { 175 177 clear(); … … 178 180 int addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 179 181 180 HGCM::Message *nextHGCMMessage( );182 HGCM::Message *nextHGCMMessage(void); 181 183 int nextMessageInfo(uint32_t *puMsg, uint32_t *pcParms); 182 184 int nextMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]); 183 185 184 void clear( );185 186 bool hasActiveOperation( ) const { return m_fOpInProcess; }186 void clear(void); 187 188 bool hasActiveOperation(void) const { return m_fOpInProcess; } 187 189 188 190 private: … … 196 198 void *m_pvProgressUser; 197 199 }; 198 199 200 #endif /* ___VBox_HostService_DnD_dndmanager_h */ 200 201 -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r50308 r50460 470 470 DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data; 471 471 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS; 472 data.uPercentage = uPercentage;472 data.uPercentage = RT_CLAMP(uPercentage, 0, 100); 473 473 data.uState = uState; 474 474 data.rc = rc;
Note:
See TracChangeset
for help on using the changeset viewer.