Changeset 50508 in vbox
- Timestamp:
- Feb 19, 2014 3:45:58 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 14 edited
-
include/VBox/GuestHost/DragAndDrop.h (modified) (5 diffs)
-
include/VBox/HostServices/DragAndDropSvc.h (modified) (9 diffs)
-
include/VBox/VBoxGuestLib.h (modified) (1 diff)
-
src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp (modified) (8 diffs)
-
src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h (modified) (1 diff)
-
src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp (modified) (2 diffs)
-
src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp (modified) (24 diffs)
-
src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp (modified) (10 diffs)
-
src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp (modified) (10 diffs)
-
src/VBox/HostServices/DragAndDrop/dndmanager.cpp (modified) (13 diffs)
-
src/VBox/HostServices/DragAndDrop/service.cpp (modified) (1 diff)
-
src/VBox/Main/include/GuestDnDImpl.h (modified) (3 diffs)
-
src/VBox/Main/src-client/GuestDnDImpl.cpp (modified) (23 diffs)
-
src/VBox/Runtime/common/misc/uri.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/DragAndDrop.h
r50460 r50508 1 1 /* $Id$ */ 2 2 /** @file 3 * DnD: Share functions between host and guest.3 * DnD: Shared functions between host and guest. 4 4 */ 5 5 … … 22 22 #include <iprt/cdefs.h> 23 23 #include <iprt/err.h> 24 #include <iprt/file.h> 24 25 #include <iprt/types.h> 25 26 … … 36 37 int DnDPathSanitize(char *pszPath, size_t cbPath); 37 38 38 typedef struct DnDURIPath 39 class DnDURIObject 39 40 { 40 DnDURIPath(const RTCString &strSrcPath, 41 const RTCString &strDstPath, 42 uint32_t fMode, uint64_t cbSize) 43 : m_strSrcPath(strSrcPath) 44 , m_strDstPath(strDstPath) 45 , m_fMode(fMode) 46 , m_cbSize(cbSize) {} 41 public: 47 42 43 enum Type 44 { 45 Unknown = 0, 46 File, 47 Directory 48 }; 49 50 DnDURIObject(Type type, 51 const RTCString &strSrcPath, 52 const RTCString &strDstPath, 53 uint32_t fMode, uint64_t cbSize); 54 virtual ~DnDURIObject(void); 55 56 public: 57 58 RTCString GetSourcePath(void) const { return m_strSrcPath; } 59 RTCString GetDestPath(void) const { return m_strDstPath; } 60 uint32_t GetMode(void) const { return m_fMode; } 61 uint64_t GetSize(void) const { return m_cbSize; } 62 Type GetType(void) const { return m_Type; } 63 64 public: 65 66 bool IsComplete(void) const; 67 static int RebaseURIPath(RTCString &strPath, const RTCString &strBaseOld, const RTCString &strBaseNew); 68 int Read(void *pvBuf, uint32_t cbToRead, uint32_t *pcbRead); 69 70 protected: 71 72 void closeInternal(void); 73 74 protected: 75 76 Type m_Type; 48 77 RTCString m_strSrcPath; 49 78 RTCString m_strDstPath; 50 79 uint32_t m_fMode; 80 /** Size (in bytes) to read/write. */ 51 81 uint64_t m_cbSize; 82 /** Bytes processed reading/writing. */ 83 uint64_t m_cbProcessed; 52 84 53 } DnDURIPath; 85 union 86 { 87 RTFILE m_hFile; 88 } u; 89 }; 54 90 55 91 class DnDURIList … … 62 98 public: 63 99 64 int AppendPath(const char *pszPath, uint32_t fFlags); 65 int AppendPathsFromList(const RTCList<RTCString> &lstURI, uint32_t fFlags); 100 int AppendNativePath(const char *pszPath, uint32_t fFlags); 101 int AppendNativePathsFromList(const char *pszNativePaths, size_t cbNativePaths, uint32_t fFlags); 102 int AppendNativePathsFromList(const RTCList<RTCString> &lstNativePaths, uint32_t fFlags); 103 int AppendURIPath(const char *pszURI, uint32_t fFlags); 104 int AppendURIPathsFromList(const char *pszURIPaths, size_t cbURIPaths, uint32_t fFlags); 105 int AppendURIPathsFromList(const RTCList<RTCString> &lstURI, uint32_t fFlags); 106 66 107 void Clear(void); 67 const DnDURIPath &First(void) const{ return m_lstTree.first(); }108 DnDURIObject &First(void) { return m_lstTree.first(); } 68 109 bool IsEmpty(void) { return m_lstTree.isEmpty(); } 69 110 void RemoveFirst(void); 70 RTCString RootToString(void) { return RTCString::join(m_lstRoot, "\r\n") + "\r\n"; } 111 int RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags); 112 RTCString RootToString(const RTCString &strBasePath = ""); 113 size_t RootCount(void) { return m_lstRoot.size(); } 71 114 size_t TotalBytes(void) { return m_cbTotal; } 72 115 … … 77 120 protected: 78 121 79 /** List of top-level (root) URIentries. */122 /** List of all top-level file/directory entries. */ 80 123 RTCList<RTCString> m_lstRoot; 81 124 /** List of all URI objects added. */ 82 RTCList<DnDURI Path>m_lstTree;125 RTCList<DnDURIObject> m_lstTree; 83 126 /** Total size of all URI objects, that is, the file 84 127 * size of all objects (in bytes). */ -
trunk/include/VBox/HostServices/DragAndDropSvc.h
r50460 r50508 221 221 HGCMFunctionParameter cFormat; /* OUT uint32_t */ 222 222 HGCMFunctionParameter pvData; /* OUT ptr */ 223 HGCMFunctionParameter c Data;/* OUT uint32_t */223 HGCMFunctionParameter cbData; /* OUT uint32_t */ 224 224 } VBOXDNDHGSENDDATAMSG; 225 225 … … 235 235 */ 236 236 HGCMFunctionParameter pvData; /* OUT ptr */ 237 HGCMFunctionParameter c Data;/* OUT uint32_t */237 HGCMFunctionParameter cbData; /* OUT uint32_t */ 238 238 } VBOXDNDHGSENDMOREDATAMSG; 239 239 … … 249 249 */ 250 250 HGCMFunctionParameter pvName; /* OUT ptr */ 251 HGCMFunctionParameter c Name;/* OUT uint32_t */251 HGCMFunctionParameter cbName; /* OUT uint32_t */ 252 252 HGCMFunctionParameter fMode; /* OUT uint32_t */ 253 253 } VBOXDNDHGSENDDIRMSG; … … 264 264 */ 265 265 HGCMFunctionParameter pvName; /* OUT ptr */ 266 HGCMFunctionParameter c Name;/* OUT uint32_t */266 HGCMFunctionParameter cbName; /* OUT uint32_t */ 267 267 HGCMFunctionParameter pvData; /* OUT ptr */ 268 HGCMFunctionParameter c Data;/* OUT uint32_t */268 HGCMFunctionParameter cbData; /* OUT uint32_t */ 269 269 HGCMFunctionParameter fMode; /* OUT uint32_t */ 270 270 } VBOXDNDHGSENDFILEMSG; … … 316 316 /** Number of parameters the message needs. */ 317 317 HGCMFunctionParameter num_parms; /* OUT uint32_t */ 318 /** Whether or not to block (wait) for a 319 * new message to arrive. */ 318 320 HGCMFunctionParameter block; /* OUT uint32_t */ 319 321 … … 371 373 * GUEST_DND_GH_SND_DATA 372 374 */ 373 HGCMFunctionParameter pData; /* OUT ptr */ 374 HGCMFunctionParameter uSize; /* OUT uint32_t */ 375 HGCMFunctionParameter pvData; /* OUT ptr */ 376 /** Total bytes to send. This can be more than 377 * the data block specified in pvData above, e.g. 378 * when sending over file objects. */ 379 HGCMFunctionParameter cbTotalBytes; /* OUT uint32_t */ 375 380 } VBOXDNDGHSENDDATAMSG; 381 382 typedef struct VBOXDNDGHSENDDIRMSG 383 { 384 VBoxGuestHGCMCallInfo hdr; 385 386 /** 387 * GH Directory event. 388 * 389 * Used by: 390 * GUEST_DND_HG_SND_DIR 391 */ 392 HGCMFunctionParameter pvName; /* OUT ptr */ 393 HGCMFunctionParameter cbName; /* OUT uint32_t */ 394 HGCMFunctionParameter fMode; /* OUT uint32_t */ 395 } VBOXDNDGHSENDDIRMSG; 396 397 typedef struct VBOXDNDGHSENDFILEMSG 398 { 399 VBoxGuestHGCMCallInfo hdr; 400 401 /** 402 * GH File event. 403 * 404 * Used by: 405 * GUEST_DND_HG_SND_FILE 406 */ 407 HGCMFunctionParameter pvName; /* OUT ptr */ 408 HGCMFunctionParameter cbName; /* OUT uint32_t */ 409 HGCMFunctionParameter pvData; /* OUT ptr */ 410 HGCMFunctionParameter cbData; /* OUT uint32_t */ 411 HGCMFunctionParameter fMode; /* OUT uint32_t */ 412 } VBOXDNDGHSENDFILEMSG; 376 413 377 414 typedef struct VBOXDNDGHEVTERRORMSG … … 391 428 392 429 /* 393 * Callback handler430 * Callback data magics. 394 431 */ 395 432 enum … … 400 437 CB_MAGIC_DND_GH_ACK_PENDING = 0xbe975a14, 401 438 CB_MAGIC_DND_GH_SND_DATA = 0x4eb61bff, 439 CB_MAGIC_DND_GH_SND_DIR = 0x411ca754, 440 CB_MAGIC_DND_GH_SND_FILE = 0x65e35eaf, 402 441 CB_MAGIC_DND_GH_EVT_ERROR = 0x117a87c4 403 442 }; … … 454 493 void *pvData; 455 494 uint32_t cbData; 456 uint32_t cbAllSize; /** @todo Why is this transmitted every time? */ 495 /** Total metadata size (in bytes). This is transmitted 496 * with every message because the size can change. */ 497 uint32_t cbTotalSize; 457 498 } VBOXDNDCBSNDDATADATA; 458 499 typedef VBOXDNDCBSNDDATADATA *PVBOXDNDCBSNDDATADATA; 500 501 typedef struct VBOXDNDCBSNDDIRDATA 502 { 503 /** Callback data header. */ 504 VBOXDNDCBHEADERDATA hdr; 505 char *pszPath; 506 uint32_t cbPath; 507 uint32_t fMode; 508 } VBOXDNDCBSNDDIRDATA; 509 typedef VBOXDNDCBSNDDIRDATA *PVBOXDNDCBSNDDIRDATA; 510 511 typedef struct VBOXDNDCBSNDFILEDATA 512 { 513 /** Callback data header. */ 514 VBOXDNDCBHEADERDATA hdr; 515 char *pszFilePath; 516 uint32_t cbFilePath; 517 uint32_t fMode; 518 void *pvData; 519 uint32_t cbData; 520 } VBOXDNDCBSNDFILEDATA; 521 typedef VBOXDNDCBSNDFILEDATA *PVBOXDNDCBSNDFILEDATA; 459 522 460 523 typedef struct VBOXDNDCBEVTERRORDATA -
trunk/include/VBox/VBoxGuestLib.h
r50305 r50508 723 723 # ifdef VBOX_WITH_DRAG_AND_DROP_GH 724 724 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(uint32_t u32ClientId, uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormats); 725 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, void *pvData, uint32_t cbData);725 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, const char *pszFormat, void *pvData, uint32_t cbData); 726 726 VBGLR3DECL(int) VbglR3DnDGHErrorEvent(uint32_t u32ClientId, int rcOp); 727 727 # endif /* VBOX_WITH_DRAG_AND_DROP_GH */ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
r50467 r50508 49 49 * at NT4 SP3+. */ 50 50 typedef BOOL (WINAPI *PFNSENDINPUT)(UINT, LPINPUT, int); 51 typedef BOOL (WINAPI* PFNENUMDISPLAYMONITORS)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); 51 52 52 53 /** Static pointer to SendInput() function. */ 53 54 static PFNSENDINPUT s_pfnSendInput = NULL; 55 static PFNENUMDISPLAYMONITORS s_pfnEnumDisplayMonitors = NULL; 54 56 55 57 static LRESULT CALLBACK vboxDnDWndProcInstance(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); … … 58 60 VBoxDnDWnd::VBoxDnDWnd(void) 59 61 : hWnd(NULL), 60 mpfnEnumDisplayMonitors(NULL),61 62 mfMouseButtonDown(false), 62 63 #ifdef VBOX_WITH_DRAG_AND_DROP_GH … … 85 86 /* Save the context. */ 86 87 this->pContext = pContext; 87 88 HMODULE hUser = GetModuleHandle("user32.dll");89 if (hUser)90 {91 *(uintptr_t *)&mpfnEnumDisplayMonitors = (uintptr_t)GetProcAddress(hUser, "EnumDisplayMonitors");92 Log(("DnD: EnumDisplayMonitors = %p\n", mpfnEnumDisplayMonitors));93 }94 88 95 89 int rc = RTSemEventCreate(&mEventSem); … … 1014 1008 AssertReturn(cbFormats, VERR_INVALID_PARAMETER); 1015 1009 1016 LogFlowThisFunc(("mMode=%ld, mState=%ld, pDropTarget=0x%p, uDefAction=0x%x\n",1017 mMode, mState, pDropTarget, uDefAction));1010 LogFlowThisFunc(("mMode=%ld, mState=%ld, pDropTarget=0x%p, pszFormat=%s, uDefAction=0x%x\n", 1011 mMode, mState, pDropTarget, pszFormat, uDefAction)); 1018 1012 1019 1013 int rc; … … 1025 1019 { 1026 1020 /** @todo Respect uDefAction. */ 1027 /** @todo Do data checking / conversion based on pszFormats. */1028 1029 1021 void *pvData = pDropTarget->DataMutableRaw(); 1030 1022 AssertPtr(pvData); … … 1032 1024 Assert(cbData); 1033 1025 1034 rc = VbglR3DnDGHSendData(mClientID, p vData, cbData);1026 rc = VbglR3DnDGHSendData(mClientID, pszFormat, pvData, cbData); 1035 1027 LogFlowFunc(("Sent pvData=0x%p, cbData=%RU32, rc=%Rrc\n", 1036 1028 pvData, cbData, rc)); … … 1094 1086 if (hDC) 1095 1087 { 1096 fRc = mpfnEnumDisplayMonitors? 1097 mpfnEnumDisplayMonitors(hDC, NULL, VBoxDnDWnd::MonitorEnumProc, (LPARAM)&r): 1098 FALSE; 1088 fRc = s_pfnEnumDisplayMonitors 1089 /* EnumDisplayMonitors is not available on NT4. */ 1090 ? s_pfnEnumDisplayMonitors(hDC, NULL, VBoxDnDWnd::MonitorEnumProc, (LPARAM)&r): 1091 FALSE; 1099 1092 1100 1093 if (!fRc) … … 1286 1279 RTLdrGetSystemSymbol("User32.dll", "SendInput"); 1287 1280 fSupportedOS = !RT_BOOL(s_pfnSendInput == NULL); 1281 s_pfnEnumDisplayMonitors = (PFNENUMDISPLAYMONITORS) 1282 RTLdrGetSystemSymbol("User32.dll", "EnumDisplayMonitors"); 1283 /* g_pfnEnumDisplayMonitors is optional. */ 1288 1284 1289 1285 if (!fSupportedOS) -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h
r50467 r50508 366 366 /** The window's handle. */ 367 367 HWND hWnd; 368 BOOL (WINAPI* mpfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);369 368 /** List of allowed MIME types this 370 369 * client can handle. Make this a per-instance -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp
r50399 r50508 356 356 0 /* cchFile */); 357 357 Assert(cch); 358 359 /* Add separation between filenames. */360 if (i > 0)361 {362 rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */,363 "\r\n", 2 /* Bytes */);364 if (RT_SUCCESS(rc))365 cchFiles += 2; /* Include \r\n */366 }367 358 368 359 if (RT_FAILURE(rc)) … … 418 409 if (RT_FAILURE(rc)) 419 410 break; 411 412 /* Add separation between filenames. 413 * Note: Also do this for the last element of the list. */ 414 if (i > 0) 415 { 416 rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, 417 "\r\n", 2 /* Bytes */); 418 if (RT_SUCCESS(rc)) 419 cchFiles += 2; /* Include \r\n */ 420 } 420 421 } 421 422 -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r50462 r50508 38 38 #include <iprt/cpp/ministring.h> 39 39 40 #ifdef LOG_GROUP 41 #undef LOG_GROUP 42 #endif 43 #define LOG_GROUP LOG_GROUP_GUEST_DND 44 #include <VBox/log.h> 45 40 46 #include <VBox/GuestHost/DragAndDrop.h> 41 47 #include <VBox/HostServices/DragAndDropSvc.h> … … 79 85 if (RT_SUCCESS(rc)) 80 86 { 81 /* Fetch results */82 87 rc = Msg.msg.GetUInt32(puMsg); AssertRC(rc); 83 88 rc = Msg.num_parms.GetUInt32(pcParms); AssertRC(rc); … … 128 133 if (RT_SUCCESS(rc)) 129 134 { 130 /* Fetch results */131 135 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 132 136 rc = Msg.uX.GetUInt32(puX); AssertRC(rc); … … 135 139 rc = Msg.uAllActions.GetUInt32(puAllActions); AssertRC(rc); 136 140 rc = Msg.cFormats.GetUInt32(pcbFormatsRecv); AssertRC(rc); 137 /* A little bit paranoia */ 141 138 142 AssertReturn(cbFormats >= *pcbFormatsRecv, VERR_TOO_MUCH_DATA); 139 143 } … … 191 195 192 196 Msg.pvName.SetPtr(pszDirname, cbDirname); 193 Msg.c Name.SetUInt32(0);197 Msg.cbName.SetUInt32(0); 194 198 Msg.fMode.SetUInt32(0); 195 199 … … 200 204 if (RT_SUCCESS(Msg.hdr.result)) 201 205 { 202 /* Fetch results */ 203 rc = Msg.cName.GetUInt32(pcbDirnameRecv); AssertRC(rc); 204 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 205 /* A little bit paranoia */ 206 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc); 207 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 208 206 209 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA); 207 210 } … … 235 238 236 239 Msg.pvName.SetPtr(pszFilename, cbFilename); 237 Msg.c Name.SetUInt32(0);240 Msg.cbName.SetUInt32(0); 238 241 Msg.pvData.SetPtr(pvData, cbData); 239 Msg.c Data.SetUInt32(0);242 Msg.cbData.SetUInt32(0); 240 243 Msg.fMode.SetUInt32(0); 241 244 … … 246 249 if (RT_SUCCESS(rc)) 247 250 { 248 /* Fetch results */ 249 rc = Msg.cName.GetUInt32(pcbFilenameRecv); AssertRC(rc); 250 rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc); 251 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 252 /* A little bit paranoia */ 251 rc = Msg.cbName.GetUInt32(pcbFilenameRecv); AssertRC(rc); 252 rc = Msg.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 253 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 254 253 255 AssertReturn(cbFilename >= *pcbFilenameRecv, VERR_TOO_MUCH_DATA); 254 256 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); … … 275 277 return VERR_INVALID_PARAMETER; 276 278 277 /* Make a string list out of the uri data. */ 278 RTCList<RTCString> uriList = 279 RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); 280 if (uriList.isEmpty()) 281 return VINF_SUCCESS; 282 279 /* Allocate temp buffer. */ 283 280 uint32_t cbTmpData = _1M * 10; /** @todo r=andy 10MB, uh, really?? */ 284 281 void *pvTmpData = RTMemAlloc(cbTmpData); … … 297 294 /* Patch the old drop data with the new drop directory, so the drop target 298 295 * can find the files. */ 299 RTCList<RTCString> guestUriList; 300 for (size_t i = 0; i < uriList.size(); ++i) 301 { 302 const RTCString &strUri = uriList.at(i); 303 /* Query the path component of a file URI. If this hasn't a 304 * file scheme, null is returned. */ 305 char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO); 306 if (pszFilePath) 307 { 308 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath)); 309 if (RT_FAILURE(rc)) 310 break; 311 312 /** @todo Use RTPathJoin? */ 313 RTCString strFullPath 314 = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); 315 char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); 316 if (pszNewUri) 317 { 318 guestUriList.append(pszNewUri); 319 RTStrFree(pszNewUri); 320 } 321 } 322 else 323 guestUriList.append(strUri); 324 } 325 296 DnDURIList lstURI; 297 rc = lstURI.RootFromURIData(*ppvData, *pcbDataRecv, 298 0 /* fFlags */); 326 299 if (RT_SUCCESS(rc)) 327 300 { 328 301 /* Cleanup the old data and write the new data back to the event. */ 329 302 RTMemFree(*ppvData); 330 RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n"; 331 332 *ppvData = RTStrDupN( newData.c_str(), newData.length());333 *pcbDataRecv = newData.length() + 1;303 304 RTCString strData = lstURI.RootToString(pszDropDir); 305 *ppvData = RTStrDupN(strData.c_str(), strData.length()); 306 *pcbDataRecv = strData.length() + 1; 334 307 } 335 308 … … 403 376 if (RT_SUCCESS(rc)) 404 377 { 378 /** @todo r=andy Not very safe to assume that we were last appending to the current file. */ 405 379 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); 406 380 if (RT_SUCCESS(rc)) … … 488 462 Msg.cFormat.SetUInt32(0); 489 463 Msg.pvData.SetPtr(pvData, cbData); 490 Msg.c Data.SetUInt32(0);464 Msg.cbData.SetUInt32(0); 491 465 492 466 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 497 471 || rc == VERR_BUFFER_OVERFLOW) 498 472 { 499 /* Fetch results */500 473 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 501 474 rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 502 rc = Msg.c Data.GetUInt32(pcbDataTotal); AssertRC(rc);503 /* A little bit paranoia */ 475 rc = Msg.cbData.GetUInt32(pcbDataTotal); AssertRC(rc); 476 504 477 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); 505 478 AssertReturn(cbData >= *pcbDataTotal, VERR_TOO_MUCH_DATA); … … 526 499 527 500 Msg.pvData.SetPtr(pvData, cbData); 528 Msg.c Data.SetUInt32(0);501 Msg.cbData.SetUInt32(0); 529 502 530 503 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 535 508 || rc == VERR_BUFFER_OVERFLOW) 536 509 { 537 /* Fetch results */ 538 rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc); 539 /* A little bit paranoia */ 510 rc = Msg.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 540 511 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 541 512 } … … 629 600 * This keeps the actual (guest OS-)dependent client (like VBoxClient / 630 601 * VBoxTray) small by not having too much redundant code. */ 631 if (RTStrNICmp(pszFormat, "text/uri-list", *pcbFormatRecv) == 0) 602 AssertPtr(pcbFormatRecv); 603 if (DnDMIMEHasFileURLs(pszFormat, *pcbFormatRecv)) 632 604 rc = vbglR3DnDHGProcessURIMessages(uClientId, 633 605 puScreenId, … … 661 633 rc = Msg.hdr.result; 662 634 if (RT_SUCCESS(rc)) 663 {664 /* Fetch results */665 635 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 666 }667 636 } 668 637 … … 697 666 if (RT_SUCCESS(rc)) 698 667 { 699 /* Fetch results */700 668 rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 701 669 rc = Msg.uAction.GetUInt32(puAction); AssertRC(rc); 702 /* A little bit paranoia */ 670 703 671 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); 704 672 } … … 872 840 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_ACK_OP; 873 841 Msg.hdr.cParms = 1; 874 /* Initialize parameter */ 842 875 843 Msg.uAction.SetUInt32(uAction); 876 /* Do request */ 844 877 845 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 878 846 if (RT_SUCCESS(rc)) … … 892 860 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_REQ_DATA; 893 861 Msg.hdr.cParms = 1; 894 /* Initialize parameter */ 862 895 863 Msg.pFormat.SetPtr((void*)pcszFormat, (uint32_t)strlen(pcszFormat) + 1); 896 /* Do request */ 864 897 865 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 898 866 if (RT_SUCCESS(rc)) … … 914 882 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_ACK_PENDING; 915 883 Msg.hdr.cParms = 3; 916 /* Initialize parameter */ 884 917 885 Msg.uDefAction.SetUInt32(uDefAction); 918 886 Msg.uAllActions.SetUInt32(uAllActions); 919 887 Msg.pFormat.SetPtr((void*)pcszFormats, (uint32_t)strlen(pcszFormats) + 1); 920 /* Do request */ 921 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 922 if (RT_SUCCESS(rc)) 923 rc = Msg.hdr.result; 924 925 return rc; 926 } 927 928 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, 929 void *pvData, uint32_t cbData) 888 889 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 890 if (RT_SUCCESS(rc)) 891 rc = Msg.hdr.result; 892 893 return rc; 894 } 895 896 static int vbglR3DnDGHSendDataInternal(uint32_t u32ClientId, 897 void *pvData, uint32_t cbData, 898 uint32_t cbAdditionalData) 930 899 { 931 900 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 932 AssertReturn(cbData, VERR_INVALID_PARAMETER);901 AssertReturn(cbData, VERR_INVALID_PARAMETER); 933 902 934 903 DragAndDropSvc::VBOXDNDGHSENDDATAMSG Msg; … … 938 907 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DATA; 939 908 Msg.hdr.cParms = 2; 940 Msg.uSize.SetUInt32(cbData); 941 942 int rc = VINF_SUCCESS; 943 uint32_t cbMax = _64K; /* Transfer max. 64K chunks per message. */ 944 uint32_t cbSent = 0; 909 910 /* Total amount of bytes to send (including this data block). */ 911 Msg.cbTotalBytes.SetUInt32(cbData + cbAdditionalData); 912 913 int rc; 914 915 uint32_t cbMaxChunk = _64K; /* Transfer max. 64K chunks per message. */ 916 uint32_t cbSent = 0; 945 917 946 918 while (cbSent < cbData) 947 919 { 948 uint32_t cb ToSend = RT_MIN(cbData - cbSent, cbMax);949 Msg.p Data.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbToSend);920 uint32_t cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk); 921 Msg.pvData.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbCurChunk); 950 922 951 923 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 956 928 break; 957 929 958 cbSent += cb ToSend;930 cbSent += cbCurChunk; 959 931 } 960 932 961 933 if (RT_SUCCESS(rc)) 962 934 Assert(cbSent == cbData); 935 936 LogFlowFunc(("Returning rc=%Rrc, cbData=%RU32, cbAddtionalData=%RU32\n", 937 rc, cbData, cbAdditionalData)); 938 return rc; 939 } 940 941 static int vbglR3DnDGHSendDir(uint32_t u32ClientId, DnDURIObject &obj) 942 { 943 AssertReturn(obj.GetType() == DnDURIObject::Directory, VERR_INVALID_PARAMETER); 944 945 DragAndDropSvc::VBOXDNDGHSENDDIRMSG Msg; 946 RT_ZERO(Msg); 947 Msg.hdr.result = VERR_WRONG_ORDER; 948 Msg.hdr.u32ClientID = u32ClientId; 949 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DIR; 950 Msg.hdr.cParms = 3; 951 952 RTCString strPath = obj.GetDestPath(); 953 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n", 954 strPath.c_str(), strPath.length(), obj.GetMode())); 955 956 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 957 Msg.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 958 Msg.fMode.SetUInt32(obj.GetMode()); 959 960 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 961 if (RT_SUCCESS(rc)) 962 rc = Msg.hdr.result; 963 964 LogFlowFuncLeaveRC(rc); 965 return rc; 966 } 967 968 static int vbglR3DnDGHSendFile(uint32_t u32ClientId, DnDURIObject &obj) 969 { 970 AssertReturn(obj.GetType() == DnDURIObject::File, VERR_INVALID_PARAMETER); 971 972 uint32_t cbBuf = _64K; /** @todo Make this configurable? */ 973 void *pvBuf = RTMemAlloc(cbBuf); 974 if (!pvBuf) 975 return VERR_NO_MEMORY; 976 977 DragAndDropSvc::VBOXDNDGHSENDFILEMSG Msg; 978 RT_ZERO(Msg); 979 Msg.hdr.result = VERR_WRONG_ORDER; 980 Msg.hdr.u32ClientID = u32ClientId; 981 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_FILE; 982 Msg.hdr.cParms = 5; 983 984 RTCString strPath = obj.GetDestPath(); 985 LogFlowFunc(("strFile=%s (%zu), fMode=0x%x\n", 986 strPath.c_str(), strPath.length(), obj.GetMode())); 987 988 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 989 Msg.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 990 Msg.fMode.SetUInt32(obj.GetMode()); 991 992 int rc = VINF_SUCCESS; 993 uint32_t cbData = obj.GetSize(); 994 995 do 996 { 997 uint32_t cbToRead = RT_MIN(cbData, cbBuf); 998 uint32_t cbRead = 0; 999 if (cbToRead) 1000 rc = obj.Read(pvBuf, cbToRead, &cbRead); 1001 if (RT_SUCCESS(rc)) 1002 { 1003 Msg.cbData.SetUInt32(cbRead); 1004 Msg.pvData.SetPtr(pvBuf, cbRead); 1005 1006 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1007 if (RT_SUCCESS(rc)) 1008 rc = Msg.hdr.result; 1009 } 1010 1011 if (RT_FAILURE(rc)) 1012 break; 1013 1014 Assert(cbRead <= cbData); 1015 cbData -= cbRead; 1016 1017 } while (cbData); 1018 1019 RTMemFree(pvBuf); 1020 1021 LogFlowFuncLeaveRC(rc); 1022 return rc; 1023 } 1024 1025 static int vbglR3DnDGHSendURIObject(uint32_t u32ClientId, DnDURIObject &obj) 1026 { 1027 int rc; 1028 1029 switch (obj.GetType()) 1030 { 1031 case DnDURIObject::Directory: 1032 rc = vbglR3DnDGHSendDir(u32ClientId, obj); 1033 break; 1034 1035 case DnDURIObject::File: 1036 rc = vbglR3DnDGHSendFile(u32ClientId, obj); 1037 break; 1038 1039 default: 1040 AssertMsgFailed(("Type %ld not implemented\n", 1041 obj.GetType())); 1042 rc = VERR_NOT_IMPLEMENTED; 1043 break; 1044 } 1045 1046 return rc; 1047 } 1048 1049 static int vbglR3DnDGHProcessURIMessages(uint32_t u32ClientId, 1050 void *pvData, uint32_t cbData) 1051 { 1052 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1053 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1054 1055 RTCList<RTCString> lstPaths = 1056 RTCString((const char *)pvData, cbData).split("\r\n"); 1057 1058 DnDURIList lstURI; 1059 int rc = lstURI.AppendNativePathsFromList(lstPaths, 0 /* fFlags */); 1060 if (RT_SUCCESS(rc)) 1061 { 1062 /* Send metadata; in this case it's the (non-recursive) file/directory 1063 * URI list the host needs to know to initialize the drag'n drop operation. */ 1064 RTCString strRootDest = lstURI.RootToString(); 1065 Assert(strRootDest.isNotEmpty()); 1066 1067 void *pvToSend = (void *)strRootDest.c_str(); 1068 uint32_t cbToSend = (uint32_t)strRootDest.length() + 1; 1069 1070 rc = vbglR3DnDGHSendDataInternal(u32ClientId, pvToSend, cbToSend, 1071 /* Include total bytes of all file paths, 1072 * file sizes etc. */ 1073 lstURI.TotalBytes()); 1074 } 1075 1076 if (RT_SUCCESS(rc)) 1077 { 1078 while (!lstURI.IsEmpty()) 1079 { 1080 DnDURIObject &nextObj = lstURI.First(); 1081 1082 rc = vbglR3DnDGHSendURIObject(u32ClientId, nextObj); 1083 if (RT_FAILURE(rc)) 1084 break; 1085 1086 lstURI.RemoveFirst(); 1087 } 1088 } 1089 1090 return rc; 1091 } 1092 1093 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, 1094 const char *pszFormat, 1095 void *pvData, uint32_t cbData) 1096 { 1097 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 1098 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1099 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1100 1101 int rc; 1102 if (DnDMIMEHasFileURLs(pszFormat, strlen(pszFormat))) 1103 { 1104 rc = vbglR3DnDGHProcessURIMessages(u32ClientId, pvData, cbData); 1105 } 1106 else 1107 rc = vbglR3DnDGHSendDataInternal(u32ClientId, pvData, cbData, 1108 0 /* cbAdditionalData */); 963 1109 964 1110 return rc; … … 973 1119 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_EVT_ERROR; 974 1120 Msg.hdr.cParms = 1; 975 /* Initialize parameter */ 1121 976 1122 Msg.uRC.SetUInt32(rcOp); 977 /* Do request */ 978 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 979 if (RT_SUCCESS(rc)) 980 rc = Msg.hdr.result; 981 982 return rc; 983 } 984 985 VBGLR3DECL(int) VbglR3DnDGHSendFile(uint32_t u32ClientId, const char *pszPath) 986 { 987 return 0; 988 } 989 1123 1124 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1125 if (RT_SUCCESS(rc)) 1126 rc = Msg.hdr.result; 1127 1128 return rc; 1129 } 1130 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp
r50460 r50508 53 53 HRESULT hr; 54 54 55 ULONG c AllFormats = lstFormats.size();55 ULONG cMaxFormats = 16; /* Maximum number of registered formats. */ 56 56 ULONG cRegisteredFormats = 0; 57 57 58 58 try 59 59 { 60 mpFormatEtc = new FORMATETC[c AllFormats];61 RT_BZERO(mpFormatEtc, sizeof(FORMATETC) * c AllFormats);62 mpStgMedium = new STGMEDIUM[c AllFormats];63 RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * c AllFormats);60 mpFormatEtc = new FORMATETC[cMaxFormats]; 61 RT_BZERO(mpFormatEtc, sizeof(FORMATETC) * cMaxFormats); 62 mpStgMedium = new STGMEDIUM[cMaxFormats]; 63 RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cMaxFormats); 64 64 65 65 for (int i = 0; i < lstFormats.size(); i++) … … 69 69 continue; 70 70 71 /* URI data ("text/uri-list"). */ 71 72 if (strFormat.contains("text/uri-list", Qt::CaseInsensitive)) 72 73 { 73 /* URI data ("text/uri-list"). */ 74 RegisterFormat(&mpFormatEtc[cRegisteredFormats], CF_TEXT); 75 mpStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 76 RegisterFormat(&mpFormatEtc[cRegisteredFormats], CF_UNICODETEXT); 77 mpStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 74 78 RegisterFormat(&mpFormatEtc[cRegisteredFormats], CF_HDROP); 75 79 mpStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; … … 77 81 mlstFormats << strFormat; 78 82 } 83 /* Plain text ("text/plain"). */ 79 84 else if (strFormat.contains("text/plain", Qt::CaseInsensitive)) 80 85 { 81 /* Plain text ("text/plain"). */82 86 RegisterFormat(&mpFormatEtc[cRegisteredFormats], CF_TEXT); 83 87 mpStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 88 RegisterFormat(&mpFormatEtc[cRegisteredFormats], CF_UNICODETEXT); 89 mpStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 84 90 85 91 mlstFormats << strFormat; … … 89 95 LogFlowFunc(("Total registered formats: %RU32 (of %d total)\n", 90 96 cRegisteredFormats, lstFormats.size())); 91 #ifdef VBOX_STRICT92 AssertMsg(cRegisteredFormats == cAllFormats,93 ("Registered formats count is not matching all formats count\n"));94 #endif95 97 hr = S_OK; 96 98 } … … 201 203 AssertPtrReturn(pMedium, DV_E_FORMATETC); 202 204 205 #ifdef VBOX_DND_DEBUG_FORMATS 203 206 LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium)); 207 #endif 204 208 205 209 ULONG lIndex; … … 227 231 if (mStatus == Dropped) 228 232 { 229 #if 0 230 LogFlowFunc(("Starting to transfer content from the guest ...\n")); 231 232 /* 233 * This is the right time starting to transfer the actual data 234 * from the guest: 235 * - The user just triggered an action that tells us to start, e.g. at 236 * the moment we only "listen" for releasing the left mouse button. 237 * - We're still in OLE's (modal) drag'n drop context so that all data 238 * from the guest (hopefully) will be available on the host when the 239 * drag'n drop operation is about to finish through OLE. 240 * 241 * Note that in the URI case the guest files/dirs must be somewhere 242 * on the host before OLE's drag'n drop operation is finished, otherwise 243 * the whole operation will fail. 244 */ 245 #endif 233 #ifdef VBOX_DND_DEBUG_FORMATS 246 234 LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n", 247 235 pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), … … 249 237 LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n", 250 238 mstrFormat.toAscii().constData(), mpvData, mcbData)); 251 239 #endif 252 240 QVariant::Type vaType; 253 241 QString strMIMEType; … … 495 483 STDMETHODIMP UIDnDDataObject::QueryGetData(FORMATETC *pFormatEtc) 496 484 { 497 LogFlowFunc(("\n"));498 485 return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC; 499 486 } … … 648 635 && pFormatEtc->dwAspect == mpFormatEtc[i].dwAspect) 649 636 { 637 #ifdef VBOX_DND_DEBUG_FORMATS 650 638 LogFlowFunc(("Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n", 651 639 pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(mpFormatEtc[i].cfFormat), 652 640 pFormatEtc->dwAspect, i)); 641 #endif 653 642 if (puIndex) 654 643 *puIndex = i; … … 657 646 } 658 647 648 #ifdef VBOX_DND_DEBUG_FORMATS 659 649 LogFlowFunc(("Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n", 660 650 pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), 661 651 pFormatEtc->dwAspect)); 662 652 #endif 663 653 return false; 664 654 } -
trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
r50460 r50508 34 34 #include <VBox/GuestHost/DragAndDrop.h> 35 35 36 DnDURIObject::DnDURIObject(Type type, 37 const RTCString &strSrcPath, 38 const RTCString &strDstPath, 39 uint32_t fMode, uint64_t cbSize) 40 : m_Type(type) 41 , m_strSrcPath(strSrcPath) 42 , m_strDstPath(strDstPath) 43 , m_fMode(fMode) 44 , m_cbSize(cbSize) 45 , m_cbProcessed(0) 46 { 47 RT_ZERO(u); 48 } 49 50 DnDURIObject::~DnDURIObject(void) 51 { 52 closeInternal(); 53 } 54 55 void DnDURIObject::closeInternal(void) 56 { 57 if (m_Type == File) 58 { 59 if (u.m_hFile) 60 { 61 RTFileClose(u.m_hFile); 62 u.m_hFile = NULL; 63 } 64 } 65 } 66 67 bool DnDURIObject::IsComplete(void) const 68 { 69 bool fComplete = false; 70 71 Assert(m_cbProcessed <= m_cbSize); 72 if (m_cbProcessed == m_cbSize) 73 fComplete = true; 74 75 switch (m_Type) 76 { 77 case File: 78 if (!fComplete) 79 fComplete = !u.m_hFile; 80 break; 81 82 case Directory: 83 fComplete = true; 84 break; 85 86 default: 87 break; 88 } 89 90 return fComplete; 91 } 92 93 /* static */ 94 /** @todo Put this into an own class like DnDURIPath : public RTCString? */ 95 int DnDURIObject::RebaseURIPath(RTCString &strPath, 96 const RTCString &strBaseOld, 97 const RTCString &strBaseNew) 98 { 99 int rc; 100 const char *pszPath = RTUriPath(strPath.c_str()); 101 if (pszPath) 102 { 103 const char *pszPathStart = pszPath; 104 const char *pszBaseOld = strBaseOld.c_str(); 105 if ( pszBaseOld 106 && RTPathStartsWith(pszPath, pszBaseOld)) 107 { 108 pszPathStart += strlen(pszBaseOld); 109 } 110 111 rc = VINF_SUCCESS; 112 113 if (RT_SUCCESS(rc)) 114 { 115 char *pszPathNew = RTPathJoinA(strBaseNew.c_str(), pszPathStart); 116 if (pszPathNew) 117 { 118 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */, 119 pszPathNew /* pszPath */, 120 NULL /* pszQuery */, NULL /* pszFragment */); 121 if (pszPathURI) 122 { 123 #ifdef DEBUG_andy 124 LogFlowFunc(("Rebasing \"%s\" to \"%s\"", strPath.c_str(), pszPathURI)); 125 #endif 126 strPath = RTCString(pszPathURI) + "\r\n"; 127 RTStrFree(pszPathURI); 128 129 rc = VINF_SUCCESS; 130 } 131 else 132 rc = VERR_INVALID_PARAMETER; 133 134 RTStrFree(pszPathNew); 135 } 136 else 137 rc = VERR_NO_MEMORY; 138 } 139 } 140 else 141 rc = VERR_INVALID_PARAMETER; 142 143 #ifdef DEBUG_andy 144 LogFlowFuncLeaveRC(rc); 145 #endif 146 return rc; 147 } 148 149 int DnDURIObject::Read(void *pvBuf, uint32_t cbToRead, uint32_t *pcbRead) 150 { 151 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 152 AssertReturn(cbToRead, VERR_INVALID_PARAMETER); 153 /* pcbRead is optional. */ 154 155 int rc; 156 switch (m_Type) 157 { 158 case File: 159 { 160 if (!u.m_hFile) 161 { 162 /* Open files on the source with RTFILE_O_DENY_WRITE to prevent races 163 * where the OS writes to the file while the destination side transfers 164 * it over. */ 165 rc = RTFileOpen(&u.m_hFile, m_strSrcPath.c_str(), 166 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 167 } 168 else 169 rc = VINF_SUCCESS; 170 171 bool fDone = false; 172 if (RT_SUCCESS(rc)) 173 { 174 size_t cbRead; 175 rc = RTFileRead(u.m_hFile, pvBuf, cbToRead, &cbRead); 176 if (RT_SUCCESS(rc)) 177 { 178 if (pcbRead) 179 *pcbRead = (uint32_t)cbRead; 180 181 m_cbProcessed += cbRead; 182 Assert(m_cbProcessed <= m_cbSize); 183 184 /* End of file reached or error occurred? */ 185 if ( cbRead < cbToRead 186 || RT_FAILURE(rc)) 187 closeInternal(); 188 } 189 } 190 191 break; 192 } 193 194 case Directory: 195 { 196 rc = VINF_SUCCESS; 197 break; 198 } 199 200 default: 201 rc = VERR_NOT_IMPLEMENTED; 202 break; 203 } 204 205 LogFlowFunc(("Returning strSourcePath=%s, rc=%Rrc\n", 206 m_strSrcPath.c_str(), rc)); 207 return rc; 208 } 209 210 /*** */ 211 36 212 DnDURIList::DnDURIList(void) 37 213 : m_cbTotal(0) … … 47 223 { 48 224 AssertPtrReturn(pcszPath, VERR_INVALID_POINTER); 49 AssertReturn(cbBaseLen, VERR_INVALID_PARAMETER);50 225 51 226 RTFSOBJINFO objInfo; … … 74 249 return rc; 75 250 76 m_lstTree.append(DnDURIPath(pcszPath, &pcszPath[cbBaseLen], 77 objInfo.Attr.fMode, cbSize)); 251 m_lstTree.append(DnDURIObject( RTFS_IS_DIRECTORY(objInfo.Attr.fMode) 252 ? DnDURIObject::Directory 253 : DnDURIObject::File, 254 pcszPath, &pcszPath[cbBaseLen], 255 objInfo.Attr.fMode, cbSize)); 78 256 m_cbTotal += cbSize; 79 257 #ifdef DEBUG_andy 80 LogFlowFunc(("str HostPath=%s, strGuestPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",258 LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n", 81 259 pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cbTotal)); 82 260 #endif … … 140 318 break; 141 319 142 m_lstTree.append(DnDURIPath(pszNewFile, &pszNewFile[cbBaseLen], 143 objInfo1.Attr.fMode, cbSize)); 320 m_lstTree.append(DnDURIObject(DnDURIObject::File, 321 pszNewFile, &pszNewFile[cbBaseLen], 322 objInfo1.Attr.fMode, cbSize)); 144 323 m_cbTotal += cbSize; 145 324 #ifdef DEBUG_andy 146 LogFlowFunc(("str HostPath=%s, strGuestPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",325 LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n", 147 326 pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cbTotal)); 148 327 #endif … … 163 342 } 164 343 165 int DnDURIList::Append Path(const char *pszPath, uint32_t fFlags)344 int DnDURIList::AppendNativePath(const char *pszPath, uint32_t fFlags) 166 345 { 167 346 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 168 347 348 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/" /* pszAuthority */, 349 pszPath, NULL /* pszQuery */, NULL /* pszFragment */); 350 int rc; 351 if (pszPathURI) 352 { 353 rc = AppendURIPath(pszPathURI, fFlags); 354 RTStrFree(pszPathURI); 355 } 356 else 357 rc = VERR_INVALID_PARAMETER; 358 359 return rc; 360 } 361 362 int DnDURIList::AppendNativePathsFromList(const char *pszNativePaths, size_t cbNativePaths, 363 uint32_t fFlags) 364 { 365 AssertPtrReturn(pszNativePaths, VERR_INVALID_POINTER); 366 AssertReturn(cbNativePaths, VERR_INVALID_PARAMETER); 367 368 RTCList<RTCString> lstPaths 369 = RTCString(pszNativePaths, cbNativePaths - 1).split("\r\n"); 370 return AppendNativePathsFromList(lstPaths, fFlags); 371 } 372 373 int DnDURIList::AppendNativePathsFromList(const RTCList<RTCString> &lstNativePaths, 374 uint32_t fFlags) 375 { 376 int rc = VINF_SUCCESS; 377 378 for (size_t i = 0; i < lstNativePaths.size(); i++) 379 { 380 const RTCString &strPath = lstNativePaths.at(i); 381 rc = AppendNativePath(strPath.c_str(), fFlags); 382 if (RT_FAILURE(rc)) 383 break; 384 } 385 386 LogFlowFuncLeaveRC(rc); 387 return rc; 388 } 389 390 int DnDURIList::AppendURIPath(const char *pszURI, uint32_t fFlags) 391 { 392 AssertPtrReturn(pszURI, VERR_INVALID_POINTER); 393 169 394 #ifdef DEBUG_andy 170 LogFlowFunc(("pszPath=%s, fFlags=0x%x\n", psz Path, fFlags));395 LogFlowFunc(("pszPath=%s, fFlags=0x%x\n", pszURI, fFlags)); 171 396 #endif 172 397 int rc = VINF_SUCCESS; … … 174 399 /* Query the path component of a file URI. If this hasn't a 175 400 * file scheme NULL is returned. */ 176 char *pszFilePath = RTUriFilePath(psz Path, URI_FILE_FORMAT_AUTO);401 char *pszFilePath = RTUriFilePath(pszURI, URI_FILE_FORMAT_AUTO); 177 402 if (pszFilePath) 178 403 { … … 182 407 if (pszFileName) 183 408 { 184 char *pszNewURI = RTUriFileCreate(pszFileName); 185 if (pszNewURI) 186 { 187 m_lstRoot.append(pszNewURI); 188 RTStrFree(pszNewURI); 189 190 rc = appendPathRecursive(pszFilePath, 191 pszFileName - pszFilePath, 192 fFlags); 193 } 194 } 409 Assert(pszFileName >= pszFilePath); 410 char *pszRoot = &pszFilePath[pszFileName - pszFilePath]; 411 m_lstRoot.append(pszRoot); 412 #ifdef DEBUG_andy 413 LogFlowFunc(("pszFilePath=%s, pszFileName=%s, pszRoot=%s\n", 414 pszFilePath, pszFileName, pszRoot)); 415 #endif 416 rc = appendPathRecursive(pszFilePath, 417 pszFileName - pszFilePath, 418 fFlags); 419 } 420 else 421 rc = VERR_NOT_FOUND; 195 422 196 423 RTStrFree(pszFilePath); 197 424 } 198 else /* Just append the raw data. */199 m_lstRoot.append(pszPath);425 else 426 rc = VERR_INVALID_PARAMETER; 200 427 201 428 LogFlowFuncLeaveRC(rc); … … 203 430 } 204 431 205 int DnDURIList::AppendPathsFromList(const RTCList<RTCString> &lstURI, 206 uint32_t fFlags) 432 int DnDURIList::AppendURIPathsFromList(const char *pszURIPaths, size_t cbURIPaths, 433 uint32_t fFlags) 434 { 435 AssertPtrReturn(pszURIPaths, VERR_INVALID_POINTER); 436 AssertReturn(cbURIPaths, VERR_INVALID_PARAMETER); 437 438 RTCList<RTCString> lstPaths 439 = RTCString(pszURIPaths, cbURIPaths - 1).split("\r\n"); 440 return AppendURIPathsFromList(lstPaths, fFlags); 441 } 442 443 int DnDURIList::AppendURIPathsFromList(const RTCList<RTCString> &lstURI, 444 uint32_t fFlags) 207 445 { 208 446 int rc = VINF_SUCCESS; … … 210 448 for (size_t i = 0; i < lstURI.size(); i++) 211 449 { 212 const RTCString &strURI = lstURI.at(i); 213 rc = AppendPath(strURI.c_str(), fFlags); 450 RTCString strURI = lstURI.at(i); 451 rc = AppendURIPath(strURI.c_str(), fFlags); 452 214 453 if (RT_FAILURE(rc)) 215 454 break; … … 228 467 } 229 468 469 #if 0 470 int DnDURIList::FromData(const void *pvData, size_t cbData, 471 472 uint32_t fFlags) 473 { 474 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 475 AssertReturn(cbData, VERR_INVALID_PARAMETER); 476 477 RTCList<RTCString> lstURI = 478 RTCString(static_cast<const char*>(pvData), cbData - 1).split("\r\n"); 479 if (lstURI.isEmpty()) 480 return VINF_SUCCESS; 481 482 int rc = VINF_SUCCESS; 483 484 for (size_t i = 0; i < lstURI.size(); ++i) 485 { 486 const RTCString &strUri = lstURI.at(i); 487 /* Query the path component of a file URI. If this hasn't a 488 * file scheme, null is returned. */ 489 char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO); 490 if (pszFilePath) 491 { 492 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath)); 493 if (RT_SUCCESS(rc)) 494 { 495 /** @todo Use RTPathJoin? */ 496 RTCString strFullPath; 497 if (strBasePath.isNotEmpty()) 498 strFullPath = RTCString().printf("%s%c%s", strBasePath.c_str(), 499 RTPATH_SLASH, pszFilePath); 500 else 501 strFullPath = pszFilePath; 502 503 char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); 504 if (pszNewUri) 505 { 506 m_lstRoot.append(pszNewUri); 507 RTStrFree(pszNewUri); 508 } 509 } 510 } 511 else 512 rc = VERR_INVALID_PARAMETER; 513 514 if (RT_FAILURE(rc)) 515 break; 516 } 517 518 return rc; 519 } 520 #endif 521 230 522 void DnDURIList::RemoveFirst(void) 231 523 { 232 const DnDURIPath &curPath = m_lstTree.first(); 233 234 Assert(m_cbTotal >= curPath.m_cbSize); 235 m_cbTotal -= curPath.m_cbSize; /* Adjust total size. */ 524 DnDURIObject &curPath = m_lstTree.first(); 525 526 uint64_t cbSize = curPath.GetSize(); 527 Assert(m_cbTotal >= cbSize); 528 m_cbTotal -= cbSize; /* Adjust total size. */ 236 529 237 530 m_lstTree.removeFirst(); 238 531 } 239 532 533 int DnDURIList::RootFromURIData(const void *pvData, size_t cbData, 534 uint32_t fFlags) 535 { 536 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 537 AssertReturn(cbData, VERR_INVALID_PARAMETER); 538 539 RTCList<RTCString> lstURI = 540 RTCString(static_cast<const char*>(pvData), cbData - 1).split("\r\n"); 541 if (lstURI.isEmpty()) 542 return VINF_SUCCESS; 543 544 int rc = VINF_SUCCESS; 545 546 for (size_t i = 0; i < lstURI.size(); ++i) 547 { 548 /* Query the path component of a file URI. If this hasn't a 549 * file scheme, NULL is returned. */ 550 const char *pszURI = lstURI.at(i).c_str(); 551 char *pszFilePath = RTUriFilePath(pszURI, 552 URI_FILE_FORMAT_AUTO); 553 #ifdef DEBUG_andy 554 LogFlowFunc(("pszURI=%s, pszFilePath=%s\n", pszURI, pszFilePath)); 555 #endif 556 if (pszFilePath) 557 { 558 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath)); 559 if (RT_SUCCESS(rc)) 560 m_lstRoot.append(pszFilePath); 561 562 RTStrFree(pszFilePath); 563 } 564 else 565 rc = VERR_INVALID_PARAMETER; 566 567 if (RT_FAILURE(rc)) 568 break; 569 } 570 571 return rc; 572 } 573 574 RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */) 575 { 576 RTCString strRet; 577 for (size_t i = 0; i < m_lstRoot.size(); i++) 578 { 579 const char *pszCurRoot = m_lstRoot.at(i).c_str(); 580 if (strBasePath.isNotEmpty()) 581 { 582 char *pszPath = RTPathJoinA(strBasePath.c_str(), pszCurRoot); 583 if (pszPath) 584 { 585 char *pszPathURI = RTUriFileCreate(pszPath); 586 if (pszPathURI) 587 { 588 strRet += RTCString(pszPathURI) + "\r\n"; 589 RTStrFree(pszPathURI); 590 } 591 RTStrFree(pszPath); 592 } 593 else 594 break; 595 } 596 else 597 { 598 char *pszPathURI = RTUriFileCreate(pszCurRoot); 599 if (pszPathURI) 600 { 601 strRet += RTCString(pszPathURI) + "\r\n"; 602 RTStrFree(pszPathURI); 603 } 604 else 605 break; 606 } 607 } 608 609 return strRet; 610 } 611 -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r50477 r50508 49 49 public: 50 50 51 DnDHGSendDirPrivate(const RTCString &strPath, 52 uint32_t fMode, uint64_t cbSize, 51 DnDHGSendDirPrivate(DnDURIObject URIObject, 53 52 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 54 : m_strPath(strPath) 55 , m_cbSize(cbSize) 53 : m_URIObject(URIObject) 56 54 , m_pfnProgressCallback(pfnProgressCallback) 57 55 , m_pvProgressUser(pvProgressUser) 58 56 { 59 57 VBOXHGCMSVCPARM paTmpParms[3]; 60 paTmpParms[0].setString(m_ strPath.c_str());61 paTmpParms[1].setUInt32((uint32_t)(m_ strPath.length() + 1));62 paTmpParms[2].setUInt32( fMode);58 paTmpParms[0].setString(m_URIObject.GetDestPath().c_str()); 59 paTmpParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1)); 60 paTmpParms[2].setUInt32(m_URIObject.GetMode()); 63 61 64 62 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms); … … 71 69 if ( RT_SUCCESS(rc) 72 70 && m_pfnProgressCallback) 73 rc = m_pfnProgressCallback(m_ cbSize, m_pvProgressUser);71 rc = m_pfnProgressCallback(m_URIObject.GetSize(), m_pvProgressUser); 74 72 75 73 return rc; … … 77 75 78 76 protected: 79 RTCString m_strPath; 77 78 DnDURIObject m_URIObject; 80 79 81 80 /* Progress stuff */ 82 size_t m_cbSize;83 81 PFNDNDPRIVATEPROGRESS m_pfnProgressCallback; 84 82 void *m_pvProgressUser; … … 94 92 public: 95 93 96 DnDHGSendFilePrivate(const RTCString &strHostPath, 97 const RTCString &strGuestPath, 98 uint32_t fMode, uint64_t cbSize, 94 DnDHGSendFilePrivate(DnDURIObject URIObject, 99 95 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser); 100 96 virtual ~DnDHGSendFilePrivate(void); … … 103 99 104 100 protected: 105 RTCString m_strHostPath; 106 RTCString m_strGuestPath; 107 uint64_t m_cbFileSize; 108 uint64_t m_cbFileProcessed; 109 RTFILE m_hCurFile; 101 102 DnDURIObject m_URIObject; 110 103 VBOXHGCMSVCPARM m_paSkelParms[5]; 111 104 … … 144 137 145 138 /****************************************************************************** 146 * DnDHGSendFilePrivate *139 * DnDHGSendFilePrivate * 147 140 ******************************************************************************/ 148 141 149 DnDHGSendFilePrivate::DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath, 150 uint32_t fMode, uint64_t cbSize, 142 DnDHGSendFilePrivate::DnDHGSendFilePrivate(DnDURIObject URIObject, 151 143 PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser) 152 : m_strHostPath(strHostPath) 153 , m_strGuestPath(strGuestPath) 154 , m_cbFileSize(cbSize) 155 , m_cbFileProcessed(0) 156 , m_hCurFile(0) 144 : m_URIObject(URIObject) 157 145 , m_pfnProgressCallback(pfnProgressCallback) 158 146 , m_pvProgressUser(pvProgressUser) 159 147 { 160 m_paSkelParms[0].setString(m_ strGuestPath.c_str());161 m_paSkelParms[1].setUInt32((uint32_t)(m_ strGuestPath.length() + 1));148 m_paSkelParms[0].setString(m_URIObject.GetDestPath().c_str()); 149 m_paSkelParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1)); 162 150 m_paSkelParms[2].setPointer(NULL, 0); 163 151 m_paSkelParms[3].setUInt32(0); 164 m_paSkelParms[4].setUInt32( fMode);152 m_paSkelParms[4].setUInt32(m_URIObject.GetMode()); 165 153 166 154 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms); … … 169 157 DnDHGSendFilePrivate::~DnDHGSendFilePrivate(void) 170 158 { 171 if (m_hCurFile)172 RTFileClose(m_hCurFile);173 159 } 174 160 … … 184 170 return rc; 185 171 186 if (!m_hCurFile) 187 { 188 /* Open files on the host with RTFILE_O_DENY_WRITE to prevent races where the host 189 * writes to the file while the guest transfers it over. */ 190 rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(), 191 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 192 } 193 194 size_t cbRead; 172 uint32_t cbRead; 195 173 if (RT_SUCCESS(rc)) 196 174 { … … 200 178 void *pvBuf = paParms[2].u.pointer.addr; 201 179 AssertPtr(pvBuf); 202 rc = RTFileRead(m_hCurFile, pvBuf, cbToRead, &cbRead); 180 181 rc = m_URIObject.Read(pvBuf, cbToRead, &cbRead); 203 182 if (RT_LIKELY(RT_SUCCESS(rc))) 204 183 { 205 /* Advance. */206 m_cbFileProcessed += cbRead;207 Assert(m_cbFileProcessed <= m_cbFileSize);208 209 184 /* Tell the guest the actual size. */ 210 185 paParms[3].setUInt32((uint32_t)cbRead); … … 214 189 if (RT_SUCCESS(rc)) 215 190 { 216 /* Check if we are done. */ 217 Assert(m_cbFileProcessed <= m_cbFileSize); 218 bool fDone = m_cbFileSize == m_cbFileProcessed; 219 if (!fDone) 191 if (!m_URIObject.IsComplete()) 220 192 { 221 193 try 222 194 { 223 /* More data !Prepare the next message. */195 /* More data needed to send over. Prepare the next message. */ 224 196 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */, 225 197 m_paSkelParms); … … 236 208 { 237 209 rc = m_pfnProgressCallback(cbRead, m_pvProgressUser); 238 }239 240 if ( fDone241 || RT_FAILURE(rc))242 {243 RTFileClose(m_hCurFile);244 m_hCurFile = NIL_RTFILE;245 210 } 246 211 } … … 365 330 if (!lstURIOrg.isEmpty()) 366 331 { 367 rc = m_lstURI.Append PathsFromList(lstURIOrg, 0 /* fFlags */);332 rc = m_lstURI.AppendNativePathsFromList(lstURIOrg, 0 /* fFlags */); 368 333 if (RT_SUCCESS(rc)) 369 334 { 370 335 /* Add the total size of all meta data + files transferred to 371 * the message's total count. */336 * the message's total byte count. */ 372 337 m_cbTotal += m_lstURI.TotalBytes(); 373 338 374 339 /* 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 will376 * add the correct path again ,before sending the DnD drop event to340 * just decode the filename into the new data. The Guest Additions will 341 * add the correct path again before sending the DnD drop event to 377 342 * some window. */ 378 343 strNewURIs = m_lstURI.RootToString(); … … 445 410 /* Create new messages based on our internal path list. Currently 446 411 * this could be directories or regular files. */ 447 const DnDURI Path &nextPath= m_lstURI.First();412 const DnDURIObject &nextObj = m_lstURI.First(); 448 413 try 449 414 { 415 uint32_t fMode = nextObj.GetMode(); 450 416 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 455 if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) 456 m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strDstPath, 457 nextPath.m_fMode, nextPath.m_cbSize, 458 &DnDHGSendDataMessage::progressCallback, 417 nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str(), 418 fMode, nextObj.GetSize(), 419 RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode))); 420 421 if (RTFS_IS_DIRECTORY(fMode)) 422 m_pNextPathMsg = new DnDHGSendDirPrivate(nextObj, 423 &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, 459 424 this /* pvProgressUser */); 460 else if (RTFS_IS_FILE(nextPath.m_fMode)) 461 m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strSrcPath, nextPath.m_strDstPath, 462 nextPath.m_fMode, nextPath.m_cbSize, 463 &DnDHGSendDataMessage::progressCallback, 425 else if (RTFS_IS_FILE(fMode)) 426 m_pNextPathMsg = new DnDHGSendFilePrivate(nextObj, 427 &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, 464 428 this /* pvProgressUser */); 465 429 else 466 430 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.c_str()),431 fMode, nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str()), 468 432 VERR_NO_DATA); 469 433 -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r50463 r50508 169 169 } 170 170 171 void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 171 void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, 172 void *pvClient, uint32_t u32Function, 173 uint32_t cParms, VBOXHGCMSVCPARM paParms[]) 172 174 { 173 175 LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32\n", 174 176 u32ClientID, u32Function, cParms)); 175 177 176 int rc = VINF_SUCCESS; 178 /* Check if we've the right mode set. */ 179 bool fIgnoreRequest = true; /* Play safe. */ 177 180 switch (u32Function) 178 181 { 179 /* Note: Older VBox versions with enabled DnD guest->host support (< 4.4)180 * used the same ID (300) for GUEST_DND_GET_NEXT_HOST_MSG and181 * HOST_DND_GH_REQ_PENDING, which led this service returning182 * VERR_INVALID_PARAMETER when the guest wanted to actually183 * handle HOST_DND_GH_REQ_PENDING. */184 182 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG: 185 { 186 LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n")); 187 if ( cParms != 3 188 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */ 189 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* parameter count */ 190 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* blocking */) 191 rc = VERR_INVALID_PARAMETER; 183 if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF) 184 { 185 fIgnoreRequest = false; 186 } 192 187 else 193 { 194 rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32); 195 if ( RT_FAILURE(rc) 196 && paParms[2].u.uint32) /* Blocking? */ 197 { 198 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms)); 199 rc = VINF_HGCM_ASYNC_EXECUTE; 200 } 201 } 188 LogFlowFunc(("Drag'n drop disabled, ignoring request\n")); 202 189 break; 203 }204 190 case DragAndDropSvc::GUEST_DND_HG_ACK_OP: 205 { 206 LogFlowFunc(("GUEST_DND_HG_ACK_OP\n")); 207 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 208 && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST) 209 { 210 LogFlowFunc(("Wrong DnD mode, ignoring request\n")); 211 break; 212 } 213 214 if ( cParms != 1 215 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* action */) 216 rc = VERR_INVALID_PARAMETER; 191 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA: 192 if ( modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 193 || modeGet() == VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST) 194 { 195 fIgnoreRequest = false; 196 } 217 197 else 218 { 219 DragAndDropSvc::VBOXDNDCBHGACKOPDATA data; 220 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP; 221 paParms[0].getUInt32(&data.uAction); 222 if (m_pfnHostCallback) 223 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 224 // m_pHelpers->pfnCallComplete(callHandle, rc); 225 } 198 LogFlowFunc(("Host -> guest DnD mode disabled, ignoring request\n")); 226 199 break; 227 }228 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:229 {230 LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n"));231 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL232 && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)233 {234 LogFlowFunc(("Wrong DnD mode, ignoring request\n"));235 break;236 }237 238 if ( cParms != 1239 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */)240 rc = VERR_INVALID_PARAMETER;241 else242 {243 DragAndDropSvc::VBOXDNDCBHGREQDATADATA data;244 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA;245 uint32_t cTmp;246 paParms[0].getPointer((void**)&data.pszFormat, &cTmp);247 if (m_pfnHostCallback)248 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));249 // m_pHelpers->pfnCallComplete(callHandle, rc);250 // if (data.pszFormat)251 // RTMemFree(data.pszFormat);252 // if (data.pszTmpPath)253 // RTMemFree(data.pszTmpPath);254 }255 break;256 }257 200 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 258 201 case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING: 259 { 260 LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n")); 261 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 262 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 263 { 264 LogFlowFunc(("Wrong DnD mode, ignoring request\n")); 265 break; 266 } 267 268 if ( cParms != 3 269 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* defaction */ 270 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* allactions */ 271 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* format */) 272 rc = VERR_INVALID_PARAMETER; 202 case DragAndDropSvc::GUEST_DND_GH_SND_DATA: 203 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 204 case DragAndDropSvc::GUEST_DND_GH_SND_FILE: 205 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR: 206 if ( modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 207 || modeGet() == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST) 208 { 209 fIgnoreRequest = false; 210 } 273 211 else 274 { 275 DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA data; 276 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING; 277 paParms[0].getUInt32(&data.uDefAction); 278 paParms[1].getUInt32(&data.uAllActions); 279 uint32_t cTmp; 280 paParms[2].getPointer((void**)&data.pszFormat, &cTmp); 281 if (m_pfnHostCallback) 282 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 283 } 212 LogFlowFunc(("Guest -> host DnD mode disabled, ignoring request\n")); 284 213 break; 285 }286 case DragAndDropSvc::GUEST_DND_GH_SND_DATA:287 {288 LogFlowFunc(("GUEST_DND_GH_SND_DATA\n"));289 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL290 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)291 {292 LogFlowFunc(("Wrong DnD mode, ignoring request\n"));293 break;294 }295 296 if ( cParms != 2297 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* data */298 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)299 rc = VERR_INVALID_PARAMETER;300 else301 {302 DragAndDropSvc::VBOXDNDCBSNDDATADATA data;303 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA;304 paParms[0].getPointer((void**)&data.pvData, &data.cbData);305 paParms[1].getUInt32(&data.cbAllSize);306 if (m_pfnHostCallback)307 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));308 }309 break;310 }311 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:312 {313 LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n"));314 if ( modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL315 && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)316 {317 LogFlowFunc(("Wrong DnD mode, ignoring request\n"));318 break;319 }320 321 if ( cParms != 1322 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */)323 rc = VERR_INVALID_PARAMETER;324 else325 {326 DragAndDropSvc::VBOXDNDCBEVTERRORDATA data;327 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR;328 uint32_t rcOp;329 paParms[0].getUInt32(&rcOp);330 data.rc = rcOp;331 if (m_pfnHostCallback)332 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));333 }334 break;335 }336 214 #endif 337 215 default: 216 /* Reach through to DnD manager. */ 217 fIgnoreRequest = false; 218 break; 219 } 220 221 int rc; 222 if (!fIgnoreRequest) 223 { 224 rc = VINF_SUCCESS; 225 switch (u32Function) 338 226 { 339 /* All other messages are handled by the DnD manager. */ 340 rc = m_pManager->nextMessage(u32Function, cParms, paParms); 341 break; 227 /* Note: Older VBox versions with enabled DnD guest->host support (< 4.4) 228 * used the same message ID (300) for GUEST_DND_GET_NEXT_HOST_MSG and 229 * HOST_DND_GH_REQ_PENDING, which led this service returning 230 * VERR_INVALID_PARAMETER when the guest wanted to actually 231 * handle HOST_DND_GH_REQ_PENDING. */ 232 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG: 233 { 234 LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n")); 235 if ( cParms != 3 236 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */ 237 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* parameter count */ 238 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* blocking */) 239 rc = VERR_INVALID_PARAMETER; 240 else 241 { 242 rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32); 243 if ( RT_FAILURE(rc) 244 && paParms[2].u.uint32) /* Blocking? */ 245 { 246 m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms)); 247 rc = VINF_HGCM_ASYNC_EXECUTE; 248 } 249 } 250 break; 251 } 252 case DragAndDropSvc::GUEST_DND_HG_ACK_OP: 253 { 254 LogFlowFunc(("GUEST_DND_HG_ACK_OP\n")); 255 if ( cParms != 1 256 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* action */) 257 rc = VERR_INVALID_PARAMETER; 258 else 259 { 260 DragAndDropSvc::VBOXDNDCBHGACKOPDATA data; 261 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP; 262 paParms[0].getUInt32(&data.uAction); 263 if (m_pfnHostCallback) 264 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 265 // m_pHelpers->pfnCallComplete(callHandle, rc); 266 } 267 break; 268 } 269 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA: 270 { 271 LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n")); 272 if ( cParms != 1 273 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */) 274 rc = VERR_INVALID_PARAMETER; 275 else 276 { 277 DragAndDropSvc::VBOXDNDCBHGREQDATADATA data; 278 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA; 279 uint32_t cTmp; 280 paParms[0].getPointer((void**)&data.pszFormat, &cTmp); 281 if (m_pfnHostCallback) 282 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 283 // m_pHelpers->pfnCallComplete(callHandle, rc); 284 // if (data.pszFormat) 285 // RTMemFree(data.pszFormat); 286 // if (data.pszTmpPath) 287 // RTMemFree(data.pszTmpPath); 288 } 289 break; 290 } 291 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 292 case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING: 293 { 294 LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n")); 295 if ( cParms != 3 296 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* defaction */ 297 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* allactions */ 298 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* format */) 299 rc = VERR_INVALID_PARAMETER; 300 else 301 { 302 DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA data; 303 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING; 304 paParms[0].getUInt32(&data.uDefAction); 305 paParms[1].getUInt32(&data.uAllActions); 306 uint32_t cTmp; 307 paParms[2].getPointer((void**)&data.pszFormat, &cTmp); 308 if (m_pfnHostCallback) 309 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 310 } 311 break; 312 } 313 case DragAndDropSvc::GUEST_DND_GH_SND_DATA: 314 { 315 LogFlowFunc(("GUEST_DND_GH_SND_DATA\n")); 316 if ( cParms != 2 317 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 318 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 319 rc = VERR_INVALID_PARAMETER; 320 else 321 { 322 DragAndDropSvc::VBOXDNDCBSNDDATADATA data; 323 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA; 324 paParms[0].getPointer((void**)&data.pvData, &data.cbData); 325 paParms[1].getUInt32(&data.cbTotalSize); 326 if (m_pfnHostCallback) 327 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 328 } 329 break; 330 } 331 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 332 { 333 LogFlowFunc(("GUEST_DND_GH_SND_DIR\n")); 334 if ( cParms != 3 335 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */ 336 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* path length */ 337 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */) 338 rc = VERR_INVALID_PARAMETER; 339 else 340 { 341 DragAndDropSvc::VBOXDNDCBSNDDIRDATA data; 342 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR; 343 uint32_t cTmp; 344 paParms[0].getPointer((void**)&data.pszPath, &cTmp); 345 paParms[1].getUInt32(&data.cbPath); 346 paParms[2].getUInt32(&data.fMode); 347 #ifdef DEBUG_andy 348 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", 349 data.pszPath, data.cbPath, data.fMode)); 350 #endif 351 if (m_pfnHostCallback) 352 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 353 } 354 break; 355 } 356 case DragAndDropSvc::GUEST_DND_GH_SND_FILE: 357 { 358 LogFlowFunc(("GUEST_DND_GH_SND_FILE\n")); 359 if ( cParms != 5 360 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* file path */ 361 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* file path length */ 362 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* file data */ 363 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* file data length */ 364 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */) 365 rc = VERR_INVALID_PARAMETER; 366 else 367 { 368 DragAndDropSvc::VBOXDNDCBSNDFILEDATA data; 369 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE; 370 uint32_t cTmp; 371 paParms[0].getPointer((void**)&data.pszFilePath, &cTmp); 372 paParms[1].getUInt32(&data.cbFilePath); 373 paParms[2].getPointer((void**)&data.pvData, &data.cbData); 374 /* paParms[3] is cbData. */ 375 paParms[4].getUInt32(&data.fMode); 376 #ifdef DEBUG_andy 377 LogFlowFunc(("pszFilePath=%s, cbData=%RU32, pvData=0x%p, fMode=0x%x\n", 378 data.pszFilePath, data.cbData, data.pvData, data.fMode)); 379 #endif 380 if (m_pfnHostCallback) 381 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 382 } 383 break; 384 } 385 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR: 386 { 387 LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n")); 388 if ( cParms != 1 389 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */) 390 rc = VERR_INVALID_PARAMETER; 391 else 392 { 393 DragAndDropSvc::VBOXDNDCBEVTERRORDATA data; 394 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR; 395 uint32_t rcOp; 396 paParms[0].getUInt32(&rcOp); 397 data.rc = rcOp; 398 if (m_pfnHostCallback) 399 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 400 } 401 break; 402 } 403 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 404 default: 405 { 406 /* All other messages are handled by the DnD manager. */ 407 rc = m_pManager->nextMessage(u32Function, cParms, paParms); 408 break; 409 } 342 410 } 343 411 } 412 else 413 rc = VERR_NOT_SUPPORTED; 414 344 415 /* If async execute is requested, we didn't notify the guest about 345 416 * completion. The client is queued into the waiters list and will be -
trunk/src/VBox/Main/include/GuestDnDImpl.h
r42866 r50508 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 … … 20 20 /* Forward declaration of the d-pointer. */ 21 21 class GuestDnDPrivate; 22 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 23 class DnDGuestResponse; 24 #endif 22 25 23 26 class GuestDnD … … 42 45 static DECLCALLBACK(int) notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms); 43 46 47 protected: 48 49 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 50 int onGHSendData(DnDGuestResponse *pResp, const void *pvData, size_t cbData, size_t cbTotalSize); 51 int onGHSendDir(DnDGuestResponse *pResp, const char *pszPath, size_t cbPath, uint32_t fMode); 52 int onGHSendFile(DnDGuestResponse *pResp, const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode); 53 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 54 44 55 private: 45 56 -
trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
r50460 r50508 191 191 Utf8Str format(void) const { return m_strFormat; } 192 192 193 int dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize); 193 void setDropDir(const Utf8Str &strDropDir) { m_strDropDir = strDropDir; } 194 Utf8Str dropDir(void) const { return m_strDropDir; } 195 196 int dataAdd(const void *pvData, uint32_t cbData, uint32_t *pcbCurSize); 197 int dataSetStatus(size_t cbDataAdd, size_t cbDataTotal = 0); 194 198 void reset(void); 195 199 const void *data(void) { return m_pvData; } … … 205 209 uint32_t m_allActions; 206 210 Utf8Str m_strFormat; 211 212 /** The actual MIME data.*/ 207 213 void *m_pvData; 214 /** Size (in bytes) of MIME data. */ 208 215 uint32_t m_cbData; 216 217 size_t m_cbDataCurrent; 218 size_t m_cbDataTotal; 219 /** Dropped files directory on the host. */ 220 Utf8Str m_strDropDir; 209 221 210 222 ComObjPtr<Guest> m_parent; … … 276 288 , m_pvData(0) 277 289 , m_cbData(0) 290 , m_cbDataCurrent(0) 291 , m_cbDataTotal(0) 278 292 , m_parent(pGuest) 279 293 { … … 303 317 } 304 318 305 int DnDGuestResponse::dataAdd(void *pvData, uint32_t cbData, uint32_t *pcbCurSize) 306 { 319 int DnDGuestResponse::dataAdd(const void *pvData, uint32_t cbData, 320 uint32_t *pcbCurSize) 321 { 322 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 323 AssertReturn(cbData, VERR_INVALID_PARAMETER); 324 /* pcbCurSize is optional. */ 325 307 326 int rc = VINF_SUCCESS; 308 327 … … 348 367 } 349 368 350 int DnDGuestResponse::setProgress(unsigned uPercentage, uint32_t uState, int rcOp /* = VINF_SUCCESS */) 351 { 352 LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", uPercentage, uState, rcOp)); 369 int DnDGuestResponse::setProgress(unsigned uPercentage, 370 uint32_t uState, int rcOp /* = VINF_SUCCESS */) 371 { 372 LogFlowFunc(("uPercentage=%RU32, uState=%ld, rcOp=%Rrc\n", 373 uPercentage, uState, rcOp)); 353 374 354 375 int vrc = VINF_SUCCESS; … … 364 385 COM_IIDOF(IGuest), 365 386 m_parent->getComponentName(), 366 m_parent->tr(" Guest error (%Rrc)"), rcOp);387 m_parent->tr("Drag'n drop guest error (%Rrc)"), rcOp); 367 388 } 368 389 else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED) … … 390 411 } 391 412 413 int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */) 414 { 415 if (cbDataTotal) 416 { 417 AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size size must not be smaller (%zu) than old value (%zu)\n", 418 cbDataTotal, m_cbDataTotal)); 419 m_cbDataTotal = cbDataTotal; 420 LogFlowFunc(("Updating total data size to: %zu\n", m_cbDataTotal)); 421 } 422 AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n")); 423 424 m_cbDataCurrent += cbDataAdd; 425 unsigned int cPercentage = RT_MIN(m_cbDataCurrent * 100.0 / m_cbDataTotal, 100); 426 427 /** @todo Don't use anonymous enums (uint32_t). */ 428 uint32_t uStatus = DragAndDropSvc::DND_PROGRESS_RUNNING; 429 if (m_cbDataCurrent >= m_cbDataTotal) 430 uStatus = DragAndDropSvc::DND_PROGRESS_COMPLETE; 431 432 #ifdef DEBUG_andy 433 LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n", 434 m_cbDataCurrent, m_cbDataTotal, uStatus)); 435 #endif 436 437 AssertMsg(m_cbDataCurrent <= m_cbDataTotal, 438 ("More data transferred (%RU32) than initially announced (%RU32)\n", 439 m_cbDataCurrent, m_cbDataTotal)); 440 441 int rc = setProgress(cPercentage, uStatus); 442 443 /** @todo For now we instantly confirm the cancel. Check if the 444 * guest should first clean up stuff itself and than really confirm 445 * the cancel request by an extra message. */ 446 if (rc == VERR_CANCELLED) 447 rc = setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); 448 449 return rc; 450 } 451 392 452 HRESULT DnDGuestResponse::queryProgressTo(IProgress **ppProgress) 393 453 { … … 503 563 504 564 /* static */ 505 void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction, ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), uint32_t *pOutAllowedActions) 565 void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction, 566 uint32_t *pOutDefAction, 567 ComSafeArrayIn(DragAndDropAction_T, inAllowedActions), 568 uint32_t *pOutAllowedActions) 506 569 { 507 570 const com::SafeArray<DragAndDropAction_T> sfaInActions(ComSafeArrayInArg(inAllowedActions)); … … 529 592 DragAndDropAction_T GuestDnDPrivate::toMainAction(uint32_t uAction) 530 593 { 531 /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */ 594 /* For now it doesn't seems useful to allow a 595 * link action between host & guest. Maybe later! */ 532 596 return (isDnDCopyAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Copy : 533 597 isDnDMoveAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Move : … … 536 600 537 601 /* static */ 538 void GuestDnDPrivate::toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions)) 539 { 540 /* For now it doesn't seems useful to allow a link action between host & guest. Maybe later! */ 602 void GuestDnDPrivate::toMainActions(uint32_t uActions, 603 ComSafeArrayOut(DragAndDropAction_T, actions)) 604 { 605 /* For now it doesn't seems useful to allow a 606 * link action between host & guest. Maybe later! */ 541 607 RTCList<DragAndDropAction_T> list; 542 608 if (hasDnDCopyAction(uActions)) … … 556 622 } 557 623 558 GuestDnD::~GuestDnD( )624 GuestDnD::~GuestDnD(void) 559 625 { 560 626 delete d_ptr; 561 627 } 562 628 563 HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 629 HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, 630 DragAndDropAction_T defaultAction, 631 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 632 ComSafeArrayIn(IN_BSTR, formats), 633 DragAndDropAction_T *pResultAction) 564 634 { 565 635 DPTR(GuestDnD); … … 621 691 } 622 692 623 HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction) 693 HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, 694 DragAndDropAction_T defaultAction, 695 ComSafeArrayIn(DragAndDropAction_T, allowedActions), 696 ComSafeArrayIn(IN_BSTR, formats), 697 DragAndDropAction_T *pResultAction) 624 698 { 625 699 DPTR(GuestDnD); … … 879 953 880 954 const char *pcszFormat = strFormat.c_str(); 881 LogFlowFunc(("strFormat=%s, uAction=0x%x\n", pcszFormat, uAction)); 882 if (DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat))) 955 bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat)); 956 LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n", 957 pcszFormat, uAction, fNeedsDropDir)); 958 959 DnDGuestResponse *pDnD = d->response(); 960 AssertPtr(pDnD); 961 962 if (fNeedsDropDir) 883 963 { 884 964 char szDropDir[RTPATH_MAX]; … … 889 969 szDropDir, rc); 890 970 LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir)); 971 972 pDnD->setDropDir(szDropDir); 891 973 } 892 974 … … 899 981 paParms[i++].setUInt32(uAction); 900 982 901 DnDGuestResponse *pDnD = d->response();902 903 983 /* Reset any old data and the progress status. */ 904 984 pDnD->reset(); … … 925 1005 const ComObjPtr<Guest> &p = d->p; 926 1006 927 HRESULT rc= S_OK;928 929 DnDGuestResponse *p DnD= d->response();930 if (p DnD)1007 HRESULT hr = S_OK; 1008 1009 DnDGuestResponse *pResp = d->response(); 1010 if (pResp) 931 1011 { 932 1012 com::SafeArray<BYTE> sfaData; 933 1013 934 uint32_t cbData = pDnD->size();1014 size_t cbData = pResp->size(); 935 1015 if (cbData) 936 1016 { 937 /* Copy the data into a safe array of bytes. */ 938 const void *pvData = pDnD->data(); 939 if (sfaData.resize(cbData)) 940 memcpy(sfaData.raw(), pvData, cbData); 1017 const void *pvData = pResp->data(); 1018 AssertPtr(pvData); 1019 1020 Utf8Str strFormat = pResp->format(); 1021 LogFlowFunc(("strFormat=%s, strDropDir=%s\n", 1022 strFormat.c_str(), pResp->dropDir().c_str())); 1023 1024 if (DnDMIMEHasFileURLs(strFormat.c_str(), strFormat.length())) 1025 { 1026 DnDURIList lstURI; 1027 int rc2 = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */); 1028 if (RT_SUCCESS(rc2)) 1029 { 1030 Utf8Str strURIs = lstURI.RootToString(pResp->dropDir()); 1031 if (sfaData.resize(strURIs.length())) 1032 memcpy(sfaData.raw(), strURIs.c_str(), strURIs.length()); 1033 else 1034 hr = E_OUTOFMEMORY; 1035 } 1036 else 1037 hr = VBOX_E_IPRT_ERROR; 1038 1039 LogFlowFunc(("Found %zu root URIs, rc=%Rrc\n", lstURI.RootCount(), rc2)); 1040 } 941 1041 else 942 rc = E_OUTOFMEMORY; 1042 { 1043 /* Copy the data into a safe array of bytes. */ 1044 if (sfaData.resize(cbData)) 1045 memcpy(sfaData.raw(), pvData, cbData); 1046 else 1047 hr = E_OUTOFMEMORY; 1048 } 943 1049 } 944 1050 945 #ifdef DEBUG_andy 946 LogFlowFunc(("Received %RU32 bytes\n", cbData)); 947 #endif 1051 LogFlowFunc(("cbData=%zu\n", cbData)); 1052 948 1053 /* Detach in any case, regardless of data size. */ 949 1054 sfaData.detachTo(ComSafeArrayOutArg(data)); 950 1055 951 1056 /* Delete the data. */ 952 p DnD->reset();1057 pResp->reset(); 953 1058 } 954 1059 else 955 rc = VBOX_E_INVALID_OBJECT_STATE; 956 1060 hr = VBOX_E_INVALID_OBJECT_STATE; 1061 1062 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); 1063 return hr; 1064 } 1065 1066 int GuestDnD::onGHSendData(DnDGuestResponse *pResp, 1067 const void *pvData, size_t cbData, 1068 size_t cbTotalSize) 1069 { 1070 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1071 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1072 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1073 AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER); 1074 1075 int rc = pResp->dataAdd(pvData, cbData, NULL /* Current size */); 1076 if (RT_SUCCESS(rc)) 1077 rc = pResp->dataSetStatus(cbData, cbTotalSize); 1078 1079 LogFlowFuncLeaveRC(rc); 957 1080 return rc; 958 1081 } 1082 1083 int GuestDnD::onGHSendDir(DnDGuestResponse *pResp, 1084 const char *pszPath, size_t cbPath, 1085 uint32_t fMode) 1086 { 1087 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1088 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 1089 AssertReturn(cbPath, VERR_INVALID_PARAMETER); 1090 1091 LogFlowFunc(("strDir=%s, cbPath=%zu, fMode=0x%x\n", 1092 pszPath, cbPath, fMode)); 1093 1094 int rc; 1095 char *pszDir = RTPathJoinA(pResp->dropDir().c_str(), pszPath); 1096 if (pszDir) 1097 { 1098 rc = RTDirCreateFullPath(pszDir, fMode); 1099 RTStrFree(pszDir); 1100 } 1101 else 1102 rc = VERR_NO_MEMORY; 1103 1104 if (RT_SUCCESS(rc)) 1105 rc = pResp->dataSetStatus(cbPath); 1106 1107 LogFlowFuncLeaveRC(rc); 1108 return rc; 1109 } 1110 1111 int GuestDnD::onGHSendFile(DnDGuestResponse *pResp, 1112 const char *pszPath, size_t cbPath, 1113 void *pvData, size_t cbData, uint32_t fMode) 1114 { 1115 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 1116 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 1117 AssertReturn(cbPath, VERR_INVALID_PARAMETER); 1118 1119 LogFlowFunc(("strFile=%s, cbPath=%zu, fMode=0x%x\n", 1120 pszPath, cbPath, fMode)); 1121 1122 /** @todo Add file locking between calls! */ 1123 int rc; 1124 char *pszFile = RTPathJoinA(pResp->dropDir().c_str(), pszPath); 1125 if (pszFile) 1126 { 1127 RTFILE hFile; 1128 rc = RTFileOpen(&hFile, pszFile, 1129 RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE); 1130 if (RT_SUCCESS(rc)) 1131 { 1132 rc = RTFileWrite(hFile, pvData, cbData, 1133 NULL /* No partial writes */); 1134 RTFileClose(hFile); 1135 } 1136 RTStrFree(pszFile); 1137 } 1138 else 1139 rc = VERR_NO_MEMORY; 1140 1141 if (RT_SUCCESS(rc)) 1142 rc = pResp->dataSetStatus(cbData); 1143 1144 LogFlowFuncLeaveRC(rc); 1145 return rc; 1146 } 959 1147 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */ 960 1148 961 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms) 1149 /* static */ 1150 DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, 1151 void *pvParms, uint32_t cbParms) 962 1152 { 963 1153 LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n", … … 967 1157 if (!pGuest->m_pGuestDnD) 968 1158 return VINF_SUCCESS; 1159 1160 GuestDnD *pGuestDnD = pGuest->m_pGuestDnD; 1161 AssertPtr(pGuestDnD); 969 1162 970 1163 GuestDnDPrivate *d = static_cast<GuestDnDPrivate*>(pGuest->m_pGuestDnD->d_ptr); … … 984 1177 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER); 985 1178 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1179 986 1180 pResp->setDefAction(pCBData->uAction); 1181 987 1182 rc = pResp->notifyAboutGuestResponse(); 988 1183 break; … … 995 1190 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER); 996 1191 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1192 997 1193 pResp->setFormat(pCBData->pszFormat); 1194 998 1195 rc = pResp->notifyAboutGuestResponse(); 999 1196 break; … … 1006 1203 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER); 1007 1204 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1205 1008 1206 rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc); 1009 1207 break; … … 1017 1215 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER); 1018 1216 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1217 1019 1218 pResp->setFormat(pCBData->pszFormat); 1020 1219 pResp->setDefAction(pCBData->uDefAction); 1021 1220 pResp->setAllActions(pCBData->uAllActions); 1221 1022 1222 rc = pResp->notifyAboutGuestResponse(); 1023 1223 break; … … 1031 1231 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1032 1232 1033 uint32_t cbCurSize = 0; 1034 rc = pResp->dataAdd(pCBData->pvData, pCBData->cbData, &cbCurSize); 1035 if (RT_SUCCESS(rc)) 1036 { 1037 /** @todo Store pCBData->cbAllSize in the guest's response struct 1038 * if not set already. */ 1039 uint32_t cbTotalSize = pCBData->cbAllSize; 1040 unsigned int cPercentage; 1041 if (!cbTotalSize) /* Watch out for division by zero. */ 1042 cPercentage = 100; 1043 else 1044 cPercentage = cbCurSize * 100.0 / cbTotalSize; 1045 1046 /** @todo Don't use anonymous enums. */ 1047 uint32_t uState = DragAndDropSvc::DND_PROGRESS_RUNNING; 1048 if ( cbTotalSize == cbCurSize 1049 /* Empty data? Should not happen, but anyway ... */ 1050 || !cbTotalSize) 1051 { 1052 uState = DragAndDropSvc::DND_PROGRESS_COMPLETE; 1053 } 1054 1055 rc = pResp->setProgress(cPercentage, uState); 1056 } 1057 1058 /** @todo For now we instantly confirm the cancel. Check if the 1059 * guest should first clean up stuff itself and than really confirm 1060 * the cancel request by an extra message. */ 1061 if (rc == VERR_CANCELLED) 1062 pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED); 1233 rc = pGuestDnD->onGHSendData(pResp, pCBData->pvData, pCBData->cbData, 1234 pCBData->cbTotalSize); 1235 break; 1236 } 1237 1238 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 1239 { 1240 DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms); 1241 AssertPtr(pCBData); 1242 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER); 1243 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1244 1245 rc = pGuestDnD->onGHSendDir(pResp, pCBData->pszPath, pCBData->cbPath, pCBData->fMode); 1246 break; 1247 } 1248 1249 case DragAndDropSvc::GUEST_DND_GH_SND_FILE: 1250 { 1251 DragAndDropSvc::PVBOXDNDCBSNDFILEDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATA>(pvParms); 1252 AssertPtr(pCBData); 1253 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDFILEDATA) == cbParms, VERR_INVALID_PARAMETER); 1254 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1255 1256 rc = pGuestDnD->onGHSendFile(pResp, pCBData->pszFilePath, pCBData->cbFilePath, 1257 pCBData->pvData, pCBData->cbData, pCBData->fMode); 1063 1258 break; 1064 1259 } … … 1071 1266 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1072 1267 1073 /* Cleanup */1268 /* Cleanup. */ 1074 1269 pResp->reset(); 1075 1270 rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc); -
trunk/src/VBox/Runtime/common/misc/uri.cpp
r49996 r50508 137 137 szNum[1] = pszString[iIn++]; 138 138 szNum[2] = '\0'; 139 139 140 140 uint8_t u8; 141 141 rc = RTStrToUInt8Ex(szNum, NULL, 16, &u8); … … 654 654 { 655 655 uint32_t uFIntern = uFormat; 656 /* Auto is based on the current hostOS. */656 /* Auto is based on the current OS. */ 657 657 if (uFormat == URI_FILE_FORMAT_AUTO) 658 658 #ifdef RT_OS_WINDOWS
Note:
See TracChangeset
for help on using the changeset viewer.

