Changeset 58212 in vbox
- Timestamp:
- Oct 13, 2015 11:49:33 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 103344
- Location:
- trunk
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/DragAndDrop.h
r57776 r58212 59 59 int AddFile(const char *pszFile); 60 60 int AddDir(const char *pszDir); 61 int Close(void); 61 62 bool IsOpen(void) const; 62 63 int OpenEx(const char *pszPath, uint32_t fFlags); 63 64 int OpenTemp(uint32_t fFlags); 64 65 const char *GetDirAbs(void) const; 66 int Reopen(void); 65 67 int Reset(bool fDeleteContent); 66 68 int Rollback(void); … … 68 70 protected: 69 71 72 int closeInternal(void); 73 74 protected: 75 76 /** Open flags. */ 77 uint32_t fOpen; 70 78 /** Directory handle for drop directory. */ 71 79 PRTDIR hDir; 72 /** Flag indicating whether the drop directory73 * has been opened for processing or not. */74 bool fOpen;75 80 /** Absolute path to drop directory. */ 76 81 RTCString strPathAbs; … … 197 202 void RemoveFirst(void); 198 203 int RootFromURIData(const void *pvData, size_t cbData, uint32_t fFlags); 199 RTCString RootToString(const RTCString &strPathBase = "", const RTCString &strSeparator = "\r\n") ;204 RTCString RootToString(const RTCString &strPathBase = "", const RTCString &strSeparator = "\r\n") const; 200 205 size_t RootCount(void) const { return m_lstRoot.size(); } 201 206 uint32_t TotalCount(void) const { return m_cTotal; } -
trunk/include/VBox/HostServices/DragAndDropSvc.h
r57500 r58212 22 22 * You may elect to license modified versions of this file under the 23 23 * terms and conditions of either the GPL or the CDDL or both. 24 */ 25 26 /** 27 * Protocol handling and notes: 28 * All client/server components should be backwards compatible. 29 * 30 ****************************************************************************** 31 * 32 * Protocol changelog: 33 * 34 * Protocol v1 (VBox < 5.0): 35 * - Initial implementation which only implemented host to guest transfers. 36 * - For file transfers all file information such as the file name and file size were 37 * transferred with every file data chunk being sent. 38 * 39 * Protocol v2 (VBox 5.0): 40 * - Added support for guest to host transfers. 41 * - Added protocol version support through VBOXDNDCONNECTMSG. The host takes the installed 42 * Guest Additions version as indicator which protocol to use for communicating with the guest. 43 * The guest itself uses VBOXDNDCONNECTMSG to report its supported protocol version to the DnD service. 44 * 45 * Protocol v3 (VBox 5.0+): 46 * - Added VBOXDNDSNDDATAHDR and VBOXDNDCBSNDDATAHDRDATA to support (simple) accounting of objects 47 * being transferred, along with supplying separate meta data size (which is part of the total size being sent). 48 * - Added new HOST_DND_HG_SND_DATA_HDR + GUEST_DND_GH_SND_DATA_HDR commands which now allow specifying an optional 49 * compression type and defining a checksum for the overall data transfer. 50 * - Enhannced VBOXDNDGHSENDDATAMSG to support (rolling) checksums for the supplied data block. 51 * - VBOXDNDHGSENDFILEDATAMSG and VBOXDNDGHSENDFILEDATAMSG are now sharing the same HGCM mesasge. 52 * - VBOXDNDHGSENDDATAMSG and VBOXDNDGHSENDDATAMSG can now contain an optional checksum for the current data block. 53 * - Removed unused HOST_DND_GH_RECV_DIR, HOST_DND_GH_RECV_FILE_DATA and HOST_DND_GH_RECV_FILE_HDR commands. 24 54 */ 25 55 … … 106 136 /** The host requested to cancel the current DnD operation. */ 107 137 HOST_DND_HG_EVT_CANCEL = 204, 108 /** Gets the actual MIME data, based on 109 * the format(s) specified by HOST_DND_HG_EVT_ENTER. If the guest 110 * supplied buffer too small to send the actual data, the host 111 * will send a HOST_DND_HG_SND_MORE_DATA message as follow-up. */ 138 /** Sends the data header at the beginning of a (new) 139 * data transfer. */ 140 HOST_DND_HG_SND_DATA_HDR = 210, 141 /** 142 * Sends the actual meta data, based on 143 * the format(s) specified by HOST_DND_HG_EVT_ENTER. 144 * 145 * Protocol v1/v2: If the guest supplied buffer too small to send 146 * the actual data, the host will send a HOST_DND_HG_SND_MORE_DATA 147 * message as follow-up. 148 * Protocol v3+: The incoming meta data size is specified upfront in the 149 * HOST_DND_HG_SND_DATA_HDR message and must be handled accordingly. 150 */ 112 151 HOST_DND_HG_SND_DATA = 205, 113 /** Sent when the actual buffer for HOST_DND_HG_SND_DATA 114 * was too small, issued by the DnD host service. */152 /** Sent when the actual buffer for HOST_DND_HG_SND_DATA was too small. */ 153 /** @todo Deprecated function; do not use anymore. */ 115 154 HOST_DND_HG_SND_MORE_DATA = 206, 116 155 /** Directory entry to be sent to the guest. */ … … 133 172 * a specific MIME type. */ 134 173 HOST_DND_GH_EVT_DROPPED = 601, 135 /** Creates a directory on the guest. */136 HOST_DND_GH_RECV_DIR = 650,137 /** Retrieves file data from the guest. */138 HOST_DND_GH_RECV_FILE_DATA = 670,139 /** Retrieves a file header from the guest.140 * Note: Only for protocol version 2 and up (>= VBox 5.0). */141 HOST_DND_GH_RECV_FILE_HDR = 671,142 174 /** Blow the type up to 32-bit. */ 143 175 HOST_DND_32BIT_HACK = 0x7fffffff … … 185 217 */ 186 218 GUEST_DND_GH_ACK_PENDING = 500, 219 /** Sends the data header at the beginning of a (new) 220 * data transfer. */ 221 GUEST_DND_GH_SND_DATA_HDR = 503, 187 222 /** 188 223 * Sends data of the requested format to the host. There can … … 227 262 */ 228 263 264 /** 265 * Action message for telling the guest about the currently ongoing 266 * drag and drop action when entering the guest's area, moving around in it 267 * and dropping content into it from the host. 268 * 269 * Used by: 270 * HOST_DND_HG_EVT_ENTER 271 * HOST_DND_HG_EVT_MOVE 272 * HOST_DND_HG_EVT_DROPPED 273 */ 229 274 typedef struct VBOXDNDHGACTIONMSG 230 275 { 231 276 VBoxGuestHGCMCallInfo hdr; 232 277 233 /**234 * HG Action event.235 *236 * Used by:237 * HOST_DND_HG_EVT_ENTER238 * HOST_DND_HG_EVT_MOVE239 * HOST_DND_HG_EVT_DROPPED240 */241 278 HGCMFunctionParameter uScreenId; /* OUT uint32_t */ 242 279 HGCMFunctionParameter uX; /* OUT uint32_t */ … … 248 285 } VBOXDNDHGACTIONMSG; 249 286 287 /** 288 * Tells the guest that the host has left its drag and drop area on the guest. 289 * 290 * Used by: 291 * HOST_DND_HG_EVT_LEAVE 292 */ 250 293 typedef struct VBOXDNDHGLEAVEMSG 251 294 { 252 295 VBoxGuestHGCMCallInfo hdr; 296 } VBOXDNDHGLEAVEMSG; 297 298 299 /** 300 * Tells the guest that the host wants to cancel the current drag and drop operation. 301 * 302 * Used by: 303 * HOST_DND_HG_EVT_CANCEL 304 */ 305 typedef struct VBOXDNDHGCANCELMSG 306 { 307 VBoxGuestHGCMCallInfo hdr; 308 } VBOXDNDHGCANCELMSG; 309 310 /** 311 * Sends the header of an incoming (meta) data block. 312 * 313 * Used by: 314 * HOST_DND_HG_SND_DATA_HDR 315 * GUEST_DND_GH_SND_DATA_HDR 316 * 317 * New since protocol v3. 318 */ 319 typedef struct VBOXDNDHGSENDDATAHDRMSG 320 { 321 VBoxGuestHGCMCallInfo hdr; 322 323 /** Context ID. Unused at the moment. */ 324 HGCMFunctionParameter uContext; /* OUT uint32_t */ 325 /** Data transfer flags. Not yet used and must be 0. */ 326 HGCMFunctionParameter uFlags; /* OUT uint32_t */ 327 /** Screen ID where the data originates from. */ 328 HGCMFunctionParameter uScreenId; /* OUT uint32_t */ 329 /** Total size (in bytes) to transfer. */ 330 HGCMFunctionParameter cbTotal; /* OUT uint64_t */ 253 331 /** 254 * HG Leave event. 332 * Total meta data size (in bytes) to transfer. 333 * This size also is part of cbTotal already, so: 255 334 * 256 * Used by: 257 * HOST_DND_HG_EVT_LEAVE 335 * cbTotal = cbMeta + additional size for files etc. 258 336 */ 259 } VBOXDNDHGLEAVEMSG; 260 261 typedef struct VBOXDNDHGCANCELMSG 262 { 263 VBoxGuestHGCMCallInfo hdr; 264 265 /** 266 * HG Cancel return event. 267 * 268 * Used by: 269 * HOST_DND_HG_EVT_CANCEL 270 */ 271 } VBOXDNDHGCANCELMSG; 272 337 HGCMFunctionParameter cbMeta; /* OUT uint64_t */ 338 /** Meta data format. */ 339 HGCMFunctionParameter pvMetaFmt; /* OUT ptr */ 340 /** Size (in bytes) of meta data format. */ 341 HGCMFunctionParameter cbMetaFmt; /* OUT uint32_t */ 342 /* Number of objects (files/directories) to transfer. */ 343 HGCMFunctionParameter cObjects; /* OUT uint64_t */ 344 /** Compression type. */ 345 HGCMFunctionParameter enmCompression; /* OUT uint32_t */ 346 /** Checksum type. */ 347 HGCMFunctionParameter enmChecksumType; /* OUT uint32_t */ 348 /** Checksum buffer for the entire data to be transferred. */ 349 HGCMFunctionParameter pvChecksum; /* OUT ptr */ 350 /** Size (in bytes) of checksum. */ 351 HGCMFunctionParameter cbChecksum; /* OUT uint32_t */ 352 } VBOXDNDHGSENDDATAHDRMSG; 353 354 /** 355 * Sends a (meta) data block to the guest. 356 * 357 * Used by: 358 * HOST_DND_HG_SND_DATA 359 */ 273 360 typedef struct VBOXDNDHGSENDDATAMSG 274 361 { 275 362 VBoxGuestHGCMCallInfo hdr; 276 363 277 /** 278 * HG Send Data event. 279 * 280 * Used by: 281 * HOST_DND_HG_SND_DATA 282 */ 283 HGCMFunctionParameter uScreenId; /* OUT uint32_t */ 284 HGCMFunctionParameter pvFormat; /* OUT ptr */ 285 HGCMFunctionParameter cFormat; /* OUT uint32_t */ 286 HGCMFunctionParameter pvData; /* OUT ptr */ 287 HGCMFunctionParameter cbData; /* OUT uint32_t */ 364 union 365 { 366 struct 367 { 368 HGCMFunctionParameter uScreenId; /* OUT uint32_t */ 369 HGCMFunctionParameter pvFormat; /* OUT ptr */ 370 HGCMFunctionParameter cbFormat; /* OUT uint32_t */ 371 HGCMFunctionParameter pvData; /* OUT ptr */ 372 HGCMFunctionParameter cbData; /* OUT uint32_t */ 373 } v1; 374 /* No changes in v2. */ 375 struct 376 { 377 /** Context ID. Unused at the moment. */ 378 HGCMFunctionParameter uContext; /* OUT uint32_t */ 379 /** Data block to send. */ 380 HGCMFunctionParameter pvData; /* OUT ptr */ 381 /** Size (in bytes) of data block to send. */ 382 HGCMFunctionParameter cbData; /* OUT uint32_t */ 383 /** Checksum of data block, based on the checksum 384 * type in the data header. Optional. */ 385 HGCMFunctionParameter pvChecksum; /* OUT ptr */ 386 /** Size (in bytes) of checksum to send. */ 387 HGCMFunctionParameter cbChecksum; /* OUT uint32_t */ 388 } v3; 389 } u; 288 390 } VBOXDNDHGSENDDATAMSG; 289 391 392 /** 393 * Sends more (meta) data in case the data didn't fit 394 * into the current XXX_DND_HG_SND_DATA message. 395 * 396 ** @todo Deprecated since protocol v3. Don't use! Will be removed. 397 * 398 * Used by: 399 * HOST_DND_HG_SND_MORE_DATA 400 */ 290 401 typedef struct VBOXDNDHGSENDMOREDATAMSG 291 402 { 292 403 VBoxGuestHGCMCallInfo hdr; 293 404 294 /**295 * HG Send More Data event.296 *297 * Used by:298 * HOST_DND_HG_SND_MORE_DATA299 */300 405 HGCMFunctionParameter pvData; /* OUT ptr */ 301 406 HGCMFunctionParameter cbData; /* OUT uint32_t */ 302 407 } VBOXDNDHGSENDMOREDATAMSG; 303 408 409 /** 410 * Directory entry event. 411 * 412 * Used by: 413 * HOST_DND_HG_SND_DIR 414 * GUEST_DND_GH_SND_DIR 415 */ 304 416 typedef struct VBOXDNDHGSENDDIRMSG 305 417 { 306 418 VBoxGuestHGCMCallInfo hdr; 307 419 308 /** 309 * HG Directory event. 310 * 311 * Used by: 312 * HOST_DND_HG_SND_DIR 313 */ 420 /** Directory name. */ 314 421 HGCMFunctionParameter pvName; /* OUT ptr */ 422 /** Size (in bytes) of directory name. */ 315 423 HGCMFunctionParameter cbName; /* OUT uint32_t */ 424 /** Directory mode. */ 316 425 HGCMFunctionParameter fMode; /* OUT uint32_t */ 317 426 } VBOXDNDHGSENDDIRMSG; 318 427 319 428 /** 320 * File header event.429 * File header message, marking the start of transferring a new file. 321 430 * Note: Only for protocol version 2 and up. 322 431 * 323 432 * Used by: 324 433 * HOST_DND_HG_SND_FILE_HDR 325 * HOST_DND_GH_SND_FILE_HDR434 * GUEST_DND_GH_SND_FILE_HDR 326 435 */ 327 436 typedef struct VBOXDNDHGSENDFILEHDRMSG … … 341 450 /** Total size (in bytes). */ 342 451 HGCMFunctionParameter cbTotal; /* OUT uint64_t */ 343 344 452 } VBOXDNDHGSENDFILEHDRMSG; 345 453 … … 360 468 struct 361 469 { 470 /** File name. */ 362 471 HGCMFunctionParameter pvName; /* OUT ptr */ 472 /** Size (in bytes) of file name. */ 363 473 HGCMFunctionParameter cbName; /* OUT uint32_t */ 474 /** Current data chunk. */ 364 475 HGCMFunctionParameter pvData; /* OUT ptr */ 476 /** Size (in bytes) of current data chunk. */ 365 477 HGCMFunctionParameter cbData; /* OUT uint32_t */ 478 /** File mode. */ 366 479 HGCMFunctionParameter fMode; /* OUT uint32_t */ 367 480 } v1; … … 372 485 /** Context ID. Unused at the moment. */ 373 486 HGCMFunctionParameter uContext; /* OUT uint32_t */ 487 /** Current data chunk. */ 374 488 HGCMFunctionParameter pvData; /* OUT ptr */ 489 /** Size (in bytes) of current data chunk. */ 375 490 HGCMFunctionParameter cbData; /* OUT uint32_t */ 376 491 /** Note: fMode is now part of the VBOXDNDHGSENDFILEHDRMSG message. */ 377 492 } v2; 493 struct 494 { 495 /** Context ID. Unused at the moment. */ 496 HGCMFunctionParameter uContext; /* OUT uint32_t */ 497 /** Current data chunk. */ 498 HGCMFunctionParameter pvData; /* OUT ptr */ 499 /** Size (in bytes) of current data chunk. */ 500 HGCMFunctionParameter cbData; /* OUT uint32_t */ 501 /** Checksum of data block, based on the checksum 502 * type in the data header. Optional. */ 503 HGCMFunctionParameter pvChecksum; /* OUT ptr */ 504 /** Size (in bytes) of curren data chunk checksum. */ 505 HGCMFunctionParameter cbChecksum; /* OUT uint32_t */ 506 } v3; 378 507 } u; 379 380 508 } VBOXDNDHGSENDFILEDATAMSG; 381 509 510 /** 511 * Asks the guest if a guest->host DnD operation is in progress. 512 * 513 * Used by: 514 * HOST_DND_GH_REQ_PENDING 515 */ 382 516 typedef struct VBOXDNDGHREQPENDINGMSG 383 517 { 384 518 VBoxGuestHGCMCallInfo hdr; 385 519 386 /** 387 * GH Request Pending event. 388 * 389 * Used by: 390 * HOST_DND_GH_REQ_PENDING 391 */ 520 /** Screen ID. */ 392 521 HGCMFunctionParameter uScreenId; /* OUT uint32_t */ 393 522 } VBOXDNDGHREQPENDINGMSG; 394 523 524 /** 525 * Tells the guest that the host has dropped the ongoing guest->host 526 * DnD operation on a valid target on the host. 527 * 528 * Used by: 529 * HOST_DND_GH_EVT_DROPPED 530 */ 395 531 typedef struct VBOXDNDGHDROPPEDMSG 396 532 { 397 533 VBoxGuestHGCMCallInfo hdr; 398 534 399 /** 400 * GH Dropped event. 401 * 402 * Used by: 403 * HOST_DND_GH_EVT_DROPPED 404 */ 535 /** Requested format for sending the data. */ 405 536 HGCMFunctionParameter pvFormat; /* OUT ptr */ 406 HGCMFunctionParameter cFormat; /* OUT uint32_t */ 537 /** Size (in bytes) of requested format. */ 538 HGCMFunctionParameter cbFormat; /* OUT uint32_t */ 539 /** Drop action peformed on the host. */ 407 540 HGCMFunctionParameter uAction; /* OUT uint32_t */ 408 541 } VBOXDNDGHDROPPEDMSG; … … 423 556 VBoxGuestHGCMCallInfo hdr; 424 557 425 HGCMFunctionParameter msg; /* OUT uint32_t */ 558 /** Message ID. */ 559 HGCMFunctionParameter uMsg; /* OUT uint32_t */ 426 560 /** Number of parameters the message needs. */ 427 HGCMFunctionParameter num_parms; /* OUT uint32_t */561 HGCMFunctionParameter cParms; /* OUT uint32_t */ 428 562 /** Whether or not to block (wait) for a 429 563 * new message to arrive. */ 430 HGCMFunctionParameter block; /* OUT uint32_t */ 431 564 HGCMFunctionParameter fBlock; /* OUT uint32_t */ 432 565 } VBOXDNDNEXTMSGMSG; 433 566 434 567 /** 435 * Connection request. Used to tell the DnD protocol568 * Guest connection request. Used to tell the DnD protocol 436 569 * version to the (host) service. 437 570 * … … 447 580 /** Connection flags. Optional. */ 448 581 HGCMFunctionParameter uFlags; /* OUT uint32_t */ 449 450 582 } VBOXDNDCONNECTMSG; 451 583 … … 486 618 487 619 /** 488 * GH Acknowledge Pending event. 620 * Acknowledges a pending drag and drop event 621 * to the host. 489 622 * 490 623 * Used by: … … 501 634 502 635 /** 503 * GH Send Data event. 636 * Sends the header of an incoming data block 637 * to the host. 638 * 639 * Used by: 640 * GUEST_DND_GH_SND_DATA_HDR 641 * 642 * New since protocol v3. 643 */ 644 typedef struct VBOXDNDHGSENDDATAHDRMSG VBOXDNDGHSENDDATAHDRMSG; 645 646 /** 647 * Sends a (meta) data block to the host. 504 648 * 505 649 * Used by: … … 507 651 */ 508 652 typedef struct VBOXDNDGHSENDDATAMSG 509 {510 VBoxGuestHGCMCallInfo hdr;511 512 HGCMFunctionParameter pvData; /* OUT ptr */513 /** Total bytes to send. This can be more than514 * the data block specified in pvData above, e.g.515 * when sending over file objects afterwards. */516 HGCMFunctionParameter cbTotalBytes; /* OUT uint32_t */517 } VBOXDNDGHSENDDATAMSG;518 519 /**520 * GH Directory event.521 *522 * Used by:523 * GUEST_DND_GH_SND_DIR524 */525 typedef struct VBOXDNDGHSENDDIRMSG526 {527 VBoxGuestHGCMCallInfo hdr;528 529 HGCMFunctionParameter pvName; /* OUT ptr */530 HGCMFunctionParameter cbName; /* OUT uint32_t */531 HGCMFunctionParameter fMode; /* OUT uint32_t */532 } VBOXDNDGHSENDDIRMSG;533 534 /**535 * GH File header event.536 * Note: Only for protocol version 2 and up.537 *538 * Used by:539 * HOST_DND_GH_SND_FILE_HDR540 */541 typedef struct VBOXDNDHGSENDFILEHDRMSG VBOXDNDGHSENDFILEHDRMSG;542 543 /**544 * GH File data event.545 *546 * Used by:547 * GUEST_DND_HG_SND_FILE_DATA548 */549 typedef struct VBOXDNDGHSENDFILEDATAMSG550 653 { 551 654 VBoxGuestHGCMCallInfo hdr; … … 553 656 union 554 657 { 555 /* Note: Protocol v1 sends the file name + file mode 556 * every time a file data chunk is being sent. */ 557 struct 558 { 559 HGCMFunctionParameter pvName; /* OUT ptr */ 560 HGCMFunctionParameter cbName; /* OUT uint32_t */ 561 HGCMFunctionParameter fMode; /* OUT uint32_t */ 562 HGCMFunctionParameter pvData; /* OUT ptr */ 563 HGCMFunctionParameter cbData; /* OUT uint32_t */ 658 struct 659 { 660 HGCMFunctionParameter pvData; /* OUT ptr */ 661 /** Total bytes to send. This can be more than 662 * the data block specified in pvData above, e.g. 663 * when sending over file objects afterwards. */ 664 HGCMFunctionParameter cbTotalBytes; /* OUT uint32_t */ 564 665 } v1; 565 666 struct 566 667 { 567 /** Note: pvName is now part of the VBOXDNDHGSENDFILEHDRMSG message. */568 /** Note: cbName is now part of the VBOXDNDHGSENDFILEHDRMSG message. */569 668 /** Context ID. Unused at the moment. */ 570 HGCMFunctionParameter uContext; /* OUT uint32_t */ 571 HGCMFunctionParameter pvData; /* OUT ptr */ 572 HGCMFunctionParameter cbData; /* OUT uint32_t */ 573 /** Note: fMode is now part of the VBOXDNDHGSENDFILEHDRMSG message. */ 574 } v2; 669 HGCMFunctionParameter uContext; /* OUT uint32_t */ 670 /** Data block to send. */ 671 HGCMFunctionParameter pvData; /* OUT ptr */ 672 /** Size (in bytes) of data block to send. */ 673 HGCMFunctionParameter cbData; /* OUT uint32_t */ 674 /** (Rolling) Checksum, based on checksum type in data header. */ 675 HGCMFunctionParameter pvChecksum; /* OUT ptr */ 676 /** Size (in bytes) of checksum. */ 677 HGCMFunctionParameter cbChecksum; /* OUT uint32_t */ 678 } v3; 575 679 } u; 576 577 } VBOXDNDGHSENDFILEDATAMSG; 578 579 /** 580 * GH Error event. 680 } VBOXDNDGHSENDDATAMSG; 681 682 /** 683 * Sends a directory entry to the host. 684 * 685 * Used by: 686 * GUEST_DND_GH_SND_DIR 687 */ 688 typedef struct VBOXDNDHGSENDDIRMSG VBOXDNDGHSENDDIRMSG; 689 690 /** 691 * Sends a file header to the host. 692 * 693 * Used by: 694 * GUEST_DND_GH_SND_FILE_HDR 695 * 696 * New since protocol v2. 697 */ 698 typedef struct VBOXDNDHGSENDFILEHDRMSG VBOXDNDGHSENDFILEHDRMSG; 699 700 /** 701 * Sends file data to the host. 702 * 703 * Used by: 704 * GUEST_DND_GH_SND_FILE_DATA 705 */ 706 typedef struct VBOXDNDHGSENDFILEDATAMSG VBOXDNDGHSENDFILEDATAMSG; 707 708 /** 709 * Sends a guest error event to the host. 581 710 * 582 711 * Used by: … … 604 733 CB_MAGIC_DND_GH_ACK_PENDING = 0xbe975a14, 605 734 CB_MAGIC_DND_GH_SND_DATA = 0x4eb61bff, 735 CB_MAGIC_DND_GH_SND_DATA_HDR = 0x4631ee4f, 606 736 CB_MAGIC_DND_GH_SND_DIR = 0x411ca754, 607 737 CB_MAGIC_DND_GH_SND_FILE_HDR = 0x65e35eaf, … … 669 799 } VBOXDNDCBGHACKPENDINGDATA, *PVBOXDNDCBGHACKPENDINGDATA; 670 800 801 /** 802 * Data header. 803 * New since protocol v3. 804 */ 805 typedef struct VBOXDNDDATAHDR 806 { 807 /** Data transfer flags. Not yet used and must be 0. */ 808 uint32_t uFlags; 809 /** Screen ID where the data originates from. */ 810 uint32_t uScreenId; 811 /** Total size (in bytes) to transfer. */ 812 uint64_t cbTotal; 813 /** Meta data size (in bytes) to transfer. 814 * This size also is part of cbTotal already. */ 815 uint32_t cbMeta; 816 /** Meta format buffer. */ 817 void *pvMetaFmt; 818 /** Size (in bytes) of meta format buffer. */ 819 uint32_t cbMetaFmt; 820 /** Number of objects (files/directories) to transfer. */ 821 uint64_t cObjects; 822 /** Compression type. Currently unused, so specify 0. 823 **@todo Add IPRT compression type enumeration as soon as it's available. */ 824 uint32_t enmCompression; 825 /** Checksum type. Currently unused, so specify RTDIGESTTYPE_INVALID. */ 826 RTDIGESTTYPE enmChecksumType; 827 /** The actual checksum buffer for the entire data to be transferred, 828 * based on enmChksumType. If RTDIGESTTYPE_INVALID is specified, 829 * no checksum is being used and pvChecksum will be NULL. */ 830 void *pvChecksum; 831 /** Size (in bytes) of checksum. */ 832 uint32_t cbChecksum; 833 } VBOXDNDDATAHDR, *PVBOXDNDSNDDATAHDR; 834 835 /* New since protocol v3. */ 836 typedef struct VBOXDNDCBSNDDATAHDRDATA 837 { 838 /** Callback data header. */ 839 VBOXDNDCBHEADERDATA hdr; 840 /** Actual header data. */ 841 VBOXDNDDATAHDR data; 842 } VBOXDNDCBSNDDATAHDRDATA, *PVBOXDNDCBSNDDATAHDRDATA; 843 844 typedef struct VBOXDNDSNDDATA 845 { 846 union 847 { 848 struct 849 { 850 /** Data block buffer. */ 851 void *pvData; 852 /** Size (in bytes) of data block. */ 853 uint32_t cbData; 854 /** Total metadata size (in bytes). This is transmitted 855 * with every message because the size can change. */ 856 uint32_t cbTotalSize; 857 } v1; 858 /* Protocol v2: No changes. */ 859 struct 860 { 861 /** Data block buffer. */ 862 void *pvData; 863 /** Size (in bytes) of data block. */ 864 uint32_t cbData; 865 /** (Rolling) Checksum. Not yet implemented. */ 866 void *pvChecksum; 867 /** Size (in bytes) of checksum. Not yet implemented. */ 868 uint32_t cbChecksum; 869 } v3; 870 } u; 871 } VBOXDNDSNDDATA, *PVBOXDNDSNDDATA; 872 671 873 typedef struct VBOXDNDCBSNDDATADATA 672 874 { 673 875 /** Callback data header. */ 674 876 VBOXDNDCBHEADERDATA hdr; 675 void *pvData; 676 uint32_t cbData; 677 /** Total metadata size (in bytes). This is transmitted 678 * with every message because the size can change. */ 679 uint32_t cbTotalSize; 877 /** Actual data. */ 878 VBOXDNDSNDDATA data; 680 879 } VBOXDNDCBSNDDATADATA, *PVBOXDNDCBSNDDATADATA; 681 880 … … 684 883 /** Callback data header. */ 685 884 VBOXDNDCBHEADERDATA hdr; 885 /** Directory path. */ 686 886 char *pszPath; 887 /** Size (in bytes) of path. */ 687 888 uint32_t cbPath; 889 /** Directory creation mode. */ 688 890 uint32_t fMode; 689 891 } VBOXDNDCBSNDDIRDATA, *PVBOXDNDCBSNDDIRDATA; 690 892 691 /* 893 /* Note: Only for protocol version 2 and up (>= VBox 5.0). */ 692 894 typedef struct VBOXDNDCBSNDFILEHDRDATA 693 895 { … … 725 927 uint32_t fMode; 726 928 } v1; 727 /* Note: Protocol version 2 has the file attributes (name, size, 728 mode, ...) in the VBOXDNDCBSNDFILEHDRDATA structure. */ 929 /* Protocol v2 + v3: Have the file attributes (name, size, mode, ...) 930 in the VBOXDNDCBSNDFILEHDRDATA structure. */ 931 struct 932 { 933 /** Checksum for current file data chunk. */ 934 void *pvChecksum; 935 /** Size (in bytes) of current data chunk. */ 936 uint32_t cbChecksum; 937 } v3; 729 938 } u; 730 939 } VBOXDNDCBSNDFILEDATADATA, *PVBOXDNDCBSNDFILEDATADATA; -
trunk/include/VBox/VBoxGuestLib.h
r58204 r58212 125 125 * The library termination function. 126 126 */ 127 DECLVBGL(void) VbglTerminate (void);127 DECLVBGL(void) VbglTerminate (void); 128 128 129 129 … … 149 149 * @return VBox status code. 150 150 */ 151 DECLVBGL(int) VbglGRPerform (VMMDevRequestHeader *pReq);151 DECLVBGL(int) VbglGRPerform (VMMDevRequestHeader *pReq); 152 152 153 153 /** … … 158 158 * @return VBox status code. 159 159 */ 160 DECLVBGL(void) VbglGRFree (VMMDevRequestHeader *pReq);160 DECLVBGL(void) VbglGRFree (VMMDevRequestHeader *pReq); 161 161 162 162 /** … … 170 170 * @return VBox status code. 171 171 */ 172 DECLVBGL(int) VbglGRVerify (const VMMDevRequestHeader *pReq, size_t cbReq);172 DECLVBGL(int) VbglGRVerify (const VMMDevRequestHeader *pReq, size_t cbReq); 173 173 /** @} */ 174 174 … … 205 205 */ 206 206 207 DECLR0VBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo,208 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);207 DECLR0VBGL(int) VbglR0HGCMInternalConnect (VBoxGuestHGCMConnectInfo *pConnectInfo, 208 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData); 209 209 210 210 … … 226 226 */ 227 227 228 DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo,229 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);228 DECLR0VBGL(int) VbglR0HGCMInternalDisconnect (VBoxGuestHGCMDisconnectInfo *pDisconnectInfo, 229 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData); 230 230 231 231 /** Call a HGCM service. … … 243 243 * @return VBox status code. 244 244 */ 245 DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,246 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);245 DECLR0VBGL(int) VbglR0HGCMInternalCall (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 246 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData); 247 247 248 248 /** Call a HGCM service. (32 bits packet structure in a 64 bits guest) … … 260 260 * @return VBox status code. 261 261 */ 262 DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags,263 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData);262 DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 263 PFNVBGLHGCMCALLBACK pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData); 264 264 265 265 /** @name VbglR0HGCMInternalCall flags … … 296 296 * @return VBox status code. 297 297 */ 298 DECLVBGL(int) VbglHGCMConnect (VBGLHGCMHANDLE *pHandle, VBoxGuestHGCMConnectInfo *pData);298 DECLVBGL(int) VbglHGCMConnect (VBGLHGCMHANDLE *pHandle, VBoxGuestHGCMConnectInfo *pData); 299 299 300 300 /** … … 306 306 * @return VBox status code. 307 307 */ 308 DECLVBGL(int) VbglHGCMDisconnect (VBGLHGCMHANDLE handle, VBoxGuestHGCMDisconnectInfo *pData);308 DECLVBGL(int) VbglHGCMDisconnect (VBGLHGCMHANDLE handle, VBoxGuestHGCMDisconnectInfo *pData); 309 309 310 310 /** … … 317 317 * @return VBox status code. 318 318 */ 319 DECLVBGL(int) VbglHGCMCall (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData);319 DECLVBGL(int) VbglHGCMCall (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData); 320 320 321 321 /** … … 329 329 * @return VBox status code. 330 330 */ 331 DECLVBGL(int) VbglHGCMCallUserData (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData);331 DECLVBGL(int) VbglHGCMCallUserData (VBGLHGCMHANDLE handle, VBoxGuestHGCMCallInfo *pData, uint32_t cbData); 332 332 333 333 /** … … 365 365 * @returns VBox status code. 366 366 */ 367 DECLVBGL(int) VbglPhysHeapInit (void);367 DECLVBGL(int) VbglPhysHeapInit (void); 368 368 369 369 /** 370 370 * Shutdown the heap. 371 371 */ 372 DECLVBGL(void) VbglPhysHeapTerminate (void);372 DECLVBGL(void) VbglPhysHeapTerminate (void); 373 373 374 374 /** … … 376 376 * 377 377 * @returns Virtual address of the allocated memory block. 378 * @param 379 */ 380 DECLVBGL(void *) VbglPhysHeapAlloc (uint32_t cbSize);378 * @param cbSize Size of block to be allocated. 379 */ 380 DECLVBGL(void *) VbglPhysHeapAlloc (uint32_t cbSize); 381 381 382 382 /** … … 401 401 DECLVBGL(void) VbglPhysHeapFree(void *pv); 402 402 403 DECLVBGL(int) VbglQueryVMMDevMemory(VMMDevMemory **ppVMMDevMemory);404 DECLR0VBGL(bool) 403 DECLVBGL(int) VbglQueryVMMDevMemory (VMMDevMemory **ppVMMDevMemory); 404 DECLR0VBGL(bool) VbglR0CanUsePhysPageList(void); 405 405 406 406 # ifndef VBOX_GUEST 407 407 /** @name Mouse 408 408 * @{ */ 409 DECLVBGL(int) 410 DECLVBGL(int) 411 DECLVBGL(int) 409 DECLVBGL(int) VbglSetMouseNotifyCallback(PFNVBOXGUESTMOUSENOTIFY pfnNotify, void *pvUser); 410 DECLVBGL(int) VbglGetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py); 411 DECLVBGL(int) VbglSetMouseStatus(uint32_t fFeatures); 412 412 /** @} */ 413 413 # endif /* VBOX_GUEST */ … … 492 492 /** The folder for the video mode hint unix domain socket on Unix-like guests. 493 493 * @note This can be safely changed as all users are rebuilt in lock-step. */ 494 #define VBGLR3HOSTDISPSOCKETPATH 494 #define VBGLR3HOSTDISPSOCKETPATH "/tmp/.VBoxService" 495 495 /** The path to the video mode hint unix domain socket on Unix-like guests. */ 496 496 #define VBGLR3HOSTDISPSOCKET VBGLR3VIDEOMODEHINTSOCKETPATH "/VideoModeHint" … … 758 758 * Use a union for the HGCM stuff then. */ 759 759 760 /** IN: HGCM client ID to use for communication. */760 /** IN: HGCM client ID to use for communication. */ 761 761 uint32_t uClientID; 762 /** IN: Protocol version to use. */762 /** IN: Protocol version to use. */ 763 763 uint32_t uProtocol; 764 764 /** OUT: Number of parameters retrieved. */ 765 765 uint32_t uNumParms; 766 /** IN: Max chunk size (in bytes) for data transfers. */ 767 uint32_t cbMaxChunkSize; 766 768 } VBGLR3GUESTDNDCMDCTX, *PVBGLR3GUESTDNDCMDCTX; 767 769 … … 771 773 uint32_t uScreenId; /** Screen ID this request belongs to. */ 772 774 char *pszFormats; /** Format list (\r\n separated). */ 773 uint32_t cbFormats; /** Size of pszFormats (\0 included). */775 uint32_t cbFormats; /** Size (in bytes) of pszFormats (\0 included). */ 774 776 union 775 777 { … … 784 786 { 785 787 void *pvData; /** Data request. */ 786 size_t cbData; /** Sizeof pvData. */788 uint32_t cbData; /** Size (in bytes) of pvData. */ 787 789 } b; /** Values used in drop data event type. */ 788 790 } u; … … 793 795 VBGLR3DECL(int) VbglR3DnDDisconnect(PVBGLR3GUESTDNDCMDCTX pCtx); 794 796 795 VBGLR3DECL(int) VbglR3DnD ProcessNextMessage(PVBGLR3GUESTDNDCMDCTX pCtx, CPVBGLR3DNDHGCMEVENT pEvent);796 797 VBGLR3DECL(int) VbglR3DnDHG AcknowledgeOperation(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uAction);798 VBGLR3DECL(int) VbglR3DnDHG RequestData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pszFormat);799 VBGLR3DECL(int) VbglR3DnDHGSe tProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr);797 VBGLR3DECL(int) VbglR3DnDRecvNextMsg(PVBGLR3GUESTDNDCMDCTX pCtx, CPVBGLR3DNDHGCMEVENT pEvent); 798 799 VBGLR3DECL(int) VbglR3DnDHGSendAckOp(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uAction); 800 VBGLR3DECL(int) VbglR3DnDHGSendReqData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pcszFormat); 801 VBGLR3DECL(int) VbglR3DnDHGSendProgress(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uStatus, uint8_t uPercent, int rcErr); 800 802 # ifdef VBOX_WITH_DRAG_AND_DROP_GH 801 VBGLR3DECL(int) VbglR3DnDGHAcknowledgePending(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uDefAction, 802 uint32_t uAllActions, const char *pszFormats); 803 VBGLR3DECL(int) VbglR3DnDGHSendAckPending(PVBGLR3GUESTDNDCMDCTX pCtx, uint32_t uDefAction, uint32_t uAllActions, const char* pcszFormats, uint32_t cbFormats); 803 804 VBGLR3DECL(int) VbglR3DnDGHSendData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pszFormat, void *pvData, uint32_t cbData); 804 805 VBGLR3DECL(int) VbglR3DnDGHSendError(PVBGLR3GUESTDNDCMDCTX pCtx, int rcOp); -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
r58157 r58212 22 22 #include <VBox/VBoxGuestLib.h> 23 23 #include "VBox/HostServices/DragAndDropSvc.h" 24 25 using namespace DragAndDropSvc; 24 26 25 27 #include <iprt/asm.h> … … 520 522 switch (pEvent->Event.uType) 521 523 { 522 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:524 case HOST_DND_HG_EVT_ENTER: 523 525 { 524 526 LogFlowThisFunc(("HOST_DND_HG_EVT_ENTER\n")); … … 540 542 } 541 543 542 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:544 case HOST_DND_HG_EVT_MOVE: 543 545 { 544 546 LogFlowThisFunc(("HOST_DND_HG_EVT_MOVE: %d,%d\n", … … 550 552 } 551 553 552 case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:554 case HOST_DND_HG_EVT_LEAVE: 553 555 { 554 556 LogFlowThisFunc(("HOST_DND_HG_EVT_LEAVE\n")); … … 558 560 } 559 561 560 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:562 case HOST_DND_HG_EVT_DROPPED: 561 563 { 562 564 LogFlowThisFunc(("HOST_DND_HG_EVT_DROPPED\n")); … … 566 568 } 567 569 568 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 570 case HOST_DND_HG_SND_DATA: 571 /* Protocol v1 + v2: Also contains the header data. 572 /* Note: Fall through is intentional. */ 573 case HOST_DND_HG_SND_DATA_HDR: 569 574 { 570 575 LogFlowThisFunc(("HOST_DND_HG_SND_DATA\n")); … … 575 580 } 576 581 577 case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:582 case HOST_DND_HG_EVT_CANCEL: 578 583 { 579 584 LogFlowThisFunc(("HOST_DND_HG_EVT_CANCEL\n")); … … 583 588 } 584 589 585 case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:590 case HOST_DND_GH_REQ_PENDING: 586 591 { 587 592 LogFlowThisFunc(("HOST_DND_GH_REQ_PENDING\n")); … … 595 600 } 596 601 597 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:602 case HOST_DND_GH_EVT_DROPPED: 598 603 { 599 604 LogFlowThisFunc(("HOST_DND_GH_EVT_DROPPED\n")); … … 616 621 switch (pEvent->Event.uType) 617 622 { 618 case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:619 case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:620 case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:623 case HOST_DND_HG_EVT_ENTER: 624 case HOST_DND_HG_EVT_MOVE: 625 case HOST_DND_HG_EVT_DROPPED: 621 626 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 622 case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:627 case HOST_DND_GH_EVT_DROPPED: 623 628 #endif 624 629 { … … 628 633 } 629 634 630 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 635 case HOST_DND_HG_SND_DATA: 636 case HOST_DND_HG_SND_DATA_HDR: 631 637 { 632 638 if (pEvent->Event.pszFormats) … … 945 951 if (RT_SUCCESS(rc)) 946 952 { 947 rc = VbglR3DnDHG AcknowledgeOperation(&mDnDCtx, uActionNotify);953 rc = VbglR3DnDHGSendAckOp(&mDnDCtx, uActionNotify); 948 954 if (RT_FAILURE(rc)) 949 955 LogFlowThisFunc(("Acknowledging operation failed with rc=%Rrc\n", rc)); … … 1015 1021 { 1016 1022 LogRel(("DnD: Requesting data as '%s' ...\n", mFormatRequested.c_str())); 1017 rc = VbglR3DnDHG RequestData(&mDnDCtx, mFormatRequested.c_str());1023 rc = VbglR3DnDHGSendReqData(&mDnDCtx, mFormatRequested.c_str()); 1018 1024 if (RT_FAILURE(rc)) 1019 1025 LogFlowThisFunc(("Requesting data failed with rc=%Rrc\n", rc)); … … 1215 1221 uAllActions = uDefAction; 1216 1222 1217 rc = VbglR3DnDGHAcknowledgePending(&mDnDCtx, 1218 uDefAction, uAllActions, strFormats.c_str()); 1223 rc = VbglR3DnDGHSendAckPending(&mDnDCtx, 1224 uDefAction, uAllActions, 1225 strFormats.c_str(), strFormats.length() + 1 /* Include termination */); 1219 1226 if (RT_FAILURE(rc)) 1220 1227 { … … 1761 1768 /* Note: pEvent will be free'd by the consumer later. */ 1762 1769 1763 rc = VbglR3DnDProcessNextMessage(&pCtx->cmdCtx, &pEvent->Event); 1764 LogFlowFunc(("VbglR3DnDProcessNextMessage returned uType=%RU32, rc=%Rrc\n", 1765 pEvent->Event.uType, rc)); 1770 rc = VbglR3DnDRecvNextMsg(&pCtx->cmdCtx, &pEvent->Event); 1771 LogFlowFunc(("VbglR3DnDRecvNextMsg: uType=%RU32, rc=%Rrc\n", pEvent->Event.uType, rc)); 1766 1772 1767 1773 if ( RT_SUCCESS(rc) -
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 -
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r57416 r58212 939 939 uAction = toHGCMAction(static_cast<Atom>(e.xclient.data.l[XdndStatusAction])); 940 940 941 rc = VbglR3DnDHG AcknowledgeOperation(&m_dndCtx, uAction);941 rc = VbglR3DnDHGSendAckOp(&m_dndCtx, uAction); 942 942 } 943 943 else if (e.xclient.message_type == xAtom(XA_XdndFinished)) … … 1821 1821 { 1822 1822 /* No window to process, so send a ignore ack event to the host. */ 1823 rc = VbglR3DnDHG AcknowledgeOperation(&m_dndCtx, DND_IGNORE_ACTION);1823 rc = VbglR3DnDHGSendAckOp(&m_dndCtx, DND_IGNORE_ACTION); 1824 1824 } 1825 1825 else … … 1866 1866 char szFormat[] = { "text/uri-list" }; 1867 1867 1868 int rc = VbglR3DnDHG RequestData(&m_dndCtx, szFormat);1868 int rc = VbglR3DnDHGSendReqData(&m_dndCtx, szFormat); 1869 1869 logInfo("Drop event from host resuled in: %Rrc\n", rc); 1870 1870 … … 2074 2074 } 2075 2075 2076 rc2 = VbglR3DnDGHAcknowledgePending(&m_dndCtx, uDefAction, uAllActions, strFormats.c_str()); 2076 rc2 = VbglR3DnDGHSendAckPending(&m_dndCtx, uDefAction, uAllActions, 2077 strFormats.c_str(), strFormats.length() + 1 /* Include termination */); 2077 2078 LogFlowThisFunc(("uClientID=%RU32, uDefAction=0x%x, allActions=0x%x, strFormats=%s, rc=%Rrc\n", 2078 2079 m_dndCtx.uClientID, uDefAction, uAllActions, strFormats.c_str(), rc2)); … … 3196 3197 3197 3198 /* Wait for new events. */ 3198 rc = VbglR3DnD ProcessNextMessage(&dndCtx, &e.hgcm);3199 rc = VbglR3DnDRecvNextMsg(&dndCtx, &e.hgcm); 3199 3200 if ( RT_SUCCESS(rc) 3200 3201 || rc == VERR_CANCELLED) -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDebugVM.cpp
r57993 r58212 250 250 { 251 251 com::Utf8Str strTmp(strSettings); 252 strSettings = "release: 252 strSettings = "release:"; 253 253 strSettings.append(strTmp); 254 254 } -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp
r58069 r58212 42 42 UIDnDDataObject::UIDnDDataObject(UIDnDHandler *pDnDHandler, const QStringList &lstFormats) 43 43 : m_pDnDHandler(pDnDHandler) 44 , mStatus(Uninitialized) 45 , mRefCount(1) 46 , mcFormats(0) 47 , mpFormatEtc(NULL) 48 , mpStgMedium(NULL) 49 , mSemEvent(NIL_RTSEMEVENT) 50 , mpvData(NULL) 51 , mcbData(0) 44 , m_enmStatus(DnDDataObjectStatus_Uninitialized) 45 , m_cRefs(1) 46 , m_cFormats(0) 47 , m_pFormatEtc(NULL) 48 , m_pStgMedium(NULL) 49 , m_SemEvent(NIL_RTSEMEVENT) 50 , m_fDataRetrieved(false) 51 , m_pvData(NULL) 52 , m_cbData(0) 52 53 { 53 54 HRESULT hr; … … 58 59 try 59 60 { 60 m pFormatEtc = new FORMATETC[cMaxFormats];61 RT_BZERO(m pFormatEtc, sizeof(FORMATETC) * cMaxFormats);62 m pStgMedium = new STGMEDIUM[cMaxFormats];63 RT_BZERO(m pStgMedium, sizeof(STGMEDIUM) * cMaxFormats);61 m_pFormatEtc = new FORMATETC[cMaxFormats]; 62 RT_BZERO(m_pFormatEtc, sizeof(FORMATETC) * cMaxFormats); 63 m_pStgMedium = new STGMEDIUM[cMaxFormats]; 64 RT_BZERO(m_pStgMedium, sizeof(STGMEDIUM) * cMaxFormats); 64 65 65 66 for (int i = 0; … … 68 69 { 69 70 const QString &strFormat = lstFormats.at(i); 70 if (m lstFormats.contains(strFormat))71 if (m_lstFormats.contains(strFormat)) 71 72 continue; 72 73 … … 74 75 if (strFormat.contains("text/uri-list", Qt::CaseInsensitive)) 75 76 { 76 RegisterFormat(&m pFormatEtc[cRegisteredFormats], CF_TEXT);77 m pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL;78 RegisterFormat(&m pFormatEtc[cRegisteredFormats], CF_UNICODETEXT);79 m pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL;80 RegisterFormat(&m pFormatEtc[cRegisteredFormats], CF_HDROP);81 m pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL;82 83 m lstFormats << strFormat;77 RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_TEXT); 78 m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 79 RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_UNICODETEXT); 80 m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 81 RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_HDROP); 82 m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 83 84 m_lstFormats << strFormat; 84 85 } 85 86 /* Plain text ("text/plain"). */ 86 87 if (strFormat.contains("text/plain", Qt::CaseInsensitive)) 87 88 { 88 RegisterFormat(&m pFormatEtc[cRegisteredFormats], CF_TEXT);89 m pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL;90 RegisterFormat(&m pFormatEtc[cRegisteredFormats], CF_UNICODETEXT);91 m pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL;92 93 m lstFormats << strFormat;89 RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_TEXT); 90 m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 91 RegisterFormat(&m_pFormatEtc[cRegisteredFormats], CF_UNICODETEXT); 92 m_pStgMedium[cRegisteredFormats++].tymed = TYMED_HGLOBAL; 93 94 m_lstFormats << strFormat; 94 95 } 95 96 } … … 106 107 if (SUCCEEDED(hr)) 107 108 { 108 int rc2 = RTSemEventCreate(&m SemEvent);109 int rc2 = RTSemEventCreate(&m_SemEvent); 109 110 AssertRC(rc2); 110 111 … … 130 131 RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET)); 131 132 #endif 132 m cFormats= cRegisteredFormats;133 m Status = Dropped;133 m_cFormats = cRegisteredFormats; 134 m_enmStatus = DnDDataObjectStatus_Dropping; 134 135 } 135 136 … … 139 140 UIDnDDataObject::~UIDnDDataObject(void) 140 141 { 141 if (m pFormatEtc)142 delete[] m pFormatEtc;143 144 if (m pStgMedium)145 delete[] m pStgMedium;146 147 if (m pvData)148 RTMemFree(m pvData);149 150 if (m SemEvent != NIL_RTSEMEVENT)151 RTSemEventDestroy(m SemEvent);152 153 LogFlowFunc(("mRefCount=%RI32\n", m RefCount));142 if (m_pFormatEtc) 143 delete[] m_pFormatEtc; 144 145 if (m_pStgMedium) 146 delete[] m_pStgMedium; 147 148 if (m_pvData) 149 RTMemFree(m_pvData); 150 151 if (m_SemEvent != NIL_RTSEMEVENT) 152 RTSemEventDestroy(m_SemEvent); 153 154 LogFlowFunc(("mRefCount=%RI32\n", m_cRefs)); 154 155 } 155 156 … … 160 161 STDMETHODIMP_(ULONG) UIDnDDataObject::AddRef(void) 161 162 { 162 return InterlockedIncrement(&m RefCount);163 return InterlockedIncrement(&m_cRefs); 163 164 } 164 165 165 166 STDMETHODIMP_(ULONG) UIDnDDataObject::Release(void) 166 167 { 167 LONG lCount = InterlockedDecrement(&m RefCount);168 LONG lCount = InterlockedDecrement(&m_cRefs); 168 169 if (lCount == 0) 169 170 { … … 210 211 LPSTGMEDIUM pThisMedium = NULL; 211 212 213 LogFlowThisFunc(("\n")); 214 212 215 /* Format supported? */ 213 216 ULONG lIndex; 214 217 if ( LookupFormatEtc(pFormatEtc, &lIndex) 215 && lIndex < m cFormats) /* Paranoia. */216 { 217 pThisMedium = &m pStgMedium[lIndex];218 && lIndex < m_cFormats) /* Paranoia. */ 219 { 220 pThisMedium = &m_pStgMedium[lIndex]; 218 221 AssertPtr(pThisMedium); 219 pThisFormat = &m pFormatEtc[lIndex];222 pThisFormat = &m_pFormatEtc[lIndex]; 220 223 AssertPtr(pThisFormat); 221 224 222 LogFlow Func(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat));223 LogFlow Func(("mStatus=%ld\n",mStatus));224 switch (m Status)225 LogFlowThisFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat)); 226 LogFlowThisFunc(("mStatus=%RU32\n", m_enmStatus)); 227 switch (m_enmStatus) 225 228 { 226 case D ropping:229 case DnDDataObjectStatus_Dropping: 227 230 { 228 LogRel3(("DnD: Dropping\n")); 229 LogFlowFunc(("Waiting for event ...\n")); 230 int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT); 231 LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus)); 231 #if 0 232 LogRel3(("DnD: Dropping\n")); 233 LogFlowFunc(("Waiting for event ...\n")); 234 int rc2 = RTSemEventWait(m_SemEvent, RT_INDEFINITE_WAIT); 235 LogFlowFunc(("rc=%Rrc, mStatus=%RU32\n", rc2, m_enmStatus)); 236 #endif 237 break; 232 238 } 233 239 234 case D ropped:240 case DnDDataObjectStatus_Dropped: 235 241 { 236 242 LogRel3(("DnD: Dropped\n")); … … 239 245 pThisFormat->tymed, pThisFormat->dwAspect)); 240 246 LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n", 241 m strFormat.toAscii().constData(), mpvData, mcbData));247 m_strFormat.toAscii().constData(), m_pvData, m_cbData)); 242 248 243 249 QVariant::Type vaType; … … 288 294 289 295 int rc; 290 if (!mVaData.isValid()) 296 297 if (!m_fDataRetrieved) 291 298 { 292 /* Note: We're usig Qt::MoveAction because this speeds up the whole operation 293 * significantly: Instead of copying the data from the temporary location to 294 * the final destination we just move it. 295 * 296 * Note2: The Qt::MoveAction *only* affects the behavior on the host! The desired 297 * action for the guest (e.g. moving a file from guest to host) is not affected 298 * by this setting. */ 299 rc = m_pDnDHandler->retrieveData(Qt::MoveAction, 300 strMIMEType, vaType, mVaData); 299 if (m_pDnDHandler) 300 { 301 rc = m_pDnDHandler->retrieveData(Qt::CopyAction, 302 strMIMEType, vaType, m_vaData); 303 } 304 else 305 rc = VERR_NOT_FOUND; 306 307 m_fDataRetrieved = true; 308 LogFlowFunc(("Retrieving data ended with %Rrc\n", rc)); 301 309 } 302 else 303 rc = VINF_SUCCESS; /* Data already retrieved. */ 304 305 if (RT_SUCCESS(rc)) 310 else /* Data already been retrieved. */ 311 rc = VINF_SUCCESS; 312 313 if ( RT_SUCCESS(rc) 314 && m_vaData.isValid()) 306 315 { 307 316 if ( strMIMEType.startsWith("text/uri-list") 308 317 /* One item. */ 309 && ( m VaData.canConvert(QVariant::String)318 && ( m_vaData.canConvert(QVariant::String) 310 319 /* Multiple items. */ 311 || m VaData.canConvert(QVariant::StringList))320 || m_vaData.canConvert(QVariant::StringList)) 312 321 ) 313 322 { 314 QStringList lstFilesURI = m VaData.toStringList();323 QStringList lstFilesURI = m_vaData.toStringList(); 315 324 QStringList lstFiles; 316 325 for (size_t i = 0; i < lstFilesURI.size(); i++) … … 331 340 332 341 size_t cFiles = lstFiles.size(); 342 LogFlowThisFunc(("Files (%zu)\n", cFiles)); 333 343 if ( RT_SUCCESS(rc) 334 344 && cFiles) 335 345 { 336 #ifdef DEBUG 337 LogFlowFunc(("Files (%zu)\n", cFiles)); 338 for (size_t i = 0; i < cFiles; i++) 339 LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).toAscii().constData())); 340 #endif 341 size_t cchFiles = 0; /* Number of ASCII characters. */ 346 size_t cchFiles = 0; /* Number of characters. */ 342 347 for (size_t i = 0; i < cFiles; i++) 343 348 { 344 cchFiles += strlen(lstFiles.at(i).toAscii().constData()); 349 const char *pszFile = lstFiles.at(i).toAscii().constData(); 350 cchFiles += strlen(pszFile); 345 351 cchFiles += 1; /* Terminating '\0'. */ 352 LogFlowThisFunc(("\tFile: %s (cchFiles=%zu)\n", pszFile, cchFiles)); 346 353 } 347 354 348 size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16)); 355 /* List termination with '\0'. */ 356 cchFiles++; 357 358 size_t cbBuf = sizeof(DROPFILES) + (cchFiles * sizeof(RTUTF16)); 349 359 DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf); 350 360 if (pDropFiles) 351 361 { 352 pDropFiles->pFiles = sizeof(DROPFILES); 353 pDropFiles->fWide = 1; /* We use unicode. Always. */ 362 /* Put the files list right after our DROPFILES structure. */ 363 pDropFiles->pFiles = sizeof(DROPFILES); /* Offset to file list. */ 364 pDropFiles->fWide = 1; /* We use Unicode. Always. */ 354 365 355 366 uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles; 356 367 AssertPtr(pCurFile); 357 368 369 LogFlowThisFunc(("Encoded:\n")); 358 370 for (size_t i = 0; i < cFiles; i++) 359 371 { 372 const char *pszFile = lstFiles.at(i).toUtf8().constData(); 373 Assert(strlen(pszFile)); 374 360 375 size_t cchCurFile; 361 376 PRTUTF16 pwszFile; 362 rc = RTStrToUtf16( lstFiles.at(i).toAscii().constData(), &pwszFile);377 rc = RTStrToUtf16(pszFile, &pwszFile); 363 378 if (RT_SUCCESS(rc)) 364 379 { … … 376 391 *pCurFile = L'\0'; 377 392 pCurFile += sizeof(RTUTF16); 393 394 LogFlowThisFunc(("\t#%zu: cchCurFile=%zu\n", i, cchCurFile)); 378 395 } 379 396 … … 382 399 *pCurFile = L'\0'; /* Final list terminator. */ 383 400 384 pMedium->tymed = TYMED_HGLOBAL; 401 /* 402 * Fill out the medium structure we're going to report back. 403 */ 404 pMedium->tymed = TYMED_HGLOBAL; 385 405 pMedium->pUnkForRelease = NULL; 386 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT387 | GMEM_MOVEABLE388 | GMEM_DDESHARE, cbBuf);406 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT 407 | GMEM_MOVEABLE 408 | GMEM_DDESHARE, cbBuf); 389 409 if (pMedium->hGlobal) 390 410 { … … 402 422 else 403 423 rc = VERR_NO_MEMORY; 424 425 LogFlowThisFunc(("Copying to TYMED_HGLOBAL (%zu bytes): %Rrc\n", cbBuf, rc)); 404 426 } 405 427 406 428 RTMemFree(pDropFiles); 407 429 } 430 else 431 rc = VERR_NO_MEMORY; 432 433 if (RT_FAILURE(rc)) 434 LogFlowThisFunc(("Failed with %Rrc\n", rc)); 408 435 } 409 436 } 410 437 else if ( strMIMEType.startsWith("text/plain") 411 && m VaData.canConvert(QVariant::String))438 && m_vaData.canConvert(QVariant::String)) 412 439 { 413 bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT;414 int cbCh= fUnicode415 ? sizeof(WCHAR) : sizeof(char);416 417 QString strText = m VaData.toString();440 const bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT; 441 const size_t cbCh = fUnicode 442 ? sizeof(WCHAR) : sizeof(char); 443 444 QString strText = m_vaData.toString(); 418 445 size_t cbSrc = strText.length() * cbCh; 419 446 Assert(cbSrc); … … 423 450 AssertPtr(pvSrc); 424 451 425 LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cb ch=%d, fUnicode=%RTbool\n",452 LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbCh=%zu, fUnicode=%RTbool\n", 426 453 pvSrc, cbSrc, cbCh, fUnicode)); 427 454 428 pMedium->tymed = TYMED_HGLOBAL;455 pMedium->tymed = TYMED_HGLOBAL; 429 456 pMedium->pUnkForRelease = NULL; 430 pMedium->hGlobal = GlobalAlloc( GMEM_ZEROINIT 431 | GMEM_MOVEABLE 432 | GMEM_DDESHARE, 433 cbSrc); 457 pMedium->hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cbSrc); 434 458 if (pMedium->hGlobal) 435 459 { … … 449 473 } 450 474 else 451 LogFlowFunc(("MIME type=%s not supported\n", 452 strMIMEType.toAscii().constData())); 453 454 LogFlowFunc(("Handling formats ended with rc=%Rrc\n", rc)); 475 LogRel2(("DnD: MIME type '%s' not supported\n", strMIMEType.toAscii().constData())); 476 477 LogFlowThisFunc(("Handling formats ended with rc=%Rrc\n", rc)); 455 478 } 479 480 break; 456 481 } 457 482 … … 488 513 } 489 514 490 LogFlow Func(("Returning hr=%Rhrc\n", hr));515 LogFlowThisFunc(("Returning hr=%Rhrc\n", hr)); 491 516 return hr; 492 517 } … … 535 560 { 536 561 LogFlowFunc(("dwDirection=%RI32, mcFormats=%RI32, mpFormatEtc=%p\n", 537 dwDirection, m cFormats, mpFormatEtc));562 dwDirection, m_cFormats, m_pFormatEtc)); 538 563 539 564 HRESULT hr; 540 565 if (dwDirection == DATADIR_GET) 541 566 { 542 hr = UIDnDEnumFormatEtc::CreateEnumFormatEtc(m cFormats, mpFormatEtc, ppEnumFormatEtc);567 hr = UIDnDEnumFormatEtc::CreateEnumFormatEtc(m_cFormats, m_pFormatEtc, ppEnumFormatEtc); 543 568 } 544 569 else … … 571 596 { 572 597 LogFlowFunc(("Aborting ...\n")); 573 m Status =Aborted;574 return RTSemEventSignal(m SemEvent);598 m_enmStatus = DnDDataObjectStatus_Aborted; 599 return RTSemEventSignal(m_SemEvent); 575 600 } 576 601 … … 661 686 /* puIndex is optional. */ 662 687 663 for (ULONG i = 0; i < m cFormats; i++)664 { 665 if( (pFormatEtc->tymed & m pFormatEtc[i].tymed)666 && pFormatEtc->cfFormat == m pFormatEtc[i].cfFormat667 && pFormatEtc->dwAspect == m pFormatEtc[i].dwAspect)688 for (ULONG i = 0; i < m_cFormats; i++) 689 { 690 if( (pFormatEtc->tymed & m_pFormatEtc[i].tymed) 691 && pFormatEtc->cfFormat == m_pFormatEtc[i].cfFormat 692 && pFormatEtc->dwAspect == m_pFormatEtc[i].dwAspect) 668 693 { 669 694 LogRel3(("DnD: Format found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32, ulIndex=%RU32\n", 670 pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(m pFormatEtc[i].cfFormat),695 pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(m_pFormatEtc[i].cfFormat), 671 696 pFormatEtc->dwAspect, i)); 672 697 … … 677 702 } 678 703 704 #if 0 679 705 LogRel3(("DnD: Format NOT found: tyMed=%RI32, cfFormat=%RI16, sFormats=%s, dwAspect=%RI32\n", 680 706 pFormatEtc->tymed, pFormatEtc->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat), 681 707 pFormatEtc->dwAspect)); 708 #endif 682 709 683 710 return false; 684 }685 686 /* static */687 HGLOBAL UIDnDDataObject::MemDup(HGLOBAL hMemSource)688 {689 DWORD dwLen = GlobalSize(hMemSource);690 AssertReturn(dwLen, NULL);691 PVOID pvSource = GlobalLock(hMemSource);692 if (pvSource)693 {694 PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen);695 if (pvDest)696 memcpy(pvDest, pvSource, dwLen);697 698 GlobalUnlock(hMemSource);699 return pvDest;700 }701 702 return NULL;703 711 } 704 712 … … 719 727 } 720 728 721 void UIDnDDataObject::SetStatus(Status status) 722 { 723 LogFlowFunc(("Setting status to %ld\n", status)); 724 mStatus = status; 729 void UIDnDDataObject::SetStatus(DnDDataObjectStatus enmStatus) 730 { 731 LogFlowFunc(("Setting status to %RU32\n", enmStatus)); 732 m_enmStatus = enmStatus; 733 } 734 735 void UIDnDDataObject::Signal(void) 736 { 737 SetStatus(DnDDataObjectStatus_Dropped); 725 738 } 726 739 … … 732 745 int rc; 733 746 734 SetStatus(Dropped);735 736 mstrFormat = strFormat;737 747 if (cbData) 738 748 { 739 m pvData = RTMemAlloc(cbData);740 if (m pvData)749 m_pvData = RTMemAlloc(cbData); 750 if (m_pvData) 741 751 { 742 memcpy(m pvData, pvData, cbData);743 m cbData = cbData;752 memcpy(m_pvData, pvData, cbData); 753 m_cbData = cbData; 744 754 rc = VINF_SUCCESS; 745 755 } … … 750 760 rc = VINF_SUCCESS; 751 761 752 if (RT_FAILURE(rc)) 753 mStatus = Aborted; 762 if (RT_SUCCESS(rc)) 763 { 764 m_strFormat = strFormat; 765 SetStatus(DnDDataObjectStatus_Dropped); 766 } 767 else 768 SetStatus(DnDDataObjectStatus_Aborted); 754 769 755 770 /* Signal in any case. */ 756 int rc2 = RTSemEventSignal(m SemEvent);771 int rc2 = RTSemEventSignal(m_SemEvent); 757 772 if (RT_SUCCESS(rc)) 758 773 rc = rc2; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h
r56780 r58212 37 37 public: 38 38 39 enum Status39 enum DnDDataObjectStatus 40 40 { 41 Uninitialized = 0, 42 Initialized, 43 Dropping, 44 Dropped, 45 Aborted 41 DnDDataObjectStatus_Uninitialized = 0, 42 DnDDataObjectStatus_Initialized, 43 DnDDataObjectStatus_Dropping, 44 DnDDataObjectStatus_Dropped, 45 DnDDataObjectStatus_Aborted, 46 DnDDataObjectStatus_32Bit_Hack = 0x7fffffff 46 47 }; 47 48 … … 71 72 public: 72 73 73 static const char *ClipboardFormatToString(CLIPFORMAT fmt);74 static const char *ClipboardFormatToString(CLIPFORMAT fmt); 74 75 75 76 int Abort(void); 76 void S etStatus(Status status);77 void Signal(void); 77 78 int Signal(const QString &strFormat, const void *pvData, uint32_t cbData); 78 79 79 80 protected: 80 81 82 void SetStatus(DnDDataObjectStatus enmStatus); 83 81 84 bool LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex); 82 static HGLOBAL MemDup(HGLOBAL hMemSource);83 85 void RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL, 84 86 LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL); 85 87 86 UIDnDHandler *m_pDnDHandler; 87 88 Status mStatus; 89 LONG mRefCount; 88 /** Pointe rto drag and drop handler. */ 89 UIDnDHandler *m_pDnDHandler; 90 /** Current drag and drop status. */ 91 DnDDataObjectStatus m_enmStatus; 92 /** Internal reference count of this object. */ 93 LONG m_cRefs; 90 94 /** Number of native formats registered. This can be a different number than supplied with mlstFormats. */ 91 ULONG mcFormats;92 FORMATETC *mpFormatEtc;93 STGMEDIUM *mpStgMedium;94 RTSEMEVENT mSemEvent;95 QStringList mlstFormats;96 QString mstrFormat;95 ULONG m_cFormats; 96 FORMATETC *m_pFormatEtc; 97 STGMEDIUM *m_pStgMedium; 98 RTSEMEVENT m_SemEvent; 99 QStringList m_lstFormats; 100 QString m_strFormat; 97 101 /** The retrieved data as a QVariant. Needed for buffering in case a second format needs the same data, 98 102 * e.g. CF_TEXT and CF_UNICODETEXT. */ 99 QVariant mVaData; 103 QVariant m_vaData; 104 /** Whether the data already was retrieved or not. */ 105 bool m_fDataRetrieved; 100 106 /** The retrieved data as a raw buffer. */ 101 void *mpvData;107 void *m_pvData; 102 108 /** Raw buffer size (in bytes). */ 103 uint32_t mcbData;109 uint32_t m_cbData; 104 110 }; 105 111 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDropSource_win.cpp
r56780 r58212 24 24 #include <iprt/thread.h> 25 25 26 /* Qt includes: */ 27 #include <QApplication> 28 29 /* Windows includes: */ 30 #include <QApplication> 26 31 #include <windows.h> 27 32 #include <new> /* For bad_alloc. */ 28 33 29 34 #include "UIDnDDropSource_win.h" 35 #include "UIDnDDataObject_win.h" 30 36 31 32 33 UIDnDDropSource::UIDnDDropSource(QWidget *pParent) 34 : mRefCount(1), 35 mpParent(pParent), 36 mdwCurEffect(0), 37 muCurAction(Qt::IgnoreAction) 37 UIDnDDropSource::UIDnDDropSource(QWidget *pParent, UIDnDDataObject *pDataObject) 38 : m_cRefCount(1) 39 , m_pParent(pParent) 40 , m_pDataObject(pDataObject) 41 , m_dwCurEffect(DROPEFFECT_NONE) 42 , m_uCurAction(Qt::IgnoreAction) 38 43 { 39 LogFlowFunc(("pParent=0x%p\n", m pParent));44 LogFlowFunc(("pParent=0x%p\n", m_pParent)); 40 45 } 41 46 42 47 UIDnDDropSource::~UIDnDDropSource(void) 43 48 { 44 LogFlowFunc(("mRefCount=%R I32\n", mRefCount));49 LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount)); 45 50 } 46 51 … … 51 56 STDMETHODIMP_(ULONG) UIDnDDropSource::AddRef(void) 52 57 { 53 return InterlockedIncrement(&mRefCount); 58 LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount + 1)); 59 return (ULONG)InterlockedIncrement(&m_cRefCount); 54 60 } 55 61 56 62 STDMETHODIMP_(ULONG) UIDnDDropSource::Release(void) 57 63 { 58 LONG lCount = InterlockedDecrement(&mRefCount); 59 if (lCount == 0) 64 Assert(m_cRefCount > 0); 65 LogFlowFunc(("mRefCount=%RU32\n", m_cRefCount - 1)); 66 LONG lCount = InterlockedDecrement(&m_cRefCount); 67 if (lCount <= 0) 60 68 { 61 69 delete this; … … 63 71 } 64 72 65 return lCount;73 return (ULONG)lCount; 66 74 } 67 75 … … 94 102 STDMETHODIMP UIDnDDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD dwKeyState) 95 103 { 96 #ifndef DEBUG_andy 97 LogFlowFunc(("fEscapePressed=%RTbool, dwKeyState=0x%x, mdwCurEffect=%RI32, muCurAction=%RU32\n", 98 fEscapePressed, dwKeyState, mdwCurEffect, muCurAction)); 99 #endif 104 LogFlowFunc(("fEscapePressed=%RTbool, dwKeyState=0x%x, m_dwCurEffect=%RI32, m_uCurAction=%RU32\n", 105 RT_BOOL(fEscapePressed), dwKeyState, m_dwCurEffect, m_uCurAction)); 100 106 101 107 /* ESC pressed? Bail out. */ 102 108 if (fEscapePressed) 103 109 { 104 m dwCurEffect = 0;105 m uCurAction= Qt::IgnoreAction;110 m_dwCurEffect = DROPEFFECT_NONE; 111 m_uCurAction = Qt::IgnoreAction; 106 112 107 113 LogRel2(("DnD: User cancelled dropping data to the host\n")); … … 118 124 if (fDropContent) 119 125 { 126 if (m_pDataObject) 127 m_pDataObject->Signal(); 128 120 129 LogRel2(("DnD: User dropped data to the host\n")); 121 130 return DRAGDROP_S_DROP; 122 131 } 132 133 QApplication::processEvents(); 123 134 124 135 /* No change, just continue. */ … … 134 145 STDMETHODIMP UIDnDDropSource::GiveFeedback(DWORD dwEffect) 135 146 { 136 147 Qt::DropActions dropActions = Qt::IgnoreAction; 137 148 138 #ifndef DEBUG_andy139 149 LogFlowFunc(("dwEffect=0x%x\n", dwEffect)); 140 #endif141 150 if (dwEffect) 142 151 { … … 147 156 if (dwEffect & DROPEFFECT_LINK) 148 157 dropActions |= Qt::LinkAction; 158 159 m_dwCurEffect = dwEffect; 149 160 } 150 161 151 mdwCurEffect = dwEffect; 152 muCurAction = dropActions; 162 m_uCurAction = dropActions; 153 163 154 164 return DRAGDROP_S_USEDEFAULTCURSORS; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDropSource_win.h
r55821 r58212 22 22 #include "COMEnums.h" 23 23 24 class UIDnDDataObject; 25 26 /** 27 * Implementation of IDropSource for drag and drop on the host. 28 */ 24 29 class UIDnDDropSource : public IDropSource 25 30 { 26 31 public: 27 32 28 UIDnDDropSource(QWidget *pParent );33 UIDnDDropSource(QWidget *pParent, UIDnDDataObject *pDataObject); 29 34 virtual ~UIDnDDropSource(void); 30 35 31 36 public: 32 37 33 uint32_t GetCurrentAction(void) { return muCurAction; }38 uint32_t GetCurrentAction(void) const { return m_uCurAction; } 34 39 35 40 public: /* IUnknown methods. */ … … 46 51 protected: 47 52 48 LONG mRefCount; 49 QWidget *mpParent; 50 DWORD mdwCurEffect; 51 Qt::DropActions muCurAction; 53 /** Pointer to parent widget. */ 54 QWidget *m_pParent; 55 UIDnDDataObject *m_pDataObject; 56 /** The current reference count. */ 57 LONG m_cRefCount; 58 /** Current (last) drop effect issued. */ 59 DWORD m_dwCurEffect; 60 /** Current drop action to perform in case of a successful drop. */ 61 Qt::DropActions m_uCurAction; 52 62 }; 53 63 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
r57292 r58212 335 335 336 336 # ifdef RT_OS_WINDOWS 337 338 UIDnDDropSource *pDropSource = new UIDnDDropSource(m_pParent);339 if (!pDropSource)340 return VERR_NO_MEMORY;341 337 UIDnDDataObject *pDataObject = new UIDnDDataObject(this, lstFormats); 342 338 if (!pDataObject) 339 return VERR_NO_MEMORY; 340 UIDnDDropSource *pDropSource = new UIDnDDropSource(m_pParent, pDataObject); 341 if (!pDropSource) 343 342 return VERR_NO_MEMORY; 344 343 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
r57288 r58212 109 109 110 110 /* Let the user know. */ 111 LogRel(("D rag and drop support for OS X is disabled in this version."));111 LogRel(("DnD: Drag and drop support for OS X is not available in this version\n")); 112 112 # endif /* VBOX_WITH_DRAG_AND_DROP_PROMISES */ 113 113 #else /* !RT_OS_DARWIN */ … … 120 120 { 121 121 LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction)); 122 rc = VERR_ WRONG_ORDER;122 rc = VERR_NOT_FOUND; 123 123 } 124 124 #endif … … 172 172 173 173 if (RT_FAILURE(rc)) 174 LogRel (("DnD: Retrieving data failed with %Rrc\n", rc));174 LogRel2(("DnD: Retrieving data failed with %Rrc\n", rc)); 175 175 176 176 return QVariant(QVariant::Invalid); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
r58011 r58212 101 101 102 102 103 #ifdef DEBUG_andy 103 #ifdef DEBUG 104 # ifdef DEBUG_andy 104 105 /* Macro for debugging drag and drop actions which usually would 105 106 * go to Main's logging group. */ 106 # define DNDDEBUG(x) LogRel(x) 107 #else 108 # define DNDDEBUG(x) 107 # define DNDDEBUG(x) LogFlowFunc(x) 108 # else 109 # define DNDDEBUG(x) 110 # endif 109 111 #endif 110 112 -
trunk/src/VBox/GuestHost/DragAndDrop/DnDDroppedFiles.cpp
r57776 r58212 28 28 #include <VBox/GuestHost/DragAndDrop.h> 29 29 30 #ifdef LOG_GROUP 31 #undef LOG_GROUP 32 #endif 33 #define LOG_GROUP LOG_GROUP_GUEST_DND 34 #include <VBox/log.h> 35 30 36 DnDDroppedFiles::DnDDroppedFiles(void) 31 37 : hDir(NULL) 32 , fOpen( false) { }33 34 DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, uint32_t f Flags)38 , fOpen(0) { } 39 40 DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, uint32_t fOpen) 35 41 : hDir(NULL) 36 , fOpen( false)37 { 38 OpenEx(pszPath, f Flags);42 , fOpen(0) 43 { 44 OpenEx(pszPath, fOpen); 39 45 } 40 46 41 47 DnDDroppedFiles::~DnDDroppedFiles(void) 42 48 { 43 Reset(true /* fRemoveDropDir */); 49 /* Only make sure to not leak any handles and stuff, don't delete any 50 * directories / files here. */ 51 closeInternal(); 44 52 } 45 53 … … 62 70 } 63 71 72 int DnDDroppedFiles::closeInternal(void) 73 { 74 int rc; 75 if (this->hDir != NULL) 76 { 77 rc = RTDirClose(this->hDir); 78 if (RT_SUCCESS(rc)) 79 this->hDir = NULL; 80 } 81 else 82 rc = VINF_SUCCESS; 83 84 LogFlowFuncLeaveRC(rc); 85 return rc; 86 } 87 88 int DnDDroppedFiles::Close(void) 89 { 90 return closeInternal(); 91 } 92 64 93 const char *DnDDroppedFiles::GetDirAbs(void) const 65 94 { … … 69 98 bool DnDDroppedFiles::IsOpen(void) const 70 99 { 71 return this->fOpen;100 return (this->hDir != NULL); 72 101 } 73 102 … … 129 158 this->hDir = phDir; 130 159 this->strPathAbs = pszDropDir; 131 this->fOpen = true;160 this->fOpen = fFlags; 132 161 } 133 162 } … … 135 164 } while (0); 136 165 166 LogFlowFuncLeaveRC(rc); 137 167 return rc; 138 168 } … … 157 187 int DnDDroppedFiles::Reset(bool fRemoveDropDir) 158 188 { 159 int rc = VINF_SUCCESS; 160 if (this->fOpen) 161 { 162 rc = RTDirClose(this->hDir); 163 if (RT_SUCCESS(rc)) 164 { 165 this->fOpen = false; 166 this->hDir = NULL; 167 } 168 } 169 if (RT_SUCCESS(rc)) 170 { 171 this->lstDirs.clear(); 172 this->lstFiles.clear(); 173 174 if ( fRemoveDropDir 175 && this->strPathAbs.isNotEmpty()) 176 { 177 /* Try removing the (empty) drop directory in any case. */ 178 rc = RTDirRemove(this->strPathAbs.c_str()); 179 if (RT_SUCCESS(rc)) /* Only clear if successfully removed. */ 180 this->strPathAbs = ""; 181 } 182 } 183 184 return rc; 189 int rc = closeInternal(); 190 if (RT_SUCCESS(rc)) 191 { 192 if (fRemoveDropDir) 193 { 194 rc = Rollback(); 195 } 196 else 197 { 198 this->lstDirs.clear(); 199 this->lstFiles.clear(); 200 } 201 } 202 203 LogFlowFuncLeaveRC(rc); 204 return rc; 205 } 206 207 int DnDDroppedFiles::Reopen(void) 208 { 209 if (this->strPathAbs.isEmpty()) 210 return VERR_NOT_FOUND; 211 212 return OpenEx(this->strPathAbs.c_str(), this->fOpen); 185 213 } 186 214 … … 190 218 return VINF_SUCCESS; 191 219 192 Assert(this->fOpen);193 Assert(this->hDir != NULL);194 195 220 int rc = VINF_SUCCESS; 196 int rc2;197 221 198 222 /* Rollback by removing any stuff created. 199 223 * Note: Only remove empty directories, never ever delete 200 224 * anything recursive here! Steam (tm) knows best ... :-) */ 225 int rc2; 201 226 for (size_t i = 0; i < this->lstFiles.size(); i++) 202 227 { 203 228 rc2 = RTFileDelete(this->lstFiles.at(i).c_str()); 229 if (RT_SUCCESS(rc2)) 230 this->lstFiles.removeAt(i); 231 232 if (RT_SUCCESS(rc)) 233 rc = rc2; 234 /* Keep going. */ 235 } 236 237 for (size_t i = 0; i < this->lstDirs.size(); i++) 238 { 239 rc2 = RTDirRemove(this->lstDirs.at(i).c_str()); 240 if (RT_SUCCESS(rc2)) 241 this->lstDirs.removeAt(i); 242 204 243 if (RT_SUCCESS(rc)) 205 244 rc = rc2; 206 } 207 208 for (size_t i = 0; i < this->lstDirs.size(); i++) 209 { 210 rc2 = RTDirRemove(this->lstDirs.at(i).c_str()); 211 if (RT_SUCCESS(rc)) 212 rc = rc2; 213 } 214 215 /* Try to remove the empty root dropped files directory as well. */ 216 rc2 = RTDirRemove(this->strPathAbs.c_str()); 245 /* Keep going. */ 246 } 247 248 if (RT_SUCCESS(rc)) 249 { 250 Assert(this->lstFiles.isEmpty()); 251 Assert(this->lstDirs.isEmpty()); 252 253 rc2 = closeInternal(); 254 if (RT_SUCCESS(rc2)) 255 { 256 /* Try to remove the empty root dropped files directory as well. 257 * Might return VERR_DIR_NOT_EMPTY or similar. */ 258 rc2 = RTDirRemove(this->strPathAbs.c_str()); 259 } 260 } 261 217 262 if (RT_SUCCESS(rc)) 218 263 rc = rc2; 219 264 220 return rc; 221 } 222 265 LogFlowFuncLeaveRC(rc); 266 return rc; 267 } 268 -
trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
r58069 r58212 284 284 RTPathChangeToUnixSlashes(pszPathNative, true /* fForce */); 285 285 286 char *pszPathURI = RTUriCreate("file" /* pszScheme */, "/"/* pszAuthority */,286 char *pszPathURI = RTUriCreate("file" /* pszScheme */, NULL /* pszAuthority */, 287 287 pszPathNative, NULL /* pszQuery */, NULL /* pszFragment */); 288 288 if (pszPathURI) … … 486 486 487 487 RTCString DnDURIList::RootToString(const RTCString &strPathBase /* = "" */, 488 const RTCString &strSeparator /* = "\r\n" */) 488 const RTCString &strSeparator /* = "\r\n" */) const 489 489 { 490 490 RTCString strRet; … … 504 504 { 505 505 strRet += RTCString(pszPathURI) + strSeparator; 506 LogFlowFunc(("URI : %s\n", strRet.c_str()));506 LogFlowFunc(("URI (Base): %s\n", strRet.c_str())); 507 507 RTStrFree(pszPathURI); 508 508 } -
trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
r57372 r58212 84 84 } 85 85 86 case DragAndDropSvc::HOST_DND_HG_SND_DATA_HDR: 87 { 88 LogFlowFunc(("HOST_DND_HG_SND_DATA_HDR\n")); 89 break; 90 } 91 86 92 case DragAndDropSvc::HOST_DND_HG_SND_DATA: 87 93 { … … 116 122 { 117 123 LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n")); 118 119 /* Verify parameter count and types. */120 if ( cParms != 1121 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */)122 {123 rc = VERR_INVALID_PARAMETER;124 }125 124 break; 126 125 } … … 129 128 { 130 129 LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n")); 131 132 /* Verify parameter count and types. */133 if ( cParms != 3134 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */135 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */136 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)137 {138 rc = VERR_INVALID_PARAMETER;139 }140 130 break; 141 131 } … … 147 137 } 148 138 149 if (!pMessage) /* Generic message needed? */ 150 pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 151 152 if (fAppend) 153 m_dndMessageQueue.append(pMessage); 154 else 155 m_dndMessageQueue.prepend(pMessage); 139 if (RT_SUCCESS(rc)) 140 { 141 if (!pMessage) /* Generic message needed? */ 142 pMessage = new DnDGenericMessage(uMsg, cParms, paParms); 143 144 if (fAppend) 145 m_dndMessageQueue.append(pMessage); 146 else 147 m_dndMessageQueue.prepend(pMessage); 148 } 156 149 } 157 150 catch(std::bad_alloc &) -
trunk/src/VBox/HostServices/DragAndDrop/service.cpp
r57760 r58212 16 16 */ 17 17 18 /** @page pg_svc_guest_control Guest ControlHGCM Service18 /** @page pg_svc_guest_control Drag and drop HGCM Service 19 19 * 20 * This service acts as a proxy for handling and buffering host command requests 21 * and clients on the guest. It tries to be as transparent as possible to let 22 * the guest (client) and host side do their protocol handling as desired. 23 * 24 * The following terms are used: 25 * - Host: A host process (e.g. VBoxManage or another tool utilizing the Main API) 26 * which wants to control something on the guest. 27 * - Client: A client (e.g. VBoxService) running inside the guest OS waiting for 28 * new host commands to perform. There can be multiple clients connected 29 * to a service. A client is represented by its HGCM client ID. 30 * - Context ID: An (almost) unique ID automatically generated on the host (Main API) 31 * to not only distinguish clients but individual requests. Because 32 * the host does not know anything about connected clients it needs 33 * an indicator which it can refer to later. This context ID gets 34 * internally bound by the service to a client which actually processes 35 * the command in order to have a relationship between client<->context ID(s). 36 * 37 * The host can trigger commands which get buffered by the service (with full HGCM 38 * parameter info). As soon as a client connects (or is ready to do some new work) 39 * it gets a buffered host command to process it. This command then will be immediately 40 * removed from the command list. If there are ready clients but no new commands to be 41 * processed, these clients will be set into a deferred state (that is being blocked 42 * to return until a new command is available). 43 * 44 * If a client needs to inform the host that something happened, it can send a 45 * message to a low level HGCM callback registered in Main. This callback contains 46 * the actual data as well as the context ID to let the host do the next necessary 47 * steps for this context. This context ID makes it possible to wait for an event 48 * inside the host's Main API function (like starting a process on the guest and 49 * wait for getting its PID returned by the client) as well as cancelling blocking 50 * host calls in order the client terminated/crashed (HGCM detects disconnected 51 * clients and reports it to this service's callback). 20 * TODO 52 21 */ 53 22 … … 63 32 #include <map> 64 33 34 #include <VBox/GuestHost/DragAndDrop.h> 35 #include <VBox/HostServices/Service.h> 36 #include <VBox/HostServices/DragAndDropSvc.h> 37 65 38 #include "dndmanager.h" 66 39 40 using namespace DragAndDropSvc; 67 41 68 42 /********************************************************************************************************************************* … … 158 132 { 159 133 AssertMsgFailed(("Maximum number of clients reached\n")); 160 return VERR_ BUFFER_OVERFLOW;134 return VERR_MAX_PROCS_REACHED; 161 135 } 162 136 … … 263 237 switch (u32Function) 264 238 { 265 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:239 case GUEST_DND_GET_NEXT_HOST_MSG: 266 240 { 267 241 if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF) … … 277 251 } 278 252 279 /* N ote: New since protocol version2. */280 case DragAndDropSvc::GUEST_DND_CONNECT:253 /* New since protocol v2. */ 254 case GUEST_DND_CONNECT: 281 255 { 282 256 /* … … 288 262 break; 289 263 } 290 case DragAndDropSvc::GUEST_DND_HG_ACK_OP:264 case GUEST_DND_HG_ACK_OP: 291 265 /* Fall through is intentional. */ 292 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:266 case GUEST_DND_HG_REQ_DATA: 293 267 /* Fall through is intentional. */ 294 case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:268 case GUEST_DND_HG_EVT_PROGRESS: 295 269 { 296 270 if ( modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL … … 304 278 } 305 279 306 case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING: 307 case DragAndDropSvc::GUEST_DND_GH_SND_DATA: 308 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 309 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR: 310 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA: 311 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR: 280 case GUEST_DND_GH_ACK_PENDING: 281 case GUEST_DND_GH_SND_DATA_HDR: 282 case GUEST_DND_GH_SND_DATA: 283 case GUEST_DND_GH_SND_DIR: 284 case GUEST_DND_GH_SND_FILE_HDR: 285 case GUEST_DND_GH_SND_FILE_DATA: 286 case GUEST_DND_GH_EVT_ERROR: 312 287 { 313 288 #ifdef VBOX_WITH_DRAG_AND_DROP_GH … … 347 322 HGCM::Client *pClient = itClient->second; 348 323 AssertPtr(pClient); 324 325 LogFlowFunc(("Client %RU32: Protocol v%RU32\n", pClient->clientId(), pClient->protocol())); 326 327 rc = VERR_INVALID_PARAMETER; /* Play safe. */ 349 328 350 329 switch (u32Function) … … 357 336 * handle HOST_DND_GH_REQ_PENDING. 358 337 */ 359 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:338 case GUEST_DND_GET_NEXT_HOST_MSG: 360 339 { 361 340 LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n")); 362 if ( cParms != 3 363 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */ 364 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* parameter count */ 365 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* blocking */) 366 { 367 rc = VERR_INVALID_PARAMETER; 368 } 369 else 341 if (cParms == 3) 370 342 { 371 343 rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */); … … 374 346 if (m_pfnHostCallback) /* Try asking the host. */ 375 347 { 376 DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSG data;377 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG;348 VBOXDNDCBHGGETNEXTHOSTMSG data; 349 data.hdr.u32Magic = CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG; 378 350 rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data)); 379 351 if (RT_SUCCESS(rc)) … … 405 377 break; 406 378 } 407 case DragAndDropSvc::GUEST_DND_CONNECT:379 case GUEST_DND_CONNECT: 408 380 { 409 381 LogFlowFunc(("GUEST_DND_CONNECT\n")); 410 if ( cParms != 2 411 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* protocol version */ 412 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* additional connection flags */) 413 rc = VERR_INVALID_PARAMETER; 414 else 382 if (cParms == 2) 415 383 { 416 384 uint32_t uProtocol; … … 420 388 if (RT_SUCCESS(rc)) 421 389 { 390 LogFlowFunc(("Client %RU32 is now using protocol v%RU32\n", pClient->clientId(), pClient->protocol())); 422 391 /** @todo Handle connection flags (paParms[1]). */ 423 392 } … … 428 397 break; 429 398 } 430 case DragAndDropSvc::GUEST_DND_HG_ACK_OP:399 case GUEST_DND_HG_ACK_OP: 431 400 { 432 401 LogFlowFunc(("GUEST_DND_HG_ACK_OP\n")); 433 if ( cParms != 1 434 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* action */) 435 rc = VERR_INVALID_PARAMETER; 436 else 437 { 438 DragAndDropSvc::VBOXDNDCBHGACKOPDATA data; 439 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP; 402 if (cParms == 1) 403 { 404 VBOXDNDCBHGACKOPDATA data; 405 data.hdr.u32Magic = CB_MAGIC_DND_HG_ACK_OP; 440 406 rc = paParms[0].getUInt32(&data.uAction); /* Get drop action. */ 441 407 DO_HOST_CALLBACK(); … … 443 409 break; 444 410 } 445 case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:411 case GUEST_DND_HG_REQ_DATA: 446 412 { 447 413 LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n")); 448 if ( cParms != 1 449 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */) 450 rc = VERR_INVALID_PARAMETER; 451 else 452 { 453 DragAndDropSvc::VBOXDNDCBHGREQDATADATA data; 454 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA; 414 if (cParms == 1) 415 { 416 VBOXDNDCBHGREQDATADATA data; 417 data.hdr.u32Magic = CB_MAGIC_DND_HG_REQ_DATA; 455 418 rc = paParms[0].getPointer((void**)&data.pszFormat, &data.cbFormat); 456 419 DO_HOST_CALLBACK(); … … 458 421 break; 459 422 } 460 case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:423 case GUEST_DND_HG_EVT_PROGRESS: 461 424 { 462 425 LogFlowFunc(("GUEST_DND_HG_EVT_PROGRESS\n")); 463 if ( cParms != 3 464 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* status */ 465 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* percent */ 466 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */) 467 rc = VERR_INVALID_PARAMETER; 468 else 469 { 470 DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data; 471 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS; 426 if (cParms == 3) 427 { 428 VBOXDNDCBHGEVTPROGRESSDATA data; 429 data.hdr.u32Magic = CB_MAGIC_DND_HG_EVT_PROGRESS; 472 430 rc = paParms[0].getUInt32(&data.uStatus); 473 431 if (RT_SUCCESS(rc)) … … 480 438 } 481 439 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 482 case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:440 case GUEST_DND_GH_ACK_PENDING: 483 441 { 484 442 LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n")); 485 if ( cParms != 3 486 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* defaction */ 487 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* alloctions */ 488 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* format */) 489 rc = VERR_INVALID_PARAMETER; 490 else 491 { 492 DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA data; 493 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING; 443 if (cParms == 3) 444 { 445 VBOXDNDCBGHACKPENDINGDATA data; 446 data.hdr.u32Magic = CB_MAGIC_DND_GH_ACK_PENDING; 494 447 rc = paParms[0].getUInt32(&data.uDefAction); 495 448 if (RT_SUCCESS(rc)) … … 501 454 break; 502 455 } 503 case DragAndDropSvc::GUEST_DND_GH_SND_DATA: 456 /* New since protocol v3. */ 457 case GUEST_DND_GH_SND_DATA_HDR: 458 { 459 LogFlowFunc(("GUEST_DND_GH_SND_DATA_HDR\n")); 460 if (cParms == 12) 461 { 462 VBOXDNDCBSNDDATAHDRDATA data; 463 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_DATA_HDR; 464 rc = paParms[0].getUInt32(&data.hdr.u32ContextID); 465 if (RT_SUCCESS(rc)) 466 rc = paParms[1].getUInt32(&data.data.uFlags); 467 if (RT_SUCCESS(rc)) 468 rc = paParms[2].getUInt32(&data.data.uScreenId); 469 if (RT_SUCCESS(rc)) 470 rc = paParms[3].getUInt64(&data.data.cbTotal); 471 if (RT_SUCCESS(rc)) 472 rc = paParms[4].getUInt32(&data.data.cbMeta); 473 if (RT_SUCCESS(rc)) 474 rc = paParms[5].getPointer(&data.data.pvMetaFmt, &data.data.cbMetaFmt); 475 if (RT_SUCCESS(rc)) 476 rc = paParms[6].getUInt32(&data.data.cbMetaFmt); 477 if (RT_SUCCESS(rc)) 478 rc = paParms[7].getUInt64(&data.data.cObjects); 479 if (RT_SUCCESS(rc)) 480 rc = paParms[8].getUInt32(&data.data.enmCompression); 481 if (RT_SUCCESS(rc)) 482 rc = paParms[9].getUInt32((uint32_t *)&data.data.enmChecksumType); 483 if (RT_SUCCESS(rc)) 484 rc = paParms[10].getPointer(&data.data.pvChecksum, &data.data.cbChecksum); 485 if (RT_SUCCESS(rc)) 486 rc = paParms[11].getUInt32(&data.data.cbChecksum); 487 488 LogFlowFunc(("fFlags=0x%x, cbTotalSize=%RU64, cObj=%RU64\n", 489 data.data.uFlags, data.data.cbTotal, data.data.cObjects)); 490 DO_HOST_CALLBACK(); 491 } 492 break; 493 } 494 case GUEST_DND_GH_SND_DATA: 504 495 { 505 496 LogFlowFunc(("GUEST_DND_GH_SND_DATA\n")); 506 if ( cParms != 2 507 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* data */ 508 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* size */) 509 rc = VERR_INVALID_PARAMETER; 510 else 511 { 512 DragAndDropSvc::VBOXDNDCBSNDDATADATA data; 513 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA; 514 rc = paParms[0].getPointer((void**)&data.pvData, &data.cbData); 515 if (RT_SUCCESS(rc)) 516 rc = paParms[1].getUInt32(&data.cbTotalSize); 517 DO_HOST_CALLBACK(); 518 } 519 break; 520 } 521 case DragAndDropSvc::GUEST_DND_GH_SND_DIR: 497 switch (pClient->protocol()) 498 { 499 case 3: 500 { 501 if (cParms == 5) 502 { 503 VBOXDNDCBSNDDATADATA data; 504 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_DATA; 505 rc = paParms[0].getUInt32(&data.hdr.u32ContextID); 506 if (RT_SUCCESS(rc)) 507 rc = paParms[1].getPointer((void**)&data.data.u.v3.pvData, &data.data.u.v3.cbData); 508 if (RT_SUCCESS(rc)) 509 rc = paParms[2].getUInt32(&data.data.u.v3.cbData); 510 if (RT_SUCCESS(rc)) 511 rc = paParms[3].getPointer((void**)&data.data.u.v3.pvChecksum, &data.data.u.v3.cbChecksum); 512 if (RT_SUCCESS(rc)) 513 rc = paParms[4].getUInt32(&data.data.u.v3.cbChecksum); 514 DO_HOST_CALLBACK(); 515 } 516 break; 517 } 518 519 case 2: 520 default: 521 { 522 if (cParms == 2) 523 { 524 VBOXDNDCBSNDDATADATA data; 525 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_DATA; 526 rc = paParms[0].getPointer((void**)&data.data.u.v1.pvData, &data.data.u.v1.cbData); 527 if (RT_SUCCESS(rc)) 528 rc = paParms[1].getUInt32(&data.data.u.v1.cbTotalSize); 529 DO_HOST_CALLBACK(); 530 } 531 break; 532 } 533 } 534 break; 535 } 536 case GUEST_DND_GH_SND_DIR: 522 537 { 523 538 LogFlowFunc(("GUEST_DND_GH_SND_DIR\n")); 524 if ( cParms != 3 525 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* path */ 526 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* path length */ 527 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */) 528 rc = VERR_INVALID_PARAMETER; 529 else 530 { 531 DragAndDropSvc::VBOXDNDCBSNDDIRDATA data; 532 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR; 539 if (cParms == 3) 540 { 541 VBOXDNDCBSNDDIRDATA data; 542 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_DIR; 533 543 uint32_t cTmp; 534 544 rc = paParms[0].getPointer((void**)&data.pszPath, &cTmp); … … 543 553 break; 544 554 } 545 /* N ote: Since protocol v2 (>= VBox 5.0). */546 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR:555 /* New since protocol v2 (>= VBox 5.0). */ 556 case GUEST_DND_GH_SND_FILE_HDR: 547 557 { 548 558 LogFlowFunc(("GUEST_DND_GH_SND_FILE_HDR\n")); 549 if ( cParms != 6 550 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* context ID */ 551 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* file path */ 552 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* file path length */ 553 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* flags */ 554 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* file mode */ 555 || paParms[5].type != VBOX_HGCM_SVC_PARM_64BIT /* file size */) 556 rc = VERR_INVALID_PARAMETER; 557 else 558 { 559 DragAndDropSvc::VBOXDNDCBSNDFILEHDRDATA data; 560 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_HDR; 559 if (cParms == 6) 560 { 561 VBOXDNDCBSNDFILEHDRDATA data; 562 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_FILE_HDR; 561 563 uint32_t cTmp; 562 564 /* paParms[0] is context ID; unused yet. */ … … 577 579 break; 578 580 } 579 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA:581 case GUEST_DND_GH_SND_FILE_DATA: 580 582 { 581 583 LogFlowFunc(("GUEST_DND_GH_SND_FILE_DATA\n")); … … 583 585 switch (pClient->protocol()) 584 586 { 585 case 2: /* Protocol version 2 only sends the next data chunks to reduce traffic. */ 587 /* Protocol v3 adds (optional) checksums. */ 588 case 3: 586 589 { 587 if ( cParms != 3 588 /* paParms[0] is context ID; unused yet. */ 589 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* file data */ 590 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* file data length */) 590 if (cParms == 5) 591 591 { 592 rc = VERR_INVALID_PARAMETER; 592 VBOXDNDCBSNDFILEDATADATA data; 593 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_FILE_DATA; 594 rc = paParms[0].getUInt32(&data.hdr.u32ContextID); 595 if (RT_SUCCESS(rc)) 596 rc = paParms[1].getPointer((void**)&data.pvData, &data.cbData); 597 if (RT_SUCCESS(rc)) 598 rc = paParms[2].getUInt32(&data.cbData); 599 if (RT_SUCCESS(rc)) 600 rc = paParms[3].getPointer((void**)&data.u.v3.pvChecksum, &data.u.v3.cbChecksum); 601 if (RT_SUCCESS(rc)) 602 rc = paParms[4].getUInt32(&data.u.v3.cbChecksum); 603 604 LogFlowFunc(("pvData=0x%p, cbData=%RU32\n", data.pvData, data.cbData)); 605 DO_HOST_CALLBACK(); 593 606 } 594 else 607 break; 608 } 609 /* Protocol v2 only sends the next data chunks to reduce traffic. */ 610 case 2: 611 { 612 if (cParms == 3) 595 613 { 596 DragAndDropSvc::VBOXDNDCBSNDFILEDATADATA data; 597 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_DATA; 598 /* paParms[0] is context ID; unused yet. */ 599 rc = paParms[1].getPointer((void**)&data.pvData, &data.cbData); 614 VBOXDNDCBSNDFILEDATADATA data; 615 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_FILE_DATA; 616 rc = paParms[0].getUInt32(&data.hdr.u32ContextID); 617 if (RT_SUCCESS(rc)) 618 rc = paParms[1].getPointer((void**)&data.pvData, &data.cbData); 600 619 if (RT_SUCCESS(rc)) 601 620 rc = paParms[2].getUInt32(&data.cbData); … … 606 625 break; 607 626 } 627 /* Protocol v1 sends the file path and attributes for every file chunk (!). */ 608 628 default: 609 629 { 610 if ( cParms != 5 611 || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* file path */ 612 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* file path length */ 613 || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR /* file data */ 614 || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* file data length */ 615 || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */) 630 if (cParms == 5) 616 631 { 617 rc = VERR_INVALID_PARAMETER; 618 } 619 else 620 { 621 DragAndDropSvc::VBOXDNDCBSNDFILEDATADATA data; 622 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_DATA; 632 VBOXDNDCBSNDFILEDATADATA data; 633 data.hdr.u32Magic = CB_MAGIC_DND_GH_SND_FILE_DATA; 623 634 uint32_t cTmp; 624 635 rc = paParms[0].getPointer((void**)&data.u.v1.pszFilePath, &cTmp); … … 641 652 break; 642 653 } 643 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:654 case GUEST_DND_GH_EVT_ERROR: 644 655 { 645 656 LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n")); 646 if ( cParms != 1 647 || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */) 648 rc = VERR_INVALID_PARAMETER; 649 else 650 { 651 DragAndDropSvc::VBOXDNDCBEVTERRORDATA data; 652 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR; 657 if (cParms == 1) 658 { 659 VBOXDNDCBEVTERRORDATA data; 660 data.hdr.u32Magic = CB_MAGIC_DND_GH_EVT_ERROR; 653 661 654 662 uint32_t rcOp; … … 670 678 if (m_pfnHostCallback) 671 679 { 672 DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSGDATA data;673 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA;680 VBOXDNDCBHGGETNEXTHOSTMSGDATA data; 681 data.hdr.u32Magic = CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA; 674 682 data.uMsg = u32Function; 675 683 data.cParms = cParms; … … 728 736 729 737 int rc; 730 if (u32Function == DragAndDropSvc::HOST_DND_SET_MODE)738 if (u32Function == HOST_DND_SET_MODE) 731 739 { 732 740 if (cParms != 1) … … 755 763 */ 756 764 uint32_t uMsg = pClient->message(); 757 if (uMsg == DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG)765 if (uMsg == GUEST_DND_GET_NEXT_HOST_MSG) 758 766 { 759 767 LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId())); … … 822 830 uStatus, uPercentage, rc)); 823 831 824 DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA data;825 data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS;832 VBOXDNDCBHGEVTPROGRESSDATA data; 833 data.hdr.u32Magic = CB_MAGIC_DND_HG_EVT_PROGRESS; 826 834 data.uPercentage = RT_MIN(uPercentage, 100); 827 835 data.uStatus = uStatus; … … 829 837 830 838 return pSelf->m_pfnHostCallback(pSelf->m_pvHostData, 831 DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS,839 GUEST_DND_HG_EVT_PROGRESS, 832 840 &data, sizeof(data)); 833 841 } -
trunk/src/VBox/Main/include/GuestDnDPrivate.h
r57776 r58212 22 22 #include <iprt/dir.h> 23 23 #include <iprt/file.h> 24 25 #include "VBox/hgcmsvc.h" /* For PVBOXHGCMSVCPARM. */ 26 #include "VBox/GuestHost/DragAndDrop.h" 24 #include <iprt/path.h> 25 26 #include <VBox/hgcmsvc.h> /* For PVBOXHGCMSVCPARM. */ 27 #include <VBox/GuestHost/DragAndDrop.h> 28 #include <VBox/HostServices/DragAndDropSvc.h> 29 30 #ifdef LOG_GROUP 31 #undef LOG_GROUP 32 #endif 33 #define LOG_GROUP LOG_GROUP_GUEST_DND 34 #include <VBox/log.h> 27 35 28 36 /** … … 36 44 class Progress; 37 45 46 /** 47 * Type definitions. 48 */ 49 50 /** List (vector) of MIME types. */ 51 typedef std::vector<com::Utf8Str> GuestDnDMIMEList; 52 38 53 class GuestDnDCallbackEvent 39 54 { … … 65 80 66 81 /** 67 * Structure for keeping the (URI) data to be sent/received.68 */ 69 typedef struct GuestDnDData82 * Class for handling the (raw) meta data. 83 */ 84 class GuestDnDMetaData 70 85 { 86 public: 87 88 GuestDnDMetaData(void) 89 : pvData(NULL) 90 , cbData(0) 91 , cbDataUsed(0) { } 92 93 virtual ~GuestDnDMetaData(void) 94 { 95 reset(); 96 } 97 98 public: 99 100 size_t add(const void *pvDataAdd, size_t cbDataAdd) 101 { 102 if (!cbDataAdd) 103 return 0; 104 AssertPtrReturn(pvDataAdd, 0); 105 106 int rc = resize(cbData + cbDataAdd); 107 if (RT_FAILURE(rc)) 108 return 0; 109 110 Assert(cbData >= cbDataUsed + cbDataAdd); 111 memcpy((uint8_t *)pvData + cbDataUsed, pvDataAdd, cbDataAdd); 112 113 cbDataUsed += cbDataAdd; 114 115 return cbDataAdd; 116 } 117 118 size_t add(const std::vector<BYTE> &vecAdd) 119 { 120 if (!vecAdd.size()) 121 return 0; 122 123 return add(&vecAdd.front(), vecAdd.size()); 124 } 125 126 void reset(void) 127 { 128 if (pvData) 129 { 130 Assert(cbData); 131 RTMemFree(pvData); 132 pvData = NULL; 133 } 134 135 cbData = 0; 136 cbDataUsed = 0; 137 } 138 139 const void *getData(void) const { return pvData; } 140 141 void *getDataMutable(void) { return pvData; } 142 143 size_t getSize(void) const { return cbDataUsed; } 144 145 public: 146 147 int fromString(const RTCString &strData) 148 { 149 int rc = VINF_SUCCESS; 150 151 if (strData.isNotEmpty()) 152 { 153 const size_t cbData = strData.length() + 1; /* Include terminating zero. */ 154 rc = resize(cbData); 155 if (RT_SUCCESS(rc)) 156 memcpy(pvData, strData.c_str(), cbData); 157 } 158 159 return rc; 160 } 161 162 int fromURIList(const DnDURIList &lstURI) 163 { 164 return fromString(lstURI.RootToString()); 165 } 166 167 protected: 168 169 int resize(size_t cbSize) 170 { 171 if (!cbSize) 172 { 173 reset(); 174 return VINF_SUCCESS; 175 } 176 177 if (cbSize == cbData) 178 return VINF_SUCCESS; 179 180 void *pvTmp = NULL; 181 if (!cbData) 182 { 183 Assert(cbDataUsed == 0); 184 pvTmp = RTMemAllocZ(cbSize); 185 } 186 else 187 { 188 AssertPtr(pvData); 189 pvTmp = RTMemRealloc(pvData, cbSize); 190 RT_BZERO(pvTmp, cbSize); 191 } 192 193 if (pvTmp) 194 { 195 pvData = pvTmp; 196 cbData = cbSize; 197 return VINF_SUCCESS; 198 } 199 200 return VERR_NO_MEMORY; 201 } 202 203 protected: 204 205 void *pvData; 206 size_t cbData; 207 size_t cbDataUsed; 208 }; 209 210 /** 211 * Class for keeping drag and drop (meta) data 212 * to be sent/received. 213 */ 214 class GuestDnDData 215 { 216 public: 217 71 218 GuestDnDData(void) 72 : cbToProcess(0) 73 , cbProcessed(0) { } 74 75 void Reset(void) 76 { 77 vecData.clear(); 78 cbToProcess = 0; 219 : cbProcessed(0) 220 , cbAddData(0) { } 221 222 virtual ~GuestDnDData(void) 223 { 224 reset(); 225 } 226 227 public: 228 229 uint64_t addProcessed(uint32_t cbDataAdd) 230 { 231 const uint64_t cbTotal = getTotal(); 232 Assert(cbProcessed + cbDataAdd <= cbTotal); 233 cbProcessed += cbDataAdd; 234 return cbProcessed; 235 } 236 237 bool isComplete(void) const 238 { 239 const uint64_t cbTotal = getTotal(); 240 Assert(cbProcessed <= cbTotal); 241 return (cbProcessed == cbTotal); 242 } 243 244 void *getChkSumMutable(void) { return dataHdr.pvChecksum; } 245 246 uint32_t getChkSumSize(void) const { return dataHdr.cbChecksum; } 247 248 void *getFmtMutable(void) { return dataHdr.pvMetaFmt; } 249 250 uint32_t getFmtSize(void) const { return dataHdr.cbMetaFmt; } 251 252 GuestDnDMetaData &getMeta(void) { return dataMeta; } 253 254 uint8_t getPercentComplete(void) const 255 { 256 int64_t cbTotal = RT_MAX(getTotal(), 1); 257 return (uint8_t)(cbProcessed * 100 / cbTotal); 258 } 259 260 uint64_t getProcessed(void) const { return cbProcessed; } 261 262 uint64_t getRemaining(void) const 263 { 264 const uint64_t cbTotal = getTotal(); 265 Assert(cbProcessed <= cbTotal); 266 return cbTotal - cbProcessed; 267 } 268 269 uint64_t getTotal(void) const { return dataMeta.getSize() + cbAddData; } 270 271 void reset(void) 272 { 273 clearFmt(); 274 clearChkSum(); 275 276 RT_ZERO(dataHdr); 277 278 dataMeta.reset(); 79 279 cbProcessed = 0; 80 } 81 82 /** Array (vector) of guest DnD data. This might be an URI list, according 83 * to the format being set. */ 84 std::vector<BYTE> vecData; 85 /** Overall size (in bytes) of data to send. */ 86 uint64_t cbToProcess; 87 /** Overall size (in bytes) of processed file data. */ 88 uint64_t cbProcessed; 89 90 } GuestDnDData; 280 cbAddData = 0; 281 } 282 283 int setFmt(const void *pvFmt, uint32_t cbFmt) 284 { 285 if (cbFmt) 286 { 287 AssertPtrReturn(pvFmt, VERR_INVALID_POINTER); 288 void *pvFmtTmp = RTMemAlloc(cbFmt); 289 if (!pvFmtTmp) 290 return VERR_NO_MEMORY; 291 292 clearFmt(); 293 294 memcpy(pvFmtTmp, pvFmt, cbFmt); 295 296 dataHdr.pvMetaFmt = pvFmtTmp; 297 dataHdr.cbMetaFmt = cbFmt; 298 } 299 else 300 clearFmt(); 301 302 return VINF_SUCCESS; 303 } 304 305 void setAdditionalSize(uint64_t cbAdd) 306 { 307 LogFlowFunc(("cbAdd=%RU64\n", cbAdd)); 308 309 cbAddData = cbAdd; 310 311 invalidate(); 312 } 313 314 void setEstimatedSize(uint64_t cbTotal, uint32_t cbMeta) 315 { 316 Assert(cbMeta <= cbTotal); 317 318 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU64\n", cbTotal, cbMeta)); 319 320 dataMeta.reset(); 321 322 dataHdr.cbMeta = cbMeta; 323 setAdditionalSize(cbTotal - cbMeta); 324 } 325 326 protected: 327 328 void clearChkSum(void) 329 { 330 if (dataHdr.pvChecksum) 331 { 332 Assert(dataHdr.cbChecksum); 333 RTMemFree(dataHdr.pvChecksum); 334 dataHdr.pvChecksum = NULL; 335 } 336 337 dataHdr.cbChecksum = 0; 338 } 339 340 void clearFmt(void) 341 { 342 if (dataHdr.pvMetaFmt) 343 { 344 Assert(dataHdr.cbMetaFmt); 345 RTMemFree(dataHdr.pvMetaFmt); 346 dataHdr.pvMetaFmt = NULL; 347 } 348 349 dataHdr.cbMetaFmt = 0; 350 } 351 352 void invalidate(void) 353 { 354 /* Update data header. */ 355 dataHdr.cbMeta = dataMeta.getSize(); 356 dataHdr.cbTotal = dataHdr.cbMeta + cbAddData; 357 358 LogFlowFunc(("cbTotal=%RU64, cbMeta=%RU32\n", dataHdr.cbTotal, dataHdr.cbMeta)); 359 } 360 361 protected: 362 363 /** The data header. */ 364 VBOXDNDDATAHDR dataHdr; 365 /** For storing the actual meta data. 366 * This might be an URI list or just plain raw data, 367 * according to the format being sent. */ 368 GuestDnDMetaData dataMeta; 369 /** Overall size (in bytes) of processed data. */ 370 uint64_t cbProcessed; 371 /** Additional data to process which does not count 372 * as meta data. Just in here for accounting reasons. */ 373 uint64_t cbAddData; 374 }; 91 375 92 376 /** 93 * Structure for keeping a n URI object'scontext around.94 */ 95 typedef structGuestDnDURIObjCtx377 * Structure for keeping a DnDURIObject context around. 378 */ 379 class GuestDnDURIObjCtx 96 380 { 381 public: 382 97 383 GuestDnDURIObjCtx(void) 98 384 : pObjURI(NULL) 99 , f Allocated(false)385 , fIntermediate(false) 100 386 , fHeaderSent(false) { } 101 387 102 388 virtual ~GuestDnDURIObjCtx(void) 103 389 { 104 Reset(); 105 } 106 107 public: 108 109 void Reset(void) 390 destroy(); 391 } 392 393 public: 394 395 DnDURIObject *createIntermediate(void) 396 { 397 reset(); 398 399 try 400 { 401 pObjURI = new DnDURIObject(); 402 fIntermediate = true; 403 } 404 catch (std::bad_alloc &) 405 { 406 } 407 408 return pObjURI; 409 } 410 411 void destroy(void) 110 412 { 111 413 if ( pObjURI 112 && f Allocated)414 && fIntermediate) 113 415 { 114 416 delete pObjURI; 115 } 116 117 pObjURI = NULL; 118 119 fAllocated = false; 120 fHeaderSent = false; 121 } 122 417 fIntermediate = false; 418 } 419 420 pObjURI = NULL; 421 } 422 423 bool isIntermediate(void) { return fIntermediate; } 424 425 bool isValid(void) const { return (pObjURI != NULL); } 426 427 void reset(void) 428 { 429 destroy(); 430 431 fIntermediate = false; 432 fHeaderSent = false; 433 } 123 434 124 435 /** Pointer to current object being handled. */ 125 436 DnDURIObject *pObjURI; 126 437 /** Flag whether pObjURI needs deletion after use. */ 127 bool f Allocated;438 bool fIntermediate; 128 439 /** Flag whether the object's file header has been sent already. */ 129 440 bool fHeaderSent; 130 441 /** @todo Add more statistics / information here. */ 131 132 } GuestDnDURIObjCtx; 442 }; 133 443 134 444 /** 135 * Structure for keeping around URI (list) data.136 */ 137 typedef structGuestDnDURIData445 * Structure for keeping around an URI (data) transfer. 446 */ 447 class GuestDnDURIData 138 448 { 449 450 public: 451 139 452 GuestDnDURIData(void) 140 : pvScratchBuf(NULL) 453 : cObjToProcess(0) 454 , cObjProcessed(0) 455 , pvScratchBuf(NULL) 141 456 , cbScratchBuf(0) { } 142 457 143 458 virtual ~GuestDnDURIData(void) 144 459 { 145 Reset(); 146 } 147 148 int Init(size_t cbBuf = _64K) 149 { 150 Reset(); 460 reset(); 461 462 if (pvScratchBuf) 463 { 464 Assert(cbScratchBuf); 465 RTMemFree(pvScratchBuf); 466 pvScratchBuf = NULL; 467 } 468 cbScratchBuf = 0; 469 } 470 471 DnDDroppedFiles &getDroppedFiles(void) { return droppedFiles; } 472 473 DnDURIList &getURIList(void) { return lstURI; } 474 475 int init(size_t cbBuf = _64K) 476 { 477 reset(); 151 478 152 479 pvScratchBuf = RTMemAlloc(cbBuf); … … 158 485 } 159 486 160 const void *GetBuffer(void) const { return pvScratchBuf; } 161 162 void *GetBufferMutable(void) { return pvScratchBuf; } 163 164 size_t GetBufferSize(void) const { return cbScratchBuf; } 165 166 void Reset(void) 167 { 487 bool isComplete(void) const 488 { 489 LogFlowFunc(("cObjToProcess=%RU64, cObjProcessed=%RU64\n", cObjToProcess, cObjProcessed)); 490 Assert(cObjProcessed <= cObjToProcess); 491 return (cObjProcessed == cObjToProcess); 492 } 493 494 const void *getBuffer(void) const { return pvScratchBuf; } 495 496 void *getBufferMutable(void) { return pvScratchBuf; } 497 498 size_t getBufferSize(void) const { return cbScratchBuf; } 499 500 GuestDnDURIObjCtx &getObj(uint64_t uID = 0) 501 { 502 AssertMsg(uID == 0, ("Other objects than object 0 is not supported yet\n")); 503 return objCtx; 504 } 505 506 GuestDnDURIObjCtx &getObjCurrent(void) 507 { 508 DnDURIObject *pCurObj = lstURI.First(); 509 if ( !lstURI.IsEmpty() 510 && pCurObj) 511 { 512 /* Point the context object to the current DnDURIObject to process. */ 513 objCtx.pObjURI = pCurObj; 514 } 515 else 516 objCtx.reset(); 517 518 return objCtx; 519 } 520 521 uint64_t getObjToProcess(void) const { return cObjToProcess; } 522 523 uint64_t getObjProcessed(void) const { return cObjProcessed; } 524 525 int processObject(const DnDURIObject &Obj) 526 { 527 int rc; 528 529 /** @todo Find objct in lstURI first! */ 530 switch (Obj.GetType()) 531 { 532 case DnDURIObject::Directory: 533 rc = processDirectory(Obj.GetDestPath().c_str(), Obj.GetMode()); 534 break; 535 536 case DnDURIObject::File: 537 rc = VINF_SUCCESS; 538 break; 539 540 default: 541 rc = VERR_NOT_IMPLEMENTED; 542 break; 543 } 544 545 if (RT_SUCCESS(rc)) 546 { 547 if (cObjToProcess) 548 { 549 cObjProcessed++; 550 Assert(cObjProcessed <= cObjToProcess); 551 } 552 } 553 554 return rc; 555 } 556 557 void removeObjCurrent(void) 558 { 559 if (cObjToProcess) 560 { 561 cObjProcessed++; 562 Assert(cObjProcessed <= cObjToProcess); 563 } 564 565 lstURI.RemoveFirst(); 566 objCtx.reset(); 567 } 568 569 void reset(uint64_t cObjs = 0) 570 { 571 cObjToProcess = cObjs; 572 cObjProcessed = 0; 573 574 LogFlowFunc(("cObjToProcess=%RU64\n", cObjToProcess)); 575 576 droppedFiles.Close(); 577 168 578 lstURI.Clear(); 169 objCtx.Reset(); 170 171 int rc2 = droppedFiles.Rollback(); 172 AssertRC(rc2); 173 rc2 = droppedFiles.Reset(true /* fRemoveDropDir */); 174 AssertRC(rc2); 175 176 if (pvScratchBuf) 177 { 178 Assert(cbScratchBuf); 179 RTMemFree(pvScratchBuf); 180 pvScratchBuf = NULL; 181 } 182 cbScratchBuf = 0; 183 } 184 579 objCtx.reset(); 580 } 581 582 public: 583 584 int fromMetaData(const GuestDnDMetaData &Data) 585 { 586 reset(); 587 588 size_t cbList = Data.getSize(); 589 const char *pszList = (const char *)Data.getData(); 590 if ( !pszList 591 || !cbList) 592 { 593 return VINF_SUCCESS; 594 } 595 596 RTCList<RTCString> lstURIOrg = RTCString(pszList, cbList).split("\r\n"); 597 if (lstURIOrg.isEmpty()) 598 return VINF_SUCCESS; 599 600 /* Note: All files to be transferred will be kept open during the entire DnD 601 * operation, also to keep the accounting right. */ 602 return lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN); 603 } 604 605 int toMetaData(std::vector<BYTE> &vecData) 606 { 607 const char *pszDroppedFilesDir = droppedFiles.GetDirAbs(); 608 609 Utf8Str strURIs = lstURI.RootToString(RTCString(pszDroppedFilesDir)); 610 size_t cbData = strURIs.length(); 611 612 LogFlowFunc(("%zu root URIs (%zu bytes)\n", lstURI.RootCount(), cbData)); 613 614 int rc; 615 616 try 617 { 618 vecData.resize(cbData + 1 /* Include termination */); 619 memcpy(&vecData.front(), strURIs.c_str(), cbData); 620 621 rc = VINF_SUCCESS; 622 } 623 catch (std::bad_alloc &) 624 { 625 rc = VERR_NO_MEMORY; 626 } 627 628 return rc; 629 } 630 631 protected: 632 633 int processDirectory(const char *pszPath, uint32_t fMode) 634 { 635 /** @todo Find directory in lstURI first! */ 636 int rc; 637 638 const char *pszDroppedFilesDir = droppedFiles.GetDirAbs(); 639 char *pszDir = RTPathJoinA(pszDroppedFilesDir, pszPath); 640 if (pszDir) 641 { 642 rc = RTDirCreateFullPath(pszDir, fMode); 643 if (cObjToProcess) 644 { 645 cObjProcessed++; 646 Assert(cObjProcessed <= cObjToProcess); 647 } 648 649 RTStrFree(pszDir); 650 } 651 else 652 rc = VERR_NO_MEMORY; 653 654 return rc; 655 } 656 657 protected: 658 659 /** Number of objects to process. */ 660 uint64_t cObjToProcess; 661 /** Number of objects already processed. */ 662 uint64_t cObjProcessed; 185 663 /** Handles all drop files for this operation. */ 186 664 DnDDroppedFiles droppedFiles; … … 191 669 * only have one context at a time. */ 192 670 GuestDnDURIObjCtx objCtx; 193 194 protected:195 196 671 /** Pointer to an optional scratch buffer to use for 197 672 * doing the actual chunk transfers. */ … … 199 674 /** Size (in bytes) of scratch buffer. */ 200 675 size_t cbScratchBuf; 201 202 } GuestDnDURIData; 203 204 /** List (vector) of MIME types. */ 205 typedef std::vector<com::Utf8Str> GuestDnDMIMEList; 676 }; 206 677 207 678 /** … … 227 698 GuestDnDURIData mURI; 228 699 /** Callback event to use. */ 229 GuestDnDCallbackEvent mC allback;700 GuestDnDCallbackEvent mCBEvent; 230 701 231 702 } SENDDATACTX, *PSENDDATACTX; … … 247 718 /** Original drop format requested to receive from the guest. */ 248 719 com::Utf8Str mFmtReq; 249 /** Intermediate drop format to be received from the host.720 /** Intermediate drop format to be received from the guest. 250 721 * Some original drop formats require a different intermediate 251 722 * drop format: … … 253 724 * Receiving a file link as "text/plain" requires still to 254 725 * receive the file from the guest as "text/uri-list" first, 255 * then pointing to the file path on the host in the "text/plain"256 * datareturned. */726 * then pointing to the file path on the host with the data 727 * in "text/plain" format returned. */ 257 728 com::Utf8Str mFmtRecv; 258 729 /** Desired drop action to perform on the host. … … 266 737 GuestDnDURIData mURI; 267 738 /** Callback event to use. */ 268 GuestDnDCallbackEvent mC allback;739 GuestDnDCallbackEvent mCBEvent; 269 740 270 741 } RECVDATACTX, *PRECVDATACTX; … … 284 755 285 756 virtual ~GuestDnDMsg(void) 757 { 758 reset(); 759 } 760 761 public: 762 763 PVBOXHGCMSVCPARM getNextParam(void) 764 { 765 if (cParms >= cParmsAlloc) 766 { 767 if (!paParms) 768 paParms = (PVBOXHGCMSVCPARM)RTMemAlloc(4 * sizeof(VBOXHGCMSVCPARM)); 769 else 770 paParms = (PVBOXHGCMSVCPARM)RTMemRealloc(paParms, (cParmsAlloc + 4) * sizeof(VBOXHGCMSVCPARM)); 771 if (!paParms) 772 throw VERR_NO_MEMORY; 773 RT_BZERO(&paParms[cParmsAlloc], 4 * sizeof(VBOXHGCMSVCPARM)); 774 cParmsAlloc += 4; 775 } 776 777 return &paParms[cParms++]; 778 } 779 780 uint32_t getCount(void) const { return cParms; } 781 PVBOXHGCMSVCPARM getParms(void) const { return paParms; } 782 uint32_t getType(void) const { return uMsg; } 783 784 void reset(void) 286 785 { 287 786 if (paParms) … … 299 798 300 799 RTMemFree(paParms); 301 } 302 } 303 304 public: 305 306 PVBOXHGCMSVCPARM getNextParam(void) 307 { 308 if (cParms >= cParmsAlloc) 309 { 310 paParms = (PVBOXHGCMSVCPARM)RTMemRealloc(paParms, (cParmsAlloc + 4) * sizeof(VBOXHGCMSVCPARM)); 311 if (!paParms) 312 throw VERR_NO_MEMORY; 313 RT_BZERO(&paParms[cParmsAlloc], 4 * sizeof(VBOXHGCMSVCPARM)); 314 cParmsAlloc += 4; 315 } 316 317 return &paParms[cParms++]; 318 } 319 320 uint32_t getCount(void) const { return cParms; } 321 PVBOXHGCMSVCPARM getParms(void) const { return paParms; } 322 uint32_t getType(void) const { return uMsg; } 800 paParms = NULL; 801 } 802 803 uMsg = cParms = cParmsAlloc = 0; 804 } 323 805 324 806 int setNextPointer(void *pvBuf, uint32_t cbBuf) 325 807 { 326 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);327 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);328 329 808 PVBOXHGCMSVCPARM pParm = getNextParam(); 330 809 if (!pParm) 331 810 return VERR_NO_MEMORY; 332 811 333 void *pvTmp = RTMemDup(pvBuf, cbBuf); 334 if (!pvTmp) 335 { 336 RTMemFree(pParm); 337 return VERR_NO_MEMORY; 812 void *pvTmp = NULL; 813 if (pvBuf) 814 { 815 Assert(cbBuf); 816 pvTmp = RTMemDup(pvBuf, cbBuf); 817 if (!pvTmp) 818 return VERR_NO_MEMORY; 338 819 } 339 820 … … 350 831 char *pszTemp = RTStrDup(pszString); 351 832 if (!pszTemp) 352 {353 RTMemFree(pParm);354 833 return VERR_NO_MEMORY; 355 }356 834 357 835 pParm->setString(pszTemp); … … 477 955 GuestDnDMIMEList m_lstFormats; 478 956 /** Pointer to IGuest parent object. */ 479 ComObjPtr<Guest> m_p arent;957 ComObjPtr<Guest> m_pParent; 480 958 /** Pointer to associated progress object. Optional. */ 481 ComObjPtr<Progress> m_p rogress;959 ComObjPtr<Progress> m_pProgress; 482 960 /** Callback map. */ 483 961 GuestDnDCallbackMap m_mapCallbacks; … … 488 966 * implementation. Can't be instanciated directly, only via 489 967 * the factory pattern. 968 * 969 ** @todo Move this into GuestDnDBase. 490 970 */ 491 971 class GuestDnD … … 524 1004 /** @name Public helper functions. 525 1005 * @{ */ 526 HRESULT 527 int 528 GuestDnDResponse 529 std::vector<com::Utf8Str>defaultFormats(void) const { return m_strDefaultFormats; }1006 HRESULT adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const; 1007 int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const; 1008 GuestDnDResponse *response(void) { return m_pResponse; } 1009 GuestDnDMIMEList defaultFormats(void) const { return m_strDefaultFormats; } 530 1010 /** @} */ 531 1011 … … 555 1035 * @{ */ 556 1036 /** List of supported default MIME/Content-type formats. */ 557 std::vector<com::Utf8Str>m_strDefaultFormats;1037 GuestDnDMIMEList m_strDefaultFormats; 558 1038 /** Pointer to guest implementation. */ 559 1039 const ComObjPtr<Guest> m_pGuest; … … 610 1090 611 1091 int sendCancel(void); 612 int waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp); 1092 int updateProgress(GuestDnDData *pData, GuestDnDResponse *pResp, uint32_t cbDataAdd = 0); 1093 int waitForEvent(GuestDnDCallbackEvent *pEvent, GuestDnDResponse *pResp, RTMSINTERVAL msTimeout); 613 1094 614 1095 protected: … … 624 1105 /** @} */ 625 1106 1107 /** 1108 * Internal stuff. 1109 */ 626 1110 struct 627 1111 { 628 /** Flag indicating whether a drop operation currently 629 * is in progress or not. */ 630 bool mfTransferIsPending; 1112 /** Number of active transfers (guest->host or host->guest). */ 1113 uint32_t m_cTransfersPending; 631 1114 /** The DnD protocol version to use, depending on the 632 * installed Guest Additions. */ 633 uint32_t mProtocolVersion; 634 /** Outgoing message queue. */ 635 GuestDnDMsgList mListOutgoing; 1115 * installed Guest Additions. See DragAndDropSvc.h for 1116 * a protocol changelog. */ 1117 uint32_t m_uProtocolVersion; 1118 /** Outgoing message queue (FIFO). */ 1119 GuestDnDMsgList m_lstMsgOut; 636 1120 } mDataBase; 637 1121 }; -
trunk/src/VBox/Main/include/GuestDnDSourceImpl.h
r57500 r58212 18 18 #ifndef ____H_GUESTDNDSOURCEIMPL 19 19 #define ____H_GUESTDNDSOURCEIMPL 20 21 #include <VBox/GuestHost/DragAndDrop.h> 22 #include <VBox/HostServices/DragAndDropSvc.h> 23 24 using namespace DragAndDropSvc; 20 25 21 26 #include "GuestDnDSourceWrap.h" … … 65 70 /** @name Dispatch handlers for the HGCM callbacks. 66 71 * @{ */ 67 int i_onReceiveData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData, uint64_t cbTotalSize); 72 int i_onReceiveDataHdr(PRECVDATACTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr); 73 int i_onReceiveData(PRECVDATACTX pCtx, PVBOXDNDSNDDATA pSndData); 68 74 int i_onReceiveDir(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath, uint32_t fMode); 69 int i_onReceiveFileHdr(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx,const char *pszPath, uint32_t cbPath, uint64_t cbSize, uint32_t fMode, uint32_t fFlags);70 int i_onReceiveFileData(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx,const void *pvData, uint32_t cbData);75 int i_onReceiveFileHdr(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath, uint64_t cbSize, uint32_t fMode, uint32_t fFlags); 76 int i_onReceiveFileData(PRECVDATACTX pCtx,const void *pvData, uint32_t cbData); 71 77 /** @} */ 72 78 #endif … … 93 99 int i_receiveRawData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout); 94 100 int i_receiveURIData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout); 95 int i_updateProcess(PRECVDATACTX pCtx, uint64_t cbDataAdd);96 101 97 102 protected: … … 101 106 /** Maximum data block size (in bytes) the source can handle. */ 102 107 uint32_t mcbBlockSize; 103 /** The context for receiving data from the guest. */ 108 /** The context for receiving data from the guest. 109 * At the moment only one transfer at a time is supported. */ 104 110 RECVDATACTX mRecvCtx; 105 111 } mData; -
trunk/src/VBox/Main/include/GuestDnDTargetImpl.h
r57500 r58212 85 85 int i_cancelOperation(void); 86 86 int i_sendData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 87 int i_sendDataBody(PSENDDATACTX pCtx, GuestDnDData *pData); 88 int i_sendDataHeader(PSENDDATACTX pCtx, GuestDnDData *pData, GuestDnDURIData *pURIData /* = NULL */); 87 89 int i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg); 88 90 int i_sendFile(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg); 89 91 int i_sendFileData(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg); 92 int i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 90 93 int i_sendURIData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout); 91 int i_sendRawData(PSENDDATACTX pCtx, RTMSINTERVAL msTimeout);92 94 int i_sendURIDataLoop(PSENDDATACTX pCtx, GuestDnDMsg *pMsg); 93 95 -
trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
r57500 r58212 194 194 , m_defAction(0) 195 195 , m_allActions(0) 196 , m_p arent(pGuest)196 , m_pParent(pGuest) 197 197 { 198 198 int rc = RTSemEventCreate(&m_EventSem); … … 226 226 HRESULT GuestDnDResponse::resetProgress(const ComObjPtr<Guest>& pParent) 227 227 { 228 m_p rogress.setNull();229 230 HRESULT hr = m_p rogress.createObject();228 m_pProgress.setNull(); 229 230 HRESULT hr = m_pProgress.createObject(); 231 231 if (SUCCEEDED(hr)) 232 232 { 233 hr = m_p rogress->init(static_cast<IGuest *>(pParent),234 Bstr(pParent->tr("Dropping data")).raw(),235 TRUE /* aCancelable */);233 hr = m_pProgress->init(static_cast<IGuest *>(pParent), 234 Bstr(pParent->tr("Dropping data")).raw(), 235 TRUE /* aCancelable */); 236 236 } 237 237 … … 242 242 { 243 243 BOOL fCanceled; 244 if (!m_p rogress.isNull())245 { 246 HRESULT hr = m_p rogress->COMGETTER(Canceled)(&fCanceled);244 if (!m_pProgress.isNull()) 245 { 246 HRESULT hr = m_pProgress->COMGETTER(Canceled)(&fCanceled); 247 247 AssertComRC(hr); 248 248 } … … 285 285 286 286 int rc = VINF_SUCCESS; 287 if (!m_p rogress.isNull())287 if (!m_pProgress.isNull()) 288 288 { 289 289 BOOL fCompleted; 290 HRESULT hr = m_p rogress->COMGETTER(Completed)(&fCompleted);290 HRESULT hr = m_pProgress->COMGETTER(Completed)(&fCompleted); 291 291 AssertComRC(hr); 292 292 293 293 BOOL fCanceled; 294 hr = m_p rogress->COMGETTER(Canceled)(&fCanceled);294 hr = m_pProgress->COMGETTER(Canceled)(&fCanceled); 295 295 AssertComRC(hr); 296 296 … … 303 303 case DragAndDropSvc::DND_PROGRESS_ERROR: 304 304 { 305 hr = m_p rogress->i_notifyComplete(VBOX_E_IPRT_ERROR,306 COM_IIDOF(IGuest),307 m_parent->getComponentName(), strMsg.c_str());305 hr = m_pProgress->i_notifyComplete(VBOX_E_IPRT_ERROR, 306 COM_IIDOF(IGuest), 307 m_pParent->getComponentName(), strMsg.c_str()); 308 308 reset(); 309 309 break; … … 312 312 case DragAndDropSvc::DND_PROGRESS_CANCELLED: 313 313 { 314 hr = m_p rogress->i_notifyComplete(S_OK);314 hr = m_pProgress->i_notifyComplete(S_OK); 315 315 AssertComRC(hr); 316 316 … … 324 324 if (!fCanceled) 325 325 { 326 hr = m_p rogress->SetCurrentOperationProgress(uPercentage);326 hr = m_pProgress->SetCurrentOperationProgress(uPercentage); 327 327 AssertComRC(hr); 328 328 if ( uStatus == DragAndDropSvc::DND_PROGRESS_COMPLETE 329 329 || uPercentage >= 100) 330 330 { 331 hr = m_p rogress->i_notifyComplete(S_OK);331 hr = m_pProgress->i_notifyComplete(S_OK); 332 332 AssertComRC(hr); 333 333 } … … 341 341 } 342 342 343 hr = m_p rogress->COMGETTER(Completed)(&fCompleted);343 hr = m_pProgress->COMGETTER(Completed)(&fCompleted); 344 344 AssertComRC(hr); 345 hr = m_p rogress->COMGETTER(Canceled)(&fCanceled);345 hr = m_pProgress->COMGETTER(Canceled)(&fCanceled); 346 346 AssertComRC(hr); 347 347 … … 382 382 383 383 if ( pCBData->cbFormat == 0 384 || pCBData->cbFormat > _64K) 384 || pCBData->cbFormat > _64K) /** @todo Make this configurable? */ 385 385 { 386 386 rc = VERR_INVALID_PARAMETER; … … 470 470 HRESULT GuestDnDResponse::queryProgressTo(IProgress **ppProgress) 471 471 { 472 return m_p rogress.queryInterfaceTo(ppProgress);472 return m_pProgress.queryInterfaceTo(ppProgress); 473 473 } 474 474 … … 738 738 GuestDnDBase::GuestDnDBase(void) 739 739 { 740 mDataBase.mfTransferIsPending = false; 741 742 /* 743 * Initialize public attributes. 744 */ 740 /* Initialize public attributes. */ 745 741 m_lstFmtSupported = GuestDnDInst()->defaultFormats(); 742 743 /* Initialzie private stuff. */ 744 mDataBase.m_cTransfersPending = 0; 746 745 } 747 746 … … 796 795 } 797 796 798 int GuestDnDBase::getProtocolVersion(uint32_t *pu Version)799 { 800 AssertPtrReturn(pu Version, VERR_INVALID_POINTER);797 int GuestDnDBase::getProtocolVersion(uint32_t *puProto) 798 { 799 AssertPtrReturn(puProto, VERR_INVALID_POINTER); 801 800 802 801 int rc; 803 802 804 uint32_t uVer, uVerAdditions = 0; 803 uint32_t uProto = 1; /* Use protocol v1 as a fallback. */ 804 uint32_t uVerAdditions = 0; 805 805 if ( m_pGuest 806 806 && (uVerAdditions = m_pGuest->i_getAdditionsVersion()) > 0) 807 807 { 808 uint32_t uVBoxMajor = VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions); 809 uint32_t uVBoxMinor = VBOX_FULL_VERSION_GET_MINOR(uVerAdditions); 810 811 #if 0 /*def DEBUG_andy*/ 808 #if 1 812 809 /* Hardcode the to-used protocol version; nice for testing side effects. */ 813 u Ver = 2;810 uProto = 3; 814 811 #else 815 uVer = ( uVBoxMajor >= 5) 816 ? 2 /* VBox 5.0 and up: Protocol version 2. */ 817 : 1; /* VBox <= 4.3: Protocol version 1. */ 818 /* Build revision is ignored. */ 812 if (uVerAdditions >= VBOX_FULL_VERSION_MAKE(5, 0, 0)) 813 { 814 if (uVerAdditions >= VBOX_FULL_VERSION_MAKE(5, 0, 8)) 815 { 816 uProto = 3; /* Since VBox 5.0.8: Protocol v3. */ 817 } 818 else 819 uProto = 2; /* VBox 5.0.0 - 5.0.6: Protocol v2. */ 820 } 819 821 #endif 820 821 LogFlowThisFunc(("uVerAdditions=%RU32 (%RU32.%RU32)\n", uVerAdditions, uVBoxMajor, uVBoxMinor)); 822 LogRel3(("DnD: uVerAdditions=%RU32 (%RU32.%RU32.%RU32)\n", 823 uVerAdditions, VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions), 824 VBOX_FULL_VERSION_GET_BUILD(uVerAdditions))); 822 825 rc = VINF_SUCCESS; 823 826 } 824 827 else 825 828 { 826 u Ver= 1; /* Fallback. */829 uProto = 1; /* Fallback. */ 827 830 rc = VERR_NOT_FOUND; 828 831 } 829 832 830 Log FlowThisFunc(("uVer=%RU32, uVerAdditions=%RU32, rc=%Rrc\n", uVer, uVerAdditions, rc));831 832 *pu Version = uVer;833 LogRel3(("DnD: uProto=%RU32, rc=%Rrc\n", uProto, rc)); 834 835 *puProto = uProto; 833 836 return rc; 834 837 } … … 836 839 int GuestDnDBase::msgQueueAdd(GuestDnDMsg *pMsg) 837 840 { 838 mDataBase.m ListOutgoing.push_back(pMsg);841 mDataBase.m_lstMsgOut.push_back(pMsg); 839 842 return VINF_SUCCESS; 840 843 } … … 842 845 GuestDnDMsg *GuestDnDBase::msgQueueGetNext(void) 843 846 { 844 if (mDataBase.m ListOutgoing.empty())847 if (mDataBase.m_lstMsgOut.empty()) 845 848 return NULL; 846 return mDataBase.m ListOutgoing.front();849 return mDataBase.m_lstMsgOut.front(); 847 850 } 848 851 849 852 void GuestDnDBase::msgQueueRemoveNext(void) 850 853 { 851 if (!mDataBase.m ListOutgoing.empty())852 { 853 GuestDnDMsg *pMsg = mDataBase.m ListOutgoing.front();854 if (!mDataBase.m_lstMsgOut.empty()) 855 { 856 GuestDnDMsg *pMsg = mDataBase.m_lstMsgOut.front(); 854 857 if (pMsg) 855 858 delete pMsg; 856 mDataBase.m ListOutgoing.pop_front();859 mDataBase.m_lstMsgOut.pop_front(); 857 860 } 858 861 } … … 860 863 void GuestDnDBase::msgQueueClear(void) 861 864 { 862 GuestDnDMsgList::iterator itMsg = mDataBase.mListOutgoing.begin(); 863 while (itMsg != mDataBase.mListOutgoing.end()) 864 { 865 delete *itMsg; 866 } 867 868 mDataBase.mListOutgoing.clear(); 865 LogFlowFunc(("cMsg=%zu\n", mDataBase.m_lstMsgOut.size())); 866 867 GuestDnDMsgList::iterator itMsg = mDataBase.m_lstMsgOut.begin(); 868 while (itMsg != mDataBase.m_lstMsgOut.end()) 869 { 870 GuestDnDMsg *pMsg = *itMsg; 871 if (pMsg) 872 delete pMsg; 873 874 itMsg++; 875 } 876 877 mDataBase.m_lstMsgOut.clear(); 869 878 } 870 879 … … 888 897 } 889 898 899 int GuestDnDBase::updateProgress(GuestDnDData *pData, GuestDnDResponse *pResp, 900 uint32_t cbDataAdd /* = 0 */) 901 { 902 AssertPtrReturn(pData, VERR_INVALID_POINTER); 903 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 904 /* cbDataAdd is optional. */ 905 906 LogFlowFunc(("cbTotal=%RU64, cbProcessed=%RU64, cbRemaining=%RU64, cbDataAdd=%RU32\n", 907 pData->getProcessed(), pData->getProcessed(), pData->getRemaining(), cbDataAdd)); 908 909 if (!pResp) 910 return VINF_SUCCESS; 911 912 if (cbDataAdd) 913 pData->addProcessed(cbDataAdd); 914 915 int rc = pResp->setProgress(pData->getPercentComplete(), 916 pData->isComplete() 917 ? DND_PROGRESS_COMPLETE 918 : DND_PROGRESS_RUNNING); 919 LogFlowFuncLeaveRC(rc); 920 return rc; 921 } 922 890 923 /** @todo GuestDnDResponse *pResp needs to go. */ 891 int GuestDnDBase::waitForEvent(RTMSINTERVAL msTimeout, GuestDnDCallbackEvent &Event, GuestDnDResponse *pResp) 892 { 924 int GuestDnDBase::waitForEvent(GuestDnDCallbackEvent *pEvent, GuestDnDResponse *pResp, RTMSINTERVAL msTimeout) 925 { 926 AssertPtrReturn(pEvent, VERR_INVALID_POINTER); 927 AssertPtrReturn(pResp, VERR_INVALID_POINTER); 928 893 929 int rc; 894 930 … … 901 937 * respond, do busy waiting here. 902 938 */ 903 rc = Event.Wait(500 /* ms */);939 rc = pEvent->Wait(500 /* ms */); 904 940 if (RT_SUCCESS(rc)) 905 941 { 906 rc = Event.Result();942 rc = pEvent->Result(); 907 943 LogFlowFunc(("Callback done, result is %Rrc\n", rc)); 908 944 break; -
trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
r57776 r58212 37 37 38 38 #include <VBox/com/array.h> 39 #include <VBox/GuestHost/DragAndDrop.h>40 #include <VBox/HostServices/DragAndDropSvc.h>41 39 42 40 #ifdef LOG_GROUP … … 246 244 247 245 /* Determine guest DnD protocol to use. */ 248 GuestDnDBase::getProtocolVersion(&mDataBase.m ProtocolVersion);246 GuestDnDBase::getProtocolVersion(&mDataBase.m_uProtocolVersion); 249 247 250 248 /* Default is ignoring the action. */ … … 254 252 255 253 GuestDnDMsg Msg; 256 Msg.setType( DragAndDropSvc::HOST_DND_GH_REQ_PENDING);254 Msg.setType(HOST_DND_GH_REQ_PENDING); 257 255 Msg.setNextUInt32(uScreenId); 258 256 … … 333 331 return S_OK; 334 332 335 /* Note: At the moment we only support one transfer at a time. */ 336 if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending)) 333 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 334 335 /* At the moment we only support one transfer at a time. */ 336 if (mDataBase.m_cTransfersPending) 337 337 return setError(E_INVALIDARG, tr("Another drop operation already is in progress")); 338 339 /* Gets reset when the thread is finished. */340 ASMAtomicWriteBool(&mDataBase.mfTransferIsPending, true);341 338 342 339 /* Dito. */ … … 363 360 LogFlowFunc(("Starting thread ...\n")); 364 361 365 int rc = RTThreadCreate(NULL, GuestDnDSource::i_receiveDataThread, 362 RTTHREAD threadRcv; 363 int rc = RTThreadCreate(&threadRcv, GuestDnDSource::i_receiveDataThread, 366 364 (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndSrcRcvData"); 367 365 if (RT_SUCCESS(rc)) 368 366 { 369 hr = pResp->queryProgressTo(aProgress.asOutParam()); 370 ComAssertComRC(hr); 371 372 /* Note: pTask is now owned by the worker thread. */ 367 rc = RTThreadUserWait(threadRcv, 30 * 1000 /* 30s timeout */); 368 if (RT_SUCCESS(rc)) 369 { 370 mDataBase.m_cTransfersPending++; 371 372 hr = pResp->queryProgressTo(aProgress.asOutParam()); 373 ComAssertComRC(hr); 374 375 /* Note: pTask is now owned by the worker thread. */ 376 } 377 else 378 hr = setError(VBOX_E_IPRT_ERROR, tr("Waiting for receiving thread failed (%Rrc)"), rc); 373 379 } 374 380 else 375 381 hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc); 382 383 if (FAILED(hr)) 384 delete pTask; 376 385 } 377 386 catch(std::bad_alloc &) … … 379 388 hr = setError(E_OUTOFMEMORY); 380 389 } 381 382 /* Note: mDataBase.mfTransferIsPending will be set to false again by i_receiveDataThread. */383 390 384 391 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); … … 393 400 #else /* VBOX_WITH_DRAG_AND_DROP */ 394 401 395 /* Input validation. */396 397 402 AutoCaller autoCaller(this); 398 403 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 399 404 400 /* Don't allow receiving the actual data until our transfer 401 * actually is complete. */ 402 if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending)) 403 return setError(E_INVALIDARG, tr("Current drop operation still in progress")); 405 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 406 407 /* Don't allow receiving the actual data until our transfer actually is complete. */ 408 if (mDataBase.m_cTransfersPending) 409 return setError(E_FAIL, tr("Current drop operation still in progress")); 404 410 405 411 PRECVDATACTX pCtx = &mData.mRecvCtx; 406 412 407 if (pCtx->mData.vecData.empty()) 408 { 413 if (pCtx->mData.getMeta().getSize() == 0) 414 { 415 LogFlowFunc(("No data available, returning 0\n")); 409 416 aData.resize(0); 410 417 return S_OK; … … 419 426 if (fHasURIList) 420 427 { 421 const char *pszDroppedFilesDir = pCtx->mURI.droppedFiles.GetDirAbs(); 422 Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(RTCString(pszDroppedFilesDir)); 423 cbData = strURIs.length(); 424 425 LogFlowFunc(("Found %zu root URIs (%zu bytes)\n", pCtx->mURI.lstURI.RootCount(), cbData)); 426 427 aData.resize(cbData + 1 /* Include termination */); 428 memcpy(&aData.front(), strURIs.c_str(), cbData); 428 LogRel2(("DnD: Drop directory is: %s\n", pCtx->mURI.getDroppedFiles().GetDirAbs())); 429 int rc2 = pCtx->mURI.toMetaData(aData); 430 if (RT_FAILURE(rc2)) 431 hr = E_OUTOFMEMORY; 429 432 } 430 433 else 431 434 { 432 cbData = pCtx->mData. vecData.size();435 cbData = pCtx->mData.getMeta().getSize(); 433 436 434 437 /* Copy the data into a safe array of bytes. */ 435 438 aData.resize(cbData); 436 memcpy(&aData.front(), &pCtx->mData.vecData[0], cbData);439 memcpy(&aData.front(), pCtx->mData.getMeta().getData(), cbData); 437 440 } 438 441 } … … 523 526 524 527 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 525 int GuestDnDSource::i_onReceiveData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData, uint64_t cbTotalSize) 528 int GuestDnDSource::i_onReceiveDataHdr(PRECVDATACTX pCtx, PVBOXDNDSNDDATAHDR pDataHdr) 529 { 530 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 531 AssertReturn(pDataHdr, VERR_INVALID_POINTER); 532 533 pCtx->mData.setEstimatedSize(pDataHdr->cbTotal, pDataHdr->cbMeta); 534 535 Assert(pCtx->mURI.getObjToProcess() == 0); 536 pCtx->mURI.reset(pDataHdr->cObjects); 537 538 /** @todo Handle compression type. */ 539 /** @todo Handle checksum type. */ 540 541 LogFlowFuncLeave(); 542 return VINF_SUCCESS; 543 } 544 545 int GuestDnDSource::i_onReceiveData(PRECVDATACTX pCtx, PVBOXDNDSNDDATA pSndData) 526 546 { 527 547 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 528 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 529 AssertReturn(cbData, VERR_INVALID_PARAMETER); 530 AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER); 531 532 LogFlowFunc(("cbData=%RU32, cbTotalSize=%RU64\n", cbData, cbTotalSize)); 548 AssertPtrReturn(pSndData, VERR_INVALID_POINTER); 533 549 534 550 int rc = VINF_SUCCESS; … … 536 552 try 537 553 { 538 if ( cbData > cbTotalSize 539 || cbData > mData.mcbBlockSize) 540 { 541 LogFlowFunc(("Data sizes invalid: cbData=%RU32, cbTotalSize=%RU64\n", cbData, cbTotalSize)); 554 GuestDnDData *pData = &pCtx->mData; 555 GuestDnDURIData *pURI = &pCtx->mURI; 556 557 uint32_t cbData; 558 void *pvData; 559 uint64_t cbToProcess; 560 uint32_t cbMeta; 561 562 if (mDataBase.m_uProtocolVersion < 3) 563 { 564 cbData = pSndData->u.v1.cbData; 565 pvData = pSndData->u.v1.pvData; 566 567 /* Sends the total data size to receive for every data chunk. */ 568 cbToProcess = pSndData->u.v1.cbTotalSize; 569 570 /* Meta data size always is cbData, meaning there cannot be an 571 * extended data chunk transfer by sending further data. */ 572 cbMeta = cbData; 573 } 574 else 575 { 576 cbData = pSndData->u.v3.cbData; 577 pvData = pSndData->u.v3.pvData; 578 579 /* Note: Data sizes get updated in i_onReceiveDataHdr(). */ 580 cbToProcess = pData->getTotal(); 581 cbMeta = pData->getMeta().getSize(); 582 } 583 Assert(cbToProcess); 584 585 if ( cbData == 0 586 || cbData > cbToProcess /* Paranoia */) 587 { 588 LogFlowFunc(("Incoming data size invalid: cbData=%RU32, cbToProcess=%RU64\n", cbData, pData->getTotal())); 542 589 rc = VERR_INVALID_PARAMETER; 543 590 } 544 else if (cb Data < pCtx->mData.vecData.size())545 { 546 AssertMsgFailed((" New size (%RU64) is smaller than current size (%zu)\n", cbTotalSize, pCtx->mData.vecData.size()));591 else if (cbToProcess < cbMeta) 592 { 593 AssertMsgFailed(("cbToProcess (%RU64) is smaller than meta size (%zu)\n", cbToProcess, cbMeta)); 547 594 rc = VERR_INVALID_PARAMETER; 548 595 } … … 550 597 if (RT_SUCCESS(rc)) 551 598 { 552 pCtx->mData.vecData.insert(pCtx->mData.vecData.begin(), (BYTE *)pvData, (BYTE *)pvData + cbData); 553 554 LogFlowFunc(("vecDataSize=%zu, cbData=%RU32, cbTotalSize=%RU64\n", pCtx->mData.vecData.size(), cbData, cbTotalSize)); 555 556 /* Data transfer complete? */ 557 Assert(cbData <= pCtx->mData.vecData.size()); 558 if (cbData == pCtx->mData.vecData.size()) 599 pData->getMeta().add(pvData, cbData); 600 LogFlowThisFunc(("cbMetaSize=%zu, cbData=%RU32, cbMeta=%RU32, cbToProcess=%RU64\n", 601 pData->getMeta().getSize(), cbData, cbMeta, cbToProcess)); 602 } 603 604 if (RT_SUCCESS(rc)) 605 { 606 /* (Meta) Data transfer complete? */ 607 Assert(cbMeta <= pData->getMeta().getSize()); 608 if (cbMeta == pData->getMeta().getSize()) 559 609 { 560 610 bool fHasURIList = DnDMIMENeedsDropDir(pCtx->mFmtRecv.c_str(), pCtx->mFmtRecv.length()); 561 LogFlow Func(("fHasURIList=%RTbool, cbTotalSize=%RU32\n", fHasURIList, cbTotalSize));611 LogFlowThisFunc(("fHasURIList=%RTbool\n", fHasURIList)); 562 612 if (fHasURIList) 563 613 { 564 614 /* Try parsing the data as URI list. */ 565 rc = p Ctx->mURI.lstURI.RootFromURIData(&pCtx->mData.vecData[0], pCtx->mData.vecData.size(), 0 /* uFlags */);615 rc = pURI->fromMetaData(pData->getMeta()); 566 616 if (RT_SUCCESS(rc)) 567 617 { 568 /* Reset processed bytes. */569 pCtx->mData.cbProcessed = 0;618 if (mDataBase.m_uProtocolVersion < 3) 619 pData->setEstimatedSize(cbToProcess, cbMeta); 570 620 571 621 /* 572 * Assign new total size which also includes all file data to receive 573 * from the guest. 622 * Update our process with the data we already received. 623 * Note: The total size will consist of the meta data (in pVecData) and 624 * the actual accumulated file/directory data from the guest. 574 625 */ 575 pCtx->mData.cbToProcess = cbTotalSize; 576 577 /* Update our process with the data we already received. 578 * Note: The total size will consist of the meta data (in vecData) and 579 * the actual accumulated file/directory data from the guest. */ 580 rc = i_updateProcess(pCtx, (uint64_t)pCtx->mData.vecData.size()); 581 582 LogFlowFunc(("URI data => cbProcessed=%RU64, cbToProcess=%RU64, rc=%Rrc\n", 583 pCtx->mData.cbProcessed, pCtx->mData.cbToProcess, rc)); 626 rc = updateProgress(pData, pCtx->mpResp, (uint32_t)pData->getMeta().getSize()); 584 627 } 585 628 } … … 604 647 LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n", pszPath, cbPath, fMode)); 605 648 649 /* 650 * Sanity checking. 651 */ 652 if ( !cbPath 653 || cbPath > RTPATH_MAX) 654 { 655 return VERR_INVALID_PARAMETER; 656 } 657 658 if (!RTStrIsValidEncoding(pszPath)) 659 return VERR_INVALID_PARAMETER; 660 661 if (pCtx->mURI.isComplete()) 662 return VERR_INVALID_PARAMETER; 663 664 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 665 DnDURIObject *pObj = objCtx.createIntermediate(); 666 if (!pObj) 667 return VERR_NO_MEMORY; 668 606 669 int rc; 607 670 608 const char *pszDroppedFilesDir = pCtx->mURI. droppedFiles.GetDirAbs();671 const char *pszDroppedFilesDir = pCtx->mURI.getDroppedFiles().GetDirAbs(); 609 672 char *pszDir = RTPathJoinA(pszDroppedFilesDir, pszPath); 610 673 if (pszDir) 611 674 { 675 #ifdef RT_OS_WINDOWS 676 RTPathChangeToDosSlashes(pszDir, true /* fForce */); 677 #else 678 RTPathChangeToDosSlashes(pszDir, true /* fForce */); 679 #endif 612 680 rc = RTDirCreateFullPath(pszDir, fMode); 613 if (RT_FAILURE(rc)) 614 LogRel2(("DnD: Error creating guest directory '%s' on the host, rc=%Rrc\n", pszDir, rc)); 681 if (RT_SUCCESS(rc)) 682 LogRel2(("DnD: Created guest directory on host: %s\n", pszDir)); 683 else 684 LogRel(("DnD: Error creating guest directory '%s' on host, rc=%Rrc\n", pszDir, rc)); 685 686 pCtx->mURI.removeObjCurrent(); 615 687 616 688 RTStrFree(pszDir); … … 623 695 } 624 696 625 int GuestDnDSource::i_onReceiveFileHdr(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx,const char *pszPath, uint32_t cbPath,697 int GuestDnDSource::i_onReceiveFileHdr(PRECVDATACTX pCtx, const char *pszPath, uint32_t cbPath, 626 698 uint64_t cbSize, uint32_t fMode, uint32_t fFlags) 627 699 { 628 700 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 629 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);630 701 AssertPtrReturn(pszPath, VERR_INVALID_POINTER); 631 702 AssertReturn(cbPath, VERR_INVALID_PARAMETER); … … 635 706 LogFlowFunc(("pszPath=%s, cbPath=%RU32, cbSize=%RU64, fMode=0x%x, fFlags=0x%x\n", pszPath, cbPath, cbSize, fMode, fFlags)); 636 707 708 /* 709 * Sanity checking. 710 */ 711 if ( !cbPath 712 || cbPath > RTPATH_MAX) 713 { 714 return VERR_INVALID_PARAMETER; 715 } 716 717 if (!RTStrIsValidEncoding(pszPath)) 718 return VERR_INVALID_PARAMETER; 719 720 if (cbSize > pCtx->mData.getTotal()) 721 { 722 AssertMsgFailed(("File size (%RU64) exceeds total size to transfer (%RU64)\n", cbSize, pCtx->mData.getTotal())); 723 return VERR_INVALID_PARAMETER; 724 } 725 726 if (pCtx->mURI.isComplete()) 727 return VERR_INVALID_PARAMETER; 728 637 729 int rc = VINF_SUCCESS; 638 730 639 731 do 640 732 { 641 DnDURIObject *pObj = pObjCtx->pObjURI; 642 643 if ( pObj 644 && pObj->IsOpen() 645 && !pObj->IsComplete()) 646 { 647 AssertMsgFailed(("Object '%s' not complete yet\n", pObj->GetDestPath().c_str())); 648 rc = VERR_WRONG_ORDER; 649 break; 650 } 651 652 if ( pObj 653 && pObj->IsOpen()) /* File already opened? */ 654 { 655 AssertMsgFailed(("Current opened object is '%s', close this first\n", pObj->GetDestPath().c_str())); 656 rc = VERR_WRONG_ORDER; 657 break; 658 } 659 660 if (cbSize > pCtx->mData.cbToProcess) 661 { 662 AssertMsgFailed(("File size (%RU64) exceeds total size to transfer (%RU64)\n", cbSize, pCtx->mData.cbToProcess)); 663 rc = VERR_INVALID_PARAMETER; 664 break; 665 } 666 667 const char *pszDroppedFilesDir = pCtx->mURI.droppedFiles.GetDirAbs(); 668 669 char pszPathAbs[RTPATH_MAX]; 670 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszDroppedFilesDir, pszPath); 671 if (RT_FAILURE(rc)) 672 { 673 LogFlowFunc(("Warning: Rebasing current file failed with rc=%Rrc\n", rc)); 674 break; 675 } 676 677 rc = DnDPathSanitize(pszPathAbs, sizeof(pszPathAbs)); 678 if (RT_FAILURE(rc)) 679 { 680 LogFlowFunc(("Warning: Rebasing current file failed with rc=%Rrc\n", rc)); 681 break; 682 } 683 684 LogFunc(("Rebased to: %s\n", pszPathAbs)); 685 686 if ( pObj 687 && pObjCtx->fAllocated) 688 { 689 delete pObj; 690 pObj = NULL; 691 } 692 693 try 694 { 695 pObj = new DnDURIObject(); 696 697 pObjCtx->pObjURI = pObj; 698 pObjCtx->fAllocated = true; 699 } 700 catch (std::bad_alloc &) 701 { 733 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 734 DnDURIObject *pObj = objCtx.pObjURI; 735 736 /* 737 * Sanity checking. 738 */ 739 if (pObj) 740 { 741 if ( pObj->IsOpen() 742 && !pObj->IsComplete()) 743 { 744 AssertMsgFailed(("Object '%s' not complete yet\n", pObj->GetDestPath().c_str())); 745 rc = VERR_WRONG_ORDER; 746 break; 747 } 748 749 if (pObj->IsOpen()) /* File already opened? */ 750 { 751 AssertMsgFailed(("Current opened object is '%s', close this first\n", pObj->GetDestPath().c_str())); 752 rc = VERR_WRONG_ORDER; 753 break; 754 } 755 } 756 757 /* 758 * Create new intermediate object to work with. 759 */ 760 pObj = objCtx.createIntermediate(); 761 if (!pObj) 702 762 rc = VERR_NO_MEMORY; 703 }704 763 705 764 if (RT_SUCCESS(rc)) 706 765 { 766 const char *pszDroppedFilesDir = pCtx->mURI.getDroppedFiles().GetDirAbs(); 767 768 char pszPathAbs[RTPATH_MAX]; 769 rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszDroppedFilesDir, pszPath); 770 if (RT_FAILURE(rc)) 771 { 772 LogFlowFunc(("Warning: Rebasing current file failed with rc=%Rrc\n", rc)); 773 break; 774 } 775 776 rc = DnDPathSanitize(pszPathAbs, sizeof(pszPathAbs)); 777 if (RT_FAILURE(rc)) 778 { 779 LogFlowFunc(("Warning: Rebasing current file failed with rc=%Rrc\n", rc)); 780 break; 781 } 782 783 LogFunc(("Rebased to: %s\n", pszPathAbs)); 784 707 785 /** @todo Add sparse file support based on fFlags? (Use Open(..., fFlags | SPARSE). */ 708 786 rc = pObj->OpenEx(pszPathAbs, DnDURIObject::File, DnDURIObject::Target, … … 714 792 { 715 793 /* Note: Protocol v1 does not send any file sizes, so always 0. */ 716 if (mDataBase.m ProtocolVersion >= 2)794 if (mDataBase.m_uProtocolVersion >= 2) 717 795 rc = pObj->SetSize(cbSize); 718 796 … … 740 818 } 741 819 742 int GuestDnDSource::i_onReceiveFileData(PRECVDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx,const void *pvData, uint32_t cbData)820 int GuestDnDSource::i_onReceiveFileData(PRECVDATACTX pCtx, const void *pvData, uint32_t cbData) 743 821 { 744 822 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 745 AssertPtrReturn(pObjCtx, VERR_INVALID_POINTER);746 823 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 747 824 AssertReturn(cbData, VERR_INVALID_PARAMETER); … … 749 826 int rc = VINF_SUCCESS; 750 827 828 /* 829 * Sanity checking. 830 */ 831 if (cbData > mData.mcbBlockSize) 832 return VERR_INVALID_PARAMETER; 833 751 834 do 752 835 { 753 DnDURIObject *pObj = pObjCtx->pObjURI; 836 GuestDnDURIObjCtx objCtx = pCtx->mURI.getObj(0); /** @todo Fill in context ID. */ 837 DnDURIObject *pObj = objCtx.pObjURI; 838 754 839 if (!pObj) 755 840 { … … 784 869 785 870 if (RT_SUCCESS(rc)) 786 rc = i_updateProcess(pCtx, cbWritten);871 rc = updateProgress(&pCtx->mData, pCtx->mpResp, cbWritten); 787 872 } 788 873 … … 793 878 /** @todo Sanitize path. */ 794 879 LogRel2(("DnD: File transfer to host complete: %s\n", pObj->GetDestPath().c_str())); 880 objCtx.reset(); 881 795 882 rc = VINF_EOF; 796 797 /* Deletion needed? */798 if (pObjCtx->fAllocated)799 {800 delete pObj;801 pObj = NULL;802 803 pObjCtx->fAllocated = false;804 }805 883 } 806 884 } … … 821 899 { 822 900 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 901 902 /* Is this context already in receiving state? */ 903 if (ASMAtomicReadBool(&pCtx->mIsActive)) 904 return VERR_WRONG_ORDER; 905 ASMAtomicWriteBool(&pCtx->mIsActive, true); 823 906 824 907 GuestDnD *pInst = GuestDnDInst(); … … 829 912 AssertPtr(pCtx->mpResp); 830 913 831 /* Is this context already in receiving state? */ 832 if (ASMAtomicReadBool(&pCtx->mIsActive)) 833 return VERR_WRONG_ORDER; 834 835 ASMAtomicWriteBool(&pCtx->mIsActive, true); 836 837 int rc = pCtx->mCallback.Reset(); 914 int rc = pCtx->mCBEvent.Reset(); 838 915 if (RT_FAILURE(rc)) 839 916 return rc; … … 842 919 * Reset any old data. 843 920 */ 844 pCtx->mData. Reset();845 pCtx->mURI. Reset();921 pCtx->mData.reset(); 922 pCtx->mURI.reset(); 846 923 pResp->reset(); 847 924 … … 901 978 AssertPtrReturn(pTask, VERR_INVALID_POINTER); 902 979 903 const ComObjPtr<GuestDnDSource> pSource(pTask->getSource()); 904 Assert(!pSource.isNull()); 905 906 int rc; 907 908 AutoCaller autoCaller(pSource); 909 if (SUCCEEDED(autoCaller.rc())) 910 { 911 rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 912 } 913 else 914 rc = VERR_COM_INVALID_OBJECT_STATE; 915 916 ASMAtomicWriteBool(&pSource->mDataBase.mfTransferIsPending, false); 980 const ComObjPtr<GuestDnDSource> pThis(pTask->getSource()); 981 Assert(!pThis.isNull()); 982 983 AutoCaller autoCaller(pThis); 984 if (FAILED(autoCaller.rc())) return VERR_COM_INVALID_OBJECT_STATE; 985 986 int rc = RTThreadUserSignal(Thread); 987 AssertRC(rc); 988 989 rc = pThis->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 917 990 918 991 if (pTask) 919 992 delete pTask; 920 993 921 LogFlowFunc(("pSource=%p returning rc=%Rrc\n", (GuestDnDSource *)pSource, rc)); 994 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS); 995 996 Assert(pThis->mDataBase.m_cTransfersPending); 997 pThis->mDataBase.m_cTransfersPending--; 998 999 LogFlowFunc(("pSource=%p returning rc=%Rrc\n", (GuestDnDSource *)pThis, rc)); 922 1000 return rc; 923 1001 } … … 948 1026 * Register callbacks. 949 1027 */ 950 REGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);951 REGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_SND_DATA);1028 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1029 REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); 952 1030 953 1031 do … … 957 1035 */ 958 1036 GuestDnDMsg Msg; 959 Msg.setType( DragAndDropSvc::HOST_DND_GH_EVT_DROPPED);1037 Msg.setType(HOST_DND_GH_EVT_DROPPED); 960 1038 Msg.setNextPointer((void*)pCtx->mFmtRecv.c_str(), (uint32_t)pCtx->mFmtRecv.length() + 1); 961 1039 Msg.setNextUInt32((uint32_t)pCtx->mFmtRecv.length() + 1); … … 967 1045 if (RT_SUCCESS(rc)) 968 1046 { 969 rc = waitForEvent( msTimeout, pCtx->mCallback, pCtx->mpResp);1047 rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout); 970 1048 if (RT_SUCCESS(rc)) 971 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, VINF_SUCCESS);1049 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 972 1050 } 973 1051 … … 977 1055 * Unregister callbacks. 978 1056 */ 979 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);980 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_SND_DATA);1057 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1058 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); 981 1059 982 1060 #undef REGISTER_CALLBACK … … 987 1065 if (rc == VERR_CANCELLED) 988 1066 { 989 int rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_CANCELLED, VINF_SUCCESS);1067 int rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 990 1068 AssertRC(rc2); 991 1069 … … 995 1073 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 996 1074 { 997 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR,1075 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, 998 1076 rc, GuestDnDSource::i_hostErrorToString(rc)); 999 1077 } … … 1032 1110 */ 1033 1111 /* Guest callbacks. */ 1034 REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_EVT_ERROR); 1035 REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DATA); 1036 REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DIR); 1037 if (mDataBase.mProtocolVersion >= 2) 1038 REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR); 1039 REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA); 1040 1041 DnDDroppedFiles &droppedFiles = pCtx->mURI.droppedFiles; 1112 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1113 if (mDataBase.m_uProtocolVersion >= 3) 1114 REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA_HDR); 1115 REGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); 1116 REGISTER_CALLBACK(GUEST_DND_GH_SND_DIR); 1117 if (mDataBase.m_uProtocolVersion >= 2) 1118 REGISTER_CALLBACK(GUEST_DND_GH_SND_FILE_HDR); 1119 REGISTER_CALLBACK(GUEST_DND_GH_SND_FILE_DATA); 1120 1121 DnDDroppedFiles &droppedFiles = pCtx->mURI.getDroppedFiles(); 1042 1122 1043 1123 do … … 1054 1134 */ 1055 1135 GuestDnDMsg Msg; 1056 Msg.setType( DragAndDropSvc::HOST_DND_GH_EVT_DROPPED);1136 Msg.setType(HOST_DND_GH_EVT_DROPPED); 1057 1137 Msg.setNextPointer((void*)pCtx->mFmtRecv.c_str(), (uint32_t)pCtx->mFmtRecv.length() + 1); 1058 1138 Msg.setNextUInt32((uint32_t)pCtx->mFmtRecv.length() + 1); … … 1066 1146 LogFlowFunc(("Waiting ...\n")); 1067 1147 1068 rc = waitForEvent( msTimeout, pCtx->mCallback, pCtx->mpResp);1148 rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout); 1069 1149 if (RT_SUCCESS(rc)) 1070 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, VINF_SUCCESS);1150 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 1071 1151 1072 1152 LogFlowFunc(("Waiting ended with rc=%Rrc\n", rc)); … … 1078 1158 * Unregister callbacks. 1079 1159 */ 1080 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);1081 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_SND_DATA);1082 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_SND_DIR);1083 if (mDataBase.mProtocolVersion >= 2)1084 UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR);1085 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA);1160 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1161 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA_HDR); 1162 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DATA); 1163 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_DIR); 1164 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_FILE_HDR); 1165 UNREGISTER_CALLBACK(GUEST_DND_GH_SND_FILE_DATA); 1086 1166 1087 1167 #undef REGISTER_CALLBACK … … 1094 1174 if (rc == VERR_CANCELLED) 1095 1175 { 1096 rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_CANCELLED, VINF_SUCCESS);1176 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1097 1177 AssertRC(rc2); 1098 1178 … … 1102 1182 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1103 1183 { 1104 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR,1184 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, 1105 1185 rc, GuestDnDSource::i_hostErrorToString(rc)); 1106 1186 } … … 1109 1189 if (RT_FAILURE(rc)) 1110 1190 { 1111 rc2 = droppedFiles.Rollback(); /** @todo Inform user on rollback failure? */ 1112 LogFlowFunc(("Rolling back ended with rc=%Rrc\n", rc2)); 1113 } 1114 1115 rc2 = droppedFiles.Reset(RT_FAILURE(rc) ? true : false /* fRemoveDropDir */); 1116 if (RT_SUCCESS(rc)) 1117 rc = rc2; 1191 rc2 = droppedFiles.Rollback(); 1192 if (RT_FAILURE(rc2)) 1193 LogRel2(("DnD: Rollback failed with %Rrc\n", rc2)); 1194 } 1195 1196 droppedFiles.Close(); 1118 1197 1119 1198 LogFlowFuncLeaveRC(rc); … … 1140 1219 { 1141 1220 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1142 case DragAndDropSvc::GUEST_DND_GH_SND_DATA:1143 { 1144 DragAndDropSvc::PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDATADATA>(pvParms);1221 case GUEST_DND_GH_SND_DATA_HDR: 1222 { 1223 PVBOXDNDCBSNDDATAHDRDATA pCBData = reinterpret_cast<PVBOXDNDCBSNDDATAHDRDATA>(pvParms); 1145 1224 AssertPtr(pCBData); 1146 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);1147 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA== pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1148 1149 rc = pThis->i_onReceiveData (pCtx, pCBData->pvData, pCBData->cbData, pCBData->cbTotalSize);1150 break; 1151 } 1152 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:1153 { 1154 DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);1225 AssertReturn(sizeof(VBOXDNDCBSNDDATAHDRDATA) == cbParms, VERR_INVALID_PARAMETER); 1226 AssertReturn(CB_MAGIC_DND_GH_SND_DATA_HDR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1227 1228 rc = pThis->i_onReceiveDataHdr(pCtx, &pCBData->data); 1229 break; 1230 } 1231 case GUEST_DND_GH_SND_DATA: 1232 { 1233 PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<PVBOXDNDCBSNDDATADATA>(pvParms); 1155 1234 AssertPtr(pCBData); 1156 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER); 1157 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1235 AssertReturn(sizeof(VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER); 1236 AssertReturn(CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1237 1238 rc = pThis->i_onReceiveData(pCtx, &pCBData->data); 1239 break; 1240 } 1241 case GUEST_DND_GH_EVT_ERROR: 1242 { 1243 PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<PVBOXDNDCBEVTERRORDATA>(pvParms); 1244 AssertPtr(pCBData); 1245 AssertReturn(sizeof(VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER); 1246 AssertReturn(CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1158 1247 1159 1248 pCtx->mpResp->reset(); … … 1162 1251 pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */ 1163 1252 1164 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,1253 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc, 1165 1254 GuestDnDSource::i_guestErrorToString(pCBData->rc)); 1166 1255 if (RT_SUCCESS(rc)) … … 1176 1265 if (RT_FAILURE(rc)) 1177 1266 { 1178 int rc2 = pCtx->mC allback.Notify(rc);1267 int rc2 = pCtx->mCBEvent.Notify(rc); 1179 1268 AssertRC(rc2); 1180 1269 } … … 1203 1292 { 1204 1293 #ifdef VBOX_WITH_DRAG_AND_DROP_GH 1205 case DragAndDropSvc::GUEST_DND_GH_SND_DATA:1206 { 1207 DragAndDropSvc::PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDATADATA>(pvParms);1294 case GUEST_DND_GH_SND_DATA_HDR: 1295 { 1296 PVBOXDNDCBSNDDATAHDRDATA pCBData = reinterpret_cast<PVBOXDNDCBSNDDATAHDRDATA>(pvParms); 1208 1297 AssertPtr(pCBData); 1209 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);1210 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA== pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1211 1212 rc = pThis->i_onReceiveData (pCtx, pCBData->pvData, pCBData->cbData, pCBData->cbTotalSize);1213 break; 1214 } 1215 case DragAndDropSvc::GUEST_DND_GH_SND_DIR:1216 { 1217 DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms);1298 AssertReturn(sizeof(VBOXDNDCBSNDDATAHDRDATA) == cbParms, VERR_INVALID_PARAMETER); 1299 AssertReturn(CB_MAGIC_DND_GH_SND_DATA_HDR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1300 1301 rc = pThis->i_onReceiveDataHdr(pCtx, &pCBData->data); 1302 break; 1303 } 1304 case GUEST_DND_GH_SND_DATA: 1305 { 1306 PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<PVBOXDNDCBSNDDATADATA>(pvParms); 1218 1307 AssertPtr(pCBData); 1219 AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER); 1220 AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1308 AssertReturn(sizeof(VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER); 1309 AssertReturn(CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1310 1311 rc = pThis->i_onReceiveData(pCtx, &pCBData->data); 1312 break; 1313 } 1314 case GUEST_DND_GH_SND_DIR: 1315 { 1316 PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<PVBOXDNDCBSNDDIRDATA>(pvParms); 1317 AssertPtr(pCBData); 1318 AssertReturn(sizeof(VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER); 1319 AssertReturn(CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1221 1320 1222 1321 rc = pThis->i_onReceiveDir(pCtx, pCBData->pszPath, pCBData->cbPath, pCBData->fMode); 1223 1322 break; 1224 1323 } 1225 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR:1226 { 1227 DragAndDropSvc::PVBOXDNDCBSNDFILEHDRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEHDRDATA>(pvParms);1324 case GUEST_DND_GH_SND_FILE_HDR: 1325 { 1326 PVBOXDNDCBSNDFILEHDRDATA pCBData = reinterpret_cast<PVBOXDNDCBSNDFILEHDRDATA>(pvParms); 1228 1327 AssertPtr(pCBData); 1229 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBSNDFILEHDRDATA) == cbParms, VERR_INVALID_PARAMETER);1230 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_HDR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1231 1232 rc = pThis->i_onReceiveFileHdr(pCtx, &pCtx->mURI.objCtx,pCBData->pszFilePath, pCBData->cbFilePath,1328 AssertReturn(sizeof(VBOXDNDCBSNDFILEHDRDATA) == cbParms, VERR_INVALID_PARAMETER); 1329 AssertReturn(CB_MAGIC_DND_GH_SND_FILE_HDR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1330 1331 rc = pThis->i_onReceiveFileHdr(pCtx, pCBData->pszFilePath, pCBData->cbFilePath, 1233 1332 pCBData->cbSize, pCBData->fMode, pCBData->fFlags); 1234 1333 break; 1235 1334 } 1236 case DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA:1237 { 1238 DragAndDropSvc::PVBOXDNDCBSNDFILEDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATADATA>(pvParms);1335 case GUEST_DND_GH_SND_FILE_DATA: 1336 { 1337 PVBOXDNDCBSNDFILEDATADATA pCBData = reinterpret_cast<PVBOXDNDCBSNDFILEDATADATA>(pvParms); 1239 1338 AssertPtr(pCBData); 1240 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBSNDFILEDATADATA) == cbParms, VERR_INVALID_PARAMETER);1241 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1242 1243 if (pThis->mDataBase.m ProtocolVersion <= 1)1339 AssertReturn(sizeof(VBOXDNDCBSNDFILEDATADATA) == cbParms, VERR_INVALID_PARAMETER); 1340 AssertReturn(CB_MAGIC_DND_GH_SND_FILE_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1341 1342 if (pThis->mDataBase.m_uProtocolVersion <= 1) 1244 1343 { 1245 1344 /** … … 1250 1349 * appended data to the desired file. So just pass 0 as cbSize. 1251 1350 */ 1252 rc = pThis->i_onReceiveFileHdr(pCtx, &pCtx->mURI.objCtx, 1253 pCBData->u.v1.pszFilePath, pCBData->u.v1.cbFilePath, 1351 rc = pThis->i_onReceiveFileHdr(pCtx, pCBData->u.v1.pszFilePath, pCBData->u.v1.cbFilePath, 1254 1352 0 /* cbSize */, pCBData->u.v1.fMode, 0 /* fFlags */); 1255 1353 if (RT_SUCCESS(rc)) 1256 rc = pThis->i_onReceiveFileData(pCtx, &pCtx->mURI.objCtx,pCBData->pvData, pCBData->cbData);1354 rc = pThis->i_onReceiveFileData(pCtx, pCBData->pvData, pCBData->cbData); 1257 1355 } 1258 1356 else /* Protocol v2 and up. */ 1259 rc = pThis->i_onReceiveFileData(pCtx, &pCtx->mURI.objCtx,pCBData->pvData, pCBData->cbData);1260 break; 1261 } 1262 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:1263 { 1264 DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);1357 rc = pThis->i_onReceiveFileData(pCtx, pCBData->pvData, pCBData->cbData); 1358 break; 1359 } 1360 case GUEST_DND_GH_EVT_ERROR: 1361 { 1362 PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<PVBOXDNDCBEVTERRORDATA>(pvParms); 1265 1363 AssertPtr(pCBData); 1266 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);1267 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1364 AssertReturn(sizeof(VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER); 1365 AssertReturn(CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1268 1366 1269 1367 pCtx->mpResp->reset(); … … 1272 1370 pCBData->rc = VERR_GENERAL_FAILURE; /* Make sure some error is set. */ 1273 1371 1274 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,1372 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc, 1275 1373 GuestDnDSource::i_guestErrorToString(pCBData->rc)); 1276 1374 if (RT_SUCCESS(rc)) … … 1315 1413 } 1316 1414 1317 /* All URIdata processed? */1318 if ( pCtx->mData.cbProcessed >= pCtx->mData.cbToProcess)1319 {1320 Assert(pCtx->mData.cbProcessed == pCtx->mData.cbToProcess);1415 /* All data processed? */ 1416 if ( pCtx->mURI.isComplete() 1417 && pCtx->mData.isComplete()) 1418 { 1321 1419 fNotify = true; 1322 1420 } 1323 1421 1324 1422 LogFlowFunc(("cbProcessed=%RU64, cbToProcess=%RU64, fNotify=%RTbool, rcCallback=%Rrc, rc=%Rrc\n", 1325 pCtx->mData. cbProcessed, pCtx->mData.cbToProcess, fNotify, rcCallback, rc));1423 pCtx->mData.getProcessed(), pCtx->mData.getTotal(), fNotify, rcCallback, rc)); 1326 1424 1327 1425 if (fNotify) 1328 1426 { 1329 int rc2 = pCtx->mC allback.Notify(rcCallback);1427 int rc2 = pCtx->mCBEvent.Notify(rcCallback); 1330 1428 AssertRC(rc2); 1331 1429 } … … 1335 1433 } 1336 1434 1337 int GuestDnDSource::i_updateProcess(PRECVDATACTX pCtx, uint64_t cbDataAdd)1338 {1339 AssertPtrReturn(pCtx, VERR_INVALID_POINTER);1340 1341 LogFlowFunc(("cbProcessed=%RU64 (+ %RU64 = %RU64), cbToProcess=%RU64\n",1342 pCtx->mData.cbProcessed, cbDataAdd, pCtx->mData.cbProcessed + cbDataAdd, pCtx->mData.cbToProcess));1343 1344 pCtx->mData.cbProcessed += cbDataAdd;1345 Assert(pCtx->mData.cbProcessed <= pCtx->mData.cbToProcess);1346 1347 int64_t cbTotal = pCtx->mData.cbToProcess;1348 uint8_t uPercent = pCtx->mData.cbProcessed * 100 / (cbTotal ? cbTotal : 1);1349 1350 int rc = pCtx->mpResp->setProgress(uPercent,1351 uPercent >= 1001352 ? DragAndDropSvc::DND_PROGRESS_COMPLETE1353 : DragAndDropSvc::DND_PROGRESS_RUNNING);1354 return rc;1355 } -
trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
r57505 r58212 262 262 263 263 /* Determine guest DnD protocol to use. */ 264 GuestDnDBase::getProtocolVersion(&mDataBase.m ProtocolVersion);264 GuestDnDBase::getProtocolVersion(&mDataBase.m_uProtocolVersion); 265 265 266 266 /* Default action is ignoring. */ … … 302 302 { 303 303 GuestDnDMsg Msg; 304 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_ENTER);304 Msg.setType(HOST_DND_HG_EVT_ENTER); 305 305 Msg.setNextUInt32(aScreenId); 306 306 Msg.setNextUInt32(aX); … … 376 376 { 377 377 GuestDnDMsg Msg; 378 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_MOVE);378 Msg.setType(HOST_DND_HG_EVT_MOVE); 379 379 Msg.setNextUInt32(aScreenId); 380 380 Msg.setNextUInt32(aX); … … 418 418 419 419 HRESULT hr = S_OK; 420 int rc = GuestDnDInst()->hostCall( DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,420 int rc = GuestDnDInst()->hostCall(HOST_DND_HG_EVT_LEAVE, 421 421 0 /* cParms */, NULL /* paParms */); 422 422 if (RT_SUCCESS(rc)) … … 488 488 { 489 489 GuestDnDMsg Msg; 490 Msg.setType( DragAndDropSvc::HOST_DND_HG_EVT_DROPPED);490 Msg.setType(HOST_DND_HG_EVT_DROPPED); 491 491 Msg.setNextUInt32(aScreenId); 492 492 Msg.setNextUInt32(aX); … … 545 545 AssertPtrReturn(pTask, VERR_INVALID_POINTER); 546 546 547 const ComObjPtr<GuestDnDTarget> pTarget(pTask->getTarget()); 548 Assert(!pTarget.isNull()); 549 550 int rc; 551 552 AutoCaller autoCaller(pTarget); 553 if (SUCCEEDED(autoCaller.rc())) 554 { 555 rc = pTarget->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 556 /* Nothing to do here anymore. */ 557 } 558 else 559 rc = VERR_COM_INVALID_OBJECT_STATE; 560 561 ASMAtomicWriteBool(&pTarget->mDataBase.mfTransferIsPending, false); 547 const ComObjPtr<GuestDnDTarget> pThis(pTask->getTarget()); 548 Assert(!pThis.isNull()); 549 550 AutoCaller autoCaller(pThis); 551 if (FAILED(autoCaller.rc())) return VERR_COM_INVALID_OBJECT_STATE; 552 553 int rc = RTThreadUserSignal(Thread); 554 AssertRC(rc); 555 556 rc = pThis->i_sendData(pTask->getCtx(), RT_INDEFINITE_WAIT /* msTimeout */); 562 557 563 558 if (pTask) 564 559 delete pTask; 565 560 566 LogFlowFunc(("pTarget=%p returning rc=%Rrc\n", (GuestDnDTarget *)pTarget, rc)); 561 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS); 562 563 Assert(pThis->mDataBase.m_cTransfersPending); 564 pThis->mDataBase.m_cTransfersPending--; 565 566 LogFlowFunc(("pTarget=%p returning rc=%Rrc\n", (GuestDnDTarget *)pThis, rc)); 567 567 return rc; 568 568 } … … 594 594 return setError(E_INVALIDARG, tr("No data to send specified")); 595 595 596 /* Note: At the moment we only support one transfer at a time. */597 if (ASMAtomicReadBool(&mDataBase.mfTransferIsPending)) 598 return setError(E_INVALIDARG, tr("Another send operation already is in progress"));599 600 ASMAtomicWriteBool(&mDataBase.mfTransferIsPending, true);596 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 597 598 /* At the moment we only support one transfer at a time. */ 599 if (mDataBase.m_cTransfersPending) 600 return setError(E_INVALIDARG, tr("Another drop operation already is in progress")); 601 601 602 602 /* Dito. */ … … 617 617 pSendCtx->mScreenID = aScreenId; 618 618 pSendCtx->mFmtReq = aFormat; 619 pSendCtx->mData.vecData = aData; 619 620 pSendCtx->mData.getMeta().add(aData); 620 621 621 622 SendDataTask *pTask = new SendDataTask(this, pSendCtx); … … 624 625 LogFlowFunc(("Starting thread ...\n")); 625 626 626 int rc = RTThreadCreate(NULL, GuestDnDTarget::i_sendDataThread, 627 RTTHREAD threadSnd; 628 int rc = RTThreadCreate(&threadSnd, GuestDnDTarget::i_sendDataThread, 627 629 (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData"); 628 630 if (RT_SUCCESS(rc)) 629 631 { 630 hr = pResp->queryProgressTo(aProgress.asOutParam()); 631 ComAssertComRC(hr); 632 633 /* Note: pTask is now owned by the worker thread. */ 632 rc = RTThreadUserWait(threadSnd, 30 * 1000 /* 30s timeout */); 633 if (RT_SUCCESS(rc)) 634 { 635 mDataBase.m_cTransfersPending++; 636 637 hr = pResp->queryProgressTo(aProgress.asOutParam()); 638 ComAssertComRC(hr); 639 640 /* Note: pTask is now owned by the worker thread. */ 641 } 642 else 643 hr = setError(VBOX_E_IPRT_ERROR, tr("Waiting for sending thread failed (%Rrc)"), rc); 634 644 } 635 645 else 636 646 hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc); 637 647 638 if ( RT_FAILURE(rc))648 if (FAILED(hr)) 639 649 delete pSendCtx; 640 650 } … … 643 653 hr = setError(E_OUTOFMEMORY); 644 654 } 645 646 /* Note: mDataBase.mfTransferIsPending will be set to false again by i_sendDataThread. */647 655 648 656 LogFlowFunc(("Returning hr=%Rhrc\n", hr)); … … 662 670 663 671 LogFlowFunc(("Cancelling operation, telling guest ...\n")); 664 return GuestDnDInst()->hostCall( DragAndDropSvc::HOST_DND_HG_EVT_CANCEL, 0 /* cParms */, NULL /*paParms*/);672 return GuestDnDInst()->hostCall(HOST_DND_HG_EVT_CANCEL, 0 /* cParms */, NULL /*paParms*/); 665 673 } 666 674 … … 746 754 747 755 /* Clear all remaining outgoing messages. */ 748 mDataBase.m ListOutgoing.clear();756 mDataBase.m_lstMsgOut.clear(); 749 757 750 758 /** … … 775 783 } 776 784 785 int GuestDnDTarget::i_sendDataBody(PSENDDATACTX pCtx, GuestDnDData *pData) 786 { 787 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 788 AssertPtrReturn(pData, VERR_INVALID_POINTER); 789 790 /** @todo Add support for multiple HOST_DND_HG_SND_DATA messages in case of more than 64K data! */ 791 if (pData->getMeta().getSize() > _64K) 792 return VERR_NOT_IMPLEMENTED; 793 794 GuestDnDMsg Msg; 795 796 LogFlowFunc(("cbFmt=%RU32, cbMeta=%RU32, cbChksum=%RU32\n", 797 pData->getFmtSize(), pData->getMeta().getSize(), pData->getChkSumSize())); 798 799 Msg.setType(HOST_DND_HG_SND_DATA); 800 if (mDataBase.m_uProtocolVersion < 3) 801 { 802 Msg.setNextUInt32(pCtx->mScreenID); /* uScreenId */ 803 Msg.setNextPointer(pData->getFmtMutable(), pData->getFmtSize()); /* pvFormat */ 804 Msg.setNextUInt32(pData->getFmtSize()); /* cbFormat */ 805 Msg.setNextPointer(pData->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */ 806 /* Note1: Fill in the total data to send. 807 * Note2: Only supports uint32_t. */ 808 Msg.setNextUInt32((uint32_t)pData->getTotal()); /* cbData */ 809 } 810 else 811 { 812 Msg.setNextUInt32(0); /** @todo uContext; not used yet. */ 813 Msg.setNextPointer(pData->getMeta().getDataMutable(), pData->getMeta().getSize()); /* pvData */ 814 Msg.setNextUInt32(pData->getMeta().getSize()); /* cbData */ 815 Msg.setNextPointer(pData->getChkSumMutable(), pData->getChkSumSize()); /** @todo pvChecksum; not used yet. */ 816 Msg.setNextUInt32(pData->getChkSumSize()); /** @todo cbChecksum; not used yet. */ 817 } 818 819 int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 820 if (RT_SUCCESS(rc)) 821 rc = updateProgress(pData, pCtx->mpResp, pData->getMeta().getSize()); 822 823 LogFlowFuncLeaveRC(rc); 824 return rc; 825 } 826 827 int GuestDnDTarget::i_sendDataHeader(PSENDDATACTX pCtx, GuestDnDData *pData, GuestDnDURIData *pURIData /* = NULL */) 828 { 829 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 830 AssertPtrReturn(pData, VERR_INVALID_POINTER); 831 /* pURIData is optional. */ 832 833 GuestDnDMsg Msg; 834 835 Msg.setType(HOST_DND_HG_SND_DATA_HDR); 836 837 Msg.setNextUInt32(0); /** @todo uContext; not used yet. */ 838 Msg.setNextUInt32(0); /** @todo uFlags; not used yet. */ 839 Msg.setNextUInt32(pCtx->mScreenID); /* uScreen */ 840 Msg.setNextUInt64(pData->getTotal()); /* cbTotal */ 841 Msg.setNextUInt32(pData->getMeta().getSize()); /* cbMeta*/ 842 Msg.setNextPointer(pData->getFmtMutable(), pData->getFmtSize()); /* pvMetaFmt */ 843 Msg.setNextUInt32(pData->getFmtSize()); /* cbMetaFmt */ 844 Msg.setNextUInt64(pURIData ? pURIData->getObjToProcess() : 0); /* cObjects */ 845 Msg.setNextUInt32(0); /** @todo enmCompression; not used yet. */ 846 Msg.setNextUInt32(0); /** @todo enmChecksumType; not used yet. */ 847 Msg.setNextPointer(NULL, 0); /** @todo pvChecksum; not used yet. */ 848 Msg.setNextUInt32(0); /** @todo cbChecksum; not used yet. */ 849 850 int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms()); 851 852 LogFlowFuncLeaveRC(rc); 853 return rc; 854 } 855 777 856 int GuestDnDTarget::i_sendDirectory(PSENDDATACTX pCtx, GuestDnDURIObjCtx *pObjCtx, GuestDnDMsg *pMsg) 778 857 { … … 790 869 return VERR_BUFFER_OVERFLOW; 791 870 792 Log FlowFunc(("Sending directory \"%s\" using protocol v%RU32 ...\n", strPath.c_str(), mDataBase.mProtocolVersion));793 794 pMsg->setType( DragAndDropSvc::HOST_DND_HG_SND_DIR);871 LogRel2(("DnD: Transferring host directory to guest: %s\n", strPath.c_str())); 872 873 pMsg->setType(HOST_DND_HG_SND_DIR); 795 874 pMsg->setNextString(strPath.c_str()); /* path */ 796 pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length - note: Maximum is RTPATH_MAX on guest side. */875 pMsg->setNextUInt32((uint32_t)(strPath.length() + 1)); /* path length (maximum is RTPATH_MAX on guest side). */ 797 876 pMsg->setNextUInt32(pObj->GetMode()); /* mode */ 798 877 … … 816 895 817 896 LogFlowFunc(("Sending file with %RU32 bytes buffer, using protocol v%RU32 ...\n", 818 mData.mcbBlockSize, mDataBase.m ProtocolVersion));897 mData.mcbBlockSize, mDataBase.m_uProtocolVersion)); 819 898 LogFlowFunc(("strPathSrc=%s, fIsOpen=%RTbool, cbSize=%RU64\n", strPathSrc.c_str(), pObj->IsOpen(), pObj->GetSize())); 820 899 … … 831 910 if (RT_SUCCESS(rc)) 832 911 { 833 if (mDataBase.m ProtocolVersion >= 2)912 if (mDataBase.m_uProtocolVersion >= 2) 834 913 { 835 914 if (!pObjCtx->fHeaderSent) … … 840 919 * The just registered callback will be called by the guest afterwards. 841 920 */ 842 pMsg->setType( DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);921 pMsg->setType(HOST_DND_HG_SND_FILE_HDR); 843 922 pMsg->setNextUInt32(0); /* uContextID */ 844 923 rc = pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ … … 899 978 900 979 /* Set the message type. */ 901 pMsg->setType( DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);980 pMsg->setType(HOST_DND_HG_SND_FILE_DATA); 902 981 903 982 /* Protocol version 1 sends the file path *every* time with a new file chunk. 904 983 * In protocol version 2 we only do this once with HOST_DND_HG_SND_FILE_HDR. */ 905 if (mDataBase.m ProtocolVersion <= 1)984 if (mDataBase.m_uProtocolVersion <= 1) 906 985 { 907 986 pMsg->setNextString(pObj->GetDestPath().c_str()); /* pvName */ 908 987 pMsg->setNextUInt32((uint32_t)(pObj->GetDestPath().length() + 1)); /* cbName */ 909 988 } 910 else 911 { 912 /* Protocol version 2 also sendsthe context ID. Currently unused. */913 pMsg->setNextUInt32(0); /* context ID*/989 else if (mDataBase.m_uProtocolVersion >= 2) 990 { 991 /* Since protocol v2 we also send the context ID. Currently unused. */ 992 pMsg->setNextUInt32(0); /* uContext */ 914 993 } 915 994 916 995 uint32_t cbRead = 0; 917 996 918 int rc = pObj->Read(pCtx->mURI. GetBufferMutable(), pCtx->mURI.GetBufferSize(), &cbRead);997 int rc = pObj->Read(pCtx->mURI.getBufferMutable(), pCtx->mURI.getBufferSize(), &cbRead); 919 998 if (RT_SUCCESS(rc)) 920 999 { 921 pCtx->mData.cbProcessed += cbRead; 922 LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32, cbProcessed=%RU64, rc=%Rrc\n", 923 pCtx->mURI.GetBufferSize(), cbRead, pCtx->mData.cbProcessed, rc)); 924 925 if (mDataBase.mProtocolVersion <= 1) 926 { 927 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */ 928 pMsg->setNextUInt32(cbRead); /* cbData */ 929 pMsg->setNextUInt32(pObj->GetMode()); /* fMode */ 930 } 931 else 932 { 933 pMsg->setNextPointer(pCtx->mURI.GetBufferMutable(), cbRead); /* pvData */ 934 pMsg->setNextUInt32(cbRead); /* cbData */ 1000 pCtx->mData.addProcessed(cbRead); 1001 LogFlowFunc(("cbBufSize=%zu, cbRead=%RU32\n", pCtx->mURI.getBufferSize(), cbRead)); 1002 1003 if (mDataBase.m_uProtocolVersion <= 1) 1004 { 1005 pMsg->setNextPointer(pCtx->mURI.getBufferMutable(), cbRead); /* pvData */ 1006 pMsg->setNextUInt32(cbRead); /* cbData */ 1007 pMsg->setNextUInt32(pObj->GetMode()); /* fMode */ 1008 } 1009 else /* Protocol v2 and up. */ 1010 { 1011 pMsg->setNextPointer(pCtx->mURI.getBufferMutable(), cbRead); /* pvData */ 1012 pMsg->setNextUInt32(cbRead); /* cbData */ 1013 1014 if (mDataBase.m_uProtocolVersion >= 3) 1015 { 1016 /** @todo Calculate checksum. */ 1017 pMsg->setNextPointer(NULL, 0); /* pvChecksum */ 1018 pMsg->setNextUInt32(0); /* cbChecksum */ 1019 } 935 1020 } 936 1021 … … 961 1046 LogFlowFunc(("pThis=%p, uMsg=%RU32\n", pThis, uMsg)); 962 1047 963 int rc = VINF_SUCCESS; /* Will be reported back to guest. */964 int rcGuest = VINF_SUCCESS; /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */1048 int rc = VINF_SUCCESS; 1049 int rcGuest = VINF_SUCCESS; /* Contains error code from guest in case of VERR_GSTDND_GUEST_ERROR. */ 965 1050 bool fNotify = false; 966 1051 967 1052 switch (uMsg) 968 1053 { 969 case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:970 { 971 DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSG pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSG>(pvParms);1054 case GUEST_DND_GET_NEXT_HOST_MSG: 1055 { 1056 PVBOXDNDCBHGGETNEXTHOSTMSG pCBData = reinterpret_cast<PVBOXDNDCBHGGETNEXTHOSTMSG>(pvParms); 972 1057 AssertPtr(pCBData); 973 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSG) == cbParms, VERR_INVALID_PARAMETER);974 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1058 AssertReturn(sizeof(VBOXDNDCBHGGETNEXTHOSTMSG) == cbParms, VERR_INVALID_PARAMETER); 1059 AssertReturn(CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 975 1060 976 1061 try … … 1007 1092 break; 1008 1093 } 1009 case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:1010 { 1011 DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);1094 case GUEST_DND_GH_EVT_ERROR: 1095 { 1096 PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<PVBOXDNDCBEVTERRORDATA>(pvParms); 1012 1097 AssertPtr(pCBData); 1013 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);1014 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1098 AssertReturn(sizeof(VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER); 1099 AssertReturn(CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1015 1100 1016 1101 pCtx->mpResp->reset(); … … 1022 1107 } 1023 1108 1024 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc,1109 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, pCBData->rc, 1025 1110 GuestDnDTarget::i_guestErrorToString(pCBData->rc)); 1026 1111 if (RT_SUCCESS(rc)) … … 1031 1116 break; 1032 1117 } 1033 case DragAndDropSvc::HOST_DND_HG_SND_DIR:1034 case DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR:1035 case DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA:1036 { 1037 DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSGDATA pCBData1038 = reinterpret_cast< DragAndDropSvc::PVBOXDNDCBHGGETNEXTHOSTMSGDATA>(pvParms);1118 case HOST_DND_HG_SND_DIR: 1119 case HOST_DND_HG_SND_FILE_HDR: 1120 case HOST_DND_HG_SND_FILE_DATA: 1121 { 1122 PVBOXDNDCBHGGETNEXTHOSTMSGDATA pCBData 1123 = reinterpret_cast<PVBOXDNDCBHGGETNEXTHOSTMSGDATA>(pvParms); 1039 1124 AssertPtr(pCBData); 1040 AssertReturn(sizeof( DragAndDropSvc::VBOXDNDCBHGGETNEXTHOSTMSGDATA) == cbParms, VERR_INVALID_PARAMETER);1041 AssertReturn( DragAndDropSvc::CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);1125 AssertReturn(sizeof(VBOXDNDCBHGGETNEXTHOSTMSGDATA) == cbParms, VERR_INVALID_PARAMETER); 1126 AssertReturn(CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER); 1042 1127 1043 1128 LogFlowFunc(("pCBData->uMsg=%RU32, paParms=%p, cParms=%RU32\n", pCBData->uMsg, pCBData->paParms, pCBData->cParms)); … … 1053 1138 || pCBData->cParms != pMsg->getCount()) 1054 1139 { 1140 LogFlowFunc(("Current message does not match:\n")); 1141 LogFlowFunc(("\tCallback: uMsg=%RU32, cParms=%RU32, paParms=%p\n", 1142 pCBData->uMsg, pCBData->cParms, pCBData->paParms)); 1143 LogFlowFunc(("\t Next: uMsg=%RU32, cParms=%RU32\n", pMsg->getType(), pMsg->getCount())); 1144 1055 1145 /* Start over. */ 1056 1146 pThis->msgQueueClear(); … … 1141 1231 if (fNotify) 1142 1232 { 1143 int rc2 = pCtx->mC allback.Notify(rc); /** @todo Also pass guest error back? */1233 int rc2 = pCtx->mCBEvent.Notify(rc); /** @todo Also pass guest error back? */ 1144 1234 AssertRC(rc2); 1145 1235 } … … 1173 1263 } 1174 1264 1175 int rc = pCtx->mURI. Init(mData.mcbBlockSize);1265 int rc = pCtx->mURI.init(mData.mcbBlockSize); 1176 1266 if (RT_FAILURE(rc)) 1177 1267 return rc; 1178 1268 1179 rc = pCtx->mC allback.Reset();1269 rc = pCtx->mCBEvent.Reset(); 1180 1270 if (RT_FAILURE(rc)) 1181 1271 return rc; … … 1185 1275 */ 1186 1276 /* Guest callbacks. */ 1187 REGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG);1188 REGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);1277 REGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG); 1278 REGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1189 1279 /* Host callbacks. */ 1190 REGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_DIR);1191 if (mDataBase.m ProtocolVersion >= 2)1192 REGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);1193 REGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);1280 REGISTER_CALLBACK(HOST_DND_HG_SND_DIR); 1281 if (mDataBase.m_uProtocolVersion >= 2) 1282 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR); 1283 REGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA); 1194 1284 1195 1285 do 1196 1286 { 1197 1287 /* 1198 * Extract URI list from bytedata.1288 * Extract URI list from current meta data. 1199 1289 */ 1200 DnDURIList &lstURI = pCtx->mURI.lstURI; /* Use the URI list from the context. */ 1201 1202 const char *pszList = (const char *)&pCtx->mData.vecData.front(); 1203 URI_DATA_IS_VALID_BREAK(pszList); 1204 1205 uint32_t cbList = pCtx->mData.vecData.size(); 1206 URI_DATA_IS_VALID_BREAK(cbList); 1207 1208 RTCList<RTCString> lstURIOrg = RTCString(pszList, cbList).split("\r\n"); 1209 URI_DATA_IS_VALID_BREAK(!lstURIOrg.isEmpty()); 1210 1211 /* Note: All files to be transferred will be kept open during the entire DnD 1212 * operation, also to keep the accounting right. */ 1213 rc = lstURI.AppendURIPathsFromList(lstURIOrg, DNDURILIST_FLAGS_KEEP_OPEN); 1290 GuestDnDData *pData = &pCtx->mData; 1291 GuestDnDURIData *pURI = &pCtx->mURI; 1292 1293 rc = pURI->fromMetaData(pData->getMeta()); 1294 if (RT_FAILURE(rc)) 1295 break; 1296 1297 LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n", 1298 pURI->getURIList().RootCount(), pURI->getURIList().TotalBytes())); 1299 1300 /* 1301 * Set the new meta data with the URI list in it. 1302 */ 1303 rc = pData->getMeta().fromURIList(pURI->getURIList()); 1304 if (RT_FAILURE(rc)) 1305 break; 1306 1307 /* 1308 * Set the additional size we are going to send after the meta data header + meta data. 1309 * This additional data will contain the actual file data we want to transfer. 1310 */ 1311 pData->setAdditionalSize(pURI->getURIList().TotalBytes()); 1312 1313 void *pvFmt = (void *)pCtx->mFmtReq.c_str(); 1314 uint32_t cbFmt = pCtx->mFmtReq.length() + 1; /* Include terminating zero. */ 1315 1316 pData->setFmt(pvFmt, cbFmt); 1317 1318 /* 1319 * The first message always is the data header. The meta data itself then follows 1320 * and *only* contains the root elements of an URI list. 1321 * 1322 * After the meta data we generate the messages required to send the 1323 * file/directory data itself. 1324 * 1325 * Note: Protocol < v3 use the first data message to tell what's being sent. 1326 */ 1327 GuestDnDMsg Msg; 1328 1329 /* 1330 * Send the data header first. 1331 */ 1332 if (mDataBase.m_uProtocolVersion >= 3) 1333 rc = i_sendDataHeader(pCtx, pData, &pCtx->mURI); 1334 1335 /* 1336 * Send the (meta) data body. 1337 */ 1214 1338 if (RT_SUCCESS(rc)) 1215 LogFlowFunc(("URI root objects: %zu, total bytes (raw data to transfer): %zu\n", 1216 lstURI.RootCount(), lstURI.TotalBytes())); 1217 else 1218 break; 1219 1220 pCtx->mData.cbProcessed = 0; 1221 pCtx->mData.cbToProcess = lstURI.TotalBytes(); 1222 1223 /* 1224 * The first message always is the meta info for the data. The meta 1225 * info *only* contains the root elements of an URI list. 1226 * 1227 * After the meta data we generate the messages required to send the data itself. 1228 */ 1229 Assert(!lstURI.IsEmpty()); 1230 RTCString strData = lstURI.RootToString().c_str(); 1231 size_t cbData = strData.length() + 1; /* Include terminating zero. */ 1232 1233 GuestDnDMsg MsgSndData; 1234 MsgSndData.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA); 1235 MsgSndData.setNextUInt32(pCtx->mScreenID); 1236 MsgSndData.setNextPointer((void *)pCtx->mFmtReq.c_str(), (uint32_t)pCtx->mFmtReq.length() + 1); 1237 MsgSndData.setNextUInt32((uint32_t)pCtx->mFmtReq.length() + 1); 1238 MsgSndData.setNextPointer((void*)strData.c_str(), (uint32_t)cbData); 1239 MsgSndData.setNextUInt32((uint32_t)cbData); 1240 1241 rc = GuestDnDInst()->hostCall(MsgSndData.getType(), MsgSndData.getCount(), MsgSndData.getParms()); 1339 rc = i_sendDataBody(pCtx, pData); 1340 1242 1341 if (RT_SUCCESS(rc)) 1243 1342 { 1244 rc = waitForEvent( msTimeout, pCtx->mCallback, pCtx->mpResp);1343 rc = waitForEvent(&pCtx->mCBEvent, pCtx->mpResp, msTimeout); 1245 1344 if (RT_FAILURE(rc)) 1246 1345 { 1247 1346 if (rc == VERR_CANCELLED) 1248 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_CANCELLED, VINF_SUCCESS);1347 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_CANCELLED, VINF_SUCCESS); 1249 1348 else if (rc != VERR_GSTDND_GUEST_ERROR) /* Guest-side error are already handled in the callback. */ 1250 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, rc,1349 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1251 1350 GuestDnDTarget::i_hostErrorToString(rc)); 1252 1351 } 1253 1352 else 1254 rc = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, VINF_SUCCESS);1353 rc = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, VINF_SUCCESS); 1255 1354 } 1256 1355 … … 1261 1360 */ 1262 1361 /* Guest callbacks. */ 1263 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG);1264 UNREGISTER_CALLBACK( DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);1362 UNREGISTER_CALLBACK(GUEST_DND_GET_NEXT_HOST_MSG); 1363 UNREGISTER_CALLBACK(GUEST_DND_GH_EVT_ERROR); 1265 1364 /* Host callbacks. */ 1266 UNREGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_DIR);1267 if (mDataBase.m ProtocolVersion >= 2)1268 UNREGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);1269 UNREGISTER_CALLBACK( DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);1365 UNREGISTER_CALLBACK(HOST_DND_HG_SND_DIR); 1366 if (mDataBase.m_uProtocolVersion >= 2) 1367 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_HDR); 1368 UNREGISTER_CALLBACK(HOST_DND_HG_SND_FILE_DATA); 1270 1369 1271 1370 #undef REGISTER_CALLBACK … … 1292 1391 { 1293 1392 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1294 1295 DnDURIList &lstURI = pCtx->mURI.lstURI; 1296 1297 uint64_t cbTotal = pCtx->mData.cbToProcess; 1298 uint8_t uPercent = pCtx->mData.cbProcessed * 100 / (cbTotal ? cbTotal : 1); 1299 1300 LogFlowFunc(("%RU64 / %RU64 -- %RU8%%\n", pCtx->mData.cbProcessed, cbTotal, uPercent)); 1301 1302 bool fComplete = (uPercent >= 100) || lstURI.IsEmpty(); 1303 1304 if (pCtx->mpResp) 1305 { 1306 int rc2 = pCtx->mpResp->setProgress(uPercent, 1307 fComplete 1308 ? DragAndDropSvc::DND_PROGRESS_COMPLETE 1309 : DragAndDropSvc::DND_PROGRESS_RUNNING); 1310 AssertRC(rc2); 1311 } 1312 1313 if (fComplete) 1393 AssertPtrReturn(pMsg, VERR_INVALID_POINTER); 1394 1395 int rc = updateProgress(&pCtx->mData, pCtx->mpResp); 1396 AssertRC(rc); 1397 1398 if ( pCtx->mData.isComplete() 1399 && pCtx->mURI.isComplete()) 1400 { 1314 1401 return VINF_EOF; 1315 1316 Assert(!lstURI.IsEmpty()); 1317 DnDURIObject *pCurObj = lstURI.First(); 1318 1319 /* As we transfer all objects one after another at a time at the moment, 1320 * we only need one object context at the moment. */ 1321 GuestDnDURIObjCtx *pObjCtx = &pCtx->mURI.objCtx; 1322 1323 /* Assign the pointer of the current object to our context. */ 1324 pObjCtx->pObjURI = pCurObj; 1402 } 1403 1404 GuestDnDURIObjCtx &objCtx = pCtx->mURI.getObjCurrent(); 1405 if (!objCtx.isValid()) 1406 return VERR_WRONG_ORDER; 1407 1408 DnDURIObject *pCurObj = objCtx.pObjURI; 1409 AssertPtr(pCurObj); 1325 1410 1326 1411 uint32_t fMode = pCurObj->GetMode(); 1327 Log FlowFunc(("ProcessingsrcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",1328 1329 1330 1331 int rc; 1412 LogRel3(("DnD: Processing: srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n", 1413 pCurObj->GetSourcePath().c_str(), pCurObj->GetDestPath().c_str(), 1414 fMode, pCurObj->GetSize(), 1415 RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode))); 1416 1332 1417 if (RTFS_IS_DIRECTORY(fMode)) 1333 1418 { 1334 rc = i_sendDirectory(pCtx, pObjCtx, pMsg);1419 rc = i_sendDirectory(pCtx, &objCtx, pMsg); 1335 1420 } 1336 1421 else if (RTFS_IS_FILE(fMode)) 1337 1422 { 1338 rc = i_sendFile(pCtx, pObjCtx, pMsg);1423 rc = i_sendFile(pCtx, &objCtx, pMsg); 1339 1424 } 1340 1425 else … … 1355 1440 { 1356 1441 LogFlowFunc(("Removing \"%s\" from list, rc=%Rrc\n", pCurObj->GetSourcePath().c_str(), rc)); 1357 lstURI.RemoveFirst();1442 pCtx->mURI.removeObjCurrent(); 1358 1443 } 1359 1444 … … 1370 1455 AssertPtr(pInst); 1371 1456 1372 /** @todo At the moment we only allow sending up to 64K raw data. Fix this by 1373 * using HOST_DND_HG_SND_MORE_DATA. */ 1374 size_t cbDataTotal = pCtx->mData.vecData.size(); 1375 if ( !cbDataTotal 1376 || cbDataTotal > _64K) 1377 { 1378 return VERR_INVALID_PARAMETER; 1379 } 1380 1381 /* Just copy over the raw data. */ 1382 GuestDnDMsg Msg; 1383 Msg.setType(DragAndDropSvc::HOST_DND_HG_SND_DATA); 1384 Msg.setNextUInt32(pCtx->mScreenID); 1385 Msg.setNextPointer((void *)pCtx->mFmtReq.c_str(), (uint32_t)pCtx->mFmtReq.length() + 1); 1386 Msg.setNextUInt32((uint32_t)pCtx->mFmtReq.length() + 1); 1387 Msg.setNextPointer((void*)&pCtx->mData.vecData.front(), (uint32_t)cbDataTotal); 1388 Msg.setNextUInt32(cbDataTotal); 1389 1390 LogFlowFunc(("Transferring %zu total bytes of raw data ('%s')\n", cbDataTotal, pCtx->mFmtReq.c_str())); 1457 GuestDnDData *pData = &pCtx->mData; 1458 1459 /** @todo At the moment we only allow sending up to 64K raw data. 1460 * For protocol v1+v2: Fix this by using HOST_DND_HG_SND_MORE_DATA. 1461 * For protocol v3 : Send another HOST_DND_HG_SND_DATA message. */ 1462 if (!pData->getMeta().getSize()) 1463 return VINF_SUCCESS; 1464 1465 int rc = VINF_SUCCESS; 1466 1467 /* 1468 * Send the data header first. 1469 */ 1470 if (mDataBase.m_uProtocolVersion >= 3) 1471 rc = i_sendDataHeader(pCtx, pData, NULL /* URI list */); 1472 1473 /* 1474 * Send the (meta) data body. 1475 */ 1476 if (RT_SUCCESS(rc)) 1477 rc = i_sendDataBody(pCtx, pData); 1391 1478 1392 1479 int rc2; 1393 1394 int rc = pInst->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());1395 1480 if (RT_FAILURE(rc)) 1396 rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_ERROR, rc,1481 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_ERROR, rc, 1397 1482 GuestDnDTarget::i_hostErrorToString(rc)); 1398 1483 else 1399 rc2 = pCtx->mpResp->setProgress(100, D ragAndDropSvc::DND_PROGRESS_COMPLETE, rc);1484 rc2 = pCtx->mpResp->setProgress(100, DND_PROGRESS_COMPLETE, rc); 1400 1485 AssertRC(rc2); 1401 1486
Note:
See TracChangeset
for help on using the changeset viewer.