Changeset 58212 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
- Timestamp:
- Oct 13, 2015 11:49:33 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r58183 r58212 48 48 #include <VBox/HostServices/DragAndDropSvc.h> 49 49 50 using namespace DragAndDropSvc; 51 50 52 #include "VBGLR3Internal.h" 51 53 52 /* Here all the communication with the host over HGCM is handled platform53 * neutral. Also the receiving of URIs content (directory trees and files) is54 * done here. So the platform code of the guests, should not take care of that.55 *56 * Todo:57 * - Sending dirs/files in the G->H case58 * - Maybe the EOL converting of text MIME types (not fully sure, eventually59 * better done on the host side)60 */61 62 63 54 /********************************************************************************************************************************* 64 * Private internal functions*55 * Forward declarations * 65 56 *********************************************************************************************************************************/ 66 57 67 static int vbglR3DnDQueryNextHostMessageType(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t *puMsg, uint32_t *pcParms, bool fWait) 58 VBGLR3DECL(int) VbglR3DnDHGSendProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr); 59 60 /********************************************************************************************************************************* 61 * Private internal functions * 62 *********************************************************************************************************************************/ 63 64 static int vbglR3DnDGetNextMsgType(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t *puMsg, uint32_t *pcParms, bool fWait) 68 65 { 69 66 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 71 68 AssertPtrReturn(pcParms, VERR_INVALID_POINTER); 72 69 73 DragAndDropSvc::VBOXDNDNEXTMSGMSG Msg;70 VBOXDNDNEXTMSGMSG Msg; 74 71 RT_ZERO(Msg); 75 72 Msg.hdr.result = VERR_WRONG_ORDER; 76 73 Msg.hdr.u32ClientID = pCtx->uClientID; 77 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG;74 Msg.hdr.u32Function = GUEST_DND_GET_NEXT_HOST_MSG; 78 75 Msg.hdr.cParms = 3; 79 76 80 Msg. msg.SetUInt32(0);81 Msg. num_parms.SetUInt32(0);82 Msg. block.SetUInt32(fWait ? 1 : 0);77 Msg.uMsg.SetUInt32(0); 78 Msg.cParms.SetUInt32(0); 79 Msg.fBlock.SetUInt32(fWait ? 1 : 0); 83 80 84 81 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 88 85 if (RT_SUCCESS(rc)) 89 86 { 90 rc = Msg.msg.GetUInt32(puMsg); AssertRC(rc); 91 rc = Msg.num_parms.GetUInt32(pcParms); AssertRC(rc); 92 } 93 } 94 95 return rc; 96 } 97 98 static int vbglR3DnDHGProcessActionMessage(PVBGLR3GUESTDNDCMDCTX pCtx, 99 uint32_t uMsg, 100 uint32_t *puScreenId, 101 uint32_t *puX, 102 uint32_t *puY, 103 uint32_t *puDefAction, 104 uint32_t *puAllActions, 105 char *pszFormats, 106 uint32_t cbFormats, 107 uint32_t *pcbFormatsRecv) 87 rc = Msg.uMsg.GetUInt32(puMsg); AssertRC(rc); 88 rc = Msg.cParms.GetUInt32(pcParms); AssertRC(rc); 89 } 90 } 91 92 return rc; 93 } 94 95 /** @todo r=andy Clean up the parameter list. */ 96 static int vbglR3DnDHGRecvAction(PVBGLR3GUESTDNDCMDCTX pCtx, 97 uint32_t uMsg, 98 uint32_t *puScreenId, 99 uint32_t *puX, 100 uint32_t *puY, 101 uint32_t *puDefAction, 102 uint32_t *puAllActions, 103 char *pszFormats, 104 uint32_t cbFormats, 105 uint32_t *pcbFormatsRecv) 108 106 { 109 107 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 117 115 AssertPtrReturn(pcbFormatsRecv, VERR_INVALID_POINTER); 118 116 119 DragAndDropSvc::VBOXDNDHGACTIONMSG Msg;117 VBOXDNDHGACTIONMSG Msg; 120 118 RT_ZERO(Msg); 119 Msg.hdr.result = VERR_WRONG_ORDER; 121 120 Msg.hdr.u32ClientID = pCtx->uClientID; 122 121 Msg.hdr.u32Function = uMsg; … … 151 150 } 152 151 153 static int vbglR3DnDHG ProcessLeaveMessage(PVBGLR3GUESTDNDCMDCTX pCtx)152 static int vbglR3DnDHGRecvLeave(PVBGLR3GUESTDNDCMDCTX pCtx) 154 153 { 155 154 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 156 155 157 DragAndDropSvc::VBOXDNDHGLEAVEMSG Msg;156 VBOXDNDHGLEAVEMSG Msg; 158 157 RT_ZERO(Msg); 159 158 Msg.hdr.u32ClientID = pCtx->uClientID; 160 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_LEAVE;159 Msg.hdr.u32Function = HOST_DND_HG_EVT_LEAVE; 161 160 Msg.hdr.cParms = 0; 162 161 … … 168 167 } 169 168 170 static int vbglR3DnDHG ProcessCancelMessage(PVBGLR3GUESTDNDCMDCTX pCtx)169 static int vbglR3DnDHGRecvCancel(PVBGLR3GUESTDNDCMDCTX pCtx) 171 170 { 172 171 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 173 172 174 DragAndDropSvc::VBOXDNDHGCANCELMSG Msg;173 VBOXDNDHGCANCELMSG Msg; 175 174 RT_ZERO(Msg); 175 Msg.hdr.result = VERR_WRONG_ORDER; 176 176 Msg.hdr.u32ClientID = pCtx->uClientID; 177 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_EVT_CANCEL;177 Msg.hdr.u32Function = HOST_DND_HG_EVT_CANCEL; 178 178 Msg.hdr.cParms = 0; 179 179 … … 185 185 } 186 186 187 static int vbglR3DnDHG ProcessSendDirMessage(PVBGLR3GUESTDNDCMDCTX pCtx,188 189 190 191 187 static int vbglR3DnDHGRecvDir(PVBGLR3GUESTDNDCMDCTX pCtx, 188 char *pszDirname, 189 uint32_t cbDirname, 190 uint32_t *pcbDirnameRecv, 191 uint32_t *pfMode) 192 192 { 193 193 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 197 197 AssertPtrReturn(pfMode, VERR_INVALID_POINTER); 198 198 199 DragAndDropSvc::VBOXDNDHGSENDDIRMSG Msg;199 VBOXDNDHGSENDDIRMSG Msg; 200 200 RT_ZERO(Msg); 201 Msg.hdr.result = VERR_WRONG_ORDER; 201 202 Msg.hdr.u32ClientID = pCtx->uClientID; 202 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DIR;203 Msg.hdr.u32Function = HOST_DND_HG_SND_DIR; 203 204 Msg.hdr.cParms = 3; 204 205 205 206 Msg.pvName.SetPtr(pszDirname, cbDirname); 206 Msg.cbName.SetUInt32( 0);207 Msg.cbName.SetUInt32(cbDirname); 207 208 Msg.fMode.SetUInt32(0); 208 209 … … 223 224 } 224 225 225 static int vbglR3DnDHG ProcessSendFileMessage(PVBGLR3GUESTDNDCMDCTX pCtx,226 227 228 229 230 231 232 226 static int vbglR3DnDHGRecvFileData(PVBGLR3GUESTDNDCMDCTX pCtx, 227 char *pszFilename, 228 uint32_t cbFilename, 229 uint32_t *pcbFilenameRecv, 230 void *pvData, 231 uint32_t cbData, 232 uint32_t *pcbDataRecv, 233 uint32_t *pfMode) 233 234 { 234 235 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 241 242 AssertPtrReturn(pfMode, VERR_INVALID_POINTER); 242 243 243 DragAndDropSvc::VBOXDNDHGSENDFILEDATAMSG Msg;244 VBOXDNDHGSENDFILEDATAMSG Msg; 244 245 RT_ZERO(Msg); 246 Msg.hdr.result = VERR_WRONG_ORDER; 245 247 Msg.hdr.u32ClientID = pCtx->uClientID; 246 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA;248 Msg.hdr.u32Function = HOST_DND_HG_SND_FILE_DATA; 247 249 248 250 if (pCtx->uProtocol <= 1) 249 251 { 250 252 Msg.u.v1.pvName.SetPtr(pszFilename, cbFilename); 251 Msg.u.v1.cbName.SetUInt32( cbFilename);253 Msg.u.v1.cbName.SetUInt32(0); 252 254 Msg.u.v1.pvData.SetPtr(pvData, cbData); 253 Msg.u.v1.cbData.SetUInt32( cbData);255 Msg.u.v1.cbData.SetUInt32(0); 254 256 Msg.u.v1.fMode.SetUInt32(0); 255 257 256 258 Msg.hdr.cParms = 5; 257 259 } 258 else 259 { 260 Msg.u.v2.uContext.SetUInt32(0); /** @todo Not used yet. */260 else if (pCtx->uProtocol == 2) 261 { 262 Msg.u.v2.uContext.SetUInt32(0); 261 263 Msg.u.v2.pvData.SetPtr(pvData, cbData); 262 264 Msg.u.v2.cbData.SetUInt32(cbData); … … 264 266 Msg.hdr.cParms = 3; 265 267 } 268 else if (pCtx->uProtocol >= 3) 269 { 270 Msg.u.v3.uContext.SetUInt32(0); 271 Msg.u.v3.pvData.SetPtr(pvData, cbData); 272 Msg.u.v3.cbData.SetUInt32(0); 273 Msg.u.v3.pvChecksum.SetPtr(NULL, 0); 274 Msg.u.v3.cbChecksum.SetUInt32(0); 275 276 Msg.hdr.cParms = 5; 277 } 278 else 279 AssertMsgFailed(("Protocol %RU32 not implemented\n", pCtx->uProtocol)); 266 280 267 281 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 280 294 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 281 295 } 282 else 283 { 296 else if (pCtx->uProtocol == 2) 297 { 298 /** @todo Context ID not used yet. */ 284 299 rc = Msg.u.v2.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 285 300 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 286 301 } 287 } 288 } 289 290 LogFlowFuncLeaveRC(rc); 291 return rc; 292 } 293 294 static int vbglR3DnDHGProcessSendFileHdrMessage(PVBGLR3GUESTDNDCMDCTX pCtx, 295 char *pszFilename, 296 uint32_t cbFilename, 297 uint32_t *puFlags, 298 uint32_t *pfMode, 299 uint64_t *pcbTotal) 302 else if (pCtx->uProtocol >= 3) 303 { 304 /** @todo Context ID not used yet. */ 305 rc = Msg.u.v3.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 306 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 307 /** @todo Add checksum support. */ 308 } 309 else 310 AssertMsgFailed(("Protocol %RU32 not implemented\n", pCtx->uProtocol)); 311 } 312 } 313 314 return rc; 315 } 316 317 static int vbglR3DnDHGRecvFileHdr(PVBGLR3GUESTDNDCMDCTX pCtx, 318 char *pszFilename, 319 uint32_t cbFilename, 320 uint32_t *puFlags, 321 uint32_t *pfMode, 322 uint64_t *pcbTotal) 300 323 { 301 324 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 306 329 AssertReturn(pcbTotal, VERR_INVALID_POINTER); 307 330 308 DragAndDropSvc::VBOXDNDHGSENDFILEHDRMSG Msg;331 VBOXDNDHGSENDFILEHDRMSG Msg; 309 332 RT_ZERO(Msg); 333 Msg.hdr.result = VERR_WRONG_ORDER; 310 334 Msg.hdr.u32ClientID = pCtx->uClientID; 311 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR;335 Msg.hdr.u32Function = HOST_DND_HG_SND_FILE_HDR; 312 336 313 337 int rc; … … 348 372 } 349 373 350 static int vbglR3DnDHGProcessURIMessages(PVBGLR3GUESTDNDCMDCTX pCtx, 351 void **ppvData, 352 uint32_t cbData, 353 size_t *pcbDataRecv) 354 { 355 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 356 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 357 AssertReturn(cbData, VERR_INVALID_PARAMETER); 358 AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER); 374 static int vbglR3DnDHGRecvURIData(PVBGLR3GUESTDNDCMDCTX pCtx, DnDDroppedFiles *pDroppedFiles) 375 { 376 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 377 AssertPtrReturn(pDroppedFiles, VERR_INVALID_POINTER); 359 378 360 379 /* 361 * Allocate chunk buffer.380 * Allocate temporary chunk buffer. 362 381 */ 363 uint32_t cbChunkMax = _64K; /** @todo Make this configurable? */382 uint32_t cbChunkMax = pCtx->cbMaxChunkSize; 364 383 void *pvChunk = RTMemAlloc(cbChunkMax); 365 384 if (!pvChunk) 366 385 return VERR_NO_MEMORY; 367 uint32_t cbChunkRead = 0;386 uint32_t cbChunkRead = 0; 368 387 369 388 uint64_t cbFileSize = 0; /* Total file size (in bytes). */ … … 373 392 * Create and query the (unique) drop target directory in the user's temporary directory. 374 393 */ 375 DnDDroppedFiles droppedFiles; 376 int rc = droppedFiles.OpenTemp(0 /* fFlags */); 394 int rc = pDroppedFiles->OpenTemp(0 /* fFlags */); 377 395 if (RT_FAILURE(rc)) 378 396 { … … 381 399 } 382 400 383 const char *pszDropDir = droppedFiles.GetDirAbs();401 const char *pszDropDir = pDroppedFiles->GetDirAbs(); 384 402 AssertPtr(pszDropDir); 385 403 … … 387 405 * Enter the main loop of retieving files + directories. 388 406 */ 389 DnDURIList lstURI;390 407 DnDURIObject objFile(DnDURIObject::File); 391 408 … … 399 416 uint32_t uNextMsg; 400 417 uint32_t cNextParms; 401 rc = vbglR3DnD QueryNextHostMessageType(pCtx, &uNextMsg, &cNextParms, false /* fWait */);418 rc = vbglR3DnDGetNextMsgType(pCtx, &uNextMsg, &cNextParms, false /* fWait */); 402 419 if (RT_SUCCESS(rc)) 403 420 { … … 406 423 switch (uNextMsg) 407 424 { 408 case DragAndDropSvc::HOST_DND_HG_SND_DIR:425 case HOST_DND_HG_SND_DIR: 409 426 { 410 rc = vbglR3DnDHG ProcessSendDirMessage(pCtx,411 412 413 414 427 rc = vbglR3DnDHGRecvDir(pCtx, 428 szPathName, 429 sizeof(szPathName), 430 &cbPathName, 431 &fMode); 415 432 LogFlowFunc(("HOST_DND_HG_SND_DIR pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n", 416 433 szPathName, cbPathName, fMode, rc)); … … 426 443 rc = RTDirCreate(pszPathAbs, fCreationMode, 0); 427 444 if (RT_SUCCESS(rc)) 428 rc = droppedFiles.AddDir(pszPathAbs);445 rc = pDroppedFiles->AddDir(pszPathAbs); 429 446 430 447 RTStrFree(pszPathAbs); … … 434 451 break; 435 452 } 436 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:437 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:453 case HOST_DND_HG_SND_FILE_HDR: 454 case HOST_DND_HG_SND_FILE_DATA: 438 455 { 439 if (uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR)456 if (uNextMsg == HOST_DND_HG_SND_FILE_HDR) 440 457 { 441 rc = vbglR3DnDHGProcessSendFileHdrMessage(pCtx, 442 szPathName, 443 sizeof(szPathName), 444 &fFlags, 445 &fMode, 446 &cbFileSize); 447 LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR szPathName=%s, fFlags=0x%x, fMode=0x%x, cbFileSize=%RU64, rc=%Rrc\n", 458 rc = vbglR3DnDHGRecvFileHdr(pCtx, 459 szPathName, 460 sizeof(szPathName), 461 &fFlags, 462 &fMode, 463 &cbFileSize); 464 LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR: " 465 "szPathName=%s, fFlags=0x%x, fMode=0x%x, cbFileSize=%RU64, rc=%Rrc\n", 448 466 szPathName, fFlags, fMode, cbFileSize, rc)); 449 467 } 450 468 else 451 469 { 452 rc = vbglR3DnDHGProcessSendFileMessage(pCtx, 453 szPathName, 454 sizeof(szPathName), 455 &cbPathName, 456 pvChunk, 457 cbChunkMax, 458 &cbChunkRead, 459 &fMode); 460 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA " 470 rc = vbglR3DnDHGRecvFileData(pCtx, 471 szPathName, 472 sizeof(szPathName), 473 &cbPathName, 474 pvChunk, 475 cbChunkMax, 476 &cbChunkRead, 477 &fMode); 478 479 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA: " 461 480 "szPathName=%s, cbPathName=%RU32, cbChunkRead=%RU32, fMode=0x%x, rc=%Rrc\n", 462 481 szPathName, cbPathName, cbChunkRead, fMode, rc)); … … 464 483 465 484 if ( RT_SUCCESS(rc) 466 && ( uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR467 485 && ( uNextMsg == HOST_DND_HG_SND_FILE_HDR 486 /* Protocol v1 always sends the file name, so opening the file every time. */ 468 487 || pCtx->uProtocol <= 1) 469 488 ) … … 493 512 if (RT_SUCCESS(rc)) 494 513 { 495 rc = droppedFiles.AddFile(strPathAbs.c_str());514 rc = pDroppedFiles->AddFile(strPathAbs.c_str()); 496 515 if (RT_SUCCESS(rc)) 497 516 { … … 513 532 514 533 if ( RT_SUCCESS(rc) 515 && uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA)534 && uNextMsg == HOST_DND_HG_SND_FILE_DATA) 516 535 { 517 536 bool fClose = false; … … 521 540 if (RT_SUCCESS(rc)) 522 541 { 542 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA " 543 "cbChunkRead=%RU32, cbChunkWritten=%RU32, cbFileWritten=%RU64 cbFileSize=%RU64\n", 544 cbChunkRead, cbChunkWritten, cbFileWritten + cbChunkWritten, cbFileSize)); 545 523 546 if (pCtx->uProtocol >= 2) 524 547 { 525 548 /* Data transfer complete? Close the file. */ 526 549 fClose = objFile.IsComplete(); 550 551 /* Only since protocol v2 we know the file size upfront. */ 552 Assert(cbFileWritten <= cbFileSize); 527 553 } 528 554 else … … 530 556 531 557 cbFileWritten += cbChunkWritten; 532 Assert(cbFileWritten <= cbFileSize);533 558 } 534 559 … … 541 566 break; 542 567 } 543 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:568 case HOST_DND_HG_EVT_CANCEL: 544 569 { 545 rc = vbglR3DnDHG ProcessCancelMessage(pCtx);570 rc = vbglR3DnDHGRecvCancel(pCtx); 546 571 if (RT_SUCCESS(rc)) 547 572 rc = VERR_CANCELLED; … … 568 593 rc = VINF_SUCCESS; 569 594 570 /* Delete chunkbuffer again. */595 /* Delete temp buffer again. */ 571 596 if (pvChunk) 572 597 RTMemFree(pvChunk); … … 576 601 if (RT_FAILURE(rc)) 577 602 { 578 int rc2 = droppedFiles.Rollback(); 603 objFile.Close(); 604 605 int rc2 = pDroppedFiles->Rollback(); 579 606 AssertRC(rc2); /* Not fatal, don't report back to host. */ 580 607 } 581 608 else 582 609 { 583 /*584 * Now we need to transform the URI list which came from the host into585 * an URI list which also has the final "Dropped Files" directory as a prefix586 * for each URI entry.587 *588 * So patch the old drop data with the new drop directory to let the drop589 * target on the guest can find the files later.590 */591 void *pvURIData = *ppvData;592 size_t cbURIData = *pcbDataRecv;593 594 rc = lstURI.RootFromURIData(pvURIData, cbURIData, 0 /* fFlags */);595 if (RT_SUCCESS(rc))596 {597 /* Cleanup the old data and write the new data back to the event. */598 RTMemFree(pvURIData);599 600 RTCString strData = lstURI.RootToString(pszDropDir);601 Assert(!strData.isEmpty());602 LogFlowFunc(("New URI list now has %zu bytes (formerly %RU32 bytes)\n", strData.length() + 1, cbURIData));603 604 pvURIData = RTStrDupN(strData.c_str(), strData.length());605 if (pvURIData)606 {607 cbURIData = strData.length() + 1;608 }609 else610 rc = VERR_NO_MEMORY;611 }612 613 if (RT_SUCCESS(rc))614 {615 *ppvData = pvURIData;616 *pcbDataRecv = cbURIData;617 }618 619 610 /** @todo Compare the URI list with the dirs/files we really transferred. */ 611 /** @todo Implement checksum verification, if any. */ 620 612 } 621 613 … … 625 617 * by the client's drag'n drop operation lateron. 626 618 */ 627 int rc2 = droppedFiles.Reset(false /* fRemoveDropDir */);619 int rc2 = pDroppedFiles->Reset(false /* fRemoveDropDir */); 628 620 if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */ 629 621 LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2)); … … 633 625 } 634 626 635 static int vbglR3DnDHGProcessDataMessageInternal(PVBGLR3GUESTDNDCMDCTX pCtx, 636 uint32_t *puScreenId, 637 char *pszFormat, 638 uint32_t cbFormat, 639 uint32_t *pcbFormatRecv, 640 void *pvData, 641 uint32_t cbData, 642 uint32_t *pcbDataTotal) 643 { 644 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 645 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 646 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 647 AssertReturn(cbFormat, VERR_INVALID_PARAMETER); 648 AssertPtrReturn(pcbFormatRecv, VERR_INVALID_POINTER); 649 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 650 AssertReturn(cbData, VERR_INVALID_PARAMETER); 651 AssertPtrReturn(pcbDataTotal, VERR_INVALID_POINTER); 652 653 DragAndDropSvc::VBOXDNDHGSENDDATAMSG Msg; 627 static int vbglR3DnDHGRecvDataRaw(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, 628 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv) 629 { 630 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 631 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 632 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 633 AssertReturn(cbData, VERR_INVALID_PARAMETER); 634 /* pcbDataRecv is optional. */ 635 636 int rc; 637 638 LogFlowFunc(("pvDate=%p, cbData=%RU32\n", pvData, cbData)); 639 640 VBOXDNDHGSENDDATAMSG Msg; 654 641 RT_ZERO(Msg); 642 Msg.hdr.result = VERR_WRONG_ORDER; 655 643 Msg.hdr.u32ClientID = pCtx->uClientID; 656 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_DATA; 657 Msg.hdr.cParms = 5; 658 644 Msg.hdr.u32Function = HOST_DND_HG_SND_DATA; 645 646 do 647 { 648 uint32_t cbDataRecv; 649 650 if (pCtx->uProtocol < 3) /* For VBox < 5.0.8. */ 651 { 652 Msg.hdr.cParms = 5; 653 654 Msg.u.v1.uScreenId.SetUInt32(0); 655 Msg.u.v1.pvFormat.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 656 Msg.u.v1.cbFormat.SetUInt32(0); 657 Msg.u.v1.pvData.SetPtr(pvData, cbData); 658 Msg.u.v1.cbData.SetUInt32(0); 659 660 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 661 if (RT_SUCCESS(rc)) 662 { 663 rc = Msg.hdr.result; 664 if ( RT_SUCCESS(rc) 665 || rc == VERR_BUFFER_OVERFLOW) 666 { 667 rc = Msg.u.v1.uScreenId.GetUInt32(&pDataHdr->uScreenId); 668 AssertRC(rc); 669 670 /* 671 * In case of VERR_BUFFER_OVERFLOW get the data sizes required 672 * for the format + data blocks. 673 */ 674 uint32_t cbFormatRecv; 675 rc = Msg.u.v1.cbFormat.GetUInt32(&cbFormatRecv); 676 AssertRC(rc); 677 if (cbFormatRecv >= pDataHdr->cbMetaFmt) 678 { 679 rc = VERR_TOO_MUCH_DATA; 680 break; 681 } 682 683 rc = Msg.u.v1.cbData.GetUInt32(&cbDataRecv); 684 AssertRC(rc); 685 if (cbDataRecv >= pDataHdr->cbMeta) 686 { 687 rc = VERR_TOO_MUCH_DATA; 688 break; 689 } 690 691 pDataHdr->cbMetaFmt = cbFormatRecv; 692 } 693 } 694 695 if (RT_FAILURE(rc)) 696 break; 697 } 698 else /* Protocol v3 and up. */ 699 { 700 Msg.hdr.cParms = 5; 701 702 Msg.u.v3.uContext.SetUInt32(0); 703 Msg.u.v3.pvData.SetPtr(pvData, cbData); 704 Msg.u.v3.cbData.SetUInt32(0); 705 Msg.u.v3.pvChecksum.SetPtr(NULL, 0); 706 Msg.u.v3.cbChecksum.SetUInt32(0); 707 708 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 709 if (RT_SUCCESS(rc)) 710 { 711 rc = Msg.hdr.result; 712 if (RT_SUCCESS(rc)) 713 { 714 rc = Msg.u.v3.cbData.GetUInt32(&cbDataRecv); 715 AssertRC(rc); 716 } 717 718 /** @todo Use checksum for validating the received data. */ 719 } 720 721 if (RT_FAILURE(rc)) 722 break; 723 } 724 725 if (pcbDataRecv) 726 *pcbDataRecv = cbDataRecv; 727 728 } while (0); 729 730 LogFlowFuncLeaveRC(rc); 731 return rc; 732 } 733 734 static int vbglR3DnDHGRecvDataHdr(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr) 735 { 736 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 737 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 738 739 Assert(pCtx->uProtocol >= 3); /* Only for protocol v3 and up. */ 740 741 VBOXDNDHGSENDDATAHDRMSG Msg; 742 RT_ZERO(Msg); 743 Msg.hdr.result = VERR_WRONG_ORDER; 744 Msg.hdr.u32ClientID = pCtx->uClientID; 745 Msg.hdr.u32Function = HOST_DND_HG_SND_DATA_HDR; 746 Msg.hdr.cParms = 12; 747 748 Msg.uContext.SetUInt32(0); 749 Msg.uFlags.SetUInt32(0); 659 750 Msg.uScreenId.SetUInt32(0); 660 Msg.pvFormat.SetPtr(pszFormat, cbFormat); 661 Msg.cFormat.SetUInt32(0); 751 Msg.cbTotal.SetUInt64(0); 752 Msg.cbMeta.SetUInt32(0); 753 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 754 Msg.cbMetaFmt.SetUInt32(0); 755 Msg.cObjects.SetUInt64(0); 756 Msg.enmCompression.SetUInt32(0); 757 Msg.enmChecksumType.SetUInt32(0); 758 Msg.pvChecksum.SetPtr(pDataHdr->pvChecksum, pDataHdr->cbChecksum); 759 Msg.cbChecksum.SetUInt32(0); 760 761 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 762 if (RT_SUCCESS(rc)) 763 { 764 rc = Msg.hdr.result; 765 if (RT_SUCCESS(rc)) 766 { 767 /* Msg.uContext not needed here. */ 768 Msg.uFlags.GetUInt32(&pDataHdr->uFlags); 769 Msg.uScreenId.GetUInt32(&pDataHdr->uScreenId); 770 Msg.cbTotal.GetUInt64(&pDataHdr->cbTotal); 771 Msg.cbMeta.GetUInt32(&pDataHdr->cbMeta); 772 Msg.cbMetaFmt.GetUInt32(&pDataHdr->cbMetaFmt); 773 Msg.cObjects.GetUInt64(&pDataHdr->cObjects); 774 Msg.enmCompression.GetUInt32(&pDataHdr->enmCompression); 775 Msg.enmChecksumType.GetUInt32((uint32_t *)&pDataHdr->enmChecksumType); 776 Msg.cbChecksum.GetUInt32(&pDataHdr->cbChecksum); 777 } 778 } 779 780 LogFlowFuncLeaveRC(rc); 781 return rc; 782 } 783 784 /** @todo Deprecated function; will be removed. */ 785 static int vbglR3DnDHGRecvMoreData(PVBGLR3GUESTDNDCMDCTX pCtx, 786 void *pvData, uint32_t cbData, uint32_t *pcbDataRecv) 787 { 788 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 789 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 790 AssertReturn(cbData, VERR_INVALID_PARAMETER); 791 AssertPtrReturn(pcbDataRecv, VERR_INVALID_POINTER); 792 793 VBOXDNDHGSENDMOREDATAMSG Msg; 794 RT_ZERO(Msg); 795 Msg.hdr.result = VERR_WRONG_ORDER; 796 Msg.hdr.u32ClientID = pCtx->uClientID; 797 Msg.hdr.u32Function = HOST_DND_HG_SND_MORE_DATA; 798 Msg.hdr.cParms = 2; 799 662 800 Msg.pvData.SetPtr(pvData, cbData); 663 801 Msg.cbData.SetUInt32(0); … … 670 808 || rc == VERR_BUFFER_OVERFLOW) 671 809 { 672 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 673 674 /* 675 * In case of VERR_BUFFER_OVERFLOW get the data sizes required 676 * for the format + data blocks. 677 */ 678 rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 679 rc = Msg.cbData.GetUInt32(pcbDataTotal); AssertRC(rc); 680 681 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); 682 AssertReturn(cbData >= *pcbDataTotal, VERR_TOO_MUCH_DATA); 683 } 684 } 685 686 return rc; 687 } 688 689 static int vbglR3DnDHGProcessMoreDataMessageInternal(PVBGLR3GUESTDNDCMDCTX pCtx, 690 void *pvData, 691 uint32_t cbData, 692 uint32_t *pcbDataTotal) 693 { 694 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 695 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 696 AssertReturn(cbData, VERR_INVALID_PARAMETER); 697 AssertPtrReturn(pcbDataTotal, VERR_INVALID_POINTER); 698 699 DragAndDropSvc::VBOXDNDHGSENDMOREDATAMSG Msg; 700 RT_ZERO(Msg); 701 Msg.hdr.u32ClientID = pCtx->uClientID; 702 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA; 703 Msg.hdr.cParms = 2; 704 705 Msg.pvData.SetPtr(pvData, cbData); 706 Msg.cbData.SetUInt32(0); 707 708 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 709 if (RT_SUCCESS(rc)) 710 { 711 rc = Msg.hdr.result; 712 if ( RT_SUCCESS(rc) 713 || rc == VERR_BUFFER_OVERFLOW) 714 { 715 rc = Msg.cbData.GetUInt32(pcbDataTotal); AssertRC(rc); 716 AssertReturn(cbData >= *pcbDataTotal, VERR_TOO_MUCH_DATA); 717 } 718 } 719 return rc; 720 } 721 722 static int vbglR3DnDHGProcessSendDataMessageLoop(PVBGLR3GUESTDNDCMDCTX pCtx, 723 uint32_t *puScreenId, 724 char *pszFormat, 725 uint32_t cbFormat, 726 uint32_t *pcbFormatRecv, 727 void **ppvData, 728 uint32_t cbData, 729 size_t *pcbDataRecv) 730 { 731 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 732 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 733 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 734 AssertPtrReturn(pcbFormatRecv, VERR_INVALID_POINTER); 735 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 736 /* pcbDataRecv is optional. */ 737 738 uint32_t cbDataReq = 0; 739 int rc = vbglR3DnDHGProcessDataMessageInternal(pCtx, 740 puScreenId, 741 pszFormat, 742 cbFormat, 743 pcbFormatRecv, 744 *ppvData, 745 cbData, 746 &cbDataReq); 747 uint32_t cbDataTotal = cbDataReq; 748 void *pvData = *ppvData; 749 750 LogFlowFunc(("HOST_DND_HG_SND_DATA cbDataReq=%RU32, rc=%Rrc\n", cbDataTotal, rc)); 751 752 while (rc == VERR_BUFFER_OVERFLOW) 753 { 754 uint32_t uNextMsg; 755 uint32_t cNextParms; 756 rc = vbglR3DnDQueryNextHostMessageType(pCtx, &uNextMsg, &cNextParms, false); 757 if (RT_SUCCESS(rc)) 758 { 759 switch(uNextMsg) 760 { 761 case DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA: 810 rc = Msg.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 811 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 812 } 813 } 814 return rc; 815 } 816 817 static int vbglR3DnDHGRecvDataLoop(PVBGLR3GUESTDNDCMDCTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr, 818 void **ppvData, uint64_t *pcbData) 819 { 820 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 821 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 822 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 823 AssertPtrReturn(pcbData, VERR_INVALID_POINTER); 824 825 int rc; 826 uint32_t cbDataRecv; 827 828 if (pCtx->uProtocol < 3) /* For VBox < 5.0.8. */ 829 { 830 uint64_t cbDataTmp = pCtx->cbMaxChunkSize; 831 void *pvDataTmp = RTMemAlloc(cbDataTmp); 832 833 if (!cbDataTmp) 834 return VERR_NO_MEMORY; 835 836 /** 837 * Protocols < v3 contain the header information in every HOST_DND_HG_SND_DATA 838 * message, so do the actual retrieving immediately. 839 * 840 * Also, the initial implementation used VERR_BUFFER_OVERFLOW as a return code to 841 * indicate that there will be more data coming in after the initial data chunk. There 842 * was no way of telling the total data size upfront (in form of a header or some such), 843 * so also handle this case to not break backwards compatibility. 844 */ 845 rc = vbglR3DnDHGRecvDataRaw(pCtx, pDataHdr, pvDataTmp, pCtx->cbMaxChunkSize, &cbDataRecv); 846 847 /* See comment above. */ 848 while (rc == VERR_BUFFER_OVERFLOW) 849 { 850 uint32_t uNextMsg; 851 uint32_t cNextParms; 852 rc = vbglR3DnDGetNextMsgType(pCtx, &uNextMsg, &cNextParms, false /* fBlock */); 853 if (RT_SUCCESS(rc)) 854 { 855 switch(uNextMsg) 762 856 { 763 /** @todo r=andy Don't use reallocate here; can go wrong with *really* big URI lists. 764 * Instead send as many URI entries as possible per chunk and add those entries 765 * to our to-process list for immediata processing. Repeat the step after processing then. */ 766 LogFlowFunc(("HOST_DND_HG_SND_MORE_DATA cbDataTotal: %RU32 -> %RU32\n", cbDataReq, cbDataReq + cbData)); 767 pvData = RTMemRealloc(*ppvData, cbDataTotal + cbData); 768 if (!pvData) 857 case HOST_DND_HG_SND_MORE_DATA: 769 858 { 770 rc = VERR_NO_MEMORY; 859 /** @todo r=andy Don't use reallocate here; can go wrong with *really* big URI lists. 860 * Instead send as many URI entries as possible per chunk and add those entries 861 * to our to-process list for immediata processing. Repeat the step after processing then. */ 862 LogFlowFunc(("HOST_DND_HG_SND_MORE_DATA cbDataTotal: %RU64 -> %RU64\n", 863 cbDataTmp, cbDataTmp + pCtx->cbMaxChunkSize)); 864 void *pvDataNew = RTMemRealloc(pvDataTmp, cbDataTmp + pCtx->cbMaxChunkSize); 865 if (!pvDataNew) 866 { 867 rc = VERR_NO_MEMORY; 868 break; 869 } 870 871 pvDataTmp = pvDataNew; 872 873 uint8_t *pvDataOff = (uint8_t *)pvDataTmp + cbDataTmp; 874 rc = vbglR3DnDHGRecvMoreData(pCtx, pvDataOff, pCtx->cbMaxChunkSize, &cbDataRecv); 875 if ( RT_SUCCESS(rc) 876 || rc == VERR_BUFFER_OVERFLOW) /* Still can return VERR_BUFFER_OVERFLOW. */ 877 { 878 cbDataTmp += cbDataRecv; 879 } 771 880 break; 772 881 } 773 rc = vbglR3DnDHGProcessMoreDataMessageInternal(pCtx, 774 &((char *)pvData)[cbDataTotal], 775 cbData, 776 &cbDataReq); 777 cbDataTotal += cbDataReq; 778 break; 882 case HOST_DND_HG_EVT_CANCEL: 883 default: 884 { 885 rc = vbglR3DnDHGRecvCancel(pCtx); 886 if (RT_SUCCESS(rc)) 887 rc = VERR_CANCELLED; 888 break; 889 } 779 890 } 780 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: 781 default: 891 } 892 } 893 894 if (RT_SUCCESS(rc)) 895 { 896 /* There was no way of telling the total data size upfront 897 * (in form of a header or some such), so set the total data size here. */ 898 pDataHdr->cbTotal = cbDataTmp; 899 900 *ppvData = pvDataTmp; 901 *pcbData = cbDataTmp; 902 } 903 else 904 RTMemFree(pvDataTmp); 905 } 906 else /* Protocol v3 and up. Since VBox 5.0.8. */ 907 { 908 rc = vbglR3DnDHGRecvDataHdr(pCtx, pDataHdr); 909 if (RT_SUCCESS(rc)) 910 { 911 LogFlowFunc(("cbMeta=%RU32\n", pDataHdr->cbMeta)); 912 if (pDataHdr->cbMeta) 913 { 914 uint64_t cbDataTmp = 0; 915 void *pvDataTmp = RTMemAlloc(pDataHdr->cbMeta); 916 if (!pvDataTmp) 917 rc = VERR_NO_MEMORY; 918 919 if (RT_SUCCESS(rc)) 782 920 { 783 rc = vbglR3DnDHGProcessCancelMessage(pCtx); 921 uint8_t *pvDataOff = (uint8_t *)pvDataTmp; 922 while (cbDataTmp < pDataHdr->cbMeta) 923 { 924 rc = vbglR3DnDHGRecvDataRaw(pCtx, pDataHdr, 925 pvDataOff, RT_MIN(pDataHdr->cbMeta - cbDataTmp, pCtx->cbMaxChunkSize), 926 &cbDataRecv); 927 if (RT_SUCCESS(rc)) 928 { 929 LogFlowFunc(("cbDataRecv=%RU32, cbDataTmp=%RU64\n", cbDataRecv, cbDataTmp)); 930 Assert(cbDataTmp + cbDataRecv <= pDataHdr->cbMeta); 931 cbDataTmp += cbDataRecv; 932 pvDataOff += cbDataRecv; 933 } 934 else 935 break; 936 } 937 784 938 if (RT_SUCCESS(rc)) 785 rc = VERR_CANCELLED; 786 break; 939 { 940 Assert(cbDataTmp == pDataHdr->cbMeta); 941 942 LogFlowFunc(("Received %RU64 bytes of data\n", cbDataTmp)); 943 944 *ppvData = pvDataTmp; 945 *pcbData = cbDataTmp; 946 } 947 else 948 RTMemFree(pvDataTmp); 787 949 } 788 950 } 789 } 790 } 791 792 if (RT_SUCCESS(rc)) 793 { 794 *ppvData = pvData; 795 if (pcbDataRecv) 796 *pcbDataRecv = cbDataTotal; 951 else 952 { 953 *ppvData = NULL; 954 *pcbData = 0; 955 } 956 } 797 957 } 798 958 … … 801 961 } 802 962 803 static int vbglR3DnDHGProcessSendDataMessage(PVBGLR3GUESTDNDCMDCTX pCtx, 804 uint32_t *puScreenId, 805 char *pszFormat, 806 uint32_t cbFormat, 807 uint32_t *pcbFormatRecv, 808 void **ppvData, 809 uint32_t cbData, 810 size_t *pcbDataRecv) 811 { 812 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 813 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 814 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 815 AssertPtrReturn(pcbFormatRecv, VERR_INVALID_POINTER); 816 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 817 818 int rc = vbglR3DnDHGProcessSendDataMessageLoop(pCtx, 819 puScreenId, 820 pszFormat, 821 cbFormat, 822 pcbFormatRecv, 823 ppvData, 824 cbData, 825 pcbDataRecv); 826 if (RT_SUCCESS(rc)) 827 { 828 /* Check if this is an URI event. If so, let VbglR3 do all the actual 963 /** @todo Replace the parameters (except pCtx) with PVBOXDNDSNDDATAHDR. Later. */ 964 /** @todo Hand in the DnDURIList + DnDDroppedFiles objects so that this function 965 * can fill it directly instead of passing huge blobs of data around. */ 966 static int vbglR3DnDHGRecvDataMain(PVBGLR3GUESTDNDCMDCTX pCtx, 967 uint32_t *puScreenId, 968 char **ppszFormat, 969 uint32_t *pcbFormat, 970 void **ppvData, 971 uint32_t *pcbData) 972 { 973 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 974 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 975 AssertPtrReturn(ppszFormat, VERR_INVALID_POINTER); 976 AssertPtrReturn(pcbFormat, VERR_INVALID_POINTER); 977 AssertPtrReturn(ppvData, VERR_INVALID_POINTER); 978 AssertPtrReturn(pcbData, VERR_INVALID_POINTER); 979 980 VBOXDNDDATAHDR dataHdr; /** @todo See todo above. */ 981 RT_ZERO(dataHdr); 982 983 dataHdr.cbMetaFmt = _64K; /** @todo Make this configurable? */ 984 dataHdr.pvMetaFmt = RTMemAlloc(dataHdr.cbMetaFmt); 985 if (!dataHdr.pvMetaFmt) 986 return VERR_NO_MEMORY; 987 988 DnDURIList lstURI; 989 DnDDroppedFiles droppedFiles; 990 991 void *pvData; /** @todo See todo above. */ 992 uint64_t cbData; /** @todo See todo above. */ 993 994 int rc = vbglR3DnDHGRecvDataLoop(pCtx, &dataHdr, &pvData, &cbData); 995 if (RT_SUCCESS(rc)) 996 { 997 /** 998 * Check if this is an URI event. If so, let VbglR3 do all the actual 829 999 * data transfer + file/directory creation internally without letting 830 1000 * the caller know. 831 1001 * 832 1002 * This keeps the actual (guest OS-)dependent client (like VBoxClient / 833 * VBoxTray) small by not having too much redundant code. */ 834 AssertPtr(pcbFormatRecv); 835 if (DnDMIMEHasFileURLs(pszFormat, *pcbFormatRecv)) 836 rc = vbglR3DnDHGProcessURIMessages(pCtx, 837 ppvData, 838 cbData, 839 pcbDataRecv); 840 if (RT_FAILURE(rc)) 841 { 842 int rc2 = VbglR3DnDHGSetProgress(pCtx, DragAndDropSvc::DND_PROGRESS_ERROR, 100 /* Percent */, rc); 843 AssertRC(rc2); 844 } 1003 * VBoxTray) small by not having too much redundant code. 1004 */ 1005 Assert(dataHdr.cbMetaFmt); 1006 AssertPtr(dataHdr.pvMetaFmt); 1007 if (DnDMIMEHasFileURLs((char *)dataHdr.pvMetaFmt, dataHdr.cbMetaFmt)) 1008 { 1009 AssertPtr(pvData); 1010 Assert(cbData); 1011 rc = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */); 1012 if (RT_SUCCESS(rc)) 1013 rc = vbglR3DnDHGRecvURIData(pCtx, &droppedFiles); 1014 1015 if (RT_SUCCESS(rc)) /** @todo Remove this block as soon as we hand in DnDURIList. */ 1016 { 1017 if (pvData) 1018 { 1019 /* Reuse data buffer to fill in the transformed URI file list. */ 1020 RTMemFree(pvData); 1021 pvData = NULL; 1022 } 1023 1024 RTCString strData = lstURI.RootToString(droppedFiles.GetDirAbs()); 1025 Assert(!strData.isEmpty()); 1026 1027 cbData = strData.length() + 1; 1028 LogFlowFunc(("URI list has %zu bytes\n", cbData)); 1029 1030 pvData = RTMemAlloc(cbData); 1031 if (pvData) 1032 { 1033 memcpy(pvData, strData.c_str(), cbData); 1034 } 1035 else 1036 rc = VERR_NO_MEMORY; 1037 } 1038 } 1039 else /* Raw data. */ 1040 { 1041 const uint32_t cbDataRaw = dataHdr.cbMetaFmt; 1042 if (cbData >= cbDataRaw) 1043 { 1044 if (cbDataRaw) 1045 memcpy(pvData, dataHdr.pvMetaFmt, cbDataRaw); 1046 cbData = cbDataRaw; 1047 } 1048 else 1049 rc = VERR_BUFFER_OVERFLOW; 1050 } 1051 } 1052 1053 if ( RT_FAILURE(rc) 1054 && rc != VERR_CANCELLED) 1055 { 1056 if (dataHdr.pvMetaFmt) 1057 RTMemFree(dataHdr.pvMetaFmt); 1058 if (pvData) 1059 RTMemFree(pvData); 1060 1061 int rc2 = VbglR3DnDHGSendProgress(pCtx, DND_PROGRESS_ERROR, 100 /* Percent */, rc); 1062 AssertRC(rc2); 1063 } 1064 else if (RT_SUCCESS(rc)) 1065 { 1066 *ppszFormat = (char *)dataHdr.pvMetaFmt; 1067 *pcbFormat = dataHdr.cbMetaFmt; 1068 *ppvData = pvData; 1069 *pcbData = cbData; 845 1070 } 846 1071 … … 849 1074 } 850 1075 851 static int vbglR3DnDGHProcessRequestPendingMessage(PVBGLR3GUESTDNDCMDCTX pCtx, 852 uint32_t *puScreenId) 1076 static int vbglR3DnDGHRecvPending(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t *puScreenId) 853 1077 { 854 1078 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 855 1079 AssertPtrReturn(puScreenId, VERR_INVALID_POINTER); 856 1080 857 DragAndDropSvc::VBOXDNDGHREQPENDINGMSG Msg;1081 VBOXDNDGHREQPENDINGMSG Msg; 858 1082 RT_ZERO(Msg); 1083 Msg.hdr.result = VERR_WRONG_ORDER; 859 1084 Msg.hdr.u32ClientID = pCtx->uClientID; 860 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_REQ_PENDING;1085 Msg.hdr.u32Function = HOST_DND_GH_REQ_PENDING; 861 1086 Msg.hdr.cParms = 1; 862 1087 … … 876 1101 } 877 1102 878 static int vbglR3DnDGH ProcessDroppedMessage(PVBGLR3GUESTDNDCMDCTX pCtx,879 880 881 882 1103 static int vbglR3DnDGHRecvDropped(PVBGLR3GUESTDNDCMDCTX pCtx, 1104 char *pszFormat, 1105 uint32_t cbFormat, 1106 uint32_t *pcbFormatRecv, 1107 uint32_t *puAction) 883 1108 { 884 1109 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 888 1113 AssertPtrReturn(puAction, VERR_INVALID_POINTER); 889 1114 890 DragAndDropSvc::VBOXDNDGHDROPPEDMSG Msg;1115 VBOXDNDGHDROPPEDMSG Msg; 891 1116 RT_ZERO(Msg); 1117 Msg.hdr.result = VERR_WRONG_ORDER; 892 1118 Msg.hdr.u32ClientID = pCtx->uClientID; 893 Msg.hdr.u32Function = DragAndDropSvc::HOST_DND_GH_EVT_DROPPED;1119 Msg.hdr.u32Function = HOST_DND_GH_EVT_DROPPED; 894 1120 Msg.hdr.cParms = 3; 895 1121 896 1122 Msg.pvFormat.SetPtr(pszFormat, cbFormat); 897 Msg.c Format.SetUInt32(0);1123 Msg.cbFormat.SetUInt32(0); 898 1124 Msg.uAction.SetUInt32(0); 899 1125 … … 904 1130 if (RT_SUCCESS(rc)) 905 1131 { 906 rc = Msg.c Format.GetUInt32(pcbFormatRecv); AssertRC(rc);907 rc = Msg.uAction.GetUInt32(puAction); AssertRC(rc);1132 rc = Msg.cbFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 1133 rc = Msg.uAction.GetUInt32(puAction); AssertRC(rc); 908 1134 909 1135 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); … … 944 1170 { 945 1171 /* Set the default protocol version to use. */ 946 pCtx->uProtocol = 2;1172 pCtx->uProtocol = 3; 947 1173 948 1174 Assert(Info.u32ClientID); … … 967 1193 { 968 1194 fSupportsConnectReq = RTStrVersionCompare(pszHostVersion, "5.0") >= 0; 1195 LogFlowFunc(("pszHostVersion=%s, fSupportsConnectReq=%RTbool\n", pszHostVersion, fSupportsConnectReq)); 969 1196 VbglR3GuestPropReadValueFree(pszHostVersion); 970 1197 } … … 972 1199 VbglR3GuestPropDisconnect(uGuestPropSvcClientID); 973 1200 } 1201 1202 if (RT_FAILURE(rc2)) 1203 LogFlowFunc(("Retrieving host version failed with rc=%Rrc\n", rc2)); 974 1204 } 975 1205 … … 981 1211 * does not implement this command. 982 1212 */ 983 DragAndDropSvc::VBOXDNDCONNECTMSG Msg;1213 VBOXDNDCONNECTMSG Msg; 984 1214 RT_ZERO(Msg); 985 1215 Msg.hdr.result = VERR_WRONG_ORDER; 986 1216 Msg.hdr.u32ClientID = pCtx->uClientID; 987 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_CONNECT;1217 Msg.hdr.u32Function = GUEST_DND_CONNECT; 988 1218 Msg.hdr.cParms = 2; 989 1219 … … 1005 1235 pCtx->uProtocol = 1; /* Fall back to protocol version 1 (< VBox 5.0). */ 1006 1236 1237 pCtx->cbMaxChunkSize = _64K; /** @todo Use a scratch buffer on the heap? */ 1238 1007 1239 LogFlowFunc(("uClient=%RU32, uProtocol=%RU32, rc=%Rrc\n", pCtx->uClientID, pCtx->uProtocol, rc)); 1008 1240 return rc; … … 1024 1256 } 1025 1257 1026 VBGLR3DECL(int) VbglR3DnD ProcessNextMessage(PVBGLR3GUESTDNDCMDCTX pCtx, CPVBGLR3DNDHGCMEVENT pEvent)1258 VBGLR3DECL(int) VbglR3DnDRecvNextMsg(PVBGLR3GUESTDNDCMDCTX pCtx, CPVBGLR3DNDHGCMEVENT pEvent) 1027 1259 { 1028 1260 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1029 1261 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 1030 1262 1031 uint32_t uMsg = 0; 1032 uint32_t uNumParms = 0; 1033 const uint32_t ccbFormats = _64K; 1034 const uint32_t ccbData = _64K; 1035 int rc = vbglR3DnDQueryNextHostMessageType(pCtx, &uMsg, &uNumParms, 1036 true /* fWait */); 1263 uint32_t uMsg = 0; 1264 uint32_t uNumParms = 0; 1265 1266 const uint32_t cbDataMax = pCtx->cbMaxChunkSize; 1267 const uint32_t cbFormatMax = pCtx->cbMaxChunkSize; 1268 1269 int rc = vbglR3DnDGetNextMsgType(pCtx, &uMsg, &uNumParms, true /* fWait */); 1037 1270 if (RT_SUCCESS(rc)) 1038 1271 { … … 1041 1274 switch(uMsg) 1042 1275 { 1043 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:1044 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:1045 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:1046 { 1047 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(c cbFormats));1276 case HOST_DND_HG_EVT_ENTER: 1277 case HOST_DND_HG_EVT_MOVE: 1278 case HOST_DND_HG_EVT_DROPPED: 1279 { 1280 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(cbFormatMax)); 1048 1281 if (!pEvent->pszFormats) 1049 1282 rc = VERR_NO_MEMORY; 1050 1283 1051 1284 if (RT_SUCCESS(rc)) 1052 rc = vbglR3DnDHG ProcessActionMessage(pCtx,1053 1054 1055 1056 1057 1058 1059 1060 ccbFormats,1061 1285 rc = vbglR3DnDHGRecvAction(pCtx, 1286 uMsg, 1287 &pEvent->uScreenId, 1288 &pEvent->u.a.uXpos, 1289 &pEvent->u.a.uYpos, 1290 &pEvent->u.a.uDefAction, 1291 &pEvent->u.a.uAllActions, 1292 pEvent->pszFormats, 1293 cbFormatMax, 1294 &pEvent->cbFormats); 1062 1295 break; 1063 1296 } 1064 case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:1065 { 1066 rc = vbglR3DnDHG ProcessLeaveMessage(pCtx);1297 case HOST_DND_HG_EVT_LEAVE: 1298 { 1299 rc = vbglR3DnDHGRecvLeave(pCtx); 1067 1300 break; 1068 1301 } 1069 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 1070 { 1071 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(ccbFormats)); 1072 if (!pEvent->pszFormats) 1073 rc = VERR_NO_MEMORY; 1074 1075 if (RT_SUCCESS(rc)) 1076 { 1077 pEvent->u.b.pvData = RTMemAlloc(ccbData); 1078 if (!pEvent->u.b.pvData) 1079 { 1080 RTMemFree(pEvent->pszFormats); 1081 pEvent->pszFormats = NULL; 1082 1083 rc = VERR_NO_MEMORY; 1084 } 1085 } 1086 1087 if (RT_SUCCESS(rc)) 1088 rc = vbglR3DnDHGProcessSendDataMessage(pCtx, 1089 &pEvent->uScreenId, 1090 pEvent->pszFormats, 1091 ccbFormats, 1092 &pEvent->cbFormats, 1093 &pEvent->u.b.pvData, 1094 ccbData, 1095 &pEvent->u.b.cbData); 1302 case HOST_DND_HG_SND_DATA: 1303 /* Protocol v1 + v2: Also contains the header data. 1304 /* Note: Fall through is intentional. */ 1305 case HOST_DND_HG_SND_DATA_HDR: 1306 { 1307 rc = vbglR3DnDHGRecvDataMain(pCtx, 1308 /* Screen ID */ 1309 &pEvent->uScreenId, 1310 /* Format */ 1311 &pEvent->pszFormats, 1312 &pEvent->cbFormats, 1313 /* Data */ 1314 &pEvent->u.b.pvData, 1315 &pEvent->u.b.cbData); 1096 1316 break; 1097 1317 } 1098 case DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA:1099 case DragAndDropSvc::HOST_DND_HG_SND_DIR:1100 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:1318 case HOST_DND_HG_SND_MORE_DATA: 1319 case HOST_DND_HG_SND_DIR: 1320 case HOST_DND_HG_SND_FILE_DATA: 1101 1321 { 1102 1322 /* 1103 1323 * All messages in this case are handled internally 1104 * by vbglR3DnDHGProcessSendDataMessage() and must 1105 * be specified by a preceding HOST_DND_HG_SND_DATA call. 1324 * by vbglR3DnDHGRecvDataMain() and must be specified 1325 * by a preceding HOST_DND_HG_SND_DATA or HOST_DND_HG_SND_DATA_HDR 1326 * calls. 1106 1327 */ 1107 1328 rc = VERR_WRONG_ORDER; 1108 1329 break; 1109 1330 } 1110 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:1111 { 1112 rc = vbglR3DnDHG ProcessCancelMessage(pCtx);1331 case HOST_DND_HG_EVT_CANCEL: 1332 { 1333 rc = vbglR3DnDHGRecvCancel(pCtx); 1113 1334 break; 1114 1335 } 1115 1336 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1116 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:1117 { 1118 rc = vbglR3DnDGH ProcessRequestPendingMessage(pCtx, &pEvent->uScreenId);1337 case HOST_DND_GH_REQ_PENDING: 1338 { 1339 rc = vbglR3DnDGHRecvPending(pCtx, &pEvent->uScreenId); 1119 1340 break; 1120 1341 } 1121 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:1122 { 1123 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(c cbFormats));1342 case HOST_DND_GH_EVT_DROPPED: 1343 { 1344 pEvent->pszFormats = static_cast<char*>(RTMemAlloc(cbFormatMax)); 1124 1345 if (!pEvent->pszFormats) 1125 1346 rc = VERR_NO_MEMORY; 1126 1347 1127 1348 if (RT_SUCCESS(rc)) 1128 rc = vbglR3DnDGH ProcessDroppedMessage(pCtx,1129 1130 ccbFormats,1131 1132 1349 rc = vbglR3DnDGHRecvDropped(pCtx, 1350 pEvent->pszFormats, 1351 cbFormatMax, 1352 &pEvent->cbFormats, 1353 &pEvent->u.a.uDefAction); 1133 1354 break; 1134 1355 } … … 1145 1366 } 1146 1367 1147 VBGLR3DECL(int) VbglR3DnDHG AcknowledgeOperation(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uAction)1368 VBGLR3DECL(int) VbglR3DnDHGSendAckOp(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uAction) 1148 1369 { 1149 1370 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1150 1371 1151 DragAndDropSvc::VBOXDNDHGACKOPMSG Msg;1372 VBOXDNDHGACKOPMSG Msg; 1152 1373 RT_ZERO(Msg); 1153 1374 Msg.hdr.result = VERR_WRONG_ORDER; 1154 1375 Msg.hdr.u32ClientID = pCtx->uClientID; 1155 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_ACK_OP;1376 Msg.hdr.u32Function = GUEST_DND_HG_ACK_OP; 1156 1377 Msg.hdr.cParms = 1; 1157 1378 … … 1165 1386 } 1166 1387 1167 VBGLR3DECL(int) VbglR3DnDHG RequestData(PVBGLR3GUESTDNDCMDCTX pCtx, const char* pcszFormat)1388 VBGLR3DECL(int) VbglR3DnDHGSendReqData(PVBGLR3GUESTDNDCMDCTX pCtx, const char* pcszFormat) 1168 1389 { 1169 1390 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1170 1391 AssertPtrReturn(pcszFormat, VERR_INVALID_POINTER); 1171 1392 1172 DragAndDropSvc::VBOXDNDHGREQDATAMSG Msg;1393 VBOXDNDHGREQDATAMSG Msg; 1173 1394 RT_ZERO(Msg); 1174 1395 Msg.hdr.result = VERR_WRONG_ORDER; 1175 1396 Msg.hdr.u32ClientID = pCtx->uClientID; 1176 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_REQ_DATA;1397 Msg.hdr.u32Function = GUEST_DND_HG_REQ_DATA; 1177 1398 Msg.hdr.cParms = 1; 1178 1399 1179 Msg.pFormat.SetPtr((void*)pcszFormat, (uint32_t)strlen(pcszFormat) + 1);1400 Msg.pFormat.SetPtr((void*)pcszFormat, strlen(pcszFormat) + 1 /* Include termination */); 1180 1401 1181 1402 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 1186 1407 } 1187 1408 1188 VBGLR3DECL(int) VbglR3DnDHGSe tProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr)1409 VBGLR3DECL(int) VbglR3DnDHGSendProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr) 1189 1410 { 1190 1411 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1191 AssertReturn(uStatus > D ragAndDropSvc::DND_PROGRESS_UNKNOWN, VERR_INVALID_PARAMETER);1192 1193 DragAndDropSvc::VBOXDNDHGEVTPROGRESSMSG Msg;1412 AssertReturn(uStatus > DND_PROGRESS_UNKNOWN, VERR_INVALID_PARAMETER); 1413 1414 VBOXDNDHGEVTPROGRESSMSG Msg; 1194 1415 RT_ZERO(Msg); 1195 1416 Msg.hdr.result = VERR_WRONG_ORDER; … … 1210 1431 1211 1432 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1212 VBGLR3DECL(int) VbglR3DnDGH AcknowledgePending(PVBGLR3GUESTDNDCMDCTX pCtx,1213 uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormats)1433 VBGLR3DECL(int) VbglR3DnDGHSendAckPending(PVBGLR3GUESTDNDCMDCTX pCtx, 1434 uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormats, uint32_t cbFormats) 1214 1435 { 1215 1436 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1216 1437 AssertPtrReturn(pcszFormats, VERR_INVALID_POINTER); 1217 1218 DragAndDropSvc::VBOXDNDGHACKPENDINGMSG Msg; 1438 AssertReturn(cbFormats, VERR_INVALID_PARAMETER); 1439 1440 VBOXDNDGHACKPENDINGMSG Msg; 1219 1441 RT_ZERO(Msg); 1220 1442 Msg.hdr.result = VERR_WRONG_ORDER; 1221 1443 Msg.hdr.u32ClientID = pCtx->uClientID; 1222 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_ACK_PENDING;1444 Msg.hdr.u32Function = GUEST_DND_GH_ACK_PENDING; 1223 1445 Msg.hdr.cParms = 3; 1224 1446 1225 1447 Msg.uDefAction.SetUInt32(uDefAction); 1226 1448 Msg.uAllActions.SetUInt32(uAllActions); 1227 Msg.pFormat.SetPtr((void*)pcszFormats, (uint32_t)strlen(pcszFormats) + 1);1449 Msg.pFormat.SetPtr((void*)pcszFormats, cbFormats); 1228 1450 1229 1451 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 1235 1457 1236 1458 static int vbglR3DnDGHSendDataInternal(PVBGLR3GUESTDNDCMDCTX pCtx, 1237 void *pvData, uint 32_t cbData, uint32_t cbAdditionalData)1459 void *pvData, uint64_t cbData, PVBOXDNDSNDDATAHDR pDataHdr) 1238 1460 { 1239 1461 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 1241 1463 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1242 1464 /* cbAdditionalData is optional. */ 1243 1244 DragAndDropSvc::VBOXDNDGHSENDDATAMSG Msg; 1465 /* pDataHdr is optional in protocols < v3. */ 1466 1467 int rc = VINF_SUCCESS; 1468 1469 /* For protocol v3 and up we need to send the data header first. */ 1470 if (pCtx->uProtocol > 2) 1471 { 1472 AssertPtrReturn(pDataHdr, VERR_INVALID_POINTER); 1473 1474 VBOXDNDGHSENDDATAHDRMSG Msg; 1475 RT_ZERO(Msg); 1476 Msg.hdr.result = VERR_WRONG_ORDER; 1477 Msg.hdr.u32ClientID = pCtx->uClientID; 1478 Msg.hdr.u32Function = GUEST_DND_GH_SND_DATA_HDR; 1479 Msg.hdr.cParms = 12; 1480 1481 Msg.uContext.SetUInt32(0); /** @todo Not used yet. */ 1482 Msg.uFlags.SetUInt32(0); /** @todo Not used yet. */ 1483 Msg.uScreenId.SetUInt32(0); /** @todo Not used for guest->host (yet). */ 1484 Msg.cbTotal.SetUInt64(pDataHdr->cbTotal); 1485 Msg.cbMeta.SetUInt64(pDataHdr->cbMeta); 1486 Msg.pvMetaFmt.SetPtr(pDataHdr->pvMetaFmt, pDataHdr->cbMetaFmt); 1487 Msg.cbMetaFmt.SetUInt32(pDataHdr->cbMetaFmt); 1488 Msg.cObjects.SetUInt64(pDataHdr->cObjects); 1489 Msg.enmCompression.SetUInt32(0); /** @todo Not used yet. */ 1490 Msg.enmChecksumType.SetUInt32(RTDIGESTTYPE_INVALID); /** @todo Not used yet. */ 1491 Msg.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */ 1492 Msg.cbChecksum.SetUInt32(0); /** @todo Not used yet. */ 1493 1494 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1495 if (RT_SUCCESS(rc)) 1496 rc = Msg.hdr.result; 1497 1498 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU64, cObjects=%RU64, rc=%Rrc\n", 1499 pDataHdr->cbTotal, pDataHdr->cbMeta, pDataHdr->cObjects, rc)); 1500 } 1501 1502 if (RT_SUCCESS(rc)) 1503 { 1504 VBOXDNDGHSENDDATAMSG Msg; 1505 RT_ZERO(Msg); 1506 Msg.hdr.result = VERR_WRONG_ORDER; 1507 Msg.hdr.u32ClientID = pCtx->uClientID; 1508 Msg.hdr.u32Function = GUEST_DND_GH_SND_DATA; 1509 1510 if (pCtx->uProtocol > 2) 1511 { 1512 Msg.hdr.cParms = 5; 1513 1514 Msg.u.v3.uContext.SetUInt32(0); /** @todo Not used yet. */ 1515 Msg.u.v3.pvChecksum.SetPtr(NULL, 0); /** @todo Not used yet. */ 1516 Msg.u.v3.cbChecksum.SetUInt32(0); /** @todo Not used yet. */ 1517 } 1518 else 1519 { 1520 Msg.hdr.cParms = 2; 1521 1522 /* Total amount of bytes to send (meta data + all directory/file objects). */ 1523 /* Note: Only supports uint32_t, so this is *not* a typo. */ 1524 Msg.u.v1.cbTotalBytes.SetUInt32((uint32_t)pDataHdr->cbTotal); 1525 } 1526 1527 uint32_t cbCurChunk; 1528 const uint32_t cbMaxChunk = pCtx->cbMaxChunkSize; 1529 uint32_t cbSent = 0; 1530 1531 HGCMFunctionParameter *pParm = (pCtx->uProtocol > 2) 1532 ? &Msg.u.v3.pvData 1533 : &Msg.u.v1.pvData; 1534 while (cbSent < cbData) 1535 { 1536 cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk); 1537 pParm->SetPtr(static_cast<uint8_t *>(pvData) + cbSent, cbCurChunk); 1538 if (pCtx->uProtocol > 2) 1539 Msg.u.v3.cbData.SetUInt32(cbCurChunk); 1540 1541 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1542 if (RT_SUCCESS(rc)) 1543 rc = Msg.hdr.result; 1544 1545 if (RT_FAILURE(rc)) 1546 break; 1547 1548 cbSent += cbCurChunk; 1549 } 1550 1551 if (RT_SUCCESS(rc)) 1552 Assert(cbSent == cbData); 1553 } 1554 1555 LogFlowFunc(("Returning rc=%Rrc, cbData=%RU64\n", rc, cbData)); 1556 return rc; 1557 } 1558 1559 static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj) 1560 { 1561 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 1562 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1563 AssertReturn(pObj->GetType() == DnDURIObject::Directory, VERR_INVALID_PARAMETER); 1564 1565 VBOXDNDGHSENDDIRMSG Msg; 1245 1566 RT_ZERO(Msg); 1246 1567 Msg.hdr.result = VERR_WRONG_ORDER; 1247 1568 Msg.hdr.u32ClientID = pCtx->uClientID; 1248 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DATA; 1249 Msg.hdr.cParms = 2; 1250 1251 /* Total amount of bytes to send (including this data block). */ 1252 Msg.cbTotalBytes.SetUInt32(cbData + cbAdditionalData); 1253 1254 int rc = VINF_SUCCESS; 1255 1256 uint32_t cbCurChunk; 1257 uint32_t cbMaxChunk = _64K; /** @todo Transfer max. 64K chunks per message. Configurable? */ 1258 uint32_t cbSent = 0; 1259 1260 while (cbSent < cbData) 1261 { 1262 cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk); 1263 Msg.pvData.SetPtr(static_cast<uint8_t *>(pvData) + cbSent, cbCurChunk); 1264 1265 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1266 if (RT_SUCCESS(rc)) 1267 rc = Msg.hdr.result; 1268 1269 if (RT_FAILURE(rc)) 1270 break; 1271 1272 cbSent += cbCurChunk; 1273 } 1274 1275 if (RT_SUCCESS(rc)) 1276 Assert(cbSent == cbData); 1277 1278 LogFlowFunc(("Returning rc=%Rrc, cbData=%RU32, cbAddtionalData=%RU32, cbSent=%RU32\n", 1279 rc, cbData, cbAdditionalData, cbSent)); 1280 return rc; 1281 } 1282 1283 static int vbglR3DnDGHSendDir(PVBGLR3GUESTDNDCMDCTX pCtx, DnDURIObject *pObj) 1284 { 1285 AssertPtrReturn(pObj, VERR_INVALID_POINTER); 1286 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1287 AssertReturn(pObj->GetType() == DnDURIObject::Directory, VERR_INVALID_PARAMETER); 1288 1289 DragAndDropSvc::VBOXDNDGHSENDDIRMSG Msg; 1290 RT_ZERO(Msg); 1291 Msg.hdr.result = VERR_WRONG_ORDER; 1292 Msg.hdr.u32ClientID = pCtx->uClientID; 1293 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DIR; 1569 Msg.hdr.u32Function = GUEST_DND_GH_SND_DIR; 1294 1570 Msg.hdr.cParms = 3; 1295 1571 … … 1332 1608 if (pCtx->uProtocol >= 2) /* Protocol version 2 and up sends a file header first. */ 1333 1609 { 1334 DragAndDropSvc::VBOXDNDGHSENDFILEHDRMSG MsgHdr;1610 VBOXDNDGHSENDFILEHDRMSG MsgHdr; 1335 1611 RT_ZERO(MsgHdr); 1336 1612 MsgHdr.hdr.result = VERR_WRONG_ORDER; 1337 1613 MsgHdr.hdr.u32ClientID = pCtx->uClientID; 1338 MsgHdr.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR;1614 MsgHdr.hdr.u32Function = GUEST_DND_GH_SND_FILE_HDR; 1339 1615 MsgHdr.hdr.cParms = 6; 1340 1616 … … 1360 1636 * Send the actual file data, chunk by chunk. 1361 1637 */ 1362 DragAndDropSvc::VBOXDNDGHSENDFILEDATAMSG Msg;1638 VBOXDNDGHSENDFILEDATAMSG Msg; 1363 1639 RT_ZERO(Msg); 1364 1640 Msg.hdr.result = VERR_WRONG_ORDER; 1365 1641 Msg.hdr.u32ClientID = pCtx->uClientID; 1366 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA; 1367 1368 if (pCtx->uProtocol <= 1) 1369 { 1370 Msg.hdr.cParms = 5; 1371 1372 Msg.u.v1.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 1373 Msg.u.v1.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 1374 Msg.u.v1.fMode.SetUInt32(pObj->GetMode()); 1375 } 1376 else 1377 { 1378 /* Only send context ID, file chunk + chunk size. */ 1379 Msg.hdr.cParms = 3; 1380 1381 Msg.u.v2.uContext.SetUInt32(0); /** @todo Set context ID. */ 1642 Msg.hdr.u32Function = GUEST_DND_GH_SND_FILE_DATA; 1643 1644 switch (pCtx->uProtocol) 1645 { 1646 case 3: 1647 { 1648 Msg.hdr.cParms = 5; 1649 1650 Msg.u.v3.uContext.SetUInt32(0); 1651 Msg.u.v3.pvChecksum.SetPtr(NULL, 0); 1652 Msg.u.v3.cbChecksum.SetUInt32(0); 1653 break; 1654 } 1655 1656 case 2: 1657 { 1658 Msg.hdr.cParms = 3; 1659 1660 Msg.u.v2.uContext.SetUInt32(0); 1661 break; 1662 } 1663 1664 default: /* Protocol v1 */ 1665 { 1666 Msg.hdr.cParms = 5; 1667 1668 Msg.u.v1.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 1669 Msg.u.v1.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 1670 Msg.u.v1.fMode.SetUInt32(pObj->GetMode()); 1671 break; 1672 } 1382 1673 } 1383 1674 … … 1397 1688 && cbRead) 1398 1689 { 1399 if (pCtx->uProtocol <= 1)1690 switch (pCtx->uProtocol) 1400 1691 { 1401 Msg.u.v1.pvData.SetPtr(pvBuf, cbRead); 1402 Msg.u.v1.cbData.SetUInt32(cbRead); 1403 } 1404 else 1405 { 1406 Msg.u.v2.pvData.SetPtr(pvBuf, cbRead); 1407 Msg.u.v2.cbData.SetUInt32(cbRead); 1692 case 3: 1693 { 1694 Msg.u.v3.pvData.SetPtr(pvBuf, cbRead); 1695 Msg.u.v3.cbData.SetUInt32(cbRead); 1696 /** @todo Calculate + set checksums. */ 1697 break; 1698 } 1699 1700 case 2: 1701 { 1702 Msg.u.v2.pvData.SetPtr(pvBuf, cbRead); 1703 Msg.u.v2.cbData.SetUInt32(cbRead); 1704 break; 1705 } 1706 1707 default: 1708 { 1709 Msg.u.v1.pvData.SetPtr(pvBuf, cbRead); 1710 Msg.u.v1.cbData.SetUInt32(cbRead); 1711 break; 1712 } 1408 1713 } 1409 1714 … … 1459 1764 } 1460 1765 1461 static int vbglR3DnDGH ProcessURIMessages(PVBGLR3GUESTDNDCMDCTX pCtx,1462 1766 static int vbglR3DnDGHSendURIData(PVBGLR3GUESTDNDCMDCTX pCtx, 1767 const void *pvData, uint32_t cbData) 1463 1768 { 1464 1769 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); … … 1477 1782 if (RT_SUCCESS(rc)) 1478 1783 { 1479 /* Send metadata; in this case it's the (non-recursive) file/directory 1480 * URI list the host needs to know to initialize the drag'n drop operation. */ 1784 /* 1785 * Send the (meta) data; in case of URIs it's the (non-recursive) file/directory 1786 * URI list the host needs to know upfront to set up the drag'n drop operation. 1787 */ 1481 1788 RTCString strRootDest = lstURI.RootToString(); 1482 Assert(strRootDest.isNotEmpty()); 1483 1484 void *pvToSend = (void *)strRootDest.c_str(); 1485 uint32_t cbToSend = (uint32_t)strRootDest.length() + 1; /* Include string termination. */ 1486 1487 rc = vbglR3DnDGHSendDataInternal(pCtx, pvToSend, cbToSend, 1488 /* Include total bytes of all file paths, 1489 * file sizes etc. */ 1490 (uint32_t)lstURI.TotalBytes()); 1789 if (strRootDest.isNotEmpty()) 1790 { 1791 void *pvURIList = (void *)strRootDest.c_str(); /* URI root list. */ 1792 size_t cbURLIist = strRootDest.length() + 1; /* Include string termination. */ 1793 1794 /* The total size also contains the size of the meta data. */ 1795 uint64_t cbTotal = cbURLIist; 1796 cbTotal += lstURI.TotalBytes(); 1797 1798 /* We're going to send an URI list in text format. */ 1799 char szMetaFmt[] = "text/uri-list"; 1800 1801 VBOXDNDDATAHDR dataHeader; 1802 dataHeader.uFlags = 0; /* Flags not used yet. */ 1803 dataHeader.cbTotal = cbTotal; 1804 dataHeader.cbMeta = cbURLIist; 1805 dataHeader.pvMetaFmt = (void *)szMetaFmt; 1806 dataHeader.cbMetaFmt = strlen(szMetaFmt) + 1; /* Include termination. */ 1807 dataHeader.cObjects = lstURI.TotalCount(); 1808 1809 rc = vbglR3DnDGHSendDataInternal(pCtx, 1810 pvURIList, cbURLIist, &dataHeader); 1811 } 1812 else 1813 rc = VERR_INVALID_PARAMETER; 1491 1814 } 1492 1815 … … 1520 1843 if (DnDMIMEHasFileURLs(pszFormat, strlen(pszFormat))) 1521 1844 { 1522 rc = vbglR3DnDGH ProcessURIMessages(pCtx, pvData, cbData);1523 } 1524 else 1525 { 1526 rc = vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, 0 /* cbAdditionalData*/);1845 rc = vbglR3DnDGHSendURIData(pCtx, pvData, cbData); 1846 } 1847 else /* Send raw data. */ 1848 { 1849 rc = vbglR3DnDGHSendDataInternal(pCtx, pvData, cbData, NULL /* pDataHdr */); 1527 1850 } 1528 1851 … … 1541 1864 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1542 1865 1543 DragAndDropSvc::VBOXDNDGHEVTERRORMSG Msg;1866 VBOXDNDGHEVTERRORMSG Msg; 1544 1867 RT_ZERO(Msg); 1545 1868 Msg.hdr.result = VERR_WRONG_ORDER; 1546 1869 Msg.hdr.u32ClientID = pCtx->uClientID; 1547 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_EVT_ERROR;1870 Msg.hdr.u32Function = GUEST_DND_GH_EVT_ERROR; 1548 1871 Msg.hdr.cParms = 1; 1549 1872
Note:
See TracChangeset
for help on using the changeset viewer.