Changeset 55640 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
- Timestamp:
- May 4, 2015 12:38:57 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r55571 r55640 372 372 void *pvTmpData = RTMemAlloc(cbTmpData); 373 373 if (!pvTmpData) 374 rc = VERR_NO_MEMORY; 375 376 /* Create and query the (unique) drop target directory. */ 374 return VERR_NO_MEMORY; 375 376 /* Create and query the (unique) drop target directory in the user's temporary directory. */ 377 DNDDIRDROPPEDFILES dirDroppedFiles; 378 const char *pszDropDir; 379 rc = DnDDirDroppedFilesCreateAndOpenTemp(&dirDroppedFiles); 380 if (RT_SUCCESS(rc)) 381 pszDropDir = DnDDirDroppedFilesGetDirAbs(&dirDroppedFiles); 382 377 383 DnDURIList lstURI; 378 char szDropDir[RTPATH_MAX];379 if (RT_SUCCESS(rc))380 rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));381 382 if (RT_FAILURE(rc))383 {384 int rc2 = VbglR3DnDHGSetProgress(pCtx, DragAndDropSvc::DND_PROGRESS_ERROR, 100 /* Percent */, rc);385 AssertRC(rc2);386 387 if (pvTmpData)388 RTMemFree(pvTmpData);389 return rc;390 }391 392 /* Lists for holding created files & directories in the case of a rollback. */393 RTCList<RTCString> guestDirList;394 RTCList<RTCString> guestFileList;395 396 384 DnDURIObject objFile(DnDURIObject::File); 397 385 … … 405 393 uint32_t uNextMsg; 406 394 uint32_t cNextParms; 407 LogFlowFunc(("Waiting for new message ...\n"));408 395 rc = vbglR3DnDQueryNextHostMessageType(pCtx, &uNextMsg, &cNextParms, false /* fWait */); 409 396 if (RT_SUCCESS(rc)) … … 423 410 szPathName, cbPathName, fMode, rc)); 424 411 425 /* 426 * Important: HOST_DND_HG_SND_DIR sends the path (directory) name without URI specifications, that is, 427 * only the pure name! To match the accounting though we have to translate the pure name into 428 * a valid URI again. 429 * 430 ** @todo Fix this URI translation! 431 */ 432 RTCString strPath(szPathName); 433 if (RT_SUCCESS(rc)) 434 rc = objFile.RebaseURIPath(strPath); 435 if (RT_SUCCESS(rc)) 412 char *pszPathAbs = RTPathJoinA(pszDropDir, szPathName); 413 if (pszPathAbs) 436 414 { 437 rc = DnDPathSanitize(szPathName, sizeof(szPathName)); 438 char *pszNewDir = RTPathJoinA(szDropDir, szPathName); 439 if (pszNewDir) 415 rc = RTDirCreate(pszPathAbs, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); 416 if (RT_SUCCESS(rc)) 417 rc = DnDDirDroppedAddDir(&dirDroppedFiles, pszPathAbs); 418 419 RTStrFree(pszPathAbs); 420 } 421 else 422 rc = VERR_NO_MEMORY; 423 break; 424 } 425 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR: 426 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA: 427 { 428 if (uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR) 429 rc = vbglR3DnDHGProcessSendFileHdrMessage(pCtx, 430 szPathName, 431 sizeof(szPathName), 432 &fFlags, 433 &fMode, 434 &cbDataToRead); 435 else 436 rc = vbglR3DnDHGProcessSendFileMessage(pCtx, 437 szPathName, 438 sizeof(szPathName), 439 &cbPathName, 440 pvTmpData, 441 cbTmpData, 442 &cbDataRecv, 443 &fMode); 444 if ( RT_SUCCESS(rc) 445 && ( uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR 446 /* Protocol v1 always sends the file name, so try opening every time. */ 447 || pCtx->uProtocol <= 1) 448 ) 449 { 450 char *pszPathAbs = RTPathJoinA(pszDropDir, szPathName); 451 if (pszPathAbs) 440 452 { 441 rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); 442 RTStrFree(pszNewDir); 453 LogFlowFunc(("Opening pszPathName=%s, cbPathName=%RU32, fMode=0x%x, cbSize=%RU64\n", 454 szPathName, cbPathName, fMode, cbDataToRead)); 455 456 uint64_t fOpen = RTFILE_O_WRITE | RTFILE_O_DENY_ALL; 457 if (pCtx->uProtocol <= 1) 458 fOpen |= RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND; 459 else 460 fOpen |= RTFILE_O_CREATE_REPLACE; 461 462 /* Is there already a file open, e.g. in transfer? */ 463 if (!objFile.IsOpen()) 464 { 465 466 RTCString strPathAbs(pszPathAbs); 467 rc = objFile.OpenEx(strPathAbs, DnDURIObject::File, DnDURIObject::Target, fOpen, 468 (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); 469 if (RT_SUCCESS(rc)) 470 { 471 rc = DnDDirDroppedAddFile(&dirDroppedFiles, strPathAbs.c_str()); 472 if (RT_SUCCESS(rc)) 473 { 474 cbDataWritten = 0; 475 476 if (pCtx->uProtocol >= 2) /* Set the expected file size. */ 477 objFile.SetSize(cbDataToRead); 478 } 479 } 480 } 481 else 482 rc = VERR_WRONG_ORDER; 483 484 RTStrFree(pszPathAbs); 443 485 } 444 486 else 445 487 rc = VERR_NO_MEMORY; 446 488 } 489 490 if ( RT_SUCCESS(rc) 491 && uNextMsg == DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA) 492 { 493 bool fClose = false; 494 495 uint32_t cbWritten; 496 rc = objFile.Write(pvTmpData, cbDataRecv, &cbWritten); 447 497 if (RT_SUCCESS(rc)) 448 498 { 449 if (!guestDirList.contains(strPath)) 450 guestDirList.append(strPath); 451 } 452 } 453 break; 454 } 455 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR: 456 { 457 rc = vbglR3DnDHGProcessSendFileHdrMessage(pCtx, 458 szPathName, 459 sizeof(szPathName), 460 &fFlags, 461 &fMode, 462 &cbDataToRead); 463 LogFlowFunc(("HOST_DND_HG_SND_FILE_HDR pszPathName=%s, fFlags=0x%x, fMode=0x%x, cbDataToRead=%RU64, rc=%Rrc\n", 464 szPathName, fFlags, fMode, cbDataToRead, rc)); 465 466 cbDataWritten = 0; 467 break; 468 } 469 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA: 470 { 471 rc = vbglR3DnDHGProcessSendFileMessage(pCtx, 472 szPathName, 473 sizeof(szPathName), 474 &cbPathName, 475 pvTmpData, 476 cbTmpData, 477 &cbDataRecv, 478 &fMode); 479 LogFlowFunc(("HOST_DND_HG_SND_FILE_DATA pszPathName=%s, cbPathName=%RU32, pvData=0x%p, cbDataRecv=%RU32, fMode=0x%x, rc=%Rrc\n", 480 szPathName, cbPathName, pvTmpData, cbDataRecv, fMode, rc)); 481 482 /* 483 * Important: HOST_DND_HG_SND_FILE sends the path (directory) name without URI specifications, that is, 484 * only the pure name! To match the accounting though we have to translate the pure name into 485 * a valid URI again. 486 * 487 ** @todo Fix this URI translation! 488 */ 489 RTCString strPath(szPathName); 490 if (RT_SUCCESS(rc)) 491 rc = objFile.RebaseURIPath(strPath); 492 if (RT_SUCCESS(rc)) 493 { 494 rc = DnDPathSanitize(szPathName, sizeof(szPathName)); 495 if (RT_SUCCESS(rc)) 496 { 497 char *pszPathAbs = RTPathJoinA(szDropDir, szPathName); 498 if (pszPathAbs) 499 if (pCtx->uProtocol >= 2) 499 500 { 500 RTFILE hFile; 501 /** @todo r=andy Keep the file open and locked during the actual file transfer. Otherwise this will 502 * create all sorts of funny races because we don't know if the guest has 503 * modified the file in between the file data send calls. 504 * 505 * See HOST_DND_HG_SND_FILE_HDR for a good place to do this. */ 506 rc = RTFileOpen(&hFile, pszPathAbs, 507 RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE); 508 if (RT_SUCCESS(rc)) 509 { 510 /** @todo r=andy Not very safe to assume that we were last appending to the current file. */ 511 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); 512 if (RT_SUCCESS(rc)) 513 { 514 rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0); 515 if (RT_SUCCESS(rc)) 516 { 517 if (fMode & RTFS_UNIX_MASK) /* Valid UNIX mode? */ 518 rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); 519 520 cbDataWritten += cbDataRecv; 521 Assert(cbDataWritten <= cbDataToRead); 522 } 523 } 524 525 RTFileClose(hFile); 526 527 if (!guestFileList.contains(pszPathAbs)) /* Add the file to (rollback) list. */ 528 guestFileList.append(pszPathAbs); 529 } 530 else 531 LogFlowFunc(("Opening file failed with rc=%Rrc\n", rc)); 532 533 RTStrFree(pszPathAbs); 501 /* Data transfer complete? Close the file. */ 502 fClose = objFile.IsComplete(); 534 503 } 535 504 else 536 rc = VERR_NO_MEMORY; 505 fClose = true; /* Always close the file after each chunk. */ 506 507 cbDataWritten += cbWritten; 508 Assert(cbDataWritten <= cbDataToRead); 509 } 510 511 if (fClose) 512 { 513 LogFlowFunc(("Closing file\n")); 514 objFile.Close(); 537 515 } 538 516 } … … 607 585 #endif 608 586 } 609 else610 {611 /* All URI data processed? */612 if (rc == VERR_NO_DATA)613 rc = VINF_SUCCESS;614 break;615 }616 587 617 588 if (RT_FAILURE(rc)) … … 622 593 LogFlowFunc(("Loop ended with %Rrc\n", rc)); 623 594 595 /* All URI data processed? */ 596 if (rc == VERR_NO_DATA) 597 rc = VINF_SUCCESS; 598 624 599 if (pvTmpData) 625 600 RTMemFree(pvTmpData); 626 601 627 /* Cleanup on failure or if the user has canceled the operation. */ 602 /* Cleanup on failure or if the user has canceled the operation or 603 * something else went wrong. */ 628 604 if (RT_FAILURE(rc)) 629 605 { 630 LogFlowFunc(("Rolling back ...\n")); 631 632 /* Rollback by removing any stuff created. */ 633 for (size_t i = 0; i < guestFileList.size(); ++i) 634 RTFileDelete(guestFileList.at(i).c_str()); 635 for (size_t i = 0; i < guestDirList.size(); ++i) 636 RTDirRemove(guestDirList.at(i).c_str()); 606 int rc2 = DnDDirDroppedFilesRollback(&dirDroppedFiles); 607 AssertRC(rc2); /* Not fatal, don't report back to host. */ 637 608 } 638 609 else … … 647 618 RTMemFree(pvData); 648 619 649 RTCString strData = lstURI.RootToString( szDropDir);620 RTCString strData = lstURI.RootToString(pszDropDir); 650 621 LogFlowFunc(("cbDataToRead: %zu -> %zu\n", cbDataToRead, strData.length() + 1)); 651 622 … … 663 634 } 664 635 665 /* Try removing the (empty) drop directory in any case. */ 666 int rc2 = RTDirRemove(szDropDir); 667 if (RT_FAILURE(rc2)) 668 LogFunc(("Warning: Unable to remove drop directory \"%s\": %Rrc\n", szDropDir, rc2)); 636 /* 637 * Close the dropped files directory. 638 * Don't try to remove it here, however, as the files are being needed 639 * by the client's drag'n drop operation lateron. 640 */ 641 int rc2 = DnDDirDroppedFilesClose(&dirDroppedFiles, false); 642 if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */ 643 LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2)); 669 644 670 645 LogFlowFuncLeaveRC(rc); … … 872 847 AssertPtr(pcbFormatRecv); 873 848 if (DnDMIMEHasFileURLs(pszFormat, *pcbFormatRecv)) 849 { 874 850 rc = vbglR3DnDHGProcessURIMessages(pCtx, 875 851 puScreenId, … … 880 856 cbData, 881 857 pcbDataRecv); 858 } 882 859 else 883 860 rc = VERR_NOT_SUPPORTED; 861 862 if (RT_FAILURE(rc)) 863 { 864 if (RT_FAILURE(rc)) 865 { 866 int rc2 = VbglR3DnDHGSetProgress(pCtx, DragAndDropSvc::DND_PROGRESS_ERROR, 100 /* Percent */, rc); 867 AssertRC(rc2); 868 } 869 } 884 870 } 885 871
Note:
See TracChangeset
for help on using the changeset viewer.