VirtualBox

Changeset 100367 in vbox


Ignore:
Timestamp:
Jul 4, 2023 4:23:18 PM (20 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
158104
Message:

Shared Clipboard: More work on making the internal APIs more fine grained and easier to follow. bugref:9437

Location:
trunk
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/GuestHost/SharedClipboard-transfers.h

    r100290 r100367  
    9090    /** No status set. */
    9191    SHCLTRANSFERSTATUS_NONE = 0,
    92     /** The transfer has been initialized but is not running yet. */
    93     SHCLTRANSFERSTATUS_INITIALIZED,
     92    /** Requests a transfer to be initialized by the host. Only used for H->G transfers.
     93     *  Needed as only the host creates new transfer IDs. */
     94    SHCLTRANSFERSTATUS_REQUESTED = 8,
     95    /** The transfer has been initialized and is ready to go, but is not running yet.
     96     *  At this stage the other party can start reading the root list and other stuff. */
     97    SHCLTRANSFERSTATUS_INITIALIZED = 1,
    9498    /** The transfer has been uninitialized and is not usable anymore. */
    95     SHCLTRANSFERSTATUS_UNINITIALIZED,
     99    SHCLTRANSFERSTATUS_UNINITIALIZED = 2,
    96100    /** The transfer is active and running. */
    97     SHCLTRANSFERSTATUS_STARTED,
     101    SHCLTRANSFERSTATUS_STARTED = 3,
    98102    /** The transfer has been stopped. */
    99     SHCLTRANSFERSTATUS_STOPPED,
     103    SHCLTRANSFERSTATUS_STOPPED = 4,
    100104    /** The transfer has been canceled. */
    101     SHCLTRANSFERSTATUS_CANCELED,
     105    SHCLTRANSFERSTATUS_CANCELED = 5,
    102106    /** The transfer has been killed. */
    103     SHCLTRANSFERSTATUS_KILLED,
     107    SHCLTRANSFERSTATUS_KILLED = 6,
    104108    /** The transfer ran into an unrecoverable error.
    105109     *  This results in completely aborting the operation. */
    106     SHCLTRANSFERSTATUS_ERROR,
     110    SHCLTRANSFERSTATUS_ERROR = 7,
    107111    /** The usual 32-bit hack. */
    108112    SHCLTRANSFERSTATUS_32BIT_SIZE_HACK = 0x7fffffff
     
    361365typedef struct _SHCLREPLY
    362366{
    363     /** Message type (of type VBOX_SHCL_REPLYMSGTYPE_TRANSFER_XXX). */
     367    /** Message type (of type VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_XXX). */
    364368    uint32_t uType;
    365369    /** IPRT result of overall operation. Note: int vs. uint32! */
     
    367371    union
    368372    {
    369         /** For VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS. */
     373        /** For VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS. */
    370374        struct
    371375        {
    372376            SHCLTRANSFERSTATUS uStatus;
    373377        } TransferStatus;
    374         /** For VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN. */
     378        /** For VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN. */
    375379        struct
    376380        {
    377381            SHCLLISTHANDLE uHandle;
    378382        } ListOpen;
    379         /** For VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE. */
     383        /** For VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE. */
    380384        struct
    381385        {
    382386            SHCLLISTHANDLE uHandle;
    383387        } ListClose;
    384         /** For VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN. */
     388        /** For VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN. */
    385389        struct
    386390        {
    387391            SHCLOBJHANDLE uHandle;
    388392        } ObjOpen;
    389         /** For VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE. */
     393        /** For VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE. */
    390394        struct
    391395        {
     
    647651typedef SHCLTXPROVIDERCTX *PSHCLTXPROVIDERCTX;
    648652
    649 struct SHCLTRANSFERCTX;
    650 typedef struct SHCLTRANSFERCTX *PSHCLTRANSFERCTX;
     653struct _SHCLTRANSFERCTX;
     654typedef struct _SHCLTRANSFERCTX *PSHCLTRANSFERCTX;
    651655
    652656/**
     
    907911    /** The node member for using this struct in a RTList. */
    908912    RTLISTNODE                Node;
     913    /** Critical section for serializing access. */
     914    RTCRITSECT                CritSect;
    909915    /** Number of references to this transfer. */
    910916    uint32_t                  cRefs;
     
    917923    /** Maximum data chunk size (in bytes) to transfer. Default is 64K. */
    918924    uint32_t                  cbMaxChunkSize;
     925    /** Status change event. */
     926    RTSEMEVENT                StatusChangeEvent;
    919927    /** The transfer's own event source. */
    920928    SHCLEVENTSOURCE           Events;
     
    951959    /** Contains thread-related attributes. */
    952960    SHCLTRANSFERTHREAD        Thread;
    953     /** Critical section for serializing access. */
    954     RTCRITSECT                CritSect;
    955961} SHCLTRANSFER;
    956962/** Pointer to a Shared Clipboard transfer. */
     
    976982 * Enumeration for HTTP server status changes.
    977983 *
    978  * Keep those as flags, so that we can wait for multiple statuses, if needed.
     984 * Keep those as flags, so that we can wait for multiple statuses, if ever needed.
    979985 */
    980986typedef enum _SHCLHTTPSERVERSTATUS
     
    10411047
    10421048/**
     1049 * Structure for keeping a single transfer context event.
     1050 */
     1051typedef struct _SHCLTRANSFERCTXEVENT
     1052{
     1053    /** Transfer bound to this event.
     1054     *  Can be NULL if not being used. */
     1055    PSHCLTRANSFER  pTransfer;
     1056    /** Whether a transfer was registered or not. */
     1057    bool           fRegistered;
     1058} SHCLTRANSFERCTXEVENT;
     1059/** Pointer to Shared Clipboard transfer context event. */
     1060typedef SHCLTRANSFERCTXEVENT *PSHCLTRANSFERCTXEVENT;
     1061
     1062/**
    10431063 * Structure for keeping Shared Clipboard transfer context around.
    10441064 *
    10451065 * A transfer context contains a list of (grouped) transfers for book keeping.
    10461066 */
    1047 struct SHCLTRANSFERCTX
     1067typedef struct _SHCLTRANSFERCTX
    10481068{
    10491069    /** Critical section for serializing access. */
    10501070    RTCRITSECT                  CritSect;
     1071    /** Event used for waiting. for transfer context changes. */
     1072    RTSEMEVENT                  ChangedEvent;
     1073    /** Event data for \a ChangedEvent. */
     1074    SHCLTRANSFERCTXEVENT        ChangedEventData;
    10511075    /** List of transfers. */
    10521076    RTLISTANCHOR                List;
     
    10591083    /** Number of total transfers (in list). */
    10601084    uint16_t                    cTransfers;
    1061 };
     1085} SHCLTRANSFERCTX;
     1086/** Pointer to Shared Clipboard transfer context. */
     1087typedef SHCLTRANSFERCTX *PSHCLTRANSFERCTX;
    10621088
    10631089/** @name Shared Clipboard transfer interface providers.
    10641090 *  @{
    10651091 */
    1066 PSHCLTXPROVIDERIFACE VBClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider);
     1092PSHCLTXPROVIDERIFACE ShClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider);
    10671093/** @} */
    10681094
     
    10961122 *  @{
    10971123 */
    1098 int ShClTransferCreateEx(uint32_t cbMaxChunkSize, uint32_t cMaxListHandles, uint32_t cMaxObjHandles, PSHCLTRANSFER *ppTransfer);
    1099 int ShClTransferCreate(PSHCLTRANSFER *ppTransfer);
    1100 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource);
     1124int ShClTransferCreateEx(SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, uint32_t cbMaxChunkSize, uint32_t cMaxListHandles, uint32_t cMaxObjHandles, PSHCLTRANSFER *ppTransfer);
     1125int ShClTransferCreate(SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, PSHCLTRANSFER *ppTransfer);
     1126int ShClTransferInit(PSHCLTRANSFER pTransfer);
    11011127int ShClTransferDestroy(PSHCLTRANSFER pTransfer);
    11021128void ShClTransferReset(PSHCLTRANSFER pTransfer);
     
    11131139SHCLSOURCE ShClTransferGetSource(PSHCLTRANSFER pTransfer);
    11141140SHCLTRANSFERSTATUS ShClTransferGetStatus(PSHCLTRANSFER pTransfer);
     1141int ShClTransferWaitForStatus(PSHCLTRANSFER pTransfer, RTMSINTERVAL msTimeout, SHCLTRANSFERSTATUS enmStatus);
     1142int ShClTransferWaitForStatusChange(PSHCLTRANSFER pTransfer, RTMSINTERVAL msTimeout, SHCLTRANSFERSTATUS *penmStatus);
    11151143
    11161144int ShClTransferListOpen(PSHCLTRANSFER pTransfer, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
     
    11591187
    11601188int ShClTransferRootsInitFromStringList(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots);
     1189int ShClTransferRootsInitFromStringListUnicode(PSHCLTRANSFER pTransfer, PRTUTF16 pwszRoots, size_t cbRoots);
    11611190int ShClTransferRootsInitFromFile(PSHCLTRANSFER pTransfer, const char *pszFile);
    11621191uint64_t ShClTransferRootsCount(PSHCLTRANSFER pTransfer);
     
    11731202PSHCLTRANSFER ShClTransferCtxGetTransferById(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID);
    11741203PSHCLTRANSFER ShClTransferCtxGetTransferByIndex(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx);
     1204PSHCLTRANSFER ShClTransferCtxGetTransferLast(PSHCLTRANSFERCTX pTransferCtx);
    11751205uint32_t ShClTransferCtxGetRunningTransfers(PSHCLTRANSFERCTX pTransferCtx);
    11761206uint32_t ShClTransferCtxGetTotalTransfers(PSHCLTRANSFERCTX pTransferCtx);
    11771207void ShClTransferCtxCleanup(PSHCLTRANSFERCTX pTransferCtx);
    1178 bool ShClTransferCtxTransfersMaximumReached(PSHCLTRANSFERCTX pTransferCtx);
    1179 int ShClTransferCtxTransferRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID *pidTransfer);
    1180 int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer);
    1181 int ShClTransferCtxTransferUnregisterById(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer);
     1208bool ShClTransferCtxIsMaximumReached(PSHCLTRANSFERCTX pTransferCtx);
     1209int ShClTransferCtxCreateId(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFERID pidTransfer);
     1210int ShClTransferCtxRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, PSHCLTRANSFERID pidTransfer);
     1211int ShClTransferCtxRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer);
     1212int ShClTransferCtxUnregisterById(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer);
     1213int ShClTransferCtxWait(PSHCLTRANSFERCTX pTransferCtx, RTMSINTERVAL msTimeout, bool fRegister, SHCLTRANSFERID idTransfer, PSHCLTRANSFER *ppTransfer);
    11821214/** @} */
    11831215
     
    12101242char *ShClTransferHttpServerGetAddressA(PSHCLHTTPSERVER pSrv);
    12111243char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer);
     1244bool ShClTransferHttpServerIsInitialized(PSHCLHTTPSERVER pSrv);
    12121245bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv);
    12131246int ShClTransferHttpServerWaitForStatusChange(PSHCLHTTPSERVER pSrv, SHCLHTTPSERVERSTATUS fStatus, RTMSINTERVAL msTimeout);
     
    12221255const char *ShClTransferStatusToStr(SHCLTRANSFERSTATUS enmStatus);
    12231256int ShClTransferValidatePath(const char *pcszPath, bool fMustExist);
    1224 int ShClFsObjInfoQuery(const char *pszPath, PSHCLFSOBJINFO pObjInfo);
     1257int ShClFsObjInfoQueryLocal(const char *pszPath, PSHCLFSOBJINFO pObjInfo);
    12251258int ShClFsObjInfoFromIPRT(PSHCLFSOBJINFO pDst, PCRTFSOBJINFO pSrc);
    12261259/** @} */
  • trunk/include/VBox/GuestHost/SharedClipboard-win.h

    r100206 r100367  
    231231    void Destroy(void);
    232232
    233     void SetCallbacks(PSHCLCALLBACKS pCallbacks);
    234 
    235233public: /* IUnknown methods. */
    236234
     
    263261public:
    264262
    265     int SetAndStartTransfer(PSHCLTRANSFER pTransfer);
    266     int SetStatus(Status enmStatus, int rc = VINF_SUCCESS);
     263    int SetTransfer(PSHCLTRANSFER pTransfer);
     264    int SetStatus(Status enmStatus, int rcSts = VINF_SUCCESS);
    267265
    268266public:
  • trunk/include/VBox/GuestHost/SharedClipboard-x11.h

    r100255 r100367  
    144144    /** What kind of formats does VBox have to offer? */
    145145    SHCLFORMATS      vboxFormats;
    146     /** Cache of the last unicode data that we received. */
    147     void            *pvUnicodeCache;
    148     /** Size of the unicode data in the cache. */
    149     uint32_t         cbUnicodeCache;
     146    /** Internval cache of VBox clipboard formats. */
     147    SHCLCACHE        Cache;
    150148    /** When we wish the clipboard to exit, we have to wake up the event
    151149     * loop.  We do this by writing into a pipe.  This end of the pipe is
  • trunk/include/VBox/HostServices/VBoxClipboardSvc.h

    r100234 r100367  
    330330 * @retval  VERR_WRONG_PARAMETER_COUNT
    331331 * @retval  VERR_WRONG_PARAMETER_TYPE
    332  * @since   6.1.0
     332 * @since   7.1.0
    333333 */
    334334#define VBOX_SHCL_GUEST_FN_REPORT_FEATURES          6
     
    343343 * @retval  VERR_WRONG_PARAMETER_COUNT
    344344 * @retval  VERR_WRONG_PARAMETER_TYPE
    345  * @since   6.1.0
     345 * @since   7.1.0
    346346 */
    347347#define VBOX_SHCL_GUEST_FN_QUERY_FEATURES           7
     
    365365 * @retval  VERR_WRONG_PARAMETER_COUNT
    366366 * @retval  VERR_WRONG_PARAMETER_TYPE
    367  * @since   6.1.0
     367 * @since   7.1.0
    368368 */
    369369#define VBOX_SHCL_GUEST_FN_MSG_PEEK_NOWAIT          8
     
    393393 * @retval  VERR_WRONG_PARAMETER_TYPE
    394394 * @note    This replaces VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT.
    395  * @since   6.1.0
     395 * @since   7.1.0
    396396 */
    397397#define VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT            9
     
    440440 * @since   6.1.x
    441441 */
    442 #define VBOX_SHCL_GUEST_FN_REPLY                  11
    443 /** Gets the root list header from the host.
    444  *
    445  * @retval  VINF_SUCCESS on success.
    446  * @retval  VERR_INVALID_CLIENT_ID
    447  * @retval  VERR_WRONG_PARAMETER_COUNT
    448  * @retval  VERR_WRONG_PARAMETER_TYPE
    449  * @since   6.1.x
    450  */
    451 #define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_READ     12
    452 /** Sends the root list header to the host.
    453  *
    454  * @retval  VINF_SUCCESS on success.
    455  * @retval  VERR_INVALID_CLIENT_ID
    456  * @retval  VERR_WRONG_PARAMETER_COUNT
    457  * @retval  VERR_WRONG_PARAMETER_TYPE
    458  * @since   7.1.x
    459  */
    460 #define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE    13
    461 /** Gets a root list root entry from the host.
    462  *
    463  * @retval  VINF_SUCCESS on success.
    464  * @retval  VERR_INVALID_CLIENT_ID
    465  * @retval  VERR_WRONG_PARAMETER_COUNT
    466  * @retval  VERR_WRONG_PARAMETER_TYPE
    467  * @since   7.1.x
    468  */
    469 #define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_READ   14
    470 /** Sends a root list root entry to the host.
    471  *
    472  * @retval  VINF_SUCCESS on success.
    473  * @retval  VERR_INVALID_CLIENT_ID
    474  * @retval  VERR_WRONG_PARAMETER_COUNT
    475  * @retval  VERR_WRONG_PARAMETER_TYPE
    476  * @since   7.1.x
    477  */
    478 #define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE  15
    479 /** Opens / gets a list handle from the host.
    480  *
    481  * @retval  VINF_SUCCESS on success.
    482  * @retval  VERR_INVALID_CLIENT_ID
    483  * @retval  VERR_WRONG_PARAMETER_COUNT
    484  * @retval  VERR_WRONG_PARAMETER_TYPE
    485  * @since   7.1.x
    486  */
    487 #define VBOX_SHCL_GUEST_FN_LIST_OPEN              16
    488 /** Closes a list handle from the host.
    489  *
    490  * @retval  VINF_SUCCESS on success.
    491  * @retval  VERR_INVALID_CLIENT_ID
    492  * @retval  VERR_WRONG_PARAMETER_COUNT
    493  * @retval  VERR_WRONG_PARAMETER_TYPE
    494  * @since   7.1.x
    495  */
    496 #define VBOX_SHCL_GUEST_FN_LIST_CLOSE             17
    497 /** Reads a list header from the host.
    498  *
    499  * @retval  VINF_SUCCESS on success.
    500  * @retval  VERR_INVALID_CLIENT_ID
    501  * @retval  VERR_WRONG_PARAMETER_COUNT
    502  * @retval  VERR_WRONG_PARAMETER_TYPE
    503  * @since   7.1.x
    504  */
    505 #define VBOX_SHCL_GUEST_FN_LIST_HDR_READ          18
    506 /** Writes a list header to the host.
    507  *
    508  * @retval  VINF_SUCCESS on success.
    509  * @retval  VERR_INVALID_CLIENT_ID
    510  * @retval  VERR_WRONG_PARAMETER_COUNT
    511  * @retval  VERR_WRONG_PARAMETER_TYPE
    512  * @since   7.1.x
    513  */
    514 #define VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE         19
    515 /** Reads a list entry from the host.
    516  *
    517  * @retval  VINF_SUCCESS on success.
    518  * @retval  VERR_INVALID_CLIENT_ID
    519  * @retval  VERR_WRONG_PARAMETER_COUNT
    520  * @retval  VERR_WRONG_PARAMETER_TYPE
    521  * @since   7.1.x
    522  */
    523 #define VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ        20
    524 /** Sends a list entry to the host.
    525  *
    526  * @retval  VINF_SUCCESS on success.
    527  * @retval  VERR_INVALID_CLIENT_ID
    528  * @retval  VERR_WRONG_PARAMETER_COUNT
    529  * @retval  VERR_WRONG_PARAMETER_TYPE
    530  * @since   7.1.x
    531  */
    532 #define VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE       21
    533 /** Opens an object on the host.
    534  *
    535  * @retval  VINF_SUCCESS on success.
    536  * @retval  VERR_INVALID_CLIENT_ID
    537  * @retval  VERR_WRONG_PARAMETER_COUNT
    538  * @retval  VERR_WRONG_PARAMETER_TYPE
    539  * @since   7.1.x
    540  */
    541 #define VBOX_SHCL_GUEST_FN_OBJ_OPEN               22
    542 /** Closes an object on the host.
    543  *
    544  * @retval  VINF_SUCCESS on success.
    545  * @retval  VERR_INVALID_CLIENT_ID
    546  * @retval  VERR_WRONG_PARAMETER_COUNT
    547  * @retval  VERR_WRONG_PARAMETER_TYPE
    548  * @since   7.1.x
    549  */
    550 #define VBOX_SHCL_GUEST_FN_OBJ_CLOSE              23
    551 /** Reads from an object on the host.
    552  *
    553  * @retval  VINF_SUCCESS on success.
    554  * @retval  VERR_INVALID_CLIENT_ID
    555  * @retval  VERR_WRONG_PARAMETER_COUNT
    556  * @retval  VERR_WRONG_PARAMETER_TYPE
    557  * @since   7.1.x
    558  */
    559 #define VBOX_SHCL_GUEST_FN_OBJ_READ               24
    560 /** Writes to an object on the host.
    561  *
    562  * @retval  VINF_SUCCESS on success.
    563  * @retval  VERR_INVALID_CLIENT_ID
    564  * @retval  VERR_WRONG_PARAMETER_COUNT
    565  * @retval  VERR_WRONG_PARAMETER_TYPE
    566  * @since   7.1.x
    567  */
    568 #define VBOX_SHCL_GUEST_FN_OBJ_WRITE              25
    569 /** Reports an error to the host.
     442#define VBOX_SHCL_GUEST_FN_REPLY                 11
     443/** Gets the transfer root list header from the host.
     444 *
     445 * @retval  VINF_SUCCESS on success.
     446 * @retval  VERR_INVALID_CLIENT_ID
     447 * @retval  VERR_WRONG_PARAMETER_COUNT
     448 * @retval  VERR_WRONG_PARAMETER_TYPE
     449 * @since   7.1.x
     450 */
     451#define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_READ    12
     452/** Sends the transfer root list header to the host.
     453 *
     454 * @retval  VINF_SUCCESS on success.
     455 * @retval  VERR_INVALID_CLIENT_ID
     456 * @retval  VERR_WRONG_PARAMETER_COUNT
     457 * @retval  VERR_WRONG_PARAMETER_TYPE
     458 * @since   7.1.x
     459 */
     460#define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE   13
     461/** Gets a transfer root list root entry from the host.
     462 *
     463 * @retval  VINF_SUCCESS on success.
     464 * @retval  VERR_INVALID_CLIENT_ID
     465 * @retval  VERR_WRONG_PARAMETER_COUNT
     466 * @retval  VERR_WRONG_PARAMETER_TYPE
     467 * @since   7.1.x
     468 */
     469#define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_READ  14
     470/** Sends a transfer root list root entry to the host.
     471 *
     472 * @retval  VINF_SUCCESS on success.
     473 * @retval  VERR_INVALID_CLIENT_ID
     474 * @retval  VERR_WRONG_PARAMETER_COUNT
     475 * @retval  VERR_WRONG_PARAMETER_TYPE
     476 * @since   7.1.x
     477 */
     478#define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE 15
     479/** Opens / gets a transfer list handle from the host.
     480 *
     481 * @retval  VINF_SUCCESS on success.
     482 * @retval  VERR_INVALID_CLIENT_ID
     483 * @retval  VERR_WRONG_PARAMETER_COUNT
     484 * @retval  VERR_WRONG_PARAMETER_TYPE
     485 * @since   7.1.x
     486 */
     487#define VBOX_SHCL_GUEST_FN_LIST_OPEN             16
     488/** Closes a transfer list handle from the host.
     489 *
     490 * @retval  VINF_SUCCESS on success.
     491 * @retval  VERR_INVALID_CLIENT_ID
     492 * @retval  VERR_WRONG_PARAMETER_COUNT
     493 * @retval  VERR_WRONG_PARAMETER_TYPE
     494 * @since   7.1.x
     495 */
     496#define VBOX_SHCL_GUEST_FN_LIST_CLOSE            17
     497/** Reads a transfer list header from the host.
     498 *
     499 * @retval  VINF_SUCCESS on success.
     500 * @retval  VERR_INVALID_CLIENT_ID
     501 * @retval  VERR_WRONG_PARAMETER_COUNT
     502 * @retval  VERR_WRONG_PARAMETER_TYPE
     503 * @since   7.1.x
     504 */
     505#define VBOX_SHCL_GUEST_FN_LIST_HDR_READ         18
     506/** Writes a transfer list header to the host.
     507 *
     508 * @retval  VINF_SUCCESS on success.
     509 * @retval  VERR_INVALID_CLIENT_ID
     510 * @retval  VERR_WRONG_PARAMETER_COUNT
     511 * @retval  VERR_WRONG_PARAMETER_TYPE
     512 * @since   7.1.x
     513 */
     514#define VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE        19
     515/** Reads a transfer list entry from the host.
     516 *
     517 * @retval  VINF_SUCCESS on success.
     518 * @retval  VERR_INVALID_CLIENT_ID
     519 * @retval  VERR_WRONG_PARAMETER_COUNT
     520 * @retval  VERR_WRONG_PARAMETER_TYPE
     521 * @since   7.1.x
     522 */
     523#define VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ       20
     524/** Sends a transfer list entry to the host.
     525 *
     526 * @retval  VINF_SUCCESS on success.
     527 * @retval  VERR_INVALID_CLIENT_ID
     528 * @retval  VERR_WRONG_PARAMETER_COUNT
     529 * @retval  VERR_WRONG_PARAMETER_TYPE
     530 * @since   7.1.x
     531 */
     532#define VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE      21
     533/** Opens a transfer object on the host.
     534 *
     535 * @retval  VINF_SUCCESS on success.
     536 * @retval  VERR_INVALID_CLIENT_ID
     537 * @retval  VERR_WRONG_PARAMETER_COUNT
     538 * @retval  VERR_WRONG_PARAMETER_TYPE
     539 * @since   7.1.x
     540 */
     541#define VBOX_SHCL_GUEST_FN_OBJ_OPEN              22
     542/** Closes a transfer object on the host.
     543 *
     544 * @retval  VINF_SUCCESS on success.
     545 * @retval  VERR_INVALID_CLIENT_ID
     546 * @retval  VERR_WRONG_PARAMETER_COUNT
     547 * @retval  VERR_WRONG_PARAMETER_TYPE
     548 * @since   7.1.x
     549 */
     550#define VBOX_SHCL_GUEST_FN_OBJ_CLOSE             23
     551/** Reads from a transfer object on the host.
     552 *
     553 * @retval  VINF_SUCCESS on success.
     554 * @retval  VERR_INVALID_CLIENT_ID
     555 * @retval  VERR_WRONG_PARAMETER_COUNT
     556 * @retval  VERR_WRONG_PARAMETER_TYPE
     557 * @since   7.1.x
     558 */
     559#define VBOX_SHCL_GUEST_FN_OBJ_READ              24
     560/** Writes to a transfer object on the host.
     561 *
     562 * @retval  VINF_SUCCESS on success.
     563 * @retval  VERR_INVALID_CLIENT_ID
     564 * @retval  VERR_WRONG_PARAMETER_COUNT
     565 * @retval  VERR_WRONG_PARAMETER_TYPE
     566 * @since   7.1.x
     567 */
     568#define VBOX_SHCL_GUEST_FN_OBJ_WRITE             25
     569/** Reports a transfer error to the host.
    570570 *
    571571 * @todo r=bird: Smells like GUEST_MSG_SKIP
     
    577577 * @since   6.1
    578578 */
    579 #define VBOX_SHCL_GUEST_FN_ERROR                  27
     579#define VBOX_SHCL_GUEST_FN_ERROR                 27
    580580
    581581/** For negotiating a chunk size between the guest and host.
     
    593593 * @retval  VERR_INVALID_PARAMETER if the 2nd parameter is larger than the
    594594 *          first one
    595  * @since   6.1
     595 * @since   7.1
    596596 */
    597597#define VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE     28
     
    836836
    837837/** Invalid message type, do not use. */
    838 #define VBOX_SHCL_REPLYMSGTYPE_INVALID           0
     838#define VBOX_SHCL_TX_REPLYMSGTYPE_INVALID           0
    839839/** Replies a transfer status. */
    840 #define VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS   1
     840#define VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS   1
    841841/** Replies a list open status. */
    842 #define VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN         2
     842#define VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN         2
    843843/** Replies a list close status. */
    844 #define VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE        3
     844#define VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE        3
    845845/** Replies an object open status. */
    846 #define VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN          4
     846#define VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN          4
    847847/** Replies an object close status. */
    848 #define VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE         5
     848#define VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE         5
    849849
    850850/**
     
    857857    /** uint64_t, out: Context ID. */
    858858    HGCMFunctionParameter uContext;
    859     /** uint32_t, out: Message type of type VBOX_SHCL_REPLYMSGTYPE_XXX. */
     859    /** uint32_t, out: Message type of type VBOX_SHCL_TX_REPLYMSGTYPE_XXX. */
    860860    HGCMFunctionParameter enmType;
    861861    /** uint32_t, out: IPRT result of overall operation. */
  • trunk/include/VBox/VBoxGuestLib.h

    r100362 r100367  
    637637    /** The context ID - input or/and output depending on the operation. */
    638638    uint64_t                    idContext;
    639     /** OUT: Number of parameters retrieved.
    640      * This is set by ??. */
    641     uint32_t                    cParmsRecived;
    642639# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    643640    /** Data related to Shared Clipboard file transfers. */
     
    726723
    727724#  ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     725VBGLR3DECL(int)     VbglR3ClipboardTransferRequest(PVBGLR3SHCLCMDCTX pCmdCtx);
    728726VBGLR3DECL(void)    VbglR3ClipboardTransferSetCallbacks(PSHCLTRANSFERCALLBACKS pCallbacks);
    729727VBGLR3DECL(int)     VbglR3ClipboardEventGetNextEx(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFERCTX pTransferCtx, PVBGLR3CLIPBOARDEVENT pEvent);
     
    731729VBGLR3DECL(int)     VbglR3ClipboardTransferStatusReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus);
    732730
    733 VBGLR3DECL(int)     VbglR3ClipboardRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLLIST *ppRootList);
    734 
    735 VBGLR3DECL(int)     VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots);
    736 VBGLR3DECL(int)     VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLLIST pRootList);
     731VBGLR3DECL(int)     VbglR3ClipboardTransferRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLLIST *ppRootList);
     732
     733VBGLR3DECL(int)     VbglR3ClipboardTransferRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots);
     734VBGLR3DECL(int)     VbglR3ClipboardTransferRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLLIST pRootList);
    737735VBGLR3DECL(int)     VbglR3ClipboardRootsWrite(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHDR pRoots);
    738736
    739 VBGLR3DECL(int)     VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
    740 VBGLR3DECL(int)     VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms);
    741 VBGLR3DECL(int)     VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList);
    742 
    743 VBGLR3DECL(int)     VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList);
     737VBGLR3DECL(int)     VbglR3ClipboardTransferListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
     738VBGLR3DECL(int)     VbglR3ClipboardTransferListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms);
     739VBGLR3DECL(int)     VbglR3ClipboardTransferListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList);
     740
     741VBGLR3DECL(int)     VbglR3ClipboardTransferListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList);
    744742VBGLR3DECL(int)     VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList);
    745743
    746 VBGLR3DECL(int)     VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
    747 VBGLR3DECL(int)     VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
    748 
    749 VBGLR3DECL(int)     VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms);
    750 VBGLR3DECL(int)     VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
    751 VBGLR3DECL(int)     VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
     744VBGLR3DECL(int)     VbglR3ClipboardTransferListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
     745VBGLR3DECL(int)     VbglR3ClipboardTransferListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
     746
     747VBGLR3DECL(int)     VbglR3ClipboardTransferObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms);
     748VBGLR3DECL(int)     VbglR3ClipboardTransferObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
     749VBGLR3DECL(int)     VbglR3ClipboardTransferObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
    752750                                               PSHCLOBJHANDLE phObj);
    753751
    754 VBGLR3DECL(int)     VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj);
    755 VBGLR3DECL(int)     VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
    756 VBGLR3DECL(int)     VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj);
    757 
    758 VBGLR3DECL(int)     VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t pcbToRead,
     752VBGLR3DECL(int)     VbglR3ClipboardTransferObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj);
     753VBGLR3DECL(int)     VbglR3ClipboardTransferObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
     754VBGLR3DECL(int)     VbglR3ClipboardTransferObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj);
     755
     756VBGLR3DECL(int)     VbglR3ClipboardTransferObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t pcbToRead,
    759757                                               uint32_t *pfFlags);
    760 VBGLR3DECL(int)     VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
     758VBGLR3DECL(int)     VbglR3ClipboardTransferObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
    761759                                               uint32_t *pcbRead);
    762 VBGLR3DECL(int)     VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
     760VBGLR3DECL(int)     VbglR3ClipboardTransferObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
    763761                                                uint32_t *pcbWritten);
    764762#  endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r100205 r100367  
    120120    }
    121121
    122     int rc2 = ShClTransferCtxTransferUnregister(pTransferCtx, pTransfer->State.uID);
     122    int rc2 = ShClTransferCtxUnregisterById(pTransferCtx, pTransfer->State.uID);
    123123    AssertRC(rc2);
    124124
     
    251251            SharedClipboardWinDataObject *pObj = pCtx->Win.pDataObjInFlight;
    252252            AssertPtrReturnVoid(pObj);
    253             rc = pObj->SetAndStartTransfer(pTransfer);
     253            rc = pObj->SetTransfer(pTransfer);
    254254
    255255            pCtx->Win.pDataObjInFlight = NULL; /* Hand off to Windows. */
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp

    r100291 r100367  
    118118    pCtx->fHostFeatures         = 0;
    119119    pCtx->fUseLegacyProtocol    = true;
    120     pCtx->cParmsRecived         = 0;
    121120    pCtx->idContext             = 0;
    122121
     
    687686
    688687/**
    689  * Reads a root list header from the host.
     688 * Reads a transfer root list header from the host.
    690689 *
    691690 * @returns VBox status code.
     
    693692 * @param   pRootListHdr        Where to store the received root list header.
    694693 */
    695 static int vbglR3ClipboardRootListHdrRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHDR pRootListHdr)
     694static int vbglR3ClipboardTransferRootListHdrRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHDR pRootListHdr)
    696695{
    697696    AssertPtrReturn(pCtx,         VERR_INVALID_POINTER);
     
    720719        }
    721720    }
    722 
    723     LogFlowFuncLeaveRC(rc);
    724     return rc;
    725 }
    726 
    727 /**
    728  * Reads a root list entry from the host.
     721    else
     722        LogRel(("Shared Clipboard: Reading root list header failed: %Rrc\n", rc));
     723
     724    LogFlowFuncLeaveRC(rc);
     725    return rc;
     726}
     727
     728/**
     729 * Reads a transfer root list entry from the host.
    729730 *
    730731 * @returns VBox status code.
     
    733734 * @param   pRootListEntry      Where to store the root list entry read from the host.
    734735 */
    735 static int vbglR3ClipboardRootListEntryRead(PVBGLR3SHCLCMDCTX pCtx, uint64_t uIndex, PSHCLLISTENTRY pRootListEntry)
     736static int vbglR3ClipboardTransferRootListEntryRead(PVBGLR3SHCLCMDCTX pCtx, uint64_t uIndex, PSHCLLISTENTRY pRootListEntry)
    736737{
    737738    AssertPtrReturn(pCtx,           VERR_INVALID_POINTER);
     
    794795            }
    795796        }
     797        else
     798            LogRel(("Shared Clipboard: Reading root list entry failed: %Rrc\n", rc));
    796799    }
    797800
     
    803806
    804807/**
    805  * Reads the root list from the host.
    806  *
    807  * @returns VBox status code.
    808  * @param   pCtx                Shared Clipboard command context to use for the connection.
    809  * @param   pRootList           Where to store the read root list.
    810  *
    811  */
    812 VBGLR3DECL(int) VbglR3ClipboardRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer)
     808 * Reads the transfer root list from the host.
     809 *
     810 * @returns VBox status code.
     811 * @param   pCtx                Shared Clipboard command context to use for the connection.
     812 * @param   pTransfer           Transfer to read root list for.
     813 *                              Must be in INITIALIZED state.
     814 */
     815VBGLR3DECL(int) VbglR3ClipboardTransferRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer)
    813816{
    814817    AssertPtrReturn(pCtx,      VERR_INVALID_POINTER);
    815818    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    816819
     820    AssertMsgReturn(ShClTransferGetStatus(pTransfer) == SHCLTRANSFERSTATUS_INITIALIZED,
     821                    ("Can't read root list -- wrong transfer status\n"), VERR_WRONG_ORDER);
     822
    817823    SHCLLISTHDR Hdr;
    818     int rc = vbglR3ClipboardRootListHdrRead(pCtx, &Hdr);
     824    int rc = vbglR3ClipboardTransferRootListHdrRead(pCtx, &Hdr);
    819825    if (RT_SUCCESS(rc))
    820826    {
    821827        LogFlowFunc(("cEntries=%RU64, cTotalSize=%RU64\n", Hdr.cEntries, Hdr.cbTotalSize));
     828
     829        if (!Hdr.cEntries) /* Should never happen (tm). */
     830        {
     831#ifdef DEBUG_andy
     832            AssertFailed();
     833#endif
     834            LogRel(("Shared Clipboard: Warning: Transfer %RU32 has no entries\n", ShClTransferGetID(pTransfer)));
     835        }
    822836
    823837        for (uint64_t i = 0; i < Hdr.cEntries; i++)
     
    827841            if (RT_SUCCESS(rc))
    828842            {
    829                 rc = vbglR3ClipboardRootListEntryRead(pCtx, i, pEntry);
     843                rc = vbglR3ClipboardTransferRootListEntryRead(pCtx, i, pEntry);
    830844                if (RT_SUCCESS(rc))
    831845                    rc = ShClTransferListAddEntry(&pTransfer->lstRoots, pEntry, true /* fAppend */);
     
    839853        }
    840854    }
     855    else
     856        LogRel(("Shared Clipboard: Reading root list for transfer %RU32 failed: %Rrc\n", ShClTransferGetID(pTransfer), rc));
    841857
    842858    LogFlowFuncLeaveRC(rc);
     
    900916
    901917/**
     918 * Replies to a transfer report from the host, extended version.
     919 *
     920 * @returns VBox status code.
     921 * @param   pCtx                Shared Clipboard command context to use for the connection.
     922 * @param   uCID                Context ID to use.
     923 *                              The transfer ID is part of this.
     924 * @param   uStatus             Tranfer status to reply.
     925 * @param   rcTransfer          Result code (rc) to reply.
     926 */
     927static int vbglR3ClipboardTransferStatusReplyEx(PVBGLR3SHCLCMDCTX pCtx, uint64_t uCID,
     928                                                SHCLTRANSFERSTATUS uStatus, int rcTransfer)
     929{
     930    AssertPtrReturn(pCtx,      VERR_INVALID_POINTER);
     931
     932    VBoxShClReplyMsg Msg;
     933    VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
     934                       VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
     935
     936    Msg.uContext.SetUInt64(uCID);
     937    Msg.enmType.SetUInt32(VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS);
     938    Msg.rc.SetUInt32((uint32_t )rcTransfer); /* int vs. uint32_t */
     939    Msg.pvPayload.SetPtr(NULL, 0);
     940
     941    Msg.u.TransferStatus.enmStatus.SetUInt32((uint32_t)uStatus);
     942
     943    LogFlowFunc(("%s\n", ShClTransferStatusToStr(uStatus)));
     944
     945    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     946
     947    LogFlowFuncLeaveRC(rc);
     948    return rc;
     949}
     950
     951/**
    902952 * Replies to a transfer report from the host.
    903953 *
     
    914964    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    915965
    916     RT_NOREF(pTransfer);
    917 
    918     VBoxShClReplyMsg Msg;
    919     VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->idClient,
    920                        VBOX_SHCL_GUEST_FN_REPLY, VBOX_SHCL_CPARMS_REPLY_MIN + 1);
    921 
    922     Msg.uContext.SetUInt64(pCtx->idContext);
    923     Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
    924     Msg.rc.SetUInt32((uint32_t )rcTransfer); /* int vs. uint32_t */
    925     Msg.pvPayload.SetPtr(NULL, 0);
    926 
    927     Msg.u.TransferStatus.enmStatus.SetUInt32((uint32_t)uStatus);
    928 
    929     LogFlowFunc(("%s\n", ShClTransferStatusToStr(uStatus)));
    930 
    931     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
    932 
    933     LogFlowFuncLeaveRC(rc);
    934     return rc;
    935 }
    936 
    937 /**
    938  * Receives a host request to read a root list header from the guest.
     966    int rc = vbglR3ClipboardTransferStatusReplyEx(pCtx, pCtx->idContext, uStatus, rcTransfer);
     967
     968    LogFlowFuncLeaveRC(rc);
     969    return rc;
     970}
     971
     972/**
     973 * Receives a host request to read a transfer root list header from the guest.
    939974 *
    940975 * @returns VBox status code.
     
    942977 * @param   pfRoots             Where to store the root list header flags to use, requested by the host.
    943978 */
    944 VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots)
     979VBGLR3DECL(int) VbglR3ClipboardTransferRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots)
    945980{
    946981    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     
    9701005
    9711006/**
    972  * Replies to a root list header request.
     1007 * Replies to a transfer root list header request.
    9731008 *
    9741009 * @returns VBox status code.
     
    9761011 * @param   pRootListHdr        Root lsit header to reply to the host.
    9771012 */
    978 VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHDR pRootListHdr)
     1013VBGLR3DECL(int) VbglR3ClipboardTransferRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHDR pRootListHdr)
    9791014{
    9801015    AssertPtrReturn(pCtx,         VERR_INVALID_POINTER);
     
    9971032
    9981033/**
    999  * Receives a host request to read a root list entry from the guest.
     1034 * Receives a host request to read a transfer root list entry from the guest.
    10001035 *
    10011036 * @returns VBox status code.
     
    10041039 * @param   pfInfo              Where to return the read flags the host wants to use.
    10051040 */
    1006 VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *puIndex, uint32_t *pfInfo)
     1041VBGLR3DECL(int) VbglR3ClipboardTransferRootListEntryReadReq(PVBGLR3SHCLCMDCTX pCtx, uint64_t *puIndex, uint32_t *pfInfo)
    10071042{
    10081043    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     
    10161051    Msg.Parms.uContext.SetUInt64(VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ);
    10171052    Msg.Parms.fInfo.SetUInt32(0);
    1018     Msg.Parms.uIndex.SetUInt32(0);
     1053    Msg.Parms.uIndex.SetUInt64(0);
    10191054
    10201055    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
     
    10291064        if (RT_SUCCESS(rc))
    10301065        {
    1031             rc = Msg.Parms.uIndex.GetUInt32(puIndex);
     1066            rc = Msg.Parms.uIndex.GetUInt64(puIndex);
    10321067            AssertRC(rc);
    10331068        }
     
    10391074
    10401075/**
    1041  * Replies to a root list entry read request from the host.
     1076 * Replies to a transfer root list entry read request from the host.
    10421077 *
    10431078 * @returns VBox status code.
     
    10461081 * @param   pEntry              Actual root list entry to reply.
    10471082 */
    1048 VBGLR3DECL(int) VbglR3ClipboardRootListEntryReadReply(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLLISTENTRY pEntry)
     1083VBGLR3DECL(int) VbglR3ClipboardTransferRootListEntryReadReply(PVBGLR3SHCLCMDCTX pCtx, uint32_t uIndex, PSHCLLISTENTRY pEntry)
    10491084{
    10501085    AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
     
    10561091
    10571092    Msg.Parms.uContext.SetUInt64(pCtx->idContext);
    1058     Msg.Parms.fInfo.SetUInt32(0);
    1059     Msg.Parms.uIndex.SetUInt32(uIndex);
     1093    Msg.Parms.fInfo.SetUInt32(pEntry->fInfo);
     1094    Msg.Parms.uIndex.SetUInt64(uIndex);
    10601095
    10611096    Msg.szName.SetPtr(pEntry->pszName, pEntry->cbName);
     
    10701105
    10711106/**
    1072  * Sends a request to open a list handle to the host.
     1107 * Sends a request to open a transfer list handle to the host.
    10731108 *
    10741109 * @returns VBox status code.
     
    10771112 * @param   phList              Where to return the list handle received from the host.
    10781113 */
    1079 VBGLR3DECL(int) VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
    1080                                             PSHCLLISTHANDLE phList)
     1114VBGLR3DECL(int) VbglR3ClipboardTransferListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms,
     1115                                                    PSHCLLISTHANDLE phList)
    10811116{
    10821117    AssertPtrReturn(pCtx,       VERR_INVALID_POINTER);
     
    11051140
    11061141/**
    1107  * Receives a host request to open a list handle on the guest.
     1142 * Receives a host request to open a transfer list handle on the guest.
    11081143 *
    11091144 * @returns VBox status code.
     
    11111146 * @param   pOpenParms          Where to store the open parameters the host wants to use for opening the list handle.
    11121147 */
    1113 VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms)
     1148VBGLR3DECL(int) VbglR3ClipboardTransferListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms)
    11141149{
    11151150    AssertPtrReturn(pCtx,       VERR_INVALID_POINTER);
     
    11391174
    11401175/**
    1141  * Replies to a list open request from the host.
     1176 * Replies to a transfer list open request from the host.
    11421177 *
    11431178 * @returns VBox status code.
     
    11461181 * @param   hList               List handle of (guest) list to reply to the host.
    11471182 */
    1148 VBGLR3DECL(int) VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
     1183VBGLR3DECL(int) VbglR3ClipboardTransferListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
    11491184{
    11501185    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    11551190
    11561191    Msg.uContext.SetUInt64(pCtx->idContext);
    1157     Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN);
     1192    Msg.enmType.SetUInt32(VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN);
    11581193    Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
    11591194    Msg.pvPayload.SetPtr(NULL, 0);
     
    11741209 * @param   phList              Where to store the list handle to close, received from the host.
    11751210 */
    1176 VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList)
     1211VBGLR3DECL(int) VbglR3ClipboardTransferListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList)
    11771212{
    11781213    AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
     
    12021237
    12031238/**
    1204  * Replies to a list handle close request from the host.
     1239 * Replies to a transfer list handle close request from the host.
    12051240 *
    12061241 * @returns VBox status code.
     
    12091244 * @param   hList               List handle the send the close reply for.
    12101245 */
    1211 VBGLR3DECL(int) VbglR3ClipboardListCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
     1246VBGLR3DECL(int) VbglR3ClipboardTransferListCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList)
    12121247{
    12131248    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    12181253
    12191254    Msg.uContext.SetUInt64(pCtx->idContext);
    1220     Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE);
     1255    Msg.enmType.SetUInt32(VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE);
    12211256    Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
    12221257    Msg.pvPayload.SetPtr(NULL, 0);
     
    12311266
    12321267/**
    1233  * Sends a request to close a list handle to the host.
     1268 * Sends a request to close a transfer list handle to the host.
    12341269 *
    12351270 * @returns VBox status code.
     
    12371272 * @param   hList               List handle to request for closing on the host.
    12381273 */
    1239 VBGLR3DECL(int) VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList)
     1274VBGLR3DECL(int) VbglR3ClipboardTransferListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList)
    12401275{
    12411276    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    12551290
    12561291/**
    1257  * Sends a request to read a list header to the host.
     1292 * Sends a request to read a transfer list header to the host.
    12581293 *
    12591294 * @returns VBox status code.
     
    12631298 * @param   pListHdr            Where to return the list header received from the host.
    12641299 */
    1265 VBGLR3DECL(int) VbglR3ClipboardListHdrRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, uint32_t fFlags,
    1266                                            PSHCLLISTHDR pListHdr)
     1300VBGLR3DECL(int) VbglR3ClipboardTransferListHdrRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, uint32_t fFlags,
     1301                                                   PSHCLLISTHDR pListHdr)
    12671302{
    12681303    AssertPtrReturn(pCtx,     VERR_INVALID_POINTER);
     
    12971332
    12981333/**
    1299  * Receives a host request to read a list header on the guest.
     1334 * Receives a host request to read a transfer list header on the guest.
    13001335 *
    13011336 * @returns VBox status code.
     
    13041339 * @param   pfFlags             Where to return the List header read flags to use.
    13051340 */
    1306 VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfFlags)
     1341VBGLR3DECL(int) VbglR3ClipboardTransferListHdrReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfFlags)
    13071342{
    13081343    AssertPtrReturn(pCtx,    VERR_INVALID_POINTER);
     
    13331368
    13341369/**
    1335  * Sends (writes) a list header to the host.
     1370 * Sends (writes) a transfer list header to the host.
    13361371 *
    13371372 * @returns VBox status code.
     
    13401375 * @param   pListHdr            List header to write.
    13411376 */
    1342 VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
    1343                                             PSHCLLISTHDR pListHdr)
     1377VBGLR3DECL(int) VbglR3ClipboardTransferListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
     1378                                                    PSHCLLISTHDR pListHdr)
    13441379{
    13451380    AssertPtrReturn(pCtx,     VERR_INVALID_POINTER);
     
    13661401
    13671402/**
    1368  * Sends a request to read a list entry from the host.
     1403 * Sends a request to read a transfer list entry from the host.
    13691404 *
    13701405 * @returns VBox status code.
     
    13731408 * @param   pListEntry          Where to return the list entry read from the host.
    13741409 */
    1375 VBGLR3DECL(int) VbglR3ClipboardListEntryRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
    1376                                              PSHCLLISTENTRY pListEntry)
     1410VBGLR3DECL(int) VbglR3ClipboardTransferListEntryRead(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
     1411                                                     PSHCLLISTENTRY pListEntry)
    13771412{
    13781413    AssertPtrReturn(pCtx,       VERR_INVALID_POINTER);
     
    14021437
    14031438/**
    1404  * Receives a host request to read a list entry from the guest.
     1439 * Receives a host request to read a transfer list entry from the guest.
    14051440 *
    14061441 * @returns VBox status code.
     
    14091444 * @param   pfInfo              Where to return the list read flags.
    14101445 */
    1411 VBGLR3DECL(int) VbglR3ClipboardListEntryReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfInfo)
     1446VBGLR3DECL(int) VbglR3ClipboardTransferListEntryReadRecvReq(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList, uint32_t *pfInfo)
    14121447{
    14131448    AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
     
    14441479
    14451480/**
    1446  * Sends (writes) a list entry to the host.
     1481 * Sends (writes) a transfer list entry to the host.
    14471482 *
    14481483 * @returns VBox status code.
     
    14511486 * @param   pListEntry          List entry to write.
    14521487 */
    1453 VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
    1454                                               PSHCLLISTENTRY pListEntry)
     1488VBGLR3DECL(int) VbglR3ClipboardTransferListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList,
     1489                                                      PSHCLLISTENTRY pListEntry)
    14551490{
    14561491    AssertPtrReturn(pCtx,       VERR_INVALID_POINTER);
     
    14761511
    14771512/**
    1478  * Receives a host request to open an object on the guest.
     1513 * Receives a host request to open a transfer object on the guest.
    14791514 *
    14801515 * @returns VBox status code.
     
    14821517 * @param   pCreateParms        Where to store the object open/create parameters received from the host.
    14831518 */
    1484 VBGLR3DECL(int) VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms)
     1519VBGLR3DECL(int) VbglR3ClipboardTransferObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms)
    14851520{
    14861521    AssertPtrReturn(pCtx,         VERR_INVALID_POINTER);
     
    15091544
    15101545/**
    1511  * Replies a host request to open an object.
     1546 * Replies a host request to open a transfer object.
    15121547 *
    15131548 * @returns VBox status code.
     
    15161551 * @param   hObj                Object handle of opened object to reply to the host.
    15171552 */
    1518 VBGLR3DECL(int) VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
     1553VBGLR3DECL(int) VbglR3ClipboardTransferObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
    15191554{
    15201555    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    15251560
    15261561    Msg.uContext.SetUInt64(pCtx->idContext);
    1527     Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN);
     1562    Msg.enmType.SetUInt32(VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN);
    15281563    Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
    15291564    Msg.pvPayload.SetPtr(NULL, 0);
     
    15381573
    15391574/**
    1540  * Sends an object open request to the host.
     1575 * Sends a transfer object open request to the host.
    15411576 *
    15421577 * @returns VBox status code.
     
    15451580 * @param   phObj               Where to return the object handle from the host.
    15461581 */
    1547 VBGLR3DECL(int) VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
    1548                                            PSHCLOBJHANDLE phObj)
     1582VBGLR3DECL(int) VbglR3ClipboardTransferObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
     1583                                                   PSHCLOBJHANDLE phObj)
    15491584{
    15501585    AssertPtrReturn(pCtx,         VERR_INVALID_POINTER);
     
    15721607
    15731608/**
    1574  * Receives a host request to close an object on the guest.
     1609 * Receives a host request to close a transfer object on the guest.
    15751610 *
    15761611 * @returns VBox status code.
     
    15781613 * @param   phObj               Where to return the object handle to close from the host.
    15791614 */
    1580 VBGLR3DECL(int) VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj)
     1615VBGLR3DECL(int) VbglR3ClipboardTransferObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj)
    15811616{
    15821617    AssertPtrReturn(pCtx,  VERR_INVALID_POINTER);
     
    16031638
    16041639/**
    1605  * Replies to an object open request from the host.
     1640 * Replies to a transfer object open request from the host.
    16061641 *
    16071642 * @returns VBox status code.
     
    16101645 * @param   hObj                Object handle to reply to the host.
    16111646 */
    1612 VBGLR3DECL(int) VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
     1647VBGLR3DECL(int) VbglR3ClipboardTransferObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj)
    16131648{
    16141649    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    16191654
    16201655    Msg.uContext.SetUInt64(pCtx->idContext);
    1621     Msg.enmType.SetUInt32(VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE);
     1656    Msg.enmType.SetUInt32(VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE);
    16221657    Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
    16231658    Msg.pvPayload.SetPtr(NULL, 0);
     
    16321667
    16331668/**
    1634  * Sends a request to close an object to the host.
     1669 * Sends a request to close a transfer object to the host.
    16351670 *
    16361671 * @returns VBox status code.
     
    16381673 * @param   hObj                Object handle to close on the host.
    16391674 */
    1640 VBGLR3DECL(int) VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj)
     1675VBGLR3DECL(int) VbglR3ClipboardTransferObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj)
    16411676{
    16421677    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    16561691
    16571692/**
    1658  * Receives a host request to read from an object on the guest.
     1693 * Receives a host request to read from a transfer object on the guest.
    16591694 *
    16601695 * @returns VBox status code.
     
    16641699 * @param   pfFlags             Where to return the read flags.
    16651700 */
    1666 VBGLR3DECL(int) VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t *pcbToRead,
    1667                                            uint32_t *pfFlags)
     1701VBGLR3DECL(int) VbglR3ClipboardTransferObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t *pcbToRead,
     1702                                                   uint32_t *pfFlags)
    16681703{
    16691704    AssertPtrReturn(pCtx,      VERR_INVALID_POINTER);
     
    16981733
    16991734/**
    1700  * Sends a request to read from an object to the host.
     1735 * Sends a request to read from a transfer object to the host.
    17011736 *
    17021737 * @returns VBox status code.
     
    17071742 * @param   pcbRead             Where to store the amount (in bytes) read from the object.
    17081743 */
    1709 VBGLR3DECL(int) VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
    1710                                            void *pvData, uint32_t cbData, uint32_t *pcbRead)
     1744VBGLR3DECL(int) VbglR3ClipboardTransferObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
     1745                                                   void *pvData, uint32_t cbData, uint32_t *pcbRead)
    17111746{
    17121747    AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
     
    17431778
    17441779/**
    1745  * Sends a request to write to an object to the host.
     1780 * Sends a request to write to a transfer object to the host.
    17461781 *
    17471782 * @returns VBox status code.
     
    17521787 * @param   pcbWritten          Where to store the amount (in bytes) written to the object.
    17531788 */
    1754 VBGLR3DECL(int) VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
    1755                                             void *pvData, uint32_t cbData, uint32_t *pcbWritten)
     1789VBGLR3DECL(int) VbglR3ClipboardTransferObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj,
     1790                                                    void *pvData, uint32_t cbData, uint32_t *pcbWritten)
    17561791{
    17571792    AssertPtrReturn(pCtx,   VERR_INVALID_POINTER);
     
    17971832    AssertPtr(pCmdCtx);
    17981833
    1799     int rc = VbglR3ClipboardRootListRead(pCmdCtx, pCtx->pTransfer);
     1834    int rc = VbglR3ClipboardTransferRootListRead(pCmdCtx, pCtx->pTransfer);
    18001835
    18011836    LogFlowFuncLeaveRC(rc);
     
    18121847    AssertPtr(pCmdCtx);
    18131848
    1814     int rc = VbglR3ClipboardListOpenSend(pCmdCtx, pOpenParms, phList);
     1849    int rc = VbglR3ClipboardTransferListOpenSend(pCmdCtx, pOpenParms, phList);
    18151850
    18161851    LogFlowFuncLeaveRC(rc);
     
    18261861    AssertPtr(pCmdCtx);
    18271862
    1828     int rc = VbglR3ClipboardListCloseSend(pCmdCtx, hList);
     1863    int rc = VbglR3ClipboardTransferListCloseSend(pCmdCtx, hList);
    18291864
    18301865    LogFlowFuncLeaveRC(rc);
     
    18461881        if (RT_SUCCESS(rc))
    18471882        {
    1848             rc = VbglR3ClipboardListHdrRead(pCmdCtx, hList, 0 /* fFlags */, pListHdr);
     1883            rc = VbglR3ClipboardTransferListHdrRead(pCmdCtx, hList, 0 /* fFlags */, pListHdr);
    18491884        }
    18501885        else
     
    18651900    AssertPtr(pCmdCtx);
    18661901
    1867     int rc = VbglR3ClipboardListEntryRead(pCmdCtx, hList, pListEntry);
     1902    int rc = VbglR3ClipboardTransferListEntryRead(pCmdCtx, hList, pListEntry);
    18681903
    18691904    LogFlowFuncLeaveRC(rc);
     
    18801915    AssertPtr(pCmdCtx);
    18811916
    1882     int rc = VbglR3ClipboardObjOpenSend(pCmdCtx, pCreateParms, phObj);
     1917    int rc = VbglR3ClipboardTransferObjOpenSend(pCmdCtx, pCreateParms, phObj);
    18831918
    18841919    LogFlowFuncLeaveRC(rc);
     
    18941929    AssertPtr(pCmdCtx);
    18951930
    1896     int rc = VbglR3ClipboardObjCloseSend(pCmdCtx, hObj);
     1931    int rc = VbglR3ClipboardTransferObjCloseSend(pCmdCtx, hObj);
    18971932
    18981933    LogFlowFuncLeaveRC(rc);
     
    19121947    RT_NOREF(fFlags); /* Not used yet. */
    19131948
    1914     int rc = VbglR3ClipboardObjReadSend(pCmdCtx, hObj, pvData, cbData, pcbRead);
    1915 
    1916     LogFlowFuncLeaveRC(rc);
    1917     return rc;
    1918 }
    1919 
    1920 /**
    1921  * Initializes a transfer on the guest side.
     1949    int rc = VbglR3ClipboardTransferObjReadSend(pCmdCtx, hObj, pvData, cbData, pcbRead);
     1950
     1951    LogFlowFuncLeaveRC(rc);
     1952    return rc;
     1953}
     1954
     1955/**
     1956 * Creates (and registers) a transfer on the guest side.
    19221957 *
    19231958 * @returns VBox status code.
    19241959 * @param   pCmdCtx             Command context to use.
    19251960 * @param   pTransferCtx        Transfer context to init transfer for.
    1926  * @param   uTransferID         ID to use for transfer to init.
    1927  * @param   enmDir              Direction of transfer to init.
    1928  * @param   enmSource           Source of transfer to init.
     1961 * @param   enmDir              Specifies the transfer direction of this transfer.
     1962 * @param   enmSource           Specifies the data source of the transfer.
     1963 * @param   idTransfer          ID of transfer to create.
    19291964 * @param   ppTransfer          Where to return the transfer object on success. Optional.
    19301965 */
    1931 static int vbglR3ClipboardTransferInit(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
    1932                                        SHCLTRANSFERID uTransferID, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
    1933                                        PSHCLTRANSFER *ppTransfer)
    1934 {
    1935     LogFlowFuncEnter();
     1966static int vbglR3ClipboardTransferCreate(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx,
     1967                                         SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, SHCLTRANSFERID idTransfer,
     1968                                         PSHCLTRANSFER *ppTransfer)
     1969{
     1970    AssertReturn(idTransfer != NIL_SHCLTRANSFERID, VERR_WRONG_ORDER);
     1971
     1972    RT_NOREF(pCmdCtx);
    19361973
    19371974    PSHCLTRANSFER pTransfer;
    1938     int rc = ShClTransferCreate(&pTransfer);
     1975    int rc = ShClTransferCreate(enmDir, enmSource, &pTransfer);
    19391976    if (RT_SUCCESS(rc))
    19401977    {
     
    19421979        ShClTransferSetCallbacks(pTransfer, &pCmdCtx->Transfers.Callbacks);
    19431980
    1944         rc = ShClTransferInit(pTransfer, enmDir, enmSource);
    1945         if (RT_SUCCESS(rc))
    1946         {
    1947             SHCLTXPROVIDER Provider;
    1948             RT_ZERO(Provider);
    1949 
    1950             /* Assign local provider first and overwrite interface methods below if needed. */
    1951             VBClTransferProviderLocalQueryInterface(&Provider);
    1952 
    1953             /* If this is a read transfer (reading data from host), set the interface to use
    1954              * our VbglR3 routines here. */
    1955             if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Host -> Guest */
    1956             {
    1957                 Provider.Interface.pfnRootListRead  = vbglR3ClipboardTransferIfaceRootListRead;
    1958 
    1959                 Provider.Interface.pfnListOpen      = vbglR3ClipboardTransferIfaceListOpen;
    1960                 Provider.Interface.pfnListClose     = vbglR3ClipboardTransferIfaceListClose;
    1961                 Provider.Interface.pfnListHdrRead   = vbglR3ClipboardTransferIfaceListHdrRead;
    1962                 Provider.Interface.pfnListEntryRead = vbglR3ClipboardTransferIfaceListEntryRead;
    1963 
    1964                 Provider.Interface.pfnObjOpen       = vbglR3ClipboardTransferIfaceObjOpen;
    1965                 Provider.Interface.pfnObjClose      = vbglR3ClipboardTransferIfaceObjClose;
    1966                 Provider.Interface.pfnObjRead       = vbglR3ClipboardTransferIfaceObjRead;
    1967             }
    1968 
    1969             Provider.pvUser = pCmdCtx;
    1970 
    1971             rc = ShClTransferSetProvider(pTransfer, &Provider);
    1972 
    1973             /* As a last step, register the transfer with our transfer context. */
    1974             if (RT_SUCCESS(rc))
    1975                 rc = ShClTransferCtxTransferRegisterById(pTransferCtx, pTransfer, uTransferID);
    1976 
    1977             if (RT_FAILURE(rc))
    1978                 ShClTransferCtxTransferUnregisterById(pTransferCtx, uTransferID);
    1979         }
    1980     }
    1981 
    1982     if (RT_SUCCESS(rc))
    1983     {
    1984         if (ppTransfer)
     1981        rc = ShClTransferCtxRegisterById(pTransferCtx, pTransfer, idTransfer);
     1982        if (   RT_SUCCESS(rc)
     1983            && ppTransfer)
    19851984            *ppTransfer = pTransfer;
    1986 
     1985    }
     1986
     1987    if (RT_SUCCESS(rc))
     1988        LogRel(("Shared Clipboard: Transfer %RU32 successfully created\n", idTransfer));
     1989    else
     1990        LogRel(("Shared Clipboard: Error creating transfer %RU32, rc=%Rrc\n", idTransfer, rc));
     1991
     1992    LogFlowFuncLeaveRC(rc);
     1993    return rc;
     1994}
     1995
     1996/**
     1997 * Initializes a transfer on the guest side.
     1998 *
     1999 * @returns VBox status code.
     2000 * @param   pCmdCtx             Command context to use.
     2001 * @param   pTransfer           Transfer to init.
     2002 */
     2003static int vbglR3ClipboardTransferInit(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFER pTransfer)
     2004{
     2005    LogFlowFuncEnter();
     2006
     2007    SHCLTRANSFERDIR const enmDir = ShClTransferGetDir(pTransfer);
     2008
     2009    SHCLTXPROVIDER Provider;
     2010    RT_ZERO(Provider);
     2011
     2012    /* Assign local provider first and overwrite interface methods below if needed. */
     2013    ShClTransferProviderLocalQueryInterface(&Provider);
     2014
     2015    /* If this is a read transfer (reading data from host), set the interface to use
     2016     * our VbglR3 routines here. */
     2017    if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Host -> Guest */
     2018    {
     2019        Provider.Interface.pfnRootListRead  = vbglR3ClipboardTransferIfaceRootListRead;
     2020
     2021        Provider.Interface.pfnListOpen      = vbglR3ClipboardTransferIfaceListOpen;
     2022        Provider.Interface.pfnListClose     = vbglR3ClipboardTransferIfaceListClose;
     2023        Provider.Interface.pfnListHdrRead   = vbglR3ClipboardTransferIfaceListHdrRead;
     2024        Provider.Interface.pfnListEntryRead = vbglR3ClipboardTransferIfaceListEntryRead;
     2025
     2026        Provider.Interface.pfnObjOpen       = vbglR3ClipboardTransferIfaceObjOpen;
     2027        Provider.Interface.pfnObjClose      = vbglR3ClipboardTransferIfaceObjClose;
     2028        Provider.Interface.pfnObjRead       = vbglR3ClipboardTransferIfaceObjRead;
     2029    }
     2030    else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Guest -> Host */
     2031    {
     2032        /* Uses the local provider assigned above. */
     2033    }
     2034    else
     2035        AssertFailed();
     2036
     2037    Provider.pvUser = pCmdCtx;
     2038
     2039    /* Set the provider first before calling ShClTransferInit(), as the init callback might utilize some of the
     2040     * provider functions. */
     2041    int rc = ShClTransferSetProvider(pTransfer, &Provider);
     2042    if (RT_SUCCESS(rc))
     2043    {
     2044        rc = ShClTransferInit(pTransfer);
     2045        if (RT_SUCCESS(rc))
     2046        {
     2047            /* As soon as we report the INITIALIZED state to the host, the host can start reading stuff from the transfer.
     2048             * So make sure that we really are ready here. */
     2049            if (enmDir == SHCLTRANSFERDIR_TO_REMOTE)
     2050                AssertMsgStmt(ShClTransferRootsCount(pTransfer), ("No root entries set yet!\n"
     2051                                                                  "Those have to be present as soon we report the transfer as being INITIALIZED to the host\n"),
     2052                              rc = VERR_WRONG_ORDER);
     2053        }
     2054    }
     2055
     2056    SHCLTRANSFERID const idTransfer = ShClTransferGetID(pTransfer);
     2057
     2058    if (RT_SUCCESS(rc))
     2059    {
    19872060        LogRel(("Shared Clipboard: Transfer %RU32 (%s) successfully initialized\n",
    1988                 uTransferID,
    1989                 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "host -> guest" : "guest -> host"));
     2061                idTransfer, enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "host -> guest" : "guest -> host"));
    19902062    }
    19912063    else
    1992         LogRel(("Shared Clipboard: Unable to initialize transfer %RU32, rc=%Rrc\n", uTransferID, rc));
    1993 
    1994     /* Send a reply in any case. */
    1995     int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
    1996                                                    RT_SUCCESS(rc)
    1997                                                  ? SHCLTRANSFERSTATUS_INITIALIZED : SHCLTRANSFERSTATUS_ERROR, rc);
    1998     if (RT_SUCCESS(rc))
    1999         rc = rc2;
    2000 
    2001     if (RT_FAILURE(rc))
    2002     {
    2003         ShClTransferDestroy(pTransfer);
    2004         pTransfer = NULL;
    2005     }
    2006 
    2007     LogFlowFuncLeaveRC(rc);
    2008     return rc;
    2009 }
    2010 
    2011 /**
    2012  * Uninitializes a transfer on the guest side.
     2064        LogRel(("Shared Clipboard: Unable to initialize transfer %RU32, rc=%Rrc\n", idTransfer, rc));
     2065
     2066    LogFlowFuncLeaveRC(rc);
     2067    return rc;
     2068}
     2069
     2070/**
     2071 * Destroys a transfer on the guest side.
    20132072 *
    20142073 * @returns VBox status code.
    20152074 * @param   pCmdCtx             Command context to use.
    20162075 * @param   pTransferCtx        Transfer context to uninit transfer for.
    2017  * @param   uTransferID         ID to use for transfer to uninit.
    2018  */
    2019 static int vbglR3ClipboardTransferUninit(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID uTransferID)
     2076 * @param   idTransfer          ID of transfer to initialize.
     2077 */
     2078static int vbglR3ClipboardTransferDestroy(PVBGLR3SHCLCMDCTX pCmdCtx, PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer)
    20202079{
    20212080    RT_NOREF(pCmdCtx);
     
    20252084    int rc;
    20262085
    2027     PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransferById(pTransferCtx, uTransferID);
     2086    PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransferById(pTransferCtx, idTransfer);
    20282087    if (pTransfer)
    20292088    {
    2030         rc = ShClTransferCtxTransferUnregisterById(pTransferCtx, uTransferID);
     2089        rc = ShClTransferCtxUnregisterById(pTransferCtx, idTransfer);
    20312090        if (RT_SUCCESS(rc))
    20322091            rc = ShClTransferDestroy(pTransfer);
     
    20342093        if (RT_SUCCESS(rc))
    20352094        {
    2036             LogRel(("Shared Clipboard: Transfer %RU32 successfully uninitialized\n", uTransferID));
     2095            LogRel(("Shared Clipboard: Transfer %RU32 successfully uninitialized\n", idTransfer));
    20372096        }
    20382097        else
    2039             LogRel(("Shared Clipboard: Unable to uninitialized transfer %RU32, rc=%Rrc\n", uTransferID, rc));
     2098            LogRel(("Shared Clipboard: Unable to uninitialized transfer %RU32, rc=%Rrc\n", idTransfer, rc));
    20402099    }
    20412100    else
     
    20592118
    20602119/**
     2120 * Requests a new transfer from the host.
     2121 *
     2122 * On success this will issue an INITIALIZED status reply from the host with a transfer ID set.
     2123 * This ID will be used to initialize the transfer on the guest side then.
     2124 *
     2125 * @returns VBox status code.
     2126 * @param   pCmdCtx             Command context to use.
     2127 */
     2128VBGLR3DECL(int) VbglR3ClipboardTransferRequest(PVBGLR3SHCLCMDCTX pCmdCtx)
     2129{
     2130    LogFlowFuncEnter();
     2131
     2132    LogRel2(("Shared Clipboard: Requesting new host -> guest transfer from host\n"));
     2133
     2134    int rc = vbglR3ClipboardTransferStatusReplyEx(pCmdCtx, 0 /* Context ID not needed */,
     2135                                                  SHCLTRANSFERSTATUS_REQUESTED, VINF_SUCCESS);
     2136    LogFlowFuncLeaveRC(rc);
     2137    return rc;
     2138}
     2139
     2140/**
    20612141 * Starts a transfer on the guest side.
    20622142 *
     
    21182198    if (pTransfer)
    21192199    {
    2120         rc = ShClTransferCtxTransferUnregisterById(pTransferCtx, uTransferID);
     2200        rc = ShClTransferCtxUnregisterById(pTransferCtx, uTransferID);
    21212201        if (RT_SUCCESS(rc))
    21222202        {
     
    21782258                if (RT_SUCCESS(rc))
    21792259                {
    2180                     const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
     2260                    const SHCLTRANSFERID idTransfer = VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext);
    21812261
    21822262                    LogRel(("Shared Clipboard: Received status %s (%Rrc) for transfer %RU32\n",
    2183                             ShClTransferStatusToStr(transferReport.uStatus), transferReport.rc, uTransferID));
     2263                            ShClTransferStatusToStr(transferReport.uStatus), transferReport.rc, idTransfer));
     2264
     2265                    SHCLSOURCE enmSource = SHCLSOURCE_INVALID;
    21842266
    21852267                    switch (transferReport.uStatus)
    21862268                    {
    2187                         case SHCLTRANSFERSTATUS_NONE:
    2188                             AssertFailed(); /* Should never happen. */
     2269                        case SHCLTRANSFERSTATUS_REQUESTED: /* Only used for H->G transfers. */
     2270                        {
     2271                            enmDir    = SHCLTRANSFERDIR_FROM_REMOTE;
     2272                            enmSource = SHCLSOURCE_REMOTE;
     2273
     2274                            /* The host acknowledged our request to create a new transfer.
     2275                             * So create a new transfer here with the transfer ID we just got from the host.
     2276                             *
     2277                             * Actual initialization will be done as soon as the host sends use the INITIALIZED status for it.
     2278                             */
     2279                            PSHCLTRANSFER pTransfer;
     2280                            rc = vbglR3ClipboardTransferCreate(pCmdCtx, pTransferCtx, enmDir, enmSource, idTransfer, &pTransfer);
     2281
     2282                            /* As soon as we've created our transfer locally, report back INITIALIZED to the host.
     2283                             * This will initialize the transfer on the host, so that in turn reports INITIALIZED
     2284                             * back to us (see case down below).*/
     2285                            int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
     2286                                                                           RT_SUCCESS(rc)
     2287                                                                         ? SHCLTRANSFERSTATUS_INITIALIZED : SHCLTRANSFERSTATUS_ERROR, rc);
     2288                            if (RT_SUCCESS(rc))
     2289                                rc = rc2;
    21892290                            break;
     2291                        }
    21902292
    21912293                        case SHCLTRANSFERSTATUS_INITIALIZED:
    21922294                        {
    2193                             SHCLSOURCE enmSource = SHCLSOURCE_INVALID;
    2194 
    21952295                            /* The host announces the transfer direction from its point of view, so inverse the direction here. */
    2196                             if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest */
     2296                            if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* H -> G */
    21972297                            {
    2198                                 enmDir = SHCLTRANSFERDIR_FROM_REMOTE;
     2298                                enmDir    = SHCLTRANSFERDIR_FROM_REMOTE;
    21992299                                enmSource = SHCLSOURCE_REMOTE;
    2200 
    2201                                 rc = vbglR3ClipboardTransferInit(pCmdCtx, pTransferCtx, uTransferID,
    2202                                                                  enmDir, enmSource, NULL /* ppTransfer */);
    22032300                            }
    2204                             else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host */
     2301                            else if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* G -> H */
    22052302                            {
    2206                                 /* Already initialized when remote (host) was reading the URI data. */
    2207                                 enmDir = SHCLTRANSFERDIR_TO_REMOTE;
     2303                                enmDir    = SHCLTRANSFERDIR_TO_REMOTE;
    22082304                                enmSource = SHCLSOURCE_LOCAL;
    2209 
    2210                                 rc = vbglR3ClipboardTransferInit(pCmdCtx, pTransferCtx, uTransferID,
    2211                                                                  enmDir, enmSource, NULL /* ppTransfer */);
    22122305                            }
    22132306                            else
    22142307                                AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER);
    22152308
     2309                            if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* H->G */
     2310                            {
     2311                                /* The host reported INITIALIZED for the transfer.
     2312                                 * So init our local transfer as well now. */
     2313                                PSHCLTRANSFER pTransfer = ShClTransferCtxGetTransferById(pTransferCtx, idTransfer);
     2314                                if (pTransfer)
     2315                                {
     2316                                    rc = vbglR3ClipboardTransferInit(pCmdCtx, pTransfer);
     2317
     2318                                    /* Only send back a reply on error -- we already reported INITIALIZED
     2319                                     * in the case SHCLTRANSFERSTATUS_REQUESTED above. */
     2320                                    if (RT_FAILURE(rc))
     2321                                    {
     2322                                        int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
     2323                                                                                     SHCLTRANSFERSTATUS_ERROR, rc);
     2324                                        AssertRC(rc2);
     2325                                    }
     2326                                }
     2327                                else
     2328                                    rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND;
     2329                            }
     2330                            else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* G->H */
     2331                            {
     2332                                /* The host reported the INITIALIZED status together with the transfer ID.
     2333                                 * So create a local transfer here with that ID. */
     2334                                PSHCLTRANSFER pTransfer;
     2335                                rc = vbglR3ClipboardTransferCreate(pCmdCtx, pTransferCtx, enmDir, enmSource, idTransfer, &pTransfer);
     2336                                if (RT_SUCCESS(rc))
     2337                                    rc = vbglR3ClipboardTransferInit(pCmdCtx, pTransfer);
     2338
     2339                                /* Send a reply in any case. */
     2340                                int rc2 = VbglR3ClipboardTransferStatusReply(pCmdCtx, pTransfer,
     2341                                                                               RT_SUCCESS(rc)
     2342                                                                             ? SHCLTRANSFERSTATUS_INITIALIZED : SHCLTRANSFERSTATUS_ERROR, rc);
     2343                                if (RT_SUCCESS(rc))
     2344                                    rc = rc2;
     2345                            }
     2346                            else
     2347                                AssertFailedBreakStmt(rc = VERR_INVALID_PARAMETER);
     2348
    22162349                            break;
    22172350                        }
     
    22192352                        case SHCLTRANSFERSTATUS_UNINITIALIZED:
    22202353                        {
    2221                             rc = vbglR3ClipboardTransferUninit(pCmdCtx, pTransferCtx, uTransferID);
     2354                            rc = vbglR3ClipboardTransferDestroy(pCmdCtx, pTransferCtx, idTransfer);
    22222355                            break;
    22232356                        }
     
    22252358                        case SHCLTRANSFERSTATUS_STARTED:
    22262359                        {
    2227                             rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, uTransferID);
     2360                            rc = vbglR3ClipboardTransferStart(pCmdCtx, pTransferCtx, idTransfer);
    22282361                            break;
    22292362                        }
     
    22372370                        case SHCLTRANSFERSTATUS_ERROR:
    22382371                        {
    2239                             rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx,
    2240                                                              VBOX_SHCL_CONTEXTID_GET_TRANSFER(pCmdCtx->idContext));
     2372                            rc = vbglR3ClipboardTransferStop(pCmdCtx, pTransferCtx, idTransfer);
    22412373                            break;
    22422374                        }
     
    22442376                        default:
    22452377                            LogRel(("Shared Clipboard: Received unknown status %#x (%Rrc) for transfer %RU32\n",
    2246                                     pEvent->u.TransferStatus.Report.uStatus, pEvent->u.TransferStatus.Report.rc,
     2378                                    pEvent->u.TransferStatus.Report.rc,
    22472379                                    pEvent->u.TransferStatus.uID));
    22482380                            rc = VERR_NOT_SUPPORTED;
     
    22652397            {
    22662398                uint32_t fRoots;
    2267                 rc = VbglR3ClipboardRootListHdrReadReq(pCmdCtx, &fRoots);
     2399                rc = VbglR3ClipboardTransferRootListHdrReadReq(pCmdCtx, &fRoots);
    22682400
    22692401                /** @todo Validate / handle fRoots. */
     
    22822414                    LogFlowFunc(("cRoots=%RU32\n", rootListHdr.cEntries));
    22832415
    2284                     rc = VbglR3ClipboardRootListHdrReadReply(pCmdCtx, &rootListHdr);
     2416                    rc = VbglR3ClipboardTransferRootListHdrReadReply(pCmdCtx, &rootListHdr);
    22852417                }
    22862418                break;
     
    22892421            case VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ:
    22902422            {
    2291                 uint32_t uIndex;
     2423                uint64_t uIndex;
    22922424                uint32_t fInfo;
    2293                 rc = VbglR3ClipboardRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo);
     2425                rc = VbglR3ClipboardTransferRootListEntryReadReq(pCmdCtx, &uIndex, &fInfo);
    22942426                if (RT_SUCCESS(rc))
    22952427                {
     
    23012433                    if (pEntry)
    23022434                    {
    2303                         rc = VbglR3ClipboardRootListEntryReadReply(pCmdCtx, uIndex, pEntry);
     2435                        rc = VbglR3ClipboardTransferRootListEntryReadReply(pCmdCtx, uIndex, pEntry);
    23042436                    }
    23052437                    else
     
    23152447                if (RT_SUCCESS(rc))
    23162448                {
    2317                     rc = VbglR3ClipboardListOpenRecv(pCmdCtx, &openParmsList);
     2449                    rc = VbglR3ClipboardTransferListOpenRecv(pCmdCtx, &openParmsList);
    23182450                    if (RT_SUCCESS(rc))
    23192451                    {
     
    23282460
    23292461                        /* Reply in any case. */
    2330                         int rc2 = VbglR3ClipboardListOpenReply(pCmdCtx, rc, hList);
     2462                        int rc2 = VbglR3ClipboardTransferListOpenReply(pCmdCtx, rc, hList);
    23312463                        AssertRC(rc2);
    23322464                    }
     
    23412473            {
    23422474                SHCLLISTHANDLE hList;
    2343                 rc = VbglR3ClipboardListCloseRecv(pCmdCtx, &hList);
     2475                rc = VbglR3ClipboardTransferListCloseRecv(pCmdCtx, &hList);
    23442476                if (RT_SUCCESS(rc))
    23452477                {
     
    23512483
    23522484                    /* Reply in any case. */
    2353                     int rc2 = VbglR3ClipboardListCloseReply(pCmdCtx, rc, hList);
     2485                    int rc2 = VbglR3ClipboardTransferListCloseReply(pCmdCtx, rc, hList);
    23542486                    AssertRC(rc2);
    23552487                }
     
    23642496                SHCLLISTHANDLE hList  = NIL_SHCLLISTHANDLE;
    23652497                uint32_t       fFlags = 0;
    2366                 rc = VbglR3ClipboardListHdrReadRecvReq(pCmdCtx, &hList, &fFlags);
     2498                rc = VbglR3ClipboardTransferListHdrReadRecvReq(pCmdCtx, &hList, &fFlags);
    23672499                if (RT_SUCCESS(rc))
    23682500                {
     
    23752507                    if (RT_SUCCESS(rc))
    23762508                    {
    2377                         rc = VbglR3ClipboardListHdrWrite(pCmdCtx, hList, &hdrList);
     2509                        rc = VbglR3ClipboardTransferListHdrWrite(pCmdCtx, hList, &hdrList);
    23782510
    23792511                        ShClTransferListHdrDestroy(&hdrList);
     
    23942526                    SHCLLISTHANDLE hList;
    23952527                    uint32_t       fInfo;
    2396                     rc = VbglR3ClipboardListEntryReadRecvReq(pCmdCtx, &hList, &fInfo);
     2528                    rc = VbglR3ClipboardTransferListEntryReadRecvReq(pCmdCtx, &hList, &fInfo);
    23972529                    if (RT_SUCCESS(rc))
    23982530                    {
     
    24112543                            LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
    24122544
    2413                             rc = VbglR3ClipboardListEntryWrite(pCmdCtx, hList, &entryList);
     2545                            rc = VbglR3ClipboardTransferListEntryWrite(pCmdCtx, hList, &entryList);
    24142546                        }
    24152547                    }
     
    24272559                if (RT_SUCCESS(rc))
    24282560                {
    2429                     rc = VbglR3ClipboardObjOpenRecv(pCmdCtx, &openParms);
     2561                    rc = VbglR3ClipboardTransferObjOpenRecv(pCmdCtx, &openParms);
    24302562                    if (RT_SUCCESS(rc))
    24312563                    {
     
    24382570
    24392571                        /* Reply in any case. */
    2440                         int rc2 = VbglR3ClipboardObjOpenReply(pCmdCtx, rc, hObj);
     2572                        int rc2 = VbglR3ClipboardTransferObjOpenReply(pCmdCtx, rc, hObj);
    24412573                        AssertRC(rc2);
    24422574                    }
     
    24512583            {
    24522584                SHCLOBJHANDLE hObj;
    2453                 rc = VbglR3ClipboardObjCloseRecv(pCmdCtx, &hObj);
     2585                rc = VbglR3ClipboardTransferObjCloseRecv(pCmdCtx, &hObj);
    24542586                if (RT_SUCCESS(rc))
    24552587                {
     
    24612593
    24622594                    /* Reply in any case. */
    2463                     int rc2 = VbglR3ClipboardObjCloseReply(pCmdCtx, rc, hObj);
     2595                    int rc2 = VbglR3ClipboardTransferObjCloseReply(pCmdCtx, rc, hObj);
    24642596                    AssertRC(rc2);
    24652597                }
     
    24732605                uint32_t      cbBuf;
    24742606                uint32_t      fFlags;
    2475                 rc = VbglR3ClipboardObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags);
     2607                rc = VbglR3ClipboardTransferObjReadRecv(pCmdCtx, &hObj, &cbBuf, &fFlags);
    24762608                if (RT_SUCCESS(rc))
    24772609                {
     
    24932625                        rc = ShClTransferObjRead(pTransfer, hObj, pvBuf, cbToRead, fFlags, &cbRead);
    24942626                        if (RT_SUCCESS(rc))
    2495                             rc = VbglR3ClipboardObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */);
     2627                            rc = VbglR3ClipboardTransferObjWriteSend(pCmdCtx, hObj, pvBuf, cbRead, NULL /* pcbWritten */);
    24962628
    24972629                        RTMemFree(pvBuf);
  • trunk/src/VBox/Additions/x11/VBoxClient/clipboard-x11.cpp

    r100286 r100367  
    5757#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    5858/**
    59  * Worker for waiting for a transfer status change.
    60  */
    61 static DECLCALLBACK(int) vbclX11TransferWaitForStatusWorker(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS enmSts,
    62                                                             RTMSINTERVAL msTimeout)
    63 {
    64     RT_NOREF(pCtx);
    65 
    66     LogFlowFuncEnter();
    67 
    68     int rc = VERR_TIMEOUT;
    69 
    70     ShClTransferAcquire(pTransfer);
    71 
    72     uint64_t const tsStartMs = RTTimeMilliTS();
    73 
    74     while (RTTimeMilliTS() - tsStartMs <= msTimeout)
    75     {
    76         if (ShClTransferGetStatus(pTransfer) == enmSts) /* Currently we only have busy waiting here. */
    77         {
    78             rc = VINF_SUCCESS;
    79             break;
    80         }
    81         RTThreadSleep(100);
    82     }
    83 
    84     ShClTransferRelease(pTransfer);
    85 
    86     return rc;
    87 }
    88 
    89 /**
    90  * @copydoc SHCLTRANSFERCALLBACKS::pfnOnRegistered
    91  *
    92  * This starts the HTTP server if not done yet and registers the transfer with it.
     59 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized
    9360 *
    9461 * @thread Clipboard main thread.
    9562 */
    96 static DECLCALLBACK(void) vbclX11OnHttpTransferRegisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
    97 {
    98     RT_NOREF(pTransferCtx);
    99 
     63static DECLCALLBACK(void) vbclX11OnTransferInitializedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     64{
    10065    LogFlowFuncEnter();
    10166
     
    10671    AssertPtr(pTransfer);
    10772
    108     ShClTransferAcquire(pTransfer);
     73    int rc = VINF_SUCCESS;
     74
     75    /* If this is a G->H transfer, we need to set the root list entries here, as the host
     76     * will start reading those as soon as we report the INITIALIZED status. */
     77    switch (ShClTransferGetDir(pTransfer))
     78    {
     79        case SHCLTRANSFERDIR_TO_REMOTE: /* G->H */
     80        {
     81            PSHCLEVENT pEvent;
     82            rc = ShClEventSourceGenerateAndRegisterEvent(&pCtx->EventSrc, &pEvent);
     83            if (RT_SUCCESS(rc))
     84            {
     85                rc = ShClX11ReadDataFromX11Async(&g_Ctx.X11, VBOX_SHCL_FMT_URI_LIST, UINT32_MAX, pEvent);
     86                if (RT_SUCCESS(rc))
     87                {
     88                    PSHCLEVENTPAYLOAD pPayload;
     89                    rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     90                    if (RT_SUCCESS(rc))
     91                    {
     92                        if (pPayload)
     93                        {
     94                            Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE));
     95                            PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData;
     96
     97                            rc = ShClTransferRootsInitFromStringList(pTransfer, (const char *)pResp->Read.pvData, pResp->Read.cbData);
     98
     99                            RTMemFree(pResp->Read.pvData);
     100                            pResp->Read.cbData = 0;
     101
     102                            ShClPayloadFree(pPayload);
     103                        }
     104                    }
     105                }
     106            }
     107            break;
     108        }
     109
     110        case SHCLTRANSFERDIR_FROM_REMOTE: /* H->G */
     111        {
     112            /* Retrieve the root entries as a first action, so that the transfer is ready to go
     113             * once it gets registered to HTTP server. */
     114            int rc2 = ShClTransferRootListRead(pTransfer);
     115            if (   RT_SUCCESS(rc2)
     116                /* As soon as we register the transfer with the HTTP server, the transfer needs to have its roots set. */
     117                && ShClTransferRootsCount(pTransfer))
     118            {
     119                rc2 = ShClTransferHttpServerRegisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
     120            }
     121            break;
     122        }
     123
     124        default:
     125            break;
     126    }
     127
     128    LogFlowFuncLeaveRC(rc);
     129}
     130
     131/**
     132 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnRegistered
     133 *
     134 * This starts the HTTP server if not done yet and registers the transfer with it.
     135 *
     136 * @thread Clipboard main thread.
     137 */
     138static DECLCALLBACK(void) vbclX11OnTransferRegisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
     139{
     140    RT_NOREF(pTransferCtx);
     141
     142    LogFlowFuncEnter();
     143
     144    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     145    AssertPtr(pCtx);
     146
     147    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     148    AssertPtr(pTransfer);
    109149
    110150    /* We only need to start the HTTP server when we actually receive data from the remote (host). */
    111     if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    112     {
    113         /* Retrieve the root entries as a first action, so that the transfer is ready to go
    114          * once it gets registered to HTTP server below. */
    115         int rc2 = ShClTransferRootListRead(pTransfer);
    116         if (RT_SUCCESS(rc2))
    117         {
    118             ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx);
    119             rc2 = ShClTransferHttpServerRegisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
    120         }
    121 
     151    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) /* H->G */
     152    {
     153        int rc2 = ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx);
    122154        if (RT_FAILURE(rc2))
    123155            LogRel(("Shared Clipboard: Registering HTTP transfer failed: %Rrc\n", rc2));
     
    137169 * @thread Clipboard main thread.
    138170 */
    139 static void vbclX11HttpTransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     171static void vbclX11TransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)
    140172{
    141173    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    142174    {
    143         ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
    144         ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx);
    145     }
    146 
    147     ShClTransferRelease(pTransfer);
     175        if (ShClTransferHttpServerIsInitialized(&pCtx->X11.HttpCtx.HttpServer))
     176        {
     177            ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
     178            ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx);
     179        }
     180    }
    148181}
    149182
     
    155188 * @thread Clipboard main thread.
    156189 */
    157 static DECLCALLBACK(void) vbclX11OnHttpTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
     190static DECLCALLBACK(void) vbclX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
    158191{
    159192    RT_NOREF(pTransferCtx);
    160     vbclX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
     193    vbclX11TransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
    161194}
    162195
     
    168201 * @thread Clipboard main thread.
    169202 */
    170 static DECLCALLBACK(void) vbclX11OnHttpTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc)
     203static DECLCALLBACK(void) vbclX11OnTransferCompletedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rc)
    171204{
    172205    RT_NOREF(rc);
    173     vbclX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
     206    vbclX11TransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
    174207}
    175208
     
    180213 * @thread Clipboard main thread.
    181214 */
    182 static DECLCALLBACK(void) vbclX11OnHttpTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc)
    183 {
    184     return vbclX11OnHttpTransferCompletedCallback(pCtx, rc);
     215static DECLCALLBACK(void) vbclX11OnTransferErrorCallback(PSHCLTRANSFERCALLBACKCTX pCtx, int rc)
     216{
     217    return vbclX11OnTransferCompletedCallback(pCtx, rc);
    185218}
    186219#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
     
    257290 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource
    258291 *
    259  * Requests URI data from the host.
    260  * This initiates a transfer on the host. Most of the handling will be done VbglR3 then.
     292 * Requests data from the host.
     293 *
     294 * For transfers: This requests a transfer from the host. Most of the handling will be done VbglR3 then.
    261295 *
    262296 * @thread  X11 event thread.
     
    274308    if (uFmt == VBOX_SHCL_FMT_URI_LIST)
    275309    {
    276         PSHCLHTTPSERVER pSrv = &pCtx->X11.HttpCtx.HttpServer;
    277 
    278310        rc = vbclX11ReadDataWorker(pCtx, uFmt, ppv, pcb, pvUser);
    279311        if (RT_SUCCESS(rc))
    280             rc = ShClTransferHttpServerWaitForStatusChange(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED, 5000 /* SHCL_TIMEOUT_DEFAULT_MS */);
    281         if (RT_SUCCESS(rc))
    282         {
    283             PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferLast(pSrv);
    284             if (pTransfer)
     312        {
     313            /* Request a new H->G transfer from the host.
     314             * This is needed in order to get a transfer ID from the host we can initialize our own local transfer with.
     315             * Transfer creation and set up will be done in VbglR3. */
     316            rc = VbglR3ClipboardTransferRequest(&pCtx->CmdCtx);
     317            if (RT_SUCCESS(rc))
    285318            {
    286                 rc = vbclX11TransferWaitForStatusWorker(pCtx, pTransfer, SHCLTRANSFERSTATUS_STARTED, SHCL_TIMEOUT_DEFAULT_MS);
     319                PSHCLHTTPSERVER pSrv = &pCtx->X11.HttpCtx.HttpServer;
     320
     321                /* Wait until the HTTP server got the transfer registered, so that we have something to work with. */
     322                rc = ShClTransferHttpServerWaitForStatusChange(pSrv, SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED, SHCL_TIMEOUT_DEFAULT_MS);
    287323                if (RT_SUCCESS(rc))
    288324                {
    289                     char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID);
    290                     char *pszData = NULL;
    291                     RTStrAPrintf(&pszData, "copy\n%s", pszURL);
    292 
    293                     *ppv = pszData;
    294                     *pcb = strlen(pszData) + 1 /* Include terminator */;
    295 
    296                     LogFlowFunc(("pszURL=%s\n", pszURL));
    297 
    298                     RTStrFree(pszURL);
    299 
    300                     rc = VINF_SUCCESS;
    301                 }
     325                    PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferLast(pSrv);
     326                    if (pTransfer)
     327                    {
     328                        rc = ShClTransferWaitForStatus(pTransfer, SHCL_TIMEOUT_DEFAULT_MS, SHCLTRANSFERSTATUS_INITIALIZED);
     329                        if (RT_SUCCESS(rc))
     330                        {
     331                            char *pszURL = ShClTransferHttpServerGetUrlA(pSrv, pTransfer->State.uID);
     332                            if (pszURL)
     333                            {
     334                                *ppv = pszURL;
     335                                *pcb = strlen(pszURL) + 1 /* Include terminator */;
     336
     337                                LogFlowFunc(("URL is '%s'\n", pszURL));
     338
     339                                /* ppv has ownership of pszURL. */
     340                            }
     341                            else
     342                                rc = VERR_NO_MEMORY;
     343                        }
     344                    }
     345                    else
     346                        AssertMsgFailed(("No registered transfer found for HTTP server\n"));
     347                }
     348                else
     349                    LogRel(("Shared Clipboard: Could not start transfer, as no new HTTP transfer was registered in time\n"));
    302350            }
    303             else
    304                 AssertMsgFailed(("No registered transfer found for HTTP server\n"));
    305         }
    306         else
    307             LogRel(("Shared Clipboard: Could not start transfer, as the HTTP server is not running\n"));
     351        }
    308352    }
    309353    else /* Anything else */
     
    314358
    315359    if (RT_FAILURE(rc))
    316         LogRel(("Requesting data in format %#x from host failed with %Rrc\n", uFmt, rc));
     360        LogRel(("Shared Clipboard: Requesting data in format %#x from host failed with %Rrc\n", uFmt, rc));
    317361
    318362    LogFlowFuncLeaveRC(rc);
     
    418462    pCtx->CmdCtx.Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT);
    419463
    420     pCtx->CmdCtx.Transfers.Callbacks.pfnOnRegistered   = vbclX11OnHttpTransferRegisteredCallback;
    421     pCtx->CmdCtx.Transfers.Callbacks.pfnOnUnregistered = vbclX11OnHttpTransferUnregisteredCallback;
    422     pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted    = vbclX11OnHttpTransferCompletedCallback;
    423     pCtx->CmdCtx.Transfers.Callbacks.pfnOnError        = vbclX11OnHttpTransferErrorCallback;
     464    pCtx->CmdCtx.Transfers.Callbacks.pfnOnInitialized  = vbclX11OnTransferInitializedCallback;
     465    pCtx->CmdCtx.Transfers.Callbacks.pfnOnRegistered   = vbclX11OnTransferRegisteredCallback;
     466    pCtx->CmdCtx.Transfers.Callbacks.pfnOnUnregistered = vbclX11OnTransferUnregisteredCallback;
     467    pCtx->CmdCtx.Transfers.Callbacks.pfnOnCompleted    = vbclX11OnTransferCompletedCallback;
     468    pCtx->CmdCtx.Transfers.Callbacks.pfnOnError        = vbclX11OnTransferErrorCallback;
    424469# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
    425470#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp

    r100205 r100367  
    224224    m_fThreadRunning = false;
    225225    m_pTransfer = NULL;
    226 }
    227 
    228 /**
    229  * Sets the callbacks for this object.
    230  *
    231  * @param   pCallbacks          Pointer to callbacks table to use.
    232  */
    233 void SharedClipboardWinDataObject::SetCallbacks(PSHCLCALLBACKS pCallbacks)
    234 {
    235     AssertPtrReturnVoid(pCallbacks);
    236 
    237     RT_ZERO(m_Callbacks);
    238 
    239     m_Callbacks.pfnOnRequestDataFromSource = pCallbacks->pfnOnRequestDataFromSource;
    240226}
    241227
     
    708694                /* Request the transfer from the source.
    709695                 * This will generate a transfer status message which we're waiting for here. */
     696            #if 0 // CLEAN
    710697                AssertPtr(m_Callbacks.pfnOnRequestDataFromSource);
    711698                rc = m_Callbacks.pfnOnRequestDataFromSource(m_pCtx,
     
    713700                                                            this /* pvUser */);
    714701                AssertRCBreak(rc);
     702            #else
     703                rc = ShClTransferStart(m_pTransfer);
     704                AssertRCBreak(rc);
     705            #endif
    715706
    716707                LogRel2(("Shared Clipboard: Waiting for IDataObject started status ...\n"));
     
    10141005
    10151006/**
    1016  * Assigns a transfer object and starts the transfer for the data object.
     1007 * Assigns a transfer object for the data object.
    10171008 *
    10181009 * @returns VBox status code.
    10191010 * @param   pTransfer           Transfer to assign.
    1020  */
    1021 int SharedClipboardWinDataObject::SetAndStartTransfer(PSHCLTRANSFER pTransfer)
     1011 *                              Must be in started state.
     1012 */
     1013int SharedClipboardWinDataObject::SetTransfer(PSHCLTRANSFER pTransfer)
    10221014{
    10231015    AssertReturn(m_pTransfer == NULL, VERR_WRONG_ORDER); /* Transfer already set? */
     
    10281020        if (m_enmStatus == Initialized)
    10291021        {
     1022            AssertMsgReturn(ShClTransferGetStatus(pTransfer) == SHCLTRANSFERSTATUS_STARTED,
     1023                            ("Cannot set a non-started transfer\n"), VERR_WRONG_ORDER);
     1024
    10301025            m_pTransfer = pTransfer;
    10311026
    10321027            ShClTransferAcquire(pTransfer);
    1033 
    1034             rc = setStatusLocked(Running);
    10351028        }
    10361029        else
     
    10481041 * @returns VBox status code.
    10491042 * @param   enmStatus           New status to signal.
    1050  * @param   rc                  Result code. Optional.
     1043 * @param   rcSts               Result code. Optional.
    10511044 *
    10521045 * @note    Called by the main clipboard thread + SharedClipboardWinStreamImpl.
    10531046 */
    1054 int SharedClipboardWinDataObject::SetStatus(Status enmStatus, int rc /* = VINF_SUCCESS */)
    1055 {
    1056     int rc2 = RTCritSectEnter(&m_CritSect);
    1057     if (RT_SUCCESS(rc2))
    1058     {
    1059         setStatusLocked(enmStatus, rc);
     1047int SharedClipboardWinDataObject::SetStatus(Status enmStatus, int rcSts /* = VINF_SUCCESS */)
     1048{
     1049    int rc = RTCritSectEnter(&m_CritSect);
     1050    if (RT_SUCCESS(rc))
     1051    {
     1052        rc = setStatusLocked(enmStatus, rcSts);
    10601053
    10611054        RTCritSectLeave(&m_CritSect);
    10621055    }
    10631056
    1064     return rc2;
     1057    return rc;
    10651058}
    10661059
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-http.cpp

    r100288 r100367  
    6868*********************************************************************************************************************************/
    6969
     70#ifdef DEBUG_andy
     71/** When enabled, this lets the HTTP server run at a predictable URL and port for debugging:
     72 *  URL: http://localhost:49200/transfer<ID> */
     73# define VBOX_SHCL_DEBUG_HTTPSERVER
     74#endif
     75
    7076typedef struct _SHCLHTTPSERVERTRANSFER
    7177{
     
    97103
    98104/*********************************************************************************************************************************
     105*   Static assets                                                                                                                *
     106*********************************************************************************************************************************/
     107
     108static char s_shClHttpServerPage404[] = " \
     109<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \
     110        \"http://www.w3.org/TR/html4/strict.dtd\"> \
     111<html> \
     112    <head> \
     113        <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"> \
     114        <title>VirtualBox Shared Clipboard</title> \
     115    </head> \
     116    <body> \
     117        <h1>VirtualBox Shared Clipboard</h1> \
     118        <p>Error: 404</p> \
     119        <p>Message: Entry not found.</p> \
     120    </body> \
     121</html>";
     122
     123
     124/*********************************************************************************************************************************
    99125*   Internal Shared Clipboard HTTP transfer functions                                                                            *
    100126*********************************************************************************************************************************/
     
    240266    if (pSrvTx)
    241267    {
    242         shClHttpTransferLock(pSrvTx);
    243268        pReq->pvUser = pSrvTx;
    244269    }
     
    258283    if (pSrvTx)
    259284    {
    260         shClHttpTransferUnlock(pSrvTx);
    261285        pReq->pvUser = NULL;
    262286    }
     
    298322{
    299323    RT_NOREF(pData);
     324
     325    if (pvHandle == NULL) /* Serve a 404 page if we got an invalid handle. */
     326    {
     327        Assert(cbBuf >= sizeof(s_shClHttpServerPage404)); /* Keep it simple for now. */
     328        memcpy(pvBuf, &s_shClHttpServerPage404, RT_MIN(cbBuf, sizeof(s_shClHttpServerPage404)));
     329        *pcbRead = sizeof(s_shClHttpServerPage404);
     330        return VINF_SUCCESS;
     331    }
    300332
    301333    int rc;
     
    385417            AssertPtr(pTx);
    386418
    387             /* For now we only serve single files, hence index 0 below. */
     419            /** @todo For now we only serve single files, hence index 0 below. */
    388420            PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTx, 0 /* First file */);
    389421            if (pEntry)
    390422            {
     423                LogRel2(("Shared Clipboard: Querying HTTP transfer information for '%s' ...\n", pEntry->pszName));
     424
    391425                rc = RTStrCopy(openParms.pszPath, openParms.cbPath, pEntry->pszName);
    392426                if (RT_SUCCESS(rc))
     
    402436                            PCSHCLFSOBJINFO pSrcObjInfo = (PSHCLFSOBJINFO)pEntry->pvInfo;
    403437
    404                             LogFlowFunc(("pszName=%s, cbInfo=%RU32, fMode=0x%x (type %#x)\n",
     438                            LogFlowFunc(("pszName=%s, cbInfo=%RU32, fMode=%#x (type %#x)\n",
    405439                                         pEntry->pszName, pEntry->cbInfo, pSrcObjInfo->Attr.fMode, (pSrcObjInfo->Attr.fMode & RTFS_TYPE_MASK)));
    406440
     
    411445                            }
    412446                        }
     447                        else
     448                            LogRel2(("Shared Clipboard: Supplied entry information for '%s' not supported (fInfo=%#x, cbInfo=%RU32\n",
     449                                     pEntry->pszName, pEntry->fInfo, pEntry->cbInfo));
    413450                    }
    414451                }
     
    449486    LogFlowFuncEnter();
    450487
    451     ASMAtomicXchgBool(&pSrv->fInitialized, false);
     488    pSrv->fInitialized = false;
     489    pSrv->fRunning     = false;
    452490
    453491    int rc = VINF_SUCCESS;
     
    596634
    597635/**
     636 * Translates a Shared Clipboard HTTP server status to a string.
     637 *
     638 * @returns Status as a string.
     639 * @param   uMsg                Status to translate.
     640 */
     641static const char *shClTransferHttpServerStatusToStr(SHCLHTTPSERVERSTATUS enmStatus)
     642{
     643    switch (enmStatus)
     644    {
     645        RT_CASE_RET_STR(SHCLHTTPSERVERSTATUS_NONE);
     646        RT_CASE_RET_STR(SHCLHTTPSERVERSTATUS_STARTED);
     647        RT_CASE_RET_STR(SHCLHTTPSERVERSTATUS_STOPPED);
     648        RT_CASE_RET_STR(SHCLHTTPSERVERSTATUS_TRANSFER_REGISTERED);
     649        RT_CASE_RET_STR(SHCLHTTPSERVERSTATUS_TRANSFER_UNREGISTERED);
     650    }
     651
     652    AssertFailedReturn("Unknown");
     653}
     654
     655/**
    598656 * Starts the Shared Clipboard HTTP server instance using a random port (>= 49152).
    599657 *
     
    613671    /* puPort is optional. */
    614672
     673    int rc;
     674#ifdef VBOX_SHCL_DEBUG_HTTPSERVER
     675    uint16_t uDebugPort = 49200;
     676    rc = ShClTransferHttpServerStartEx(pSrv, (uint32_t)uDebugPort);
     677    if (RT_SUCCESS(rc))
     678    {
     679        if (puPort)
     680            *puPort = uDebugPort;
     681    }
     682    return rc;
     683#endif
     684
    615685    RTRAND hRand;
    616     int rc = RTRandAdvCreateSystemFaster(&hRand); /* Should be good enough for this task. */
     686    rc = RTRandAdvCreateSystemFaster(&hRand); /* Should be good enough for this task. */
    617687    if (RT_SUCCESS(rc))
    618688    {
     
    662732     int rc = VINF_SUCCESS;
    663733
    664      if (ASMAtomicReadBool(&pSrv->fRunning))
     734     if (pSrv->fRunning)
    665735     {
    666736         Assert(pSrv->hHTTPServer != NIL_RTHTTPSERVER);
     
    740810static int shClTransferHttpServerDestroyTransfer(PSHCLHTTPSERVER pSrv, PSHCLHTTPSERVERTRANSFER pSrvTx)
    741811{
     812    Assert(RTCritSectIsOwner(&pSrv->CritSect));
     813
    742814    RTListNodeRemove(&pSrvTx->Node);
    743815
     
    751823             pSrvTx->pTransfer->State.uID, pSrv->cTransfers));
    752824
    753     int rc = RTCritSectDelete(&pSrvTx->CritSect);
    754     AssertRCReturn(rc, rc);
     825    if (RTCritSectIsInitialized(&pSrvTx->CritSect))
     826    {
     827        int rc = RTCritSectDelete(&pSrvTx->CritSect);
     828        AssertRCReturn(rc, rc);
     829    }
    755830
    756831    RTMemFree(pSrvTx);
    757832    pSrvTx = NULL;
    758833
    759     return rc;
     834    return VINF_SUCCESS;
    760835}
    761836
     
    799874        {
    800875            rc = RTCritSectInit(&pSrvTx->CritSect);
    801             AssertRC(rc);
     876            AssertRCReturn(rc, rc);
    802877
    803878            PCSHCLLISTENTRY pEntry = ShClTransferRootsEntryGet(pTransfer, 0 /* First file */);
     
    806881                /* Create the virtual HTTP path for the transfer.
    807882                 * Every transfer has a dedicated HTTP path (but live in the same URL namespace). */
     883#ifdef VBOX_SHCL_DEBUG_HTTPSERVER
     884# ifdef DEBUG_andy /** Too lazy to specify a different transfer ID for debugging. */
     885                ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/transfer");
     886# else
     887                ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/transfer%RU16",
     888                                           pTransfer->State.uID);
     889# endif
     890#else
    808891                ssize_t cch = RTStrPrintf2(pSrvTx->szPathVirtual, sizeof(pSrvTx->szPathVirtual), "/%s/%s/%s",
    809892                                           SHCL_HTTPT_URL_NAMESPACE, szUuid, pEntry->pszName);
     893#endif
    810894                AssertReturn(cch, VERR_BUFFER_OVERFLOW);
    811895
     
    10441128
    10451129/**
     1130 * Returns whether a given HTTP server instance is initialized or not.
     1131 *
     1132 * @returns \c true if running, or \c false if not.
     1133 * @param   pSrv                HTTP server instance to check initialized state for.
     1134 */
     1135bool ShClTransferHttpServerIsInitialized(PSHCLHTTPSERVER pSrv)
     1136{
     1137    AssertPtrReturn(pSrv, false);
     1138
     1139    return ASMAtomicReadBool(&pSrv->fInitialized);
     1140}
     1141
     1142/**
    10461143 * Returns whether a given HTTP server instance is running or not.
    10471144 *
     
    10601157 *
    10611158 * @returns VBox status code.
    1062  * @retval  VERR_STATE_CHANGED if the HTTP server status has changed (not running anymore).
     1159 * @retval  VERR_STATE_CHANGED if the HTTP server was uninitialized.
    10631160 * @param   pSrv                HTTP server instance to wait for.
    10641161 * @param   fStatus             Status to wait for.
     
    10771174    int rc = VERR_TIMEOUT;
    10781175
    1079     LogFlowFunc(("fStatus=%#x, msTimeout=%RU32\n", fStatus, msTimeout));
     1176    LogFlowFunc(("fStatus=%#x, msTimeout=%RU32 -- current is %#x\n", fStatus, msTimeout, pSrv->enmStatus));
    10801177
    10811178    while (RTTimeMilliTS() - tsStartMs <= msTimeout)
    10821179    {
    1083         if (   !pSrv->fInitialized
    1084             || !pSrv->fRunning)
     1180        if (!pSrv->fInitialized)
    10851181        {
    10861182            rc = VERR_STATE_CHANGED;
     
    10981194
    10991195        LogFlowFunc(("Current status now is: %#x\n", pSrv->enmStatus));
     1196        LogRel2(("Shared Clipboard: HTTP server entered status '%s'\n", shClTransferHttpServerStatusToStr(pSrv->enmStatus)));
    11001197
    11011198        if (pSrv->enmStatus & fStatus)
     
    11331230        rc = ShClTransferHttpServerStart(&pCtx->HttpServer, 32 /* cMaxAttempts */, NULL /* puPort */);
    11341231
     1232    LogFlowFuncLeaveRC(rc);
    11351233    return rc;
    11361234}
     
    11551253    }
    11561254
    1157     return rc;
    1158 }
    1159 
     1255    LogFlowFuncLeaveRC(rc);
     1256    return rc;
     1257}
     1258
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers-provider-local.cpp

    r100265 r100367  
    904904 * @param   pProvider           Provider to assign interface to.
    905905 */
    906 PSHCLTXPROVIDERIFACE VBClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider)
     906PSHCLTXPROVIDERIFACE ShClTransferProviderLocalQueryInterface(PSHCLTXPROVIDER pProvider)
    907907{
    908908    pProvider->Interface.pfnRootListRead   = shclTransferIfaceLocalRootListRead;
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp

    r100290 r100367  
    3636#include <iprt/semaphore.h>
    3737#include <iprt/uri.h>
     38#include <iprt/utf16.h>
    3839
    3940#include <VBox/err.h>
    4041#include <VBox/HostServices/VBoxClipboardSvc.h>
     42#include <VBox/GuestHost/clipboard-helper.h>
    4143#include <VBox/GuestHost/SharedClipboard-transfers.h>
    4244
    4345
     46DECLINLINE(void) shClTransferLock(PSHCLTRANSFER pTransfer);
     47DECLINLINE(void) shClTransferUnlock(PSHCLTRANSFER pTransfer);
     48static int shClTransferSetStatus(PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS enmStatus);
    4449static int shClTransferThreadCreate(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
    4550static int shClTransferThreadDestroy(PSHCLTRANSFER pTransfer, RTMSINTERVAL uTimeoutMs);
    4651
    4752static void shclTransferCtxTransferRemoveAndUnregister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer);
    48 static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uId);
     53static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID uId);
    4954static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx);
    5055
     
    10451050 *
    10461051 * @returns VBox status code.
     1052 * @param   enmDir              Specifies the transfer direction of this transfer.
     1053 * @param   enmSource           Specifies the data source of the transfer.
    10471054 * @param   cbMaxChunkSize      Maximum transfer chunk size (in bytes) to use.
    10481055 * @param   cMaxListHandles     Maximum list entries the transfer can have.
     
    10511058 *                              Must be destroyed by ShClTransferDestroy().
    10521059 */
    1053 int ShClTransferCreateEx(uint32_t cbMaxChunkSize, uint32_t cMaxListHandles, uint32_t cMaxObjHandles,
    1054                          PSHCLTRANSFER *ppTransfer)
     1060int ShClTransferCreateEx(SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
     1061                         uint32_t cbMaxChunkSize, uint32_t cMaxListHandles, uint32_t cMaxObjHandles, PSHCLTRANSFER *ppTransfer)
    10551062{
    10561063
     
    10631070    AssertPtrReturn(pTransfer, VERR_NO_MEMORY);
    10641071
    1065     pTransfer->State.uID       = 0;
     1072    pTransfer->State.uID       = NIL_SHCLTRANSFERID;
    10661073    pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_NONE;
    1067     pTransfer->State.enmDir    = SHCLTRANSFERDIR_UNKNOWN;
    1068     pTransfer->State.enmSource = SHCLSOURCE_INVALID;
     1074    pTransfer->State.enmDir    = enmDir;
     1075    pTransfer->State.enmSource = enmSource;
    10691076
    10701077    pTransfer->Thread.hThread    = NIL_RTTHREAD;
     
    10921099    ShClTransferListInit(&pTransfer->lstRoots);
    10931100
    1094     int rc = ShClEventSourceCreate(&pTransfer->Events, 0 /* uID */);
     1101    int rc = RTCritSectInit(&pTransfer->CritSect);
     1102    AssertRCReturn(rc, rc);
     1103
     1104    rc = RTSemEventCreate(&pTransfer->StatusChangeEvent);
     1105    AssertRCReturn(rc, rc);
     1106
     1107    rc = ShClEventSourceCreate(&pTransfer->Events, 0 /* uID */);
    10951108    if (RT_SUCCESS(rc))
    10961109    {
     
    11141127 *
    11151128 * @returns VBox status code.
     1129 * @param   enmDir              Specifies the transfer direction of this transfer.
     1130 * @param   enmSource           Specifies the data source of the transfer.
    11161131 * @param   ppTransfer          Where to return the created clipboard transfer struct.
    11171132 *                              Must be destroyed by ShClTransferDestroy().
    11181133 */
    1119 int ShClTransferCreate(PSHCLTRANSFER *ppTransfer)
    1120 {
    1121     return ShClTransferCreateEx(SHCL_TRANSFER_DEFAULT_MAX_CHUNK_SIZE,
     1134int ShClTransferCreate(SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, PSHCLTRANSFER *ppTransfer)
     1135{
     1136    return ShClTransferCreateEx(enmDir, enmSource,
     1137                                SHCL_TRANSFER_DEFAULT_MAX_CHUNK_SIZE,
    11221138                                SHCL_TRANSFER_DEFAULT_MAX_LIST_HANDLES,
    11231139                                SHCL_TRANSFER_DEFAULT_MAX_OBJ_HANDLES,
     
    11401156        pTransfer->Callbacks.pfnOnDestroy(&pTransfer->CallbackCtx);
    11411157
    1142     AssertMsgReturn(pTransfer->cRefs == 0, ("Number of references > 0 (%RU32)\n", pTransfer->cRefs), VERR_WRONG_ORDER);
     1158    AssertMsgReturn(ASMAtomicReadU32(&pTransfer->cRefs) == 0,
     1159                    ("Number of references > 0 (%RU32)\n", pTransfer->cRefs), VERR_WRONG_ORDER);
    11431160
    11441161    LogFlowFuncEnter();
    11451162
    1146     int rc = shClTransferThreadDestroy(pTransfer, RT_MS_30SEC /* Timeout in ms */);
     1163    int rc = shClTransferThreadDestroy(pTransfer, SHCL_TIMEOUT_DEFAULT_MS);
    11471164    if (RT_FAILURE(rc))
    11481165        return rc;
     
    11531170        RTCritSectDelete(&pTransfer->CritSect);
    11541171
     1172    rc = RTSemEventDestroy(pTransfer->StatusChangeEvent);
     1173    AssertRCReturn(rc, rc);
     1174    pTransfer->StatusChangeEvent = NIL_RTSEMEVENT;
     1175
    11551176    ShClEventSourceDestroy(&pTransfer->Events);
    11561177
     
    11641185 * @returns VBox status code.
    11651186 * @param   pTransfer           Transfer to initialize.
    1166  * @param   enmDir              Specifies the transfer direction of this transfer.
    1167  * @param   enmSource           Specifies the data source of the transfer.
    1168  */
    1169 int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource)
    1170 {
    1171     AssertMsgReturn(pTransfer->State.enmStatus < SHCLTRANSFERSTATUS_INITIALIZED,
    1172                     ("Wrong status (currently is %s)\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)),
    1173                     VERR_WRONG_ORDER);
     1187 */
     1188int ShClTransferInit(PSHCLTRANSFER pTransfer)
     1189{
     1190    shClTransferLock(pTransfer);
     1191
     1192    AssertMsgReturnStmt(pTransfer->State.enmStatus < SHCLTRANSFERSTATUS_INITIALIZED,
     1193                        ("Wrong status (currently is %s)\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)),
     1194                        shClTransferUnlock(pTransfer), VERR_WRONG_ORDER);
    11741195
    11751196    pTransfer->cRefs = 0;
    1176 
    1177     pTransfer->State.enmDir    = enmDir;
    1178     pTransfer->State.enmSource = enmSource;
    11791197
    11801198    LogFlowFunc(("uID=%RU32, enmDir=%RU32, enmSource=%RU32\n",
     
    11871205    pTransfer->uObjHandleNext  = 1;
    11881206
    1189     /* Make sure that the callback context has all values set according to the callback table.
    1190      * This only needs to be done once, so do this here. */
    1191     pTransfer->CallbackCtx.pTransfer = pTransfer;
    1192     pTransfer->CallbackCtx.pvUser    = pTransfer->Callbacks.pvUser;
    1193     pTransfer->CallbackCtx.cbUser    = pTransfer->Callbacks.cbUser;
    1194 
    1195     int rc = RTCritSectInit(&pTransfer->CritSect);
    1196     AssertRCReturn(rc, rc);
    1197 
    1198     if (pTransfer->Callbacks.pfnOnInitialized)
    1199         pTransfer->Callbacks.pfnOnInitialized(&pTransfer->CallbackCtx);
     1207    int rc = shClTransferSetStatus(pTransfer, SHCLTRANSFERSTATUS_INITIALIZED);
     1208
     1209    shClTransferUnlock(pTransfer);
    12001210
    12011211    if (RT_SUCCESS(rc))
    12021212    {
    1203         pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */
     1213        if (pTransfer->Callbacks.pfnOnInitialized)
     1214            pTransfer->Callbacks.pfnOnInitialized(&pTransfer->CallbackCtx);
    12041215    }
    12051216
     
    12491260uint32_t ShClTransferRelease(PSHCLTRANSFER pTransfer)
    12501261{
    1251     return ASMAtomicDecU32(&pTransfer->cRefs);
     1262    const uint32_t cRefs = ASMAtomicDecU32(&pTransfer->cRefs);
     1263    Assert(pTransfer->cRefs <= VBOX_SHCL_MAX_TRANSFERS); /* Not perfect, but better than nothing. */
     1264    return cRefs;
    12521265}
    12531266
     
    14981511
    14991512    ShClTransferCopyCallbacks(&pTransfer->Callbacks, pCallbacks);
     1513
     1514    /* Make sure that the callback context has all values set according to the callback table.
     1515     * This only needs to be done once, so do this here. */
     1516    pTransfer->CallbackCtx.pTransfer = pTransfer;
     1517    pTransfer->CallbackCtx.pvUser    = pTransfer->Callbacks.pvUser;
     1518    pTransfer->CallbackCtx.cbUser    = pTransfer->Callbacks.cbUser;
    15001519}
    15011520
     
    15281547
    15291548/**
     1549 * Sets the current status.
     1550 *
     1551 * @returns VBox status code.
     1552 * @param   pTransfer           Clipboard transfer to set status for.
     1553 * @param   enmStatus           Status to set.
     1554 *
     1555 * @note    Caller needs to take critical section.
     1556 */
     1557static int shClTransferSetStatus(PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS enmStatus)
     1558{
     1559    Assert(RTCritSectIsOwner(&pTransfer->CritSect));
     1560#if 0
     1561    AssertMsgReturn(pTransfer->State.enmStatus != enmStatus,
     1562                    ("Setting the same status twice in a row (%#x), please report this!\n", enmStatus), VERR_WRONG_ORDER);
     1563#endif
     1564    pTransfer->State.enmStatus = enmStatus;
     1565
     1566    LogFlowFunc(("enmStatus=%s\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)));
     1567
     1568    return RTSemEventSignal(pTransfer->StatusChangeEvent);
     1569}
     1570
     1571/**
    15301572 * Returns the number of transfer root list entries.
    15311573 *
     
    16381680 * @returns VBox status code.
    16391681 * @param   pTransfer           Clipboard transfer to read root list for.
     1682 *                              Must be in STARTED state.
    16401683 */
    16411684int ShClTransferRootListRead(PSHCLTRANSFER pTransfer)
     
    16441687
    16451688    LogFlowFuncEnter();
     1689
     1690#ifdef DEBUG
     1691    shClTransferLock(pTransfer);
     1692    AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_INITIALIZED,
     1693                    ("Cannot read root list in status %s\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)),
     1694                    VERR_WRONG_ORDER);
     1695    shClTransferUnlock(pTransfer);
     1696#endif
    16461697
    16471698    int rc;
     
    16841735    AssertReturn(cbRoots,           VERR_INVALID_PARAMETER);
    16851736
    1686     LogFlowFuncEnter();
     1737    LogFlowFunc(("\n%.*Rhxd\n", cbRoots, pszRoots));
    16871738
    16881739    if (!RTStrIsValidEncoding(pszRoots))
     
    16981749    char     *pszPathRootAbs = NULL;
    16991750
    1700     RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots - 1).split(SHCL_TRANSFER_URI_LIST_SEP_STR);
     1751    RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots).split(SHCL_TRANSFER_URI_LIST_SEP_STR);
    17011752    if (!lstRootEntries.size())
    17021753    {
     
    17251776        LogFlowFunc(("pszPathCur=%s\n", pszPathCur));
    17261777
    1727         rc = ShClTransferValidatePath(pszPathCur, false);
     1778        rc = ShClTransferValidatePath(pszPathCur, false /* fMustExist */);
    17281779        if (RT_FAILURE(rc))
    17291780        {
     
    17601811            if (RT_SUCCESS(rc))
    17611812            {
    1762                 PSHCLFSOBJINFO pFsObjInfo = (PSHCLFSOBJINFO )RTMemAlloc(sizeof(SHCLFSOBJINFO));
     1813                PSHCLFSOBJINFO pFsObjInfo = (PSHCLFSOBJINFO )RTMemAllocZ(sizeof(SHCLFSOBJINFO));
    17631814                if (pFsObjInfo)
    17641815                {
    1765                     rc = ShClFsObjInfoQuery(pszPathCur, pFsObjInfo);
     1816                    if (pTransfer->State.enmDir == SHCLTRANSFERDIR_TO_REMOTE)
     1817                        rc = ShClFsObjInfoQueryLocal(pszPathCur, pFsObjInfo);
    17661818                    if (RT_SUCCESS(rc))
    17671819                    {
     
    18311883
    18321884/**
     1885 * Initializes the root list entries for a given clipboard transfer, UTF-16 (Unicode) version.
     1886 *
     1887 * @returns VBox status code.
     1888 * @param   pTransfer           Transfer to set transfer list entries for.
     1889 * @param   pwszRoots           Unicode string list (separated by CRLF) of root entries to set.
     1890 *                              All entries must have the same root path.
     1891 * @param   cbRoots             Size (in bytes) of string list. Includes zero terminator.
     1892 *
     1893 * @note    Accepts local paths or URI string lists (absolute only).
     1894 */
     1895int ShClTransferRootsInitFromStringListUnicode(PSHCLTRANSFER pTransfer, PRTUTF16 pwszRoots, size_t cbRoots)
     1896{
     1897    AssertPtrReturn(pwszRoots, VERR_INVALID_POINTER);
     1898    AssertReturn(cbRoots, VERR_INVALID_PARAMETER);
     1899    AssertReturn(cbRoots % sizeof(RTUTF16) == 0, VERR_INVALID_PARAMETER);
     1900
     1901    size_t cwcRoots = cbRoots / sizeof(RTUTF16);
     1902
     1903    /* This may slightly overestimate the space needed. */
     1904    size_t chDst = 0;
     1905    int rc = ShClUtf16LenUtf8(pwszRoots, cwcRoots, &chDst);
     1906    if (RT_SUCCESS(rc))
     1907    {
     1908        chDst++; /* Add space for terminator. */
     1909
     1910        char *pszDst = (char *)RTStrAlloc(chDst);
     1911        if (pszDst)
     1912        {
     1913            size_t cbActual = 0;
     1914            rc = ShClConvUtf16CRLFToUtf8LF(pwszRoots, cwcRoots, pszDst, chDst, &cbActual);
     1915            if (RT_SUCCESS(rc))
     1916                rc = ShClTransferRootsInitFromStringList(pTransfer, pszDst, cbActual + 1 /* Include terminator */);
     1917
     1918            RTStrFree(pszDst);
     1919        }
     1920        else
     1921            rc = VERR_NO_MEMORY;
     1922    }
     1923
     1924    return rc;
     1925}
     1926
     1927/**
    18331928 * Initializes a single file as a transfer root.
    18341929 *
     
    20132108
    20142109    /* Ready to start? */
    2015     AssertMsgReturn(pTransfer->ProviderIface.pfnRootListRead != NULL,
    2016                     ("No provider interface set (yet)\n"),
    2017                     VERR_WRONG_ORDER);
    2018     AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_INITIALIZED,
    2019                     ("Wrong status (currently is %s)\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)),
    2020                     VERR_WRONG_ORDER);
    2021 
    2022     int rc = VINF_SUCCESS;
    2023 
    2024     pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_STARTED;
     2110    AssertMsgReturnStmt(pTransfer->ProviderIface.pfnRootListRead != NULL,
     2111                        ("No provider interface set (yet)\n"),
     2112                        shClTransferUnlock(pTransfer), VERR_WRONG_ORDER);
     2113    AssertMsgReturnStmt(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_INITIALIZED,
     2114                        ("Wrong status (currently is %s)\n", ShClTransferStatusToStr(pTransfer->State.enmStatus)),
     2115                        shClTransferUnlock(pTransfer), VERR_WRONG_ORDER);
     2116
     2117    int rc = shClTransferSetStatus(pTransfer, SHCLTRANSFERSTATUS_STARTED);
    20252118
    20262119    shClTransferUnlock(pTransfer);
     
    20632156        shClTransferUnlock(pTransfer); /* Leave lock while waiting. */
    20642157
    2065         int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, RT_MS_30SEC /* Timeout in ms */);
     2158        int rc2 = RTThreadUserWait(pTransfer->Thread.hThread, SHCL_TIMEOUT_DEFAULT_MS);
    20662159        AssertRC(rc2);
    20672160
     
    21162209}
    21172210
     2211/**
     2212 * Waits for the transfer status to change, internal version.
     2213 *
     2214 * @returns VBox status code.
     2215 * @param   pTransfer           Clipboard transfer to wait for.
     2216 * @param   msTimeout           Timeout (in ms) to wait.
     2217 * @param   penmStatus          Where to return the new (current) transfer status on success.
     2218 *                              Optional and can be NULL.
     2219 */
     2220static int shClTransferWaitForStatusChangeInternal(PSHCLTRANSFER pTransfer, RTMSINTERVAL msTimeout, SHCLTRANSFERSTATUS *penmStatus)
     2221{
     2222    LogFlowFunc(("Waiting for status change (%RU32 timeout) ...\n", msTimeout));
     2223
     2224    int rc = RTSemEventWait(pTransfer->StatusChangeEvent, msTimeout);
     2225    if (RT_SUCCESS(rc))
     2226    {
     2227        if (penmStatus)
     2228        {
     2229            shClTransferLock(pTransfer);
     2230
     2231            *penmStatus = pTransfer->State.enmStatus;
     2232
     2233            shClTransferUnlock(pTransfer);
     2234        }
     2235    }
     2236
     2237    return rc;
     2238}
     2239
     2240/**
     2241 * Waits for the transfer status to change.
     2242 *
     2243 * @returns VBox status code.
     2244 * @param   pTransfer           Clipboard transfer to wait for.
     2245 * @param   msTimeout           Timeout (in ms) to wait.
     2246 * @param   penmStatus          Where to return the new (current) transfer status on success.
     2247 *                              Optional and can be NULL.
     2248 */
     2249int ShClTransferWaitForStatusChange(PSHCLTRANSFER pTransfer, RTMSINTERVAL msTimeout, SHCLTRANSFERSTATUS *penmStatus)
     2250{
     2251    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     2252
     2253    int rc = shClTransferWaitForStatusChangeInternal(pTransfer, msTimeout, penmStatus);
     2254
     2255    LogFlowFuncLeaveRC(rc);
     2256    return rc;
     2257}
     2258
     2259/**
     2260 * Waits for a specific transfer status.
     2261 *
     2262 * @returns VBox status code.
     2263 * @param   pTransfer           Clipboard transfer to wait for.
     2264 * @param   msTimeout           Timeout (in ms) to wait.
     2265 * @param   enmStatus           Transfer status to wait for.
     2266 */
     2267int ShClTransferWaitForStatus(PSHCLTRANSFER pTransfer, RTMSINTERVAL msTimeout, SHCLTRANSFERSTATUS enmStatus)
     2268{
     2269    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     2270
     2271    int rc = VINF_SUCCESS;
     2272
     2273    uint64_t const tsStartMs = RTTimeMilliTS();
     2274    uint64_t       msLeft    = msTimeout;
     2275    for (;;)
     2276    {
     2277        SHCLTRANSFERSTATUS enmCurStatus;
     2278        rc = shClTransferWaitForStatusChangeInternal(pTransfer, msLeft, &enmCurStatus);
     2279        if (RT_FAILURE(rc))
     2280            break;
     2281
     2282        if (enmCurStatus == enmStatus)
     2283            break;
     2284
     2285        msLeft -= RT_MIN(msLeft, RTTimeMilliTS() - tsStartMs);
     2286        if (msLeft == 0)
     2287        {
     2288            rc = VERR_TIMEOUT;
     2289            break;
     2290        }
     2291    }
     2292
     2293    LogFlowFuncLeaveRC(rc);
     2294    return rc;
     2295}
     2296
    21182297
    21192298/*********************************************************************************************************************************
     
    21582337    if (RT_SUCCESS(rc))
    21592338    {
    2160         RTListInit(&pTransferCtx->List);
    2161 
    2162         pTransferCtx->cTransfers  = 0;
    2163         pTransferCtx->cRunning    = 0;
    2164         pTransferCtx->cMaxRunning = 64; /** @todo Make this configurable? */
    2165 
    2166         RT_ZERO(pTransferCtx->bmTransferIds);
    2167 
    2168         ShClTransferCtxReset(pTransferCtx);
     2339        rc = RTSemEventCreate(&pTransferCtx->ChangedEvent);
     2340        if (RT_SUCCESS(rc))
     2341        {
     2342            RT_ZERO(pTransferCtx->ChangedEventData);
     2343
     2344            RTListInit(&pTransferCtx->List);
     2345
     2346            pTransferCtx->cTransfers  = 0;
     2347            pTransferCtx->cRunning    = 0;
     2348            pTransferCtx->cMaxRunning = 64; /** @todo Make this configurable? */
     2349
     2350            RT_ZERO(pTransferCtx->bmTransferIds);
     2351
     2352            ShClTransferCtxReset(pTransferCtx);
     2353        }
    21692354    }
    21702355
     
    22012386
    22022387    shClTransferCtxUnlock(pTransferCtx);
     2388
     2389    RTSemEventDestroy(pTransferCtx->ChangedEvent);
     2390    pTransferCtx->ChangedEvent = NIL_RTSEMEVENT;
    22032391
    22042392    if (RTCritSectIsInitialized(&pTransferCtx->CritSect))
     
    22312419
    22322420/**
     2421 * Signals a change event.
     2422 *
     2423 * @returns VBox status code.
     2424 * @param   pTransferCtx        Transfer context to return transfer for.
     2425 * @param   fRegistered         Whether a transfer got registered or unregistered.
     2426 * @param   pTransfer           Transfer bound to the event.
     2427 */
     2428static int shClTransferCtxSignal(PSHCLTRANSFERCTX pTransferCtx, bool fRegistered, PSHCLTRANSFER pTransfer)
     2429{
     2430    Assert(RTCritSectIsOwner(&pTransferCtx->CritSect));
     2431
     2432    LogFlowFunc(("fRegistered=%RTbool, pTransfer=%p\n", fRegistered, pTransfer));
     2433
     2434    pTransferCtx->ChangedEventData.fRegistered = fRegistered;
     2435    pTransferCtx->ChangedEventData.pTransfer   = pTransfer;
     2436
     2437    return RTSemEventSignal(pTransferCtx->ChangedEvent);
     2438}
     2439
     2440/**
    22332441 * Returns a specific clipboard transfer, internal version.
     2442 *
     2443 * @returns Clipboard transfer found, or NULL if not found.
     2444 * @param   pTransferCtx                Transfer context to return transfer for.
     2445 * @param   idTransfer                  ID of the transfer to return.
     2446 *
     2447 * @note    Caller needs to take critical section.
     2448 */
     2449static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer)
     2450{
     2451    Assert(RTCritSectIsOwner(&pTransferCtx->CritSect));
     2452
     2453    PSHCLTRANSFER pTransfer;
     2454    RTListForEach(&pTransferCtx->List, pTransfer, SHCLTRANSFER, Node) /** @todo Slow, but works for now. */
     2455    {
     2456        if (pTransfer->State.uID == idTransfer)
     2457            return pTransfer;
     2458    }
     2459
     2460    return NULL;
     2461}
     2462
     2463/**
     2464 * Returns a specific clipboard transfer by index, internal version.
     2465 *
     2466 * @returns Clipboard transfer found, or NULL if not found.
     2467 * @param   pTransferCtx                Transfer context to return transfer for.
     2468 * @param   uIdx                        Index of the transfer to return.
     2469 *
     2470 * @note    Caller needs to take critical section.
     2471 */
     2472static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx)
     2473{
     2474    Assert(RTCritSectIsOwner(&pTransferCtx->CritSect));
     2475
     2476    uint32_t idx = 0;
     2477
     2478    PSHCLTRANSFER pTransfer;
     2479    RTListForEach(&pTransferCtx->List, pTransfer, SHCLTRANSFER, Node) /** @todo Slow, but works for now. */
     2480    {
     2481        if (uIdx == idx)
     2482            return pTransfer;
     2483        idx++;
     2484    }
     2485
     2486    return NULL;
     2487}
     2488
     2489/**
     2490 * Returns a clipboard transfer for a specific transfer ID.
    22342491 *
    22352492 * @returns Clipboard transfer found, or NULL if not found.
    22362493 * @param   pTransferCtx                Transfer context to return transfer for.
    22372494 * @param   uID                         ID of the transfer to return.
    2238  *
    2239  * @note    Caller needs to take critical section.
    2240  */
    2241 static PSHCLTRANSFER shClTransferCtxGetTransferByIdInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
    2242 {
    2243     Assert(RTCritSectIsOwner(&pTransferCtx->CritSect));
    2244 
    2245     PSHCLTRANSFER pTransfer;
    2246     RTListForEach(&pTransferCtx->List, pTransfer, SHCLTRANSFER, Node) /** @todo Slow, but works for now. */
    2247     {
    2248         if (pTransfer->State.uID == uID)
    2249             return pTransfer;
    2250     }
    2251 
    2252     return NULL;
    2253 }
    2254 
    2255 /**
    2256  * Returns a specific clipboard transfer by index, internal version.
    2257  *
    2258  * @returns Clipboard transfer found, or NULL if not found.
    2259  * @param   pTransferCtx                Transfer context to return transfer for.
    2260  * @param   uIdx                        Index of the transfer to return.
    2261  *
    2262  * @note    Caller needs to take critical section.
    2263  */
    2264 static PSHCLTRANSFER shClTransferCtxGetTransferByIndexInternal(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx)
    2265 {
    2266     Assert(RTCritSectIsOwner(&pTransferCtx->CritSect));
    2267 
    2268     uint32_t idx = 0;
    2269 
    2270     PSHCLTRANSFER pTransfer;
    2271     RTListForEach(&pTransferCtx->List, pTransfer, SHCLTRANSFER, Node) /** @todo Slow, but works for now. */
    2272     {
    2273         if (uIdx == idx)
    2274             return pTransfer;
    2275         idx++;
    2276     }
    2277 
    2278     return NULL;
    2279 }
    2280 
    2281 /**
    2282  * Returns a clipboard transfer for a specific transfer ID.
    2283  *
    2284  * @returns Clipboard transfer found, or NULL if not found.
    2285  * @param   pTransferCtx                Transfer context to return transfer for.
    2286  * @param   uID                         ID of the transfer to return.
    22872495 */
    22882496PSHCLTRANSFER ShClTransferCtxGetTransferById(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID)
     
    23152523}
    23162524
     2525
     2526/**
     2527 * Returns the last clipboard transfer registered.
     2528 *
     2529 * @returns Clipboard transfer found, or NULL if not found.
     2530 * @param   pTransferCtx                Transfer context to return transfer for.
     2531 */
     2532PSHCLTRANSFER ShClTransferCtxGetTransferLast(PSHCLTRANSFERCTX pTransferCtx)
     2533{
     2534    shClTransferCtxLock(pTransferCtx);
     2535
     2536    PSHCLTRANSFER const pTransfer = RTListGetLast(&pTransferCtx->List, SHCLTRANSFER, Node);
     2537
     2538    shClTransferCtxUnlock(pTransferCtx);
     2539
     2540    return pTransfer;
     2541}
     2542
    23172543/**
    23182544 * Returns the number of running clipboard transfers for a given transfer context.
     
    23532579}
    23542580
    2355 /**
    2356  * Registers a clipboard transfer with a transfer context, i.e. allocates a transfer ID.
    2357  *
    2358  * @return  VBox status code.
    2359  * @retval  VERR_SHCLPB_MAX_TRANSFERS_REACHED if the maximum of concurrent transfers
    2360  *          is reached.
    2361  * @param   pTransferCtx        Transfer context to register transfer to.
    2362  * @param   pTransfer           Transfer to register. The context takes ownership of the transfer on success.
    2363  * @param   pidTransfer         Where to return the transfer ID on success. Optional.
    2364  */
    2365 int ShClTransferCtxTransferRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID *pidTransfer)
    2366 {
    2367     AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
    2368     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
    2369     /* pidTransfer is optional. */
    2370 
    2371     shClTransferCtxLock(pTransferCtx);
    2372 
     2581static int shClTransferCreateIDInternal(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID *pidTransfer)
     2582{
    23732583    /*
    23742584     * Pick a random bit as starting point.  If it's in use, search forward
     
    23932603    {
    23942604        LogFunc(("Maximum number of transfers reached (%RU16 transfers)\n", pTransferCtx->cTransfers));
    2395         shClTransferCtxUnlock(pTransferCtx);
    23962605        return VERR_SHCLPB_MAX_TRANSFERS_REACHED;
    23972606    }
     2607
     2608    *pidTransfer = idTransfer;
     2609
     2610    return VINF_SUCCESS;
     2611}
     2612
     2613/**
     2614 * Creates a new transfer ID for a given transfer context.
     2615 *
     2616 * @returns VBox status code.
     2617 * @retval  VERR_SHCLPB_MAX_TRANSFERS_REACHED if the maximum of concurrent transfers is reached.
     2618 * @param   pTransferCtx        Transfer context to create transfer ID for.
     2619 * @param   pidTransfer         Where to return the transfer ID on success.
     2620 */
     2621int ShClTransferCtxCreateId(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFERID pidTransfer)
     2622{
     2623    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
     2624    AssertPtrReturn(pidTransfer, VERR_INVALID_POINTER);
     2625
     2626    shClTransferCtxLock(pTransferCtx);
     2627
     2628    int rc = shClTransferCreateIDInternal(pTransferCtx, pidTransfer);
     2629
     2630    shClTransferCtxUnlock(pTransferCtx);
     2631
     2632    return rc;
     2633}
     2634
     2635/**
     2636 * Registers a clipboard transfer with a new transfer ID.
     2637 *
     2638 * @return  VBox status code.
     2639 * @retval  VERR_SHCLPB_MAX_TRANSFERS_REACHED if the maximum of concurrent transfers is reached.
     2640 * @param   pTransferCtx        Transfer context to register transfer to.
     2641 * @param   pTransfer           Transfer to register. The context takes ownership of the transfer on success.
     2642 * @param   idTransfer          Transfer ID to use for registering the given transfer.
     2643 */
     2644static int shClTransferCtxTransferRegisterExInternal(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)
     2645{
     2646    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
     2647    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     2648    Assert(idTransfer != NIL_SHCLTRANSFERID);
     2649
     2650    shClTransferCtxLock(pTransferCtx);
    23982651
    23992652    pTransfer->State.uID = idTransfer;
     
    24102663        pTransfer->Callbacks.pfnOnRegistered(&pTransfer->CallbackCtx, pTransferCtx);
    24112664
    2412     if (pidTransfer)
    2413         *pidTransfer = idTransfer;
    2414 
    24152665    LogFlowFuncLeaveRC(VINF_SUCCESS);
    24162666    return VINF_SUCCESS;
     2667}
     2668
     2669/**
     2670 * Registers a clipboard transfer with a transfer context, i.e. allocates a transfer ID.
     2671 *
     2672 * @return  VBox status code.
     2673 * @retval  VERR_SHCLPB_MAX_TRANSFERS_REACHED if the maximum of concurrent transfers for this context has been reached.
     2674 * @param   pTransferCtx        Transfer context to register transfer to.
     2675 * @param   pTransfer           Transfer to register. The context takes ownership of the transfer on success.
     2676 * @param   pidTransfer         Where to return the transfer ID on success. Optional.
     2677 */
     2678int ShClTransferCtxRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, PSHCLTRANSFERID pidTransfer)
     2679{
     2680    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
     2681    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
     2682
     2683    shClTransferCtxLock(pTransferCtx);
     2684
     2685    SHCLTRANSFERID idTransfer;
     2686    int rc = shClTransferCreateIDInternal(pTransferCtx, &idTransfer);
     2687    if (RT_SUCCESS(rc))
     2688    {
     2689        rc = shClTransferCtxTransferRegisterExInternal(pTransferCtx, pTransfer, idTransfer);
     2690        if (RT_SUCCESS(rc))
     2691        {
     2692            if (pidTransfer)
     2693                *pidTransfer = idTransfer;
     2694        }
     2695    }
     2696
     2697    shClTransferCtxUnlock(pTransferCtx);
     2698
     2699    return rc;
    24172700}
    24182701
     
    24232706 * @retval  VERR_ALREADY_EXISTS if a transfer with the given ID already exists.
    24242707 * @retval  VERR_SHCLPB_MAX_TRANSFERS_REACHED if the maximum of concurrent transfers for this context has been reached.
    2425  * @param   pTransferCtx                Transfer context to register transfer to.
     2708 * @param   pTransferCtx        Transfer context to register transfer to.
    24262709 * @param   pTransfer           Transfer to register.
    24272710 * @param   idTransfer          Transfer ID to use for registration.
    2428  */
    2429 int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)
     2711 *
     2712 * @note    This function ASSUMES you have created \a idTransfer with ShClTransferCtxCreateId().
     2713 */
     2714int ShClTransferCtxRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer)
    24302715{
    24312716    shClTransferCtxLock(pTransferCtx);
     
    24332718    if (pTransferCtx->cTransfers < VBOX_SHCL_MAX_TRANSFERS - 2 /* First and last are not used */)
    24342719    {
    2435         if (!ASMBitTestAndSet(&pTransferCtx->bmTransferIds[0], idTransfer))
    2436         {
    2437             RTListAppend(&pTransferCtx->List, &pTransfer->Node);
    2438 
    2439             pTransfer->State.uID = idTransfer;
    2440 
    2441             shClTransferCtxUnlock(pTransferCtx);
    2442 
    2443             if (pTransfer->Callbacks.pfnOnRegistered)
    2444                 pTransfer->Callbacks.pfnOnRegistered(&pTransfer->CallbackCtx, pTransferCtx);
    2445 
    2446             shClTransferCtxLock(pTransferCtx);
    2447 
    2448             pTransferCtx->cTransfers++;
    2449 
    2450             LogFunc(("Registered transfer ID %RU16 -- now %RU16 transfers total\n", idTransfer, pTransferCtx->cTransfers));
    2451 
    2452             shClTransferCtxUnlock(pTransferCtx);
    2453             return VINF_SUCCESS;
    2454         }
    2455 
    2456         return VERR_ALREADY_EXISTS;
     2720        RTListAppend(&pTransferCtx->List, &pTransfer->Node);
     2721
     2722        shClTransferLock(pTransfer);
     2723
     2724        pTransfer->State.uID = idTransfer;
     2725
     2726        shClTransferUnlock(pTransfer);
     2727
     2728        int rc = shClTransferCtxSignal(pTransferCtx, true /* fRegistered */, pTransfer);
     2729
     2730        pTransferCtx->cTransfers++;
     2731
     2732        LogFunc(("Registered transfer ID %RU16 -- now %RU16 transfers total\n", idTransfer, pTransferCtx->cTransfers));
     2733
     2734        shClTransferCtxUnlock(pTransferCtx);
     2735
     2736        if (pTransfer->Callbacks.pfnOnRegistered)
     2737            pTransfer->Callbacks.pfnOnRegistered(&pTransfer->CallbackCtx, pTransferCtx);
     2738
     2739        return rc;
    24572740    }
    24582741
     
    25012784 * @param   idTransfer          Transfer ID to unregister.
    25022785 */
    2503 int ShClTransferCtxTransferUnregisterById(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer)
     2786int ShClTransferCtxUnregisterById(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer)
    25042787{
    25052788    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
     
    25092792
    25102793    int rc = VINF_SUCCESS;
    2511     AssertMsgStmt(ASMBitTestAndClear(&pTransferCtx->bmTransferIds, idTransfer), ("idTransfer=%#x\n", idTransfer), rc = VERR_NOT_FOUND);
    25122794
    25132795    LogFlowFunc(("idTransfer=%RU32\n", idTransfer));
    25142796
    2515     if (RT_SUCCESS(rc))
     2797    if (ASMBitTestAndClear(&pTransferCtx->bmTransferIds, idTransfer), ("idTransfer=%#x\n", idTransfer))
    25162798    {
    25172799        PSHCLTRANSFER pTransfer = shClTransferCtxGetTransferByIdInternal(pTransferCtx, idTransfer);
     2800        AssertPtr(pTransfer);
    25182801        if (pTransfer)
    25192802        {
    25202803            shclTransferCtxTransferRemoveAndUnregister(pTransferCtx, pTransfer);
     2804
     2805            rc = shClTransferCtxSignal(pTransferCtx, false /* fRegistered */, pTransfer);
    25212806        }
    2522         else
    2523             rc = VERR_NOT_FOUND;
    2524     }
     2807    }
     2808    else
     2809        rc = VERR_NOT_FOUND;
    25252810
    25262811    shClTransferCtxUnlock(pTransferCtx);
     2812
     2813    LogFlowFuncLeaveRC(rc);
     2814    return rc;
     2815}
     2816
     2817/**
     2818 * Waits for a transfer context event.
     2819 *
     2820 * @returns VBox status code.
     2821 * @param   pTransferCtx        Transfer context to wait for.
     2822 * @param   msTimeout           Timeout (in ms) to wait.
     2823 * @param   pEvent              Where to return the event data on success.
     2824 */
     2825static int shClTransferCtxWaitInternal(PSHCLTRANSFERCTX pTransferCtx, RTMSINTERVAL msTimeout, PSHCLTRANSFERCTXEVENT pEvent)
     2826{
     2827    LogFlowFunc(("Waiting for transfer context change (%RU32 timeout) ...\n", msTimeout));
     2828
     2829    int rc = RTSemEventWait(pTransferCtx->ChangedEvent, msTimeout);
     2830    if (RT_SUCCESS(rc))
     2831    {
     2832        shClTransferCtxLock(pTransferCtx);
     2833
     2834        memcpy(pEvent, &pTransferCtx->ChangedEventData, sizeof(SHCLTRANSFERCTXEVENT));
     2835
     2836        shClTransferCtxUnlock(pTransferCtx);
     2837    }
     2838
     2839    LogFlowFuncLeaveRC(rc);
     2840    return rc;
     2841}
     2842
     2843/**
     2844 * Waits for transfer to be (un-)registered.
     2845 *
     2846 * @returns VBox status code.
     2847 * @param   pTransferCtx        Transfer context to wait for.
     2848 * @param   msTimeout           Timeout (in ms) to wait.
     2849 * @param   fRegister           Pass \c true for registering, or \c false for unregistering a transfer.
     2850 * @param   idTransfer          Transfer ID to wait for.
     2851 *                              Pass NIL_SHCLTRANSFERID for any transfer.
     2852 * @param   ppTransfer          Where to return the transfer being (un-)registered. Optional and can be NULL.
     2853 */
     2854int ShClTransferCtxWait(PSHCLTRANSFERCTX pTransferCtx, RTMSINTERVAL msTimeout, bool fRegister, SHCLTRANSFERID idTransfer,
     2855                        PSHCLTRANSFER *ppTransfer)
     2856{
     2857    AssertPtrReturn(pTransferCtx, VERR_INVALID_POINTER);
     2858
     2859    int rc = VERR_TIMEOUT;
     2860
     2861    uint64_t const tsStartMs = RTTimeMilliTS();
     2862    uint64_t       msLeft    = msTimeout;
     2863    for (;;)
     2864    {
     2865        SHCLTRANSFERCTXEVENT Event;
     2866        rc = shClTransferCtxWaitInternal(pTransferCtx, msLeft, &Event);
     2867        if (RT_FAILURE(rc))
     2868            break;
     2869
     2870        shClTransferCtxLock(pTransferCtx);
     2871
     2872        if (Event.fRegistered == fRegister)
     2873        {
     2874            if (   idTransfer != NIL_SHCLTRANSFERID
     2875                && Event.pTransfer
     2876                && ShClTransferGetID(Event.pTransfer) == idTransfer)
     2877            {
     2878                if (ppTransfer)
     2879                    *ppTransfer = Event.pTransfer;
     2880                rc = VINF_SUCCESS;
     2881            }
     2882        }
     2883
     2884        shClTransferCtxUnlock(pTransferCtx);
     2885
     2886        if (RT_SUCCESS(rc))
     2887            break;
     2888
     2889        msLeft -= RT_MIN(msLeft, RTTimeMilliTS() - tsStartMs);
     2890        if (msLeft == 0)
     2891            break;
     2892    }
    25272893
    25282894    LogFlowFuncLeaveRC(rc);
     
    25842950 * @param   pTransferCtx        Transfer context to determine value for.
    25852951 */
    2586 bool ShClTransferCtxTransfersMaximumReached(PSHCLTRANSFERCTX pTransferCtx)
     2952bool ShClTransferCtxIsMaximumReached(PSHCLTRANSFERCTX pTransferCtx)
    25872953{
    25882954    AssertPtrReturn(pTransferCtx, true);
     
    26523018
    26533019/**
    2654  * Queries Shared Clipboard file system information from a given path.
     3020 * Queries local file system information from a given path.
    26553021 *
    26563022 * @returns VBox status code.
     
    26583024 * @param   pObjInfo            Where to return the queried file system information on success.
    26593025 */
    2660 int ShClFsObjInfoQuery(const char *pszPath, PSHCLFSOBJINFO pObjInfo)
     3026int ShClFsObjInfoQueryLocal(const char *pszPath, PSHCLFSOBJINFO pObjInfo)
    26613027{
    26623028    RTFSOBJINFO objInfo;
     
    26853051    {
    26863052        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_NONE);
     3053        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_REQUESTED);
    26873054        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_INITIALIZED);
    26883055        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_UNINITIALIZED);
     
    27533120    return rc;
    27543121}
     3122
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r100206 r100367  
    10701070                {
    10711071                    if (RT_SUCCESS(rc))
    1072                         pObj->SetCallbacks(pCallbacks);
    1073 
    1074                     if (RT_SUCCESS(rc))
    10751072                        pWinCtx->pDataObjInFlight = pObj;
    10761073                }
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-x11.cpp

    r100256 r100367  
    440440                 pCtx->idxFmtHTML, g_aFormats[pCtx->idxFmtHTML].pcszAtom));
    441441#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    442     LogFlowFunc((", idxFmtURI=%u ('%s')", pCtx->idxFmtURI, g_aFormats[pCtx->idxFmtURI].pcszAtom));
    443 #endif
    444     LogFlow((" -> vboxFmt=%#x\n", vboxFmt));
     442    Log((", idxFmtURI=%u ('%s')", pCtx->idxFmtURI, g_aFormats[pCtx->idxFmtURI].pcszAtom));
     443#endif
     444    Log((" -> vboxFmt=%#x\n", vboxFmt));
    445445
    446446#ifdef LOG_ENABLED
     
    12101210    }
    12111211
     1212    /* Init clipboard cache. */
     1213    ShClCacheInit(&pCtx->Cache);
     1214
    12121215    /* Install given callbacks. */
    12131216    shClX11SetCallbacksInternal(pCtx, pCallbacks);
     
    12501253
    12511254    LogFlowFunc(("pCtx=%p\n", pCtx));
     1255
     1256    /* Destroy clipboard cache. */
     1257    ShClCacheDestroy(&pCtx->Cache);
    12521258
    12531259#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     
    15021508#endif
    15031509
    1504     LogFlowFunc(("pCtx=%p, uFmt=%#x\n", pCtx, uFmt));
    1505 
    15061510    int rc = VINF_SUCCESS;
    15071511
     
    15091513    uint32_t cb = 0;
    15101514
    1511     if (uFmt == VBOX_SHCL_FMT_UNICODETEXT)
    1512     {
    1513         if (pCtx->pvUnicodeCache == NULL) /** @todo r=andy Using string cache here? */
    1514             rc = pCtx->Callbacks.pfnOnRequestDataFromSource(pCtx->pFrontend, uFmt, &pCtx->pvUnicodeCache, &pCtx->cbUnicodeCache,
    1515                                                             NULL /* pvUser */);
    1516         if (   RT_SUCCESS(rc)
    1517             /* Catch misbehaving callbacks. */
    1518             && pCtx->pvUnicodeCache
    1519             && pCtx->cbUnicodeCache)
    1520         {
    1521             pv = RTMemDup(pCtx->pvUnicodeCache, pCtx->cbUnicodeCache);
     1515    PSHCLCACHEENTRY pCacheEntry = ShClCacheGet(&pCtx->Cache, uFmt);
     1516    if (!pCacheEntry) /* Cache miss */
     1517    {
     1518        rc = pCtx->Callbacks.pfnOnRequestDataFromSource(pCtx->pFrontend, uFmt, &pv, &cb,
     1519                                                        NULL /* pvUser */);
     1520        if (RT_SUCCESS(rc))
     1521            rc = ShClCacheSet(&pCtx->Cache, uFmt, pv, cb);
     1522    }
     1523    else /* Cache hit */
     1524    {
     1525        void   *pvCache = NULL;
     1526        size_t  cbCache = 0;
     1527        ShClCacheEntryGet(pCacheEntry, &pvCache, &cbCache);
     1528        if (   pvCache
     1529            && cbCache)
     1530        {
     1531            pv = RTMemDup(pvCache, cbCache);
    15221532            if (pv)
    1523                 cb = pCtx->cbUnicodeCache;
     1533            {
     1534                cb = cbCache;
     1535            }
    15241536            else
    1525                 rc = VERR_NO_MEMORY;
    1526         }
    1527     }
    1528     else
    1529         rc = pCtx->Callbacks.pfnOnRequestDataFromSource(pCtx->pFrontend, uFmt, &pv, &cb, NULL /* pvUser */);
    1530 
    1531     /* Safey net in case the callbacks above misbehave
     1537               rc = VERR_NO_MEMORY;
     1538        }
     1539    }
     1540
     1541    LogFlowFunc(("pCtx=%p, uFmt=%#x -> Cache %s\n", pCtx, uFmt, pCacheEntry ? "HIT" : "MISS"));
     1542
     1543    /* Safey net in case the stuff above misbehaves
    15321544     * (must return VERR_NO_DATA if no data available). */
    15331545    if (   RT_SUCCESS(rc)
     
    17741786    }
    17751787#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1776     else if (fmtX11 == SHCLX11FMT_URI_LIST)
     1788    else if (   fmtX11 == SHCLX11FMT_URI_LIST
     1789             || fmtX11 == SHCLX11FMT_URI_LIST_GNOME_COPIED_FILES
     1790            /** @todo BUGBUG Not sure about the following ones; test those. */
     1791             || fmtX11 == SHCLX11FMT_URI_LIST_MATE_COPIED_FILES
     1792             || fmtX11 == SHCLX11FMT_URI_LIST_NAUTILUS_CLIPBOARD
     1793             || fmtX11 == SHCLX11FMT_URI_LIST_KDE_CUTSELECTION)
    17771794    {
    17781795        if (pCtx->vboxFormats & VBOX_SHCL_FMT_URI_LIST)
     
    17811798            if (RT_SUCCESS(rc))
    17821799            {
     1800                 if (   fmtX11 == SHCLX11FMT_URI_LIST_GNOME_COPIED_FILES
     1801                     /** @todo BUGBUG Ditto, see above. */
     1802                     || fmtX11 == SHCLX11FMT_URI_LIST_MATE_COPIED_FILES
     1803                     || fmtX11 == SHCLX11FMT_URI_LIST_NAUTILUS_CLIPBOARD
     1804                     || fmtX11 == SHCLX11FMT_URI_LIST_KDE_CUTSELECTION)
     1805                 {
     1806                    /* Note: There must be *no* final new line ('\n') at the end, otherwise Nautilus will crash! */
     1807                    char *pszData = NULL;
     1808
     1809                    RTStrAPrintf(&pszData, "copy\n%s", (const char *)pv);
     1810
     1811                    cb = strlen(pszData);
     1812                    pv = pszData;
     1813                }
     1814                else /* SHCLX11FMT_URI_LIST -> String only, w/o any special formatting. */
     1815                {
     1816                    char *pszData = NULL;
     1817                    RTStrAPrintf(&pszData, "%s\n", (const char *)pv);
     1818
     1819                    cb = strlen(pszData) + 1;
     1820                    pv = pszData;
     1821                }
     1822
     1823                LogFlowFunc(("Data:\n%.*RhXd\n", cb, pv));
     1824
    17831825                void *pvDst = (void *)XtMalloc(cb);
    17841826                if (pvDst)
     
    17941836                    rc = VERR_NO_MEMORY;
    17951837            }
     1838
     1839            RTMemFree(pv);
     1840            pv = NULL;
    17961841        }
    17971842        /* else not supported yet. */
     
    18761921
    18771922/**
    1878  * Invalidates the local cache of the data in the VBox clipboard.
     1923 * Invalidates the local clipboard cache.
    18791924 *
    18801925 * @param   pCtx                The X11 clipboard context to use.
     
    18821927static void clipInvalidateClipboardCache(PSHCLX11CTX pCtx)
    18831928{
    1884     if (pCtx->pvUnicodeCache != NULL)
    1885     {
    1886         RTMemFree(pCtx->pvUnicodeCache);
    1887         pCtx->pvUnicodeCache = NULL;
    1888     }
     1929    LogFlowFuncEnter();
     1930
     1931    ShClCacheInvalidate(&pCtx->Cache);
    18891932}
    18901933
     
    20322075    *pcbList = 0;
    20332076
     2077    LogFlowFunc(("Data:\n%.*RhXd\n", cbData, pvData));
     2078
    20342079    char **papszStrings;
    20352080    size_t cStrings;
     
    20402085        {
    20412086            const char *pszString = papszStrings[i];
     2087            LogRel2(("Shared Clipboard: Received entry #%zu from X11: '%s'\n", i, pszString));
    20422088            rc = RTStrAAppend(ppszList, pszString);
    20432089            if (RT_FAILURE(rc))
     
    22362282        {
    22372283            case SHCLX11FMT_URI_LIST:
     2284                RT_FALL_THROUGH();
     2285            case SHCLX11FMT_URI_LIST_GNOME_COPIED_FILES:
     2286                RT_FALL_THROUGH();
     2287            case SHCLX11FMT_URI_LIST_MATE_COPIED_FILES:
     2288                RT_FALL_THROUGH();
     2289            case SHCLX11FMT_URI_LIST_NAUTILUS_CLIPBOARD:
     2290                RT_FALL_THROUGH();
     2291            case SHCLX11FMT_URI_LIST_KDE_CUTSELECTION:
    22382292            {
    2239                 RTCList<RTCString> lstRootEntries;
    22402293                rc = ShClX11TransferConvertDataToStringList((const char *)pvSrc, cbSrc, (char **)&pvDst, &cbDst);
    2241                 if (RT_SUCCESS(rc))
    2242                 {
    2243             #if 0
    2244                     for (size_t i = 0; i < lstRootEntries.size(); ++i)
    2245                     {
    2246                         char *pszEntry = RTUriFilePath(lstRootEntries.at(i).c_str())
    2247                         AssertPtrBreakStmt(pszEntry, VERR_INVALID_PARAMETER);
    2248 
    2249                         LogFlowFunc(("Entry '%s' -> ", (char *)pszEntry));
    2250 
    2251                         rc = RTStrAAppend((char **)&pvDst, "http://localhost");
    2252                         AssertRCBreakStmt(rc, VERR_NO_MEMORY);
    2253                         cbDst += (uint32_t)strlen(pszEntry);
    2254 
    2255 
    2256 
    2257                         /** @todo BUGBUG Fix port! */
    2258                         /** @todo Add port + UUID (virtual path). */
    2259 
    2260                         rc = RTStrAAppend((char **)&pvDst, pszEntry);
    2261                         AssertRCBreakStmt(rc, VERR_NO_MEMORY);
    2262                         cbDst += (uint32_t)strlen(pszEntry);
    2263 
    2264                         LogFlowFunc(("'%s'\n", (char *)pvDst));
    2265 
    2266                         rc = RTStrAAppend((char **)&pvDst, SHCL_TRANSFER_URI_LIST_SEP_STR);
    2267                         AssertRCBreakStmt(rc, VERR_NO_MEMORY);
    2268                         cbDst += (uint32_t)strlen(SHCL_TRANSFER_URI_LIST_SEP_STR);
    2269 
    2270                         RTStrFree(pszEntry);
    2271                     }
    2272 
    2273                     if (cbDst)
    2274                         cbDst++; /* Include final (zero) termination. */
    2275             #endif
    2276 
    2277 
    2278                 }
    22792294                break;
    22802295            }
     
    22822297            default:
    22832298            {
    2284                 rc = VERR_INVALID_PARAMETER;
     2299                AssertFailedStmt(rc = VERR_NOT_SUPPORTED); /* Missing code? */
    22852300                break;
    22862301            }
  • trunk/src/VBox/GuestHost/SharedClipboard/testcase/tstClipboardHttpServer.cpp

    r100242 r100367  
    198198    /* Query the local transfer provider. */
    199199    SHCLTXPROVIDER Provider;
    200     RTTESTI_CHECK(VBClTransferProviderLocalQueryInterface(&Provider) != NULL);
     200    RTTESTI_CHECK(ShClTransferProviderLocalQueryInterface(&Provider) != NULL);
    201201
    202202    /* Parse options again, but this time we only fetch all files we want to serve.
     
    212212            {
    213213                PSHCLTRANSFER pTx;
    214                 RTTEST_CHECK_RC_OK(hTest, ShClTransferCreate(&pTx));
     214                RTTEST_CHECK_RC_OK(hTest, ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTx));
    215215                RTTEST_CHECK_RC_OK(hTest, ShClTransferSetProvider(pTx, &Provider));
    216                 RTTEST_CHECK_RC_OK(hTest, ShClTransferInit(pTx, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL));
     216                RTTEST_CHECK_RC_OK(hTest, ShClTransferInit(pTx));
    217217                RTTEST_CHECK_RC_OK(hTest, ShClTransferRootsInitFromFile(pTx, ValueUnion.psz));
    218                 RTTEST_CHECK_RC_OK(hTest, ShClTransferCtxTransferRegister(&TxCtx, pTx, NULL));
     218                RTTEST_CHECK_RC_OK(hTest, ShClTransferCtxRegister(&TxCtx, pTx, NULL));
    219219                RTTEST_CHECK_RC_OK(hTest, ShClTransferHttpServerRegisterTransfer(&HttpSrv, pTx));
    220220                break;
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h

    r100205 r100367  
    282282extern SHCLEXTSTATE g_ExtState;
    283283
    284 int shClSvcSetSource(PSHCLCLIENT pClient, SHCLSOURCE enmSource);
    285 
    286284void shClSvcMsgQueueReset(PSHCLCLIENT pClient);
    287285PSHCLCLIENTMSG shClSvcMsgAlloc(PSHCLCLIENT pClient, uint32_t uMsg, uint32_t cParms);
     
    302300int shClSvcClientWakeup(PSHCLCLIENT pClient);
    303301
    304 # ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    305 int shClSvcTransferModeSet(uint32_t fMode);
    306 int shClSvcTransferInit(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, PSHCLTRANSFER *ppTransfer);
    307 int shClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
    308 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest);
    309 bool shClSvcTransferMsgIsAllowed(uint32_t uMode, uint32_t uMsg);
    310 void shClSvcClientTransfersReset(PSHCLCLIENT pClient);
    311 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    312 
    313302/** @name Service functions, accessible by the backends.
    314303 * Locking is between the (host) service thread and the platform-dependent (window) thread.
     
    316305 */
    317306int ShClSvcReadDataFromGuestAsync(PSHCLCLIENT pClient, SHCLFORMATS fFormats, PSHCLEVENT *ppEvent);
     307int ShClSvcReadDataFromGuest(PSHCLCLIENT pClient, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb);
    318308int ShClSvcGuestDataSignal(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData);
    319309int ShClSvcHostReportFormats(PSHCLCLIENT pClient, SHCLFORMATS fFormats);
     
    451441 */
    452442/**
    453  * Called after a transfer got created.
     443 * Called before a transfer gets destroyed.
    454444 *
    455445 * @returns VBox status code.
    456446 * @param   pBackend            Shared Clipboard backend to use.
    457447 * @param   pClient             Shared Clipboard client context.
    458  * @param   pTransfer           Shared Clipboard transfer created.
    459  */
    460 int ShClBackendTransferCreate(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
    461 /**
    462  * Called before a transfer gets destroyed.
     448 * @param   pTransfer           Shared Clipboard transfer to destroy.
     449 */
     450int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     451/**
     452 * Called after a transfer status got processed.
    463453 *
    464454 * @returns VBox status code.
    465455 * @param   pBackend            Shared Clipboard backend to use.
    466456 * @param   pClient             Shared Clipboard client context.
    467  * @param   pTransfer           Shared Clipboard transfer to destroy.
    468  */
    469 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
    470 /**
    471  * Called when getting (determining) the transfer roots on the host side.
     457 * @param   pTransfer           Shared Clipboard transfer to process status for.
     458 * @param   enmSource           Transfer source which issues the reply.
     459 * @param   enmStatus           Transfer status.
     460 * @param   rcStatus            Status code (IPRT-style). Depends on \a enmStatus set.
     461 */
     462int ShClBackendTransferHandleStatusReply(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLSOURCE enmSource, SHCLTRANSFERSTATUS enmStatus, int rcStatus);
     463/**
     464 * Called when the guest wants to read the transfer roots.
    472465 *
    473466 * @returns VBox status code.
     
    476469 * @param   pTransfer           Shared Clipboard transfer to get roots for.
    477470 */
    478 int ShClBackendTransferGetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     471int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
    479472/** @} */
    480473#endif
     
    497490
    498491int shClSvcTransferIfaceRootsGet(PSHCLTXPROVIDERCTX pCtx, PSHCLLIST pRootList);
    499 int shClSvcTransferIfaceListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
    500 int shClSvcTransferIfaceListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList);
    501 int shClSvcTransferIfaceListHdrRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
    502 int shClSvcTransferIfaceListHdrWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
    503 int shClSvcTransferIfaceListEntryRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
    504 int shClSvcTransferIfaceListEntryWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
    505 
    506 int shClSvcTransferIfaceObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
     492int shClSvcTransferIfaceGHListOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
     493int shClSvcTransferIfaceGHListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList);
     494int shClSvcTransferIfaceGHListHdrRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
     495int shClSvcTransferIfaceHGListHdrWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
     496int shClSvcTransferIfaceGHListEntryRead(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
     497int shClSvcTransferIfaceHGListEntryWrite(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
     498
     499int shClSvcTransferIfaceGHObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
    507500                                PSHCLOBJHANDLE phObj);
    508 int shClSvcTransferIfaceObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj);
    509 int shClSvcTransferIfaceObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
     501int shClSvcTransferIfaceGHObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj);
     502int shClSvcTransferIfaceGHObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
    510503                                void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead);
    511 int shClSvcTransferIfaceObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
     504int shClSvcTransferIfaceHGObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
    512505                                 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten);
    513506/** @} */
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp

    r100291 r100367  
    6161*   Prototypes                                                                                                                   *
    6262*********************************************************************************************************************************/
    63 static int shClSvcTransferSetListOpen(uint32_t cParms, VBOXHGCMSVCPARM aParms[],
    64                                       uint64_t idCtx, PSHCLLISTOPENPARMS pOpenParms);
    65 static int shClSvcTransferSetListClose(uint32_t cParms, VBOXHGCMSVCPARM aParms[],
    66                                        uint64_t idCtx, SHCLLISTHANDLE hList);
    67 
    68 
    69 /*********************************************************************************************************************************
    70 *   Provider implementation                                                                                                      *
    71 *********************************************************************************************************************************/
    72 
    73 /**
    74  * Resets all transfers of a Shared Clipboard client.
    75  *
    76  * @param   pClient             Client to reset transfers for.
    77  */
    78 void shClSvcClientTransfersReset(PSHCLCLIENT pClient)
     63static int shClSvcTransferSendStatusAsyncInternal(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, int rcTransfer, PSHCLEVENT *ppEvent);
     64static int shClSvcTransferSetListOpen(uint32_t cParms, VBOXHGCMSVCPARM aParms[], uint64_t idCtx, PSHCLLISTOPENPARMS pOpenParms);
     65static int shClSvcTransferSetListClose(uint32_t cParms, VBOXHGCMSVCPARM aParms[], uint64_t idCtx, SHCLLISTHANDLE hList);
     66
     67
     68/**
     69 * Destroys all transfers of a Shared Clipboard client.
     70 *
     71 * @param   pClient             Client to destroy transfers for.
     72 */
     73void shClSvcTransferDestroyAll(PSHCLCLIENT pClient)
    7974{
    8075    if (!pClient)
     
    8378    LogFlowFuncEnter();
    8479
    85     /* Make sure to let the backend know that all transfers are getting destroyed. */
     80    /* Unregister and destroy all transfers.
     81     * Also make sure to let the backend know that all transfers are getting destroyed. */
    8682    uint32_t      uIdx = 0;
    8783    PSHCLTRANSFER pTransfer;
    8884    while ((pTransfer = ShClTransferCtxGetTransferByIndex(&pClient->Transfers.Ctx, uIdx++)))
    89         ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer);
    90 
    91     ShClTransferCtxDestroy(&pClient->Transfers.Ctx);
     85        ShClSvcTransferDestroy(pClient, pTransfer);
     86}
     87
     88/**
     89 * Reads a root list header from the guest, asynchronous version.
     90 *
     91 * @returns VBox status code.
     92 * @param   pClient             Client to read from.
     93 * @param   idTransfer          Transfer ID to read root list header for.
     94 * @param   ppEvent             Where to return the event to wait for.
     95 *                              Must be released by the caller with ShClEventRelease().
     96 */
     97int ShClSvcTransferGHRootListReadHdrAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, PSHCLEVENT *ppEvent)
     98{
     99    LogFlowFuncEnter();
     100
     101    int rc;
     102
     103    PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ,
     104                                             VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ);
     105    if (pMsgHdr)
     106    {
     107        PSHCLEVENT pEvent;
     108        rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     109        if (RT_SUCCESS(rc))
     110        {
     111            HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
     112                                                                        idTransfer, pEvent->idEvent));
     113            HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */);
     114
     115            shClSvcClientLock(pClient);
     116
     117            shClSvcMsgAdd(pClient, pMsgHdr, true /* fAppend */);
     118            rc = shClSvcClientWakeup(pClient);
     119
     120            shClSvcClientUnlock(pClient);
     121
     122            /* Remove event from list if caller did not request event handle or in case
     123             * of failure (in this case caller should not release event). */
     124            if (   RT_FAILURE(rc)
     125                || !ppEvent)
     126            {
     127                ShClEventRelease(pEvent);
     128                pEvent = NULL;
     129            }
     130            else if (ppEvent)
     131                *ppEvent = pEvent;
     132        }
     133        else
     134        {
     135            shClSvcMsgFree(pClient, pMsgHdr);
     136            rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
     137        }
     138    }
     139    else
     140        rc = VERR_NO_MEMORY;
     141
     142    LogFlowFuncLeaveRC(rc);
     143    return rc;
     144}
     145
     146/**
     147 * Reads a root list header from the guest.
     148 *
     149 * @returns VBox status code.
     150 * @param   pClient             Client to read from.
     151 * @param   idTransfer          Transfer ID to read root list header for.
     152 * @param   pHdr                Where to store the root list header on succeess.
     153 */
     154int ShClSvcTransferGHRootListReadHdr(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, PSHCLLISTHDR pHdr)
     155{
     156    PSHCLEVENT pEvent;
     157    int rc = ShClSvcTransferGHRootListReadHdrAsync(pClient, idTransfer, &pEvent);
     158    if (RT_SUCCESS(rc))
     159    {
     160        PSHCLEVENTPAYLOAD pPayload;
     161        rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     162        if (RT_SUCCESS(rc))
     163        {
     164            Assert(pPayload->cbData == sizeof(SHCLLISTHDR));
     165
     166            memcpy(pHdr, (PSHCLLISTHDR)pPayload->pvData, sizeof(SHCLLISTHDR));
     167
     168            LogFlowFunc(("cRoots=%RU32, fFeatures=0x%x\n", pHdr->cEntries, pHdr->fFeatures));
     169
     170            ShClPayloadFree(pPayload);
     171        }
     172
     173        ShClEventRelease(pEvent);
     174        pEvent = NULL;
     175    }
     176
     177    LogFlowFuncLeaveRC(rc);
     178    return rc;
     179}
     180
     181/**
     182 * Reads a root list entry from the guest, asynchronous version.
     183 *
     184 * @returns VBox status code.
     185 * @param   pClient             Client to read from.
     186 * @param   idTransfer          Transfer ID to read root list header for.
     187 * @param   idxEntry            Index of entry to read.
     188 * @param   ppEvent             Where to return the event to wait for.
     189 *                              Must be released by the caller with ShClEventRelease().
     190 */
     191int ShClSvcTransferGHRootListReadEntryAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint64_t idxEntry,
     192                                            PSHCLEVENT *ppEvent)
     193{
     194    LogFlowFuncEnter();
     195
     196    PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ,
     197                                               VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
     198
     199    PSHCLEVENT pEvent;
     200    int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     201    if (RT_SUCCESS(rc))
     202    {
     203        HGCMSvcSetU64(&pMsgEntry->aParms[0],
     204                      VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID, idTransfer, pEvent->idEvent));
     205        HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fFeatures */);
     206        HGCMSvcSetU64(&pMsgEntry->aParms[2], idxEntry /* uIndex */);
     207
     208        shClSvcClientLock(pClient);
     209
     210        shClSvcMsgAdd(pClient, pMsgEntry, true /* fAppend */);
     211        rc = shClSvcClientWakeup(pClient);
     212
     213        shClSvcClientUnlock(pClient);
     214
     215        /* Remove event from list if caller did not request event handle or in case
     216         * of failure (in this case caller should not release event). */
     217        if (   RT_FAILURE(rc)
     218            || !ppEvent)
     219        {
     220            ShClEventRelease(pEvent);
     221            pEvent = NULL;
     222        }
     223        else if (ppEvent)
     224            *ppEvent = pEvent;
     225    }
     226    else
     227        rc = VERR_NO_MEMORY;
     228
     229    LogFlowFuncLeave();
     230    return rc;
     231}
     232
     233/**
     234 * Reads a root list entry from the guest.
     235 *
     236 * @returns VBox status code.
     237 * @param   pClient             Client to read from.
     238 * @param   idTransfer          Transfer ID to read root list header for.
     239 * @param   idxEntry            Index of entry to read.
     240 * @param   ppListEntry         Where to return the allocated root list entry.
     241 */
     242int ShClSvcTransferGHRootListReadEntry(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint64_t idxEntry,
     243                                       PSHCLLISTENTRY *ppListEntry)
     244{
     245    AssertPtrReturn(ppListEntry, VERR_INVALID_POINTER);
     246
     247    PSHCLEVENT pEvent;
     248    int rc = ShClSvcTransferGHRootListReadEntryAsync(pClient, idTransfer, idxEntry, &pEvent);
     249    if (RT_SUCCESS(rc))
     250    {
     251        PSHCLEVENTPAYLOAD pPayload;
     252        rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     253        if (RT_SUCCESS(rc))
     254        {
     255            *ppListEntry = (PSHCLLISTENTRY)pPayload->pvData; /* ppLisEntry own pPayload-pvData now. */
     256
     257        }
     258
     259        ShClEventRelease(pEvent);
     260        pEvent = NULL;
     261    }
     262
     263    LogFlowFuncLeaveRC(rc);
     264    return rc;
    92265}
    93266
     
    98271
    99272/** @copydoc SHCLTXPROVIDERIFACE::pfnRootListRead */
    100 DECLCALLBACK(int) shClSvcTransferIfaceRootListRead(PSHCLTXPROVIDERCTX pCtx)
     273DECLCALLBACK(int) shClSvcTransferIfaceGHRootListRead(PSHCLTXPROVIDERCTX pCtx)
    101274{
    102275    LogFlowFuncEnter();
     
    105278    AssertPtr(pClient);
    106279
    107     int rc;
    108 
    109     PSHCLCLIENTMSG pMsgHdr = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ,
    110                                              VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ);
    111     if (pMsgHdr)
    112     {
    113         PSHCLEVENT pEvent;
    114         rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
    115         if (RT_SUCCESS(rc))
    116         {
    117             HGCMSvcSetU64(&pMsgHdr->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    118                                                                         pCtx->pTransfer->State.uID, pEvent->idEvent));
    119             HGCMSvcSetU32(&pMsgHdr->aParms[1], 0 /* fRoots */);
    120 
    121             shClSvcClientLock(pClient);
    122 
    123             shClSvcMsgAdd(pClient, pMsgHdr, true /* fAppend */);
    124             rc = shClSvcClientWakeup(pClient);
    125 
    126             shClSvcClientUnlock(pClient);
    127 
     280    SHCLTRANSFERID const idTransfer = ShClTransferGetID(pCtx->pTransfer);
     281
     282    SHCLLISTHDR Hdr;
     283    int rc = ShClSvcTransferGHRootListReadHdr(pClient, idTransfer, &Hdr);
     284    if (RT_SUCCESS(rc))
     285    {
     286        for (uint64_t i = 0; i < Hdr.cEntries; i++)
     287        {
     288            PSHCLLISTENTRY pEntry;
     289            rc = ShClSvcTransferGHRootListReadEntry(pClient, idTransfer, i, &pEntry);
    128290            if (RT_SUCCESS(rc))
    129             {
    130                 PSHCLEVENTPAYLOAD pPayloadHdr;
    131                 rc = ShClEventWait(pEvent, pCtx->pTransfer->uTimeoutMs, &pPayloadHdr);
    132                 if (RT_SUCCESS(rc))
    133                 {
    134                     PSHCLLISTHDR pRootListHdr = (PSHCLLISTHDR)pPayloadHdr->pvData;
    135                     Assert(pPayloadHdr->cbData == sizeof(SHCLLISTHDR));
    136 
    137                     LogFlowFunc(("cRoots=%RU32, fFeatures=0x%x\n", pRootListHdr->cEntries, pRootListHdr->fFeatures));
    138 
    139                     for (uint32_t i = 0; i < pRootListHdr->cEntries; i++)
    140                     {
    141                         PSHCLCLIENTMSG pMsgEntry = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ,
    142                                                                    VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ);
    143 
    144                         PSHCLEVENT pEventRootEntry;
    145                         rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEventRootEntry);
    146                         if (RT_SUCCESS(rc))
    147                         {
    148                             HGCMSvcSetU64(&pMsgEntry->aParms[0],
    149                                           VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uClientID,
    150                                                                    pCtx->pTransfer->State.uID, pEventRootEntry->idEvent));
    151                             HGCMSvcSetU32(&pMsgEntry->aParms[1], 0 /* fFeatures */);
    152                             HGCMSvcSetU32(&pMsgEntry->aParms[2], i /* uIndex */);
    153 
    154                             shClSvcClientLock(pClient);
    155                             shClSvcMsgAdd(pClient, pMsgEntry, true /* fAppend */);
    156                             shClSvcClientUnlock(pClient);
    157 
    158                             PSHCLEVENTPAYLOAD pPayloadEntry;
    159                             rc = ShClEventWait(pEventRootEntry, pCtx->pTransfer->uTimeoutMs, &pPayloadEntry);
    160                             if (RT_FAILURE(rc))
    161                                 break;
    162 
    163                             PSHCLLISTENTRY pRootListEntry = (PSHCLLISTENTRY)pPayloadEntry->pvData;
    164                             Assert(pPayloadEntry->cbData == sizeof(SHCLLISTENTRY));
    165 
    166                             rc = ShClTransferListAddEntry(&pCtx->pTransfer->lstRoots, pRootListEntry, true /* fAppend */);
    167                             if (RT_FAILURE(rc))
    168                                 ShClPayloadFree(pPayloadEntry);
    169                             /* else don't call ShClPayloadFree() here, as pRootList own the data now. */
    170                             pPayloadEntry = NULL;
    171 
    172                             ShClEventRelease(pEventRootEntry);
    173                             pEventRootEntry = NULL;
    174                         }
    175                         else
    176                         {
    177                             shClSvcMsgFree(pClient, pMsgEntry);
    178                             rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
    179                         }
    180 
    181                         if (RT_FAILURE(rc))
    182                             break;
    183                     }
    184 
    185                     ShClPayloadFree(pPayloadHdr);
    186                 }
    187             }
    188 
    189             ShClEventRelease(pEvent);
    190         }
    191         else
    192         {
    193             shClSvcMsgFree(pClient, pMsgHdr);
    194             rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
    195         }
    196     }
    197     else
    198         rc = VERR_NO_MEMORY;
     291                rc = ShClTransferListAddEntry(&pCtx->pTransfer->lstRoots, pEntry, true /* fAppend */);
     292
     293            if (RT_FAILURE(rc))
     294                break;
     295        }
     296    }
    199297
    200298    LogFlowFuncLeave();
     
    203301
    204302/** @copydoc SHCLTXPROVIDERIFACE::pfnListOpen */
    205 DECLCALLBACK(int) shClSvcTransferIfaceListOpen(PSHCLTXPROVIDERCTX pCtx,
    206                                                PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList)
     303DECLCALLBACK(int) shClSvcTransferIfaceGHListOpen(PSHCLTXPROVIDERCTX pCtx,
     304                                                 PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList)
    207305{
    208306    LogFlowFuncEnter();
     
    245343                        AssertPtr(pReply);
    246344
    247                         Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN);
     345                        Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN);
    248346
    249347                        LogFlowFunc(("hList=%RU64\n", pReply->u.ListOpen.uHandle));
     
    272370
    273371/** @copydoc SHCLTXPROVIDERIFACE::pfnListClose */
    274 DECLCALLBACK(int) shClSvcTransferIfaceListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
     372DECLCALLBACK(int) shClSvcTransferIfaceGHListClose(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList)
    275373{
    276374    LogFlowFuncEnter();
     
    327425
    328426/** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrRead */
    329 DECLCALLBACK(int) shClSvcTransferIfaceListHdrRead(PSHCLTXPROVIDERCTX pCtx,
    330                                                   SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
     427DECLCALLBACK(int) shClSvcTransferIfaceGHListHdrRead(PSHCLTXPROVIDERCTX pCtx,
     428                                                    SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
    331429{
    332430    LogFlowFuncEnter();
     
    387485
    388486/** @copydoc SHCLTXPROVIDERIFACE::pfnListHdrWrite */
    389 DECLCALLBACK(int) shClSvcTransferIfaceListHdrWrite(PSHCLTXPROVIDERCTX pCtx,
    390                                                    SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
     487DECLCALLBACK(int) shClSvcTransferIfaceHGListHdrWrite(PSHCLTXPROVIDERCTX pCtx,
     488                                                     SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr)
    391489{
    392490    RT_NOREF(pCtx, hList, pListHdr);
     
    398496
    399497/** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryRead */
    400 DECLCALLBACK(int) shClSvcTransferIfaceListEntryRead(PSHCLTXPROVIDERCTX pCtx,
    401                                                     SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)
     498DECLCALLBACK(int) shClSvcTransferIfaceGHListEntryRead(PSHCLTXPROVIDERCTX pCtx,
     499                                                      SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)
    402500{
    403501    LogFlowFuncEnter();
     
    458556
    459557/** @copydoc SHCLTXPROVIDERIFACE::pfnListEntryWrite */
    460 DECLCALLBACK(int) shClSvcTransferIfaceListEntryWrite(PSHCLTXPROVIDERCTX pCtx,
    461                                                      SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)
     558DECLCALLBACK(int) shClSvcTransferIfaceHGListEntryWrite(PSHCLTXPROVIDERCTX pCtx,
     559                                                       SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry)
    462560{
    463561    RT_NOREF(pCtx, hList, pListEntry);
     
    469567
    470568/** @copydoc SHCLTXPROVIDERIFACE::pfnObjOpen */
    471 DECLCALLBACK(int) shClSvcTransferIfaceObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
     569DECLCALLBACK(int) shClSvcTransferIfaceGHObjOpen(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj)
    472570{
    473571    LogFlowFuncEnter();
     
    514612                    AssertPtr(pReply);
    515613
    516                     Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN);
     614                    Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN);
    517615
    518616                    LogFlowFunc(("hObj=%RU64\n", pReply->u.ObjOpen.uHandle));
     
    540638
    541639/** @copydoc SHCLTXPROVIDERIFACE::pfnObjClose */
    542 DECLCALLBACK(int) shClSvcTransferIfaceObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
     640DECLCALLBACK(int) shClSvcTransferIfaceGHObjClose(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj)
    543641{
    544642    LogFlowFuncEnter();
     
    579677                    AssertPtr(pReply);
    580678
    581                     Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE);
     679                    Assert(pReply->uType == VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE);
    582680
    583681                    LogFlowFunc(("hObj=%RU64\n", pReply->u.ObjClose.uHandle));
     
    603701
    604702/** @copydoc SHCLTXPROVIDERIFACE::pfnObjRead */
    605 DECLCALLBACK(int) shClSvcTransferIfaceObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
    606                                               void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
     703DECLCALLBACK(int) shClSvcTransferIfaceGHObjRead(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
     704                                                void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
    607705{
    608706    LogFlowFuncEnter();
     
    672770
    673771/** @copydoc SHCLTXPROVIDERIFACE::pfnObjWrite */
    674 DECLCALLBACK(int) shClSvcTransferIfaceObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
    675                                                void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
     772DECLCALLBACK(int) shClSvcTransferIfaceHGObjWrite(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
     773                                                 void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
    676774{
    677775    LogFlowFuncEnter();
     
    851949            switch (pReply->uType)
    852950            {
    853                 case VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS:
     951                case VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS:
    854952                {
    855953                    if (cParms > idxParm)
     
    860958                }
    861959
    862                 case VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN:
     960                case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN:
    863961                {
    864962                    if (cParms > idxParm)
     
    869967                }
    870968
    871                 case VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE:
     969                case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE:
    872970                {
    873971                    if (cParms > idxParm)
     
    878976                }
    879977
    880                 case VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN:
     978                case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN:
    881979                {
    882980                    if (cParms > idxParm)
     
    887985                }
    888986
    889                 case VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE:
     987                case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE:
    890988                {
    891989                    if (cParms > idxParm)
     
    12491347 * @returns VBox status code.
    12501348 * @param   pClient             Pointer to associated client.
    1251  * @param   pTransfer           Pointer to transfer to handle guest reply for.
     1349 * @param   idTransfer          Transfer ID supplied from the guest.
    12521350 * @param   cParms              Number of function parameters supplied.
    12531351 * @param   aParms              Array function parameters supplied.
    12541352 */
    1255 static int shClSvcTransferHandleReply(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer,
    1256                                       uint32_t cParms, VBOXHGCMSVCPARM aParms[])
    1257 {
    1258     RT_NOREF(pClient, pTransfer);
    1259 
     1353static int shClSvcTransferHandleReply(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, uint32_t cParms, VBOXHGCMSVCPARM aParms[])
     1354{
    12601355    int rc;
     1356
     1357    PSHCLTRANSFER pTransfer = NULL;
    12611358
    12621359    uint32_t   cbReply = sizeof(SHCLREPLY);
     
    12671364        if (RT_SUCCESS(rc))
    12681365        {
     1366            if (   pReply->uType                    == VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS
     1367                && pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_REQUESTED)
     1368            {
     1369                /* SHCLTRANSFERSTATUS_REQUESTED is special, as it doesn't provide a transfer ID. */
     1370            }
     1371            else /* Everything else needs a valid transfer ID. */
     1372            {
     1373                pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, idTransfer);
     1374                if (!pTransfer)
     1375                {
     1376                    LogRel2(("Shared Clipboard: Transfer with ID %RU16 not found\n", idTransfer));
     1377                    rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND;
     1378                }
     1379            }
     1380
     1381            if (RT_FAILURE(rc))
     1382            {
     1383                RTMemFree(pReply);
     1384                pReply = NULL;
     1385
     1386                return rc;
     1387            }
     1388
    12691389            PSHCLEVENTPAYLOAD pPayload
    12701390                = (PSHCLEVENTPAYLOAD)RTMemAlloc(sizeof(SHCLEVENTPAYLOAD));
     
    12761396                switch (pReply->uType)
    12771397                {
    1278                     case VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS:
     1398                    case VBOX_SHCL_TX_REPLYMSGTYPE_TRANSFER_STATUS:
    12791399                    {
    1280                         LogRel(("Shared Clipboard: Guest reported status %s for transfer %RU32\n",
    1281                                 ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), pTransfer->State.uID));
     1400                        /* SHCLTRANSFERSTATUS_REQUESTED is special, as it doesn't provide a transfer ID. */
     1401                        if (SHCLTRANSFERSTATUS_REQUESTED == pReply->u.TransferStatus.uStatus)
     1402                        {
     1403                            LogRel2(("Shared Clipboard: Guest requested a new host -> guest transfer\n"));
     1404                        }
     1405                        else
     1406                            LogRel2(("Shared Clipboard: Guest reported status %s for transfer %RU32\n",
     1407                                     ShClTransferStatusToStr(pReply->u.TransferStatus.uStatus), idTransfer));
    12821408
    12831409                        switch (pReply->u.TransferStatus.uStatus)
    12841410                        {
    1285                             case SHCLTRANSFERSTATUS_INITIALIZED: /* Initialized -> Started */
    1286                                 rc = shClSvcTransferStart(pClient, pTransfer);
     1411                            case SHCLTRANSFERSTATUS_REQUESTED: /* Guest requests a H->G transfer. */
     1412                            {
     1413                                uint32_t const uMode = ShClSvcGetMode();
     1414                                if (   uMode == VBOX_SHCL_MODE_HOST_TO_GUEST
     1415                                    || uMode == VBOX_SHCL_MODE_BIDIRECTIONAL)
     1416                                {
     1417                                    /* We only create (but not initialize) the transfer here. This is the most lightweight form of
     1418                                     * having a pending transfer around. Report back the new transfer ID to the guest then. */
     1419                                    if (pTransfer == NULL) /* Must not exist yet. */
     1420                                    {
     1421                                        rc = ShClSvcTransferCreate(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,
     1422                                                                   NIL_SHCLTRANSFERID /* Creates a new transfer ID */,
     1423                                                                   &pTransfer);
     1424                                        if (RT_SUCCESS(rc))
     1425                                        {
     1426                                            shClSvcClientLock(pClient);
     1427
     1428                                            rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     1429                                                                                        SHCLTRANSFERSTATUS_REQUESTED, VINF_SUCCESS,
     1430                                                                                        NULL);
     1431                                            shClSvcClientUnlock(pClient);
     1432                                        }
     1433                                    }
     1434                                    else
     1435                                        rc = VERR_WRONG_ORDER;
     1436                                }
     1437                                else
     1438                                    rc = VERR_INVALID_PARAMETER;
     1439
    12871440                                break;
    1288 
    1289                             case SHCLTRANSFERSTATUS_STARTED:
     1441                            }
     1442
     1443                            case SHCLTRANSFERSTATUS_INITIALIZED: /* Guest reports the transfer as being initialized. */
     1444                            {
     1445                                switch (ShClTransferGetDir(pTransfer))
     1446                                {
     1447                                    case SHCLTRANSFERDIR_FROM_REMOTE: /* G->H */
     1448                                        /* Already done locally when creating the transfer. */
     1449                                        break;
     1450
     1451                                    case SHCLTRANSFERDIR_TO_REMOTE:   /* H->G */
     1452                                    {
     1453                                        /* Initialize the transfer on the host side. */
     1454                                        rc = ShClSvcTransferInit(pClient, pTransfer);
     1455                                        break;
     1456                                    }
     1457
     1458                                    default:
     1459                                        AssertFailed();
     1460                                        break;
     1461                                }
     1462
    12901463                                break;
     1464                            }
     1465                            case SHCLTRANSFERSTATUS_STARTED:     /* Guest has started the transfer on its side. */
     1466                            {
     1467                                /* We only need to start for H->G transfers here.
     1468                                 * For G->H transfers we start this as soon as the host clipboard requests data. */
     1469                                if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_TO_REMOTE)
     1470                                {
     1471                                    /* Start the transfer on the host side. */
     1472                                    rc = ShClSvcTransferStart(pClient, pTransfer);
     1473                                }
     1474                                break;
     1475                            }
     1476
     1477                            case SHCLTRANSFERSTATUS_CANCELED:
     1478                                RT_FALL_THROUGH();
     1479                            case SHCLTRANSFERSTATUS_KILLED:
     1480                            {
     1481                                LogRel(("Shared Clipboard: Guest has %s transfer %RU32\n",
     1482                                        pReply->uType == SHCLTRANSFERSTATUS_CANCELED ? "canceled" : "killed", pTransfer->State.uID));
     1483
     1484                                rc = ShClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */);
     1485
     1486                                /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host
     1487                                 * so that we don't risk of having stale transfers here. */
     1488                                ShClSvcTransferDestroy(pClient, pTransfer);
     1489                                pTransfer = NULL;
     1490                                break;
     1491                            }
     1492
     1493                            case SHCLTRANSFERSTATUS_STOPPED:
     1494                            {
     1495                                LogRel(("Shared Clipboard: Guest has stopped transfer %RU32\n", pTransfer->State.uID));
     1496
     1497                                rc = ShClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */);
     1498                                break;
     1499                            }
    12911500
    12921501                            case SHCLTRANSFERSTATUS_ERROR:
     
    12941503                                LogRel(("Shared Clipboard: Guest reported error %Rrc for transfer %RU32\n",
    12951504                                        pReply->rc, pTransfer->State.uID));
    1296 
    1297                                 rc = shClSvcTransferStop(pClient, pTransfer, false /* fWaitForGuest */);
     1505                                RT_FALL_THROUGH();
     1506                            }
     1507                            default:
     1508                            {
     1509                                /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host
     1510                                 * so that we don't risk of having stale transfers here. */
     1511                                ShClSvcTransferDestroy(pClient, pTransfer);
     1512                                pTransfer = NULL;
    12981513                                break;
    12991514                            }
    1300 
    1301                             default:
    1302                                 rc = shClSvcTransferStop(pClient, pTransfer, true /* fWaitForGuest */);
    1303                                 break;
    13041515                        }
     1516
     1517                        /* Tell the backend. */
     1518                        int rc2 = ShClBackendTransferHandleStatusReply(pClient->pBackend, pClient, pTransfer,
     1519                                                                       SHCLSOURCE_REMOTE, pReply->u.TransferStatus.uStatus,
     1520                                                                       pReply->rc);
     1521                        if (RT_SUCCESS(rc))
     1522                            rc = rc2;
    13051523
    13061524                        RT_FALL_THROUGH();
    13071525                    }
    1308                     case VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN:
     1526                    case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_OPEN:
    13091527                        RT_FALL_THROUGH();
    1310                     case VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE:
     1528                    case VBOX_SHCL_TX_REPLYMSGTYPE_LIST_CLOSE:
    13111529                        RT_FALL_THROUGH();
    1312                     case VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN:
     1530                    case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_OPEN:
    13131531                        RT_FALL_THROUGH();
    1314                     case VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE:
     1532                    case VBOX_SHCL_TX_REPLYMSGTYPE_OBJ_CLOSE:
    13151533                    {
    13161534                        uint64_t uCID;
     
    13911609    int rc = VERR_INVALID_PARAMETER; /* Play safe by default. */
    13921610
     1611    if (cParms < 1)
     1612        return rc;
     1613    ASSERT_GUEST_RETURN(aParms[0].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE);
     1614
     1615    uint64_t uCID  = 0; /* Context ID */
     1616    rc = HGCMSvcGetU64(&aParms[0], &uCID);
     1617    if (RT_FAILURE(rc))
     1618        return rc;
     1619
     1620    const SHCLTRANSFERID idTransfer = VBOX_SHCL_CONTEXTID_GET_TRANSFER(uCID);
     1621
    13931622    /*
    13941623     * Pre-check: For certain messages we need to make sure that a (right) transfer is present.
    13951624     */
    1396     uint64_t      uCID      = 0; /* Context ID */
    13971625    PSHCLTRANSFER pTransfer = NULL;
    1398 
    1399     shClSvcClientLock(pClient);
    1400     ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n",
    1401                                                           pClient->State.uClientID), VERR_RESOURCE_BUSY);
    1402     shClSvcClientUnlock(pClient);
    1403 
    14041626    switch (u32Function)
    14051627    {
     1628        case VBOX_SHCL_GUEST_FN_REPLY:
     1629            /* Function does its own lookup. */
     1630            break;
     1631
    14061632        default:
    14071633        {
    1408             if (!ShClTransferCtxGetTotalTransfers(&pClient->Transfers.Ctx))
    1409             {
    1410                 LogFunc(("No transfers found\n"));
    1411                 rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND;
    1412                 break;
    1413             }
    1414 
    1415             if (cParms < 1)
    1416                 break;
    1417 
    1418             ASSERT_GUEST_RETURN(aParms[0].type == VBOX_HGCM_SVC_PARM_64BIT, VERR_WRONG_PARAMETER_TYPE);
    1419 
    1420             rc = HGCMSvcGetU64(&aParms[0], &uCID);
    1421             if (RT_FAILURE(rc))
    1422                 break;
    1423 
    1424             const SHCLTRANSFERID uTransferID = VBOX_SHCL_CONTEXTID_GET_TRANSFER(uCID);
    1425 
    1426             pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, uTransferID);
     1634            pTransfer = ShClTransferCtxGetTransferById(&pClient->Transfers.Ctx, idTransfer);
    14271635            if (!pTransfer)
    14281636            {
    1429                 LogFunc(("Transfer with ID %RU16 not found\n", uTransferID));
     1637                LogRel(("Shared Clipboard: Transfer with ID %RU16 not found\n", idTransfer));
    14301638                rc = VERR_SHCLPB_TRANSFER_ID_NOT_FOUND;
    14311639            }
     
    14431651        case VBOX_SHCL_GUEST_FN_REPLY:
    14441652        {
    1445             rc = shClSvcTransferHandleReply(pClient, pTransfer, cParms, aParms);
     1653            rc = shClSvcTransferHandleReply(pClient, idTransfer, cParms, aParms);
    14461654            break;
    14471655        }
     
    14581666                && ShClTransferGetDir(pTransfer)    == SHCLTRANSFERDIR_TO_REMOTE)
    14591667            {
    1460                 /* Get roots if this is a local write transfer (host -> guest). */
    1461                 rc = ShClBackendTransferGetRoots(pClient->pBackend, pClient, pTransfer);
     1668                rc = ShClBackendTransferHGRootListRead(pClient->pBackend, pClient, pTransfer);
     1669                if (RT_FAILURE(rc))
     1670                    break;
    14621671            }
    14631672            else
     
    14731682            HGCMSvcSetU32(&aParms[1], rootListHdr.fFeatures);
    14741683            HGCMSvcSetU64(&aParms[2], rootListHdr.cEntries);
    1475 
    1476             rc = VINF_SUCCESS;
    14771684            break;
    14781685        }
     
    18302037    }
    18312038
     2039    /* If anything wrong has happened, make sure to unregister the transfer again (if not done already) and tell the guest. */
     2040    if (   RT_FAILURE(rc)
     2041        && pTransfer)
     2042    {
     2043        shClSvcClientLock(pClient);
     2044
     2045        /* Let the guest know. */
     2046        int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     2047                                                         SHCLTRANSFERSTATUS_ERROR, rc, NULL /* ppEvent */);
     2048        AssertRC(rc2);
     2049
     2050        ShClSvcTransferDestroy(pClient, pTransfer);
     2051
     2052        shClSvcClientUnlock(pClient);
     2053    }
     2054
    18322055    LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->State.uClientID, rc));
    18332056    return rc;
     
    18792102            break;
    18802103    }
     2104
     2105    LogFlowFuncLeaveRC(rc);
     2106    return rc;
     2107}
     2108
     2109/**
     2110 * Reports a transfer status to the guest.
     2111 *
     2112 * @returns VBox status code.
     2113 * @param   pClient             Client that owns the transfer.
     2114 * @param   idTransfer          Transfer ID to report status for.
     2115 * @param   enmDir              Transfer direction to report status for.
     2116 * @param   uStatus             Status to report.
     2117 * @param   rcTransfer          Result code to report. Optional and depending on status.
     2118 * @param   ppEvent             Where to return the wait event on success. Optional.
     2119 *                              Must be released by the caller with ShClEventRelease().
     2120 *
     2121 * @note    Caller must enter the client's critical section.
     2122 */
     2123static int shClSvcTransferSendStatusExAsync(PSHCLCLIENT pClient, SHCLTRANSFERID idTransfer, SHCLTRANSFERDIR enmDir, SHCLTRANSFERSTATUS uStatus,
     2124                                            int rcTransfer, PSHCLEVENT *ppEvent)
     2125{
     2126    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
     2127    AssertReturn(idTransfer != NIL_SHCLTRANSFERID, VERR_INVALID_PARAMETER);
     2128    /* ppEvent is optional. */
     2129
     2130    PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,
     2131                                                  VBOX_SHCL_CPARMS_TRANSFER_STATUS);
     2132    if (!pMsgReadData)
     2133        return VERR_NO_MEMORY;
     2134
     2135    PSHCLEVENT pEvent;
     2136    int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
     2137    if (RT_SUCCESS(rc))
     2138    {
     2139        HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID, idTransfer, pEvent->idEvent));
     2140        HGCMSvcSetU32(&pMsgReadData->aParms[1], enmDir);
     2141        HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus);
     2142        HGCMSvcSetU32(&pMsgReadData->aParms[3], (uint32_t)rcTransfer); /** @todo uint32_t vs. int. */
     2143        HGCMSvcSetU32(&pMsgReadData->aParms[4], 0 /* fFlags, unused */);
     2144
     2145        shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */);
     2146
     2147        rc = shClSvcClientWakeup(pClient);
     2148        if (RT_SUCCESS(rc))
     2149        {
     2150            LogRel2(("Shared Clipboard: Reported status %s (rc=%Rrc) of transfer %RU32 to guest\n",
     2151                     ShClTransferStatusToStr(uStatus), rcTransfer, idTransfer));
     2152
     2153            if (ppEvent)
     2154            {
     2155                *ppEvent = pEvent; /* Takes ownership. */
     2156            }
     2157            else /* If event is not consumed by the caller, release the event again. */
     2158                ShClEventRelease(pEvent);
     2159        }
     2160        else
     2161            ShClEventRelease(pEvent);
     2162    }
     2163    else
     2164        rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
     2165
     2166    if (RT_FAILURE(rc))
     2167        LogRel(("Shared Clipboard: Reporting status %s (%Rrc) for transfer %RU32 to guest failed with %Rrc\n",
     2168                ShClTransferStatusToStr(uStatus), rcTransfer, idTransfer, rc));
    18812169
    18822170    LogFlowFuncLeaveRC(rc);
     
    18952183 *                              Must be released by the caller with ShClEventRelease().
    18962184 *
    1897  * @note    Caller must enter critical section.
    1898  */
    1899 int shClSvcTransferSendStatus(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus,
    1900                               int rcTransfer, PSHCLEVENT *ppEvent)
     2185 * @note    Caller must enter the client's critical section.
     2186 */
     2187static int shClSvcTransferSendStatusAsyncInternal(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus,
     2188                                                  int rcTransfer, PSHCLEVENT *ppEvent)
    19012189{
    19022190    AssertPtrReturn(pClient,   VERR_INVALID_POINTER);
     
    19042192    /* ppEvent is optional. */
    19052193
    1906     PSHCLCLIENTMSG pMsgReadData = shClSvcMsgAlloc(pClient, VBOX_SHCL_HOST_MSG_TRANSFER_STATUS,
    1907                                                   VBOX_SHCL_CPARMS_TRANSFER_STATUS);
    1908     if (!pMsgReadData)
    1909         return VERR_NO_MEMORY;
    1910 
    1911     PSHCLEVENT pEvent;
    1912     int rc = ShClEventSourceGenerateAndRegisterEvent(&pClient->EventSrc, &pEvent);
    1913     if (RT_SUCCESS(rc))
    1914     {
    1915         HGCMSvcSetU64(&pMsgReadData->aParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
    1916                                                                          pTransfer->State.uID, pEvent->idEvent));
    1917         HGCMSvcSetU32(&pMsgReadData->aParms[1], pTransfer->State.enmDir);
    1918         HGCMSvcSetU32(&pMsgReadData->aParms[2], uStatus);
    1919         HGCMSvcSetU32(&pMsgReadData->aParms[3], (uint32_t)rcTransfer); /** @todo uint32_t vs. int. */
    1920         HGCMSvcSetU32(&pMsgReadData->aParms[4], 0 /* fFlags, unused */);
    1921 
    1922         shClSvcMsgAdd(pClient, pMsgReadData, true /* fAppend */);
    1923 
    1924         rc = shClSvcClientWakeup(pClient);
    1925         if (RT_SUCCESS(rc))
    1926         {
    1927             LogRel2(("Shared Clipboard: Reported status %s (rc=%Rrc) of transfer %RU32 to guest\n",
    1928                      ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID));
    1929 
    1930             if (ppEvent)
    1931             {
    1932                 *ppEvent = pEvent; /* Takes ownership. */
    1933             }
    1934             else /* If event is not consumed by the caller, release the event again. */
    1935                 ShClEventRelease(pEvent);
    1936         }
    1937         else
    1938             ShClEventRelease(pEvent);
    1939     }
    1940     else
    1941         rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
    1942 
    1943     if (RT_FAILURE(rc))
    1944         LogRel(("Shared Clipboard: Reporting status %s (%Rrc) for transfer %RU32 to guest failed with %Rrc\n",
    1945                 ShClTransferStatusToStr(uStatus), rcTransfer, pTransfer->State.uID, rc));
    1946 
    1947     LogFlowFuncLeaveRC(rc);
    1948     return rc;
    1949 }
    1950 
    1951 /**
    1952  * Cleans up (unregisters and destroys) all transfers not in the 'started' state (anymore).
     2194   return shClSvcTransferSendStatusExAsync(pClient, ShClTransferGetID(pTransfer), ShClTransferGetDir(pTransfer),
     2195                                           uStatus, rcTransfer, ppEvent);
     2196}
     2197
     2198int ShClSvcTransferSendStatusAsync(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus,
     2199                                   int rcTransfer, PSHCLEVENT *ppEvent)
     2200{
     2201    shClSvcClientLock(pClient);
     2202
     2203    int rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer, uStatus, rcTransfer, ppEvent);
     2204
     2205    shClSvcClientUnlock(pClient);
     2206
     2207    return rc;
     2208}
     2209
     2210/**
     2211 * Cleans up (unregisters and destroys) all transfers not in started state (anymore).
    19532212 *
    19542213 * @param   pClient             Client to clean up transfers for.
     
    19562215 * @note    Caller needs to take the critical section.
    19572216 */
    1958 void shClSvcTransferCleanupAllUnused(PSHCLCLIENT pClient)
    1959 {
     2217static void shClSvcTransferCleanupAllUnused(PSHCLCLIENT pClient)
     2218{
     2219    Assert(RTCritSectIsOwner(&pClient->CritSect));
     2220
    19602221    LogFlowFuncEnter();
    19612222
    19622223    PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx;
    19632224
    1964     /* Remove all transfers which are not in a running state (e.g. only announced). */
    19652225    PSHCLTRANSFER pTransfer, pTransferNext;
    19662226    RTListForEachSafe(&pTxCtx->List, pTransfer, pTransferNext, SHCLTRANSFER, Node)
    19672227    {
    1968         if (ShClTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED)
     2228        SHCLTRANSFERSTATUS const enmSts = ShClTransferGetStatus(pTransfer);
     2229        if (enmSts != SHCLTRANSFERSTATUS_STARTED)
    19692230        {
    19702231            /* Let the guest know. */
    1971             int rc2 = shClSvcTransferSendStatus(pClient, pTransfer,
    1972                                                 SHCLTRANSFERSTATUS_UNINITIALIZED, VINF_SUCCESS, NULL /* ppEvent */);
     2232            int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     2233                                                             SHCLTRANSFERSTATUS_UNINITIALIZED, VINF_SUCCESS, NULL /* ppEvent */);
    19732234            AssertRC(rc2);
    19742235
    1975             ShClTransferCtxTransferUnregisterById(pTxCtx, pTransfer->State.uID);
     2236            ShClTransferCtxUnregisterById(pTxCtx, pTransfer->State.uID);
    19762237
    19772238            ShClTransferDestroy(pTransfer);
     
    19842245
    19852246/**
    1986  * Initializes a new transfer and sends the status to the guest.
    1987  *
    1988  * @note Assumes that the client's critical section is taken.
     2247 * Creates a new transfer on the host.
    19892248 *
    19902249 * @returns VBox status code.
    19912250 * @param   pClient             Client that owns the transfer.
    1992  * @param   enmDir              Transfer direction to start.
    1993  * @param   enmSource           Transfer source to start.
    1994  * @param   ppTransfer          Where to return the created transfer on success. Optional.
    1995  */
    1996 int shClSvcTransferInit(PSHCLCLIENT pClient,
    1997                         SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource,
    1998                         PSHCLTRANSFER *ppTransfer)
    1999 {
    2000     Assert(RTCritSectIsOwner(&pClient->CritSect));
    2001 
     2251 * @param   enmDir              Transfer direction to create.
     2252 * @param   enmSource           Transfer source to create.
     2253 * @param   idTransfer          Transfer ID to use for creation.
     2254 *                              If set to NIL_SHCLTRANSFERID, a new transfer ID will be created.
     2255 * @param   ppTransfer          Where to return the created transfer on success. Optional and can be NULL.
     2256 */
     2257int ShClSvcTransferCreate(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, SHCLTRANSFERID idTransfer, PSHCLTRANSFER *ppTransfer)
     2258{
    20022259    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
    20032260    /* ppTransfer is optional. */
     
    20052262    LogFlowFuncEnter();
    20062263
     2264    shClSvcClientLock(pClient);
     2265
     2266    /* When creating a new transfer, this is a good time to clean up old stuff we don't need anymore. */
    20072267    shClSvcTransferCleanupAllUnused(pClient);
    20082268
     2269    PSHCLTRANSFER pTransfer;
     2270    int rc = ShClTransferCreate(enmDir, enmSource, &pTransfer);
     2271    if (RT_SUCCESS(rc))
     2272    {
     2273        if (idTransfer == NIL_SHCLTRANSFERID)
     2274            rc = ShClTransferCtxRegister(&pClient->Transfers.Ctx, pTransfer, &idTransfer);
     2275        else
     2276            rc = ShClTransferCtxRegisterById(&pClient->Transfers.Ctx, pTransfer, idTransfer);
     2277        if (RT_SUCCESS(rc))
     2278        {
     2279            if (ppTransfer)
     2280                *ppTransfer = pTransfer;
     2281        }
     2282    }
     2283
     2284    shClSvcClientUnlock(pClient);
     2285
     2286    if (RT_FAILURE(rc))
     2287    {
     2288        ShClTransferDestroy(pTransfer);
     2289
     2290        RTMemFree(pTransfer);
     2291        pTransfer = NULL;
     2292    }
     2293
     2294    if (RT_FAILURE(rc))
     2295       LogRel(("Shared Clipboard: Creating transfer failed with %Rrc\n", rc));
     2296
     2297    LogFlowFuncLeaveRC(rc);
     2298    return rc;
     2299}
     2300
     2301/**
     2302 * Destroys a transfer on the host.
     2303 *
     2304 * @param   pClient             Client to destroy transfer for.
     2305 * @param   pTransfer           Transfer to destroy.
     2306 *                              The pointer will be invalid after return.
     2307 */
     2308void ShClSvcTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
     2309{
     2310    if (!pTransfer)
     2311        return;
     2312
     2313    LogFlowFuncEnter();
     2314
    20092315    PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx;
    20102316
     2317    ShClTransferCtxUnregisterById(pTxCtx, pTransfer->State.uID);
     2318
     2319    ShClTransferDestroy(pTransfer);
     2320
     2321    RTMemFree(pTransfer);
     2322    pTransfer = NULL;
     2323
     2324    LogFlowFuncLeave();
     2325}
     2326
     2327/**
     2328 * Initializes a (created) transfer on the host.
     2329 *
     2330 * @returns VBox status code.
     2331 * @param   pClient             Client that owns the transfer.
     2332 * @param   pTransfer           Transfer to initialize.
     2333 */
     2334int ShClSvcTransferInit(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
     2335{
     2336    AssertPtrReturn(pClient, VERR_INVALID_POINTER);
     2337
     2338    LogFlowFuncEnter();
     2339
     2340    shClSvcClientLock(pClient);
     2341
     2342    Assert(ShClTransferGetStatus(pTransfer) == SHCLTRANSFERSTATUS_NONE);
     2343
     2344    PSHCLTRANSFERCTX pTxCtx = &pClient->Transfers.Ctx;
     2345
    20112346    int rc;
    20122347
    2013     if (!ShClTransferCtxTransfersMaximumReached(pTxCtx))
    2014     {
     2348    if (!ShClTransferCtxIsMaximumReached(pTxCtx))
     2349    {
     2350        SHCLTRANSFERDIR const enmDir = ShClTransferGetDir(pTransfer);
     2351
    20152352        LogRel2(("Shared Clipboard: Initializing %s transfer ...\n",
    20162353                 enmDir == SHCLTRANSFERDIR_FROM_REMOTE ? "guest -> host" : "host -> guest"));
    20172354
    2018         PSHCLTRANSFER pTransfer;
    2019         rc = ShClTransferCreate(&pTransfer);
    2020         if (RT_SUCCESS(rc))
    2021         {
    2022             SHCLTXPROVIDER Provider;
    2023             RT_ZERO(Provider);
    2024 
    2025             /* Assign local provider first and overwrite interface methods below if needed. */
    2026             VBClTransferProviderLocalQueryInterface(&Provider);
    2027 
    2028             if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */
    2029             {
    2030                 Provider.Interface.pfnRootListRead  = shClSvcTransferIfaceRootListRead;
    2031 
    2032                 Provider.Interface.pfnListOpen      = shClSvcTransferIfaceListOpen;
    2033                 Provider.Interface.pfnListClose     = shClSvcTransferIfaceListClose;
    2034                 Provider.Interface.pfnListHdrRead   = shClSvcTransferIfaceListHdrRead;
    2035                 Provider.Interface.pfnListEntryRead = shClSvcTransferIfaceListEntryRead;
    2036 
    2037                 Provider.Interface.pfnObjOpen       = shClSvcTransferIfaceObjOpen;
    2038                 Provider.Interface.pfnObjClose      = shClSvcTransferIfaceObjClose;
    2039                 Provider.Interface.pfnObjRead       = shClSvcTransferIfaceObjRead;
    2040             }
    2041             else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */
    2042             {
    2043                 Provider.Interface.pfnListHdrWrite   = shClSvcTransferIfaceListHdrWrite;
    2044                 Provider.Interface.pfnListEntryWrite = shClSvcTransferIfaceListEntryWrite;
    2045                 Provider.Interface.pfnObjWrite       = shClSvcTransferIfaceObjWrite;
    2046             }
    2047             else
    2048                 AssertFailed();
    2049 
    2050             Provider.enmSource = pClient->State.enmSource;
    2051             Provider.pvUser    = pClient;
    2052 
    2053             rc = ShClTransferSetProvider(pTransfer, &Provider);
     2355        SHCLTXPROVIDER Provider;
     2356        RT_ZERO(Provider);
     2357
     2358        /* Assign local provider first and overwrite interface methods below if needed. */
     2359        ShClTransferProviderLocalQueryInterface(&Provider);
     2360
     2361        if (enmDir == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host. */
     2362        {
     2363            Provider.Interface.pfnRootListRead  = shClSvcTransferIfaceGHRootListRead;
     2364
     2365            Provider.Interface.pfnListOpen      = shClSvcTransferIfaceGHListOpen;
     2366            Provider.Interface.pfnListClose     = shClSvcTransferIfaceGHListClose;
     2367            Provider.Interface.pfnListHdrRead   = shClSvcTransferIfaceGHListHdrRead;
     2368            Provider.Interface.pfnListEntryRead = shClSvcTransferIfaceGHListEntryRead;
     2369
     2370            Provider.Interface.pfnObjOpen       = shClSvcTransferIfaceGHObjOpen;
     2371            Provider.Interface.pfnObjClose      = shClSvcTransferIfaceGHObjClose;
     2372            Provider.Interface.pfnObjRead       = shClSvcTransferIfaceGHObjRead;
     2373        }
     2374        else if (enmDir == SHCLTRANSFERDIR_TO_REMOTE) /* Host -> Guest. */
     2375        {
     2376            Provider.Interface.pfnListHdrWrite   = shClSvcTransferIfaceHGListHdrWrite;
     2377            Provider.Interface.pfnListEntryWrite = shClSvcTransferIfaceHGListEntryWrite;
     2378            Provider.Interface.pfnObjWrite       = shClSvcTransferIfaceHGObjWrite;
     2379        }
     2380        else
     2381            AssertFailed();
     2382
     2383        Provider.enmSource = pClient->State.enmSource;
     2384        Provider.pvUser    = pClient;
     2385
     2386        rc = ShClTransferSetProvider(pTransfer, &Provider);
     2387        if (RT_SUCCESS(rc))
     2388        {
     2389            ShClTransferSetCallbacks(pTransfer, &pClient->Transfers.Callbacks);
     2390
     2391            rc = ShClTransferInit(pTransfer);
    20542392            if (RT_SUCCESS(rc))
    20552393            {
    2056                 ShClTransferSetCallbacks(pTransfer, &pClient->Transfers.Callbacks);
    2057 
    2058                 rc = ShClTransferInit(pTransfer, enmDir, enmSource);
    2059                 if (RT_SUCCESS(rc))
    2060                 {
    2061                     SHCLTRANSFERID uTransferID = 0;
    2062                     rc = ShClTransferCtxTransferRegister(pTxCtx, pTransfer, &uTransferID);
    2063                     if (RT_SUCCESS(rc))
    2064                     {
    2065                         rc = ShClBackendTransferCreate(pClient->pBackend, pClient, pTransfer);
    2066                         if (RT_SUCCESS(rc))
    2067                         {
    2068                             /* Tell the guest that we've initialized the transfer locally. */
    2069                             rc = shClSvcTransferSendStatus(pClient, pTransfer,
    2070                                                            SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS, NULL /* ppEvent */);
    2071                         }
    2072                     }
    2073 
    2074                     if (RT_FAILURE(rc))
    2075                         ShClTransferCtxTransferUnregisterById(pTxCtx, uTransferID);
    2076                 }
    2077             }
    2078 
    2079             if (RT_FAILURE(rc))
    2080             {
    2081                 ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer);
    2082                 ShClTransferDestroy(pTransfer);
    2083 
    2084                 RTMemFree(pTransfer);
    2085                 pTransfer = NULL;
    2086             }
    2087             else
    2088             {
    2089                 if (ppTransfer)
    2090                     *ppTransfer = pTransfer;
    2091             }
    2092         }
    2093 
    2094         if (RT_FAILURE(rc))
    2095             LogRel(("Shared Clipboard: Starting transfer failed with %Rrc\n", rc));
     2394                /* Sanity: Make sure that the transfer we're gonna report as INITIALIZED to the guest
     2395                 *         actually has some root entries set, as the guest can query for those at any time then. */
     2396                if (enmDir == SHCLTRANSFERDIR_TO_REMOTE)
     2397                    AssertMsgStmt(ShClTransferRootsCount(pTransfer), ("Transfer has no root entries set\n"), rc = VERR_WRONG_ORDER);
     2398            }
     2399        }
    20962400    }
    20972401    else
    20982402        rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
    20992403
     2404    /* Tell the guest the outcome. */
     2405    int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     2406                                                       RT_SUCCESS(rc)
     2407                                                     ? SHCLTRANSFERSTATUS_INITIALIZED : SHCLTRANSFERSTATUS_ERROR, rc,
     2408                                                     NULL /* ppEvent */);
     2409    if (RT_SUCCESS(rc))
     2410        rc2 = rc;
     2411
     2412    if (RT_FAILURE(rc))
     2413        LogRel(("Shared Clipboard: Initializing transfer failed with %Rrc\n", rc));
     2414
     2415    shClSvcClientUnlock(pClient);
     2416
    21002417    LogFlowFuncLeaveRC(rc);
    21012418    return rc;
     
    21072424 * @returns VBox status code.
    21082425 * @param   pClient             Client that owns the transfer.
    2109  * @param   pTransfer           Transfer to stop.
    2110  */
    2111 int shClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
     2426 * @param   pTransfer           Transfer to start.
     2427 */
     2428int ShClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    21122429{
    21132430    LogRel2(("Shared Clipboard: Starting transfer %RU32 ...\n", pTransfer->State.uID));
     
    21192436    /* Let the guest know in any case
    21202437     * (so that it can tear down the transfer on error as well). */
    2121     int rc2 = shClSvcTransferSendStatus(pClient, pTransfer,
    2122                                         RT_SUCCESS(rc) ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc, NULL /* ppEvent */);
     2438    int rc2 = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     2439                                                     RT_SUCCESS(rc) ? SHCLTRANSFERSTATUS_STARTED : SHCLTRANSFERSTATUS_ERROR, rc,
     2440                                                     NULL /* ppEvent */);
    21232441    if (RT_SUCCESS(rc))
    21242442        rc = rc2;
     
    21362454 * @param   fWaitForGuest       Set to \c true to wait for acknowledgement from guest, or \c false to skip waiting.
    21372455 */
    2138 int shClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest)
     2456int ShClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest)
    21392457{
    21402458    LogRel2(("Shared Clipboard: Stopping transfer %RU32 ...\n", pTransfer->State.uID));
     
    21432461
    21442462    PSHCLEVENT pEvent;
    2145     int rc = shClSvcTransferSendStatus(pClient, pTransfer,
    2146                                        SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent);
     2463    int rc = shClSvcTransferSendStatusAsyncInternal(pClient, pTransfer,
     2464                                                    SHCLTRANSFERSTATUS_STOPPED, VINF_SUCCESS, &pEvent);
    21472465    if (   RT_SUCCESS(rc)
    21482466        && fWaitForGuest)
     
    21652483                pTransfer->State.uID, rc));
    21662484
    2167     /* Regardless of whether the guest was able to report back and/or stop the transfer, remove the transfer on the host
    2168      * so that we don't risk of having stale transfers here. */
    2169     int rc2 = ShClTransferCtxTransferUnregisterById(&pClient->Transfers.Ctx, ShClTransferGetID(pTransfer));
    2170     if (RT_SUCCESS(rc2))
    2171     {
    2172         ShClBackendTransferDestroy(pClient->pBackend, pClient, pTransfer);
    2173         ShClTransferDestroy(pTransfer);
    2174         pTransfer = NULL;
    2175     }
    2176 
    2177     if (RT_SUCCESS(rc))
    2178         rc = rc2;
    2179 
    2180     if (RT_FAILURE(rc))
    2181         LogRel(("Shared Clipboard: Stopping transfer %RU32 failed with rc=%Rrc\n",
    2182                 pTransfer->State.uID, rc));
    2183 
    21842485    shClSvcClientUnlock(pClient);
    21852486
     
    22132514            AssertPtr(pClient);
    22142515
    2215             shClSvcClientTransfersReset(pClient);
     2516            shClSvcTransferDestroyAll(pClient);
    22162517
    22172518            ++itClient;
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.h

    r98103 r100367  
    3232#endif
    3333
     34int shClSvcTransferModeSet(uint32_t fMode);
     35int ShClSvcTransferCreate(PSHCLCLIENT pClient, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource, SHCLTRANSFERID idTransfer, PSHCLTRANSFER *ppTransfer);
     36void ShClSvcTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     37int ShClSvcTransferInit(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     38int ShClSvcTransferStart(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     39int ShClSvcTransferStop(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, bool fWaitForGuest);
     40int ShClSvcTransferSendStatusAsync(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus, int rcTransfer, PSHCLEVENT *ppEvent);
     41int ShClSvcTransferRootListReadFromGuest(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
     42bool shClSvcTransferMsgIsAllowed(uint32_t uMode, uint32_t uMsg);
     43void shClSvcTransferDestroyAll(PSHCLCLIENT pClient);
     44
    3445#endif /* !VBOX_INCLUDED_SRC_SharedClipboard_VBoxSharedClipboardSvc_transfers_h */
    3546
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r100205 r100367  
    166166    LogFlowFunc(("uFmt=%#x\n", uFmt));
    167167
    168     int rc;
    169 
    170     PSHCLEVENT pEvent;
    171     rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent);
    172     if (RT_SUCCESS(rc))
    173     {
    174         PSHCLEVENTPAYLOAD pPayload;
    175         rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
    176         if (RT_SUCCESS(rc))
    177         {
    178             if (ppvData)
    179                 *ppvData = pPayload ? pPayload->pvData : NULL;
    180             if (pcbData)
    181                 *pcbData = pPayload ? pPayload->cbData : 0;
    182         }
    183 
    184         ShClEventRelease(pEvent);
    185     }
    186 
     168    int rc = ShClSvcReadDataFromGuest(pCtx->pClient, uFmt, &pEvent);
    187169    if (RT_FAILURE(rc))
    188170        LogRel(("Shared Clipboard: Reading guest clipboard data for Windows host failed with %Rrc\n", rc));
     
    231213#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    232214/**
    233  * @copydoc SHCLTRANSFERCALLBACKS::pfnOnStart
    234  *
    235  * Called on transfer start to notify the "in-flight" IDataObject about a started transfer.
     215 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized
     216 *
     217 * Called on transfer intialization to notify the "in-flight" IDataObject about a data transfer.
    236218 *
    237219 * @thread  Service main thread.
    238220 */
    239 static DECLCALLBACK(void) vboxClipboardSvcWinTransferStartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     221static DECLCALLBACK(void) vboxClipboardSvcWinTransferInitializedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
    240222{
    241223    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     
    259241            SharedClipboardWinDataObject *pObj = pCtx->Win.pDataObjInFlight;
    260242            AssertPtrReturnVoid(pObj);
    261             rc = pObj->SetAndStartTransfer(pTransfer);
     243            rc = pObj->SetTransfer(pTransfer);
    262244
    263245            pCtx->Win.pDataObjInFlight = NULL; /* Hand off to Windows. */
     
    272254
    273255    LogFlowFunc(("LEAVE: idTransfer=%RU32, rc=%Rrc\n", ShClTransferGetID(pTransfer), rc));
     256}
     257
     258/**
     259 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnDestroy
     260 *
     261 * @thread  Service main thread.
     262 */
     263static DECLCALLBACK(void) vboxClipboardSvcWinTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     264{
     265    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     266    AssertPtr(pCtx);
     267
     268    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     269    AssertPtr(pTransfer);
     270
     271    SharedClipboardWinTransferDestroy(&pCtx->Win, pTransfer);
     272}
     273
     274/**
     275 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnStarted
     276 *
     277 * @thread  Service main thread.
     278 */
     279static DECLCALLBACK(void) vboxClipboardSvcWinTransferStartedCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     280{
     281    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     282    AssertPtr(pCtx);
     283
     284    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     285    AssertPtr(pTransfer);
     286
     287    if (ShClTransferGetDir(pTransfer) ==  SHCLTRANSFERDIR_FROM_REMOTE) /* G->H */
     288    {
     289        /* Report to the guest that we now entered the STARTED state. */
     290        ShClSvcTransferStart(pCtx->pClient, pTransfer);
     291    }
    274292}
    275293#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
     
    385403                void    *pvData = NULL;
    386404                uint32_t cbData = 0;
    387                 int rc = vboxClipboardSvcWinReadDataFromGuest(pCtx, uFormat, &pvData, &cbData);
     405                int rc = ShClSvcReadDataFromGuest(pCtx->pClient, uFormat, &pvData, &cbData);
    388406                if (   RT_SUCCESS(rc)
    389407                    && pvData
     
    440458
    441459            int rc = SharedClipboardWinClearAndAnnounceFormats(pWinCtx, fFormats, hWnd);
    442 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    443             if (   RT_SUCCESS(rc)
    444                 && fFormats & VBOX_SHCL_FMT_URI_LIST)
    445             {
    446                 /*
    447                  * The host requested data from the guest as URI list.
    448                  *
    449                  * This means on Windows we
    450                  * - need to first create an own IDataObject and push it on the clipboard
    451                  * - register a transfer locally so that we have a valid ID for it
    452                  *
    453                  * That way Windows will recognize that there is a data transfer "in flight".
    454                  *
    455                  * As soon as the user requests to "paste" the data (transfer), the IDataObject will try to read data via
    456                  * the pfnOnRequestDataFromSource callback.
    457                  */
    458                 SHCLCALLBACKS Callbacks;
    459                 RT_ZERO(Callbacks);
    460                 Callbacks.pfnOnRequestDataFromSource = vboxClipboardSvcWinRequestDataFromSourceCallback;
    461 
    462                 rc = SharedClipboardWinTransferCreateAndSetDataObject(pWinCtx, pCtx, &Callbacks);
    463             }
    464 #endif
    465460            if (RT_FAILURE(rc))
    466461                LogRel(("Shared Clipboard: Reporting clipboard formats %#x to Windows host failed with %Rrc\n", fFormats, rc));
     
    739734         */
    740735        RT_ZERO(pClient->Transfers.Callbacks);
    741         pClient->Transfers.Callbacks.pfnOnStarted = vboxClipboardSvcWinTransferStartedCallback;
     736        pClient->Transfers.Callbacks.pfnOnInitialized = vboxClipboardSvcWinTransferInitializedCallback;
     737        pClient->Transfers.Callbacks.pfnOnStarted     = vboxClipboardSvcWinTransferStartedCallback;
     738        pClient->Transfers.Callbacks.pfnOnDestroy     = vboxClipboardSvcWinTransferDestroyCallback;
    742739
    743740        pClient->Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */
     
    973970
    974971#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    975 int ShClBackendTransferCreate(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    976 {
    977     RT_NOREF(pBackend, pClient, pTransfer);
    978 
    979     LogFlowFuncEnter();
    980 
    981     return VINF_SUCCESS;
    982 }
    983 
    984 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    985 {
    986     RT_NOREF(pBackend);
    987 
    988     LogFlowFuncEnter();
    989 
    990     SharedClipboardWinTransferDestroy(&pClient->State.pCtx->Win, pTransfer);
    991 
    992     return VINF_SUCCESS;
    993 }
    994 
    995 int ShClBackendTransferGetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
     972int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    996973{
    997974    RT_NOREF(pBackend);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp

    r100237 r100367  
    4444#include <iprt/errcore.h>
    4545
    46 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     46#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    4747# include <VBox/GuestHost/SharedClipboard-transfers.h>
     48# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     49#  include <VBox/GuestHost/SharedClipboard-transfers.h>
     50# endif
    4851#endif
    4952
    5053#include "VBoxSharedClipboardSvc-internal.h"
     54#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     55# include "VBoxSharedClipboardSvc-transfers.h"
     56#endif
    5157
    5258/* Number of currently extablished connections. */
     
    8187static DECLCALLBACK(int) shClSvcX11RequestDataFromSourceCallback(PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser);
    8288
     89#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     90static DECLCALLBACK(void) shClSvcX11OnTransferInitCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx);
     91static DECLCALLBACK(void) shClSvcX11OnTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx);
     92static DECLCALLBACK(void) shClSvcX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx);
     93#endif
     94
    8395
    8496int ShClBackendInit(PSHCLBACKEND pBackend, VBOXHGCMSVCFNTABLE *pTable)
     
    146158                pClient->State.pCtx = pCtx;
    147159                pCtx->pClient = pClient;
     160
     161#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     162                /*
     163                 * Set callbacks.
     164                 * Those will be registered within ShClSvcTransferInit() when a new transfer gets initialized.
     165                 *
     166                 * Used for starting / stopping the HTTP server.
     167                 */
     168                RT_ZERO(pClient->Transfers.Callbacks);
     169
     170                pClient->Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */
     171                pClient->Transfers.Callbacks.cbUser = sizeof(SHCLCONTEXT);
     172
     173                pClient->Transfers.Callbacks.pfnOnInitialized  = shClSvcX11OnTransferInitCallback;
     174                pClient->Transfers.Callbacks.pfnOnDestroy      = shClSvcX11OnTransferDestroyCallback;
     175                pClient->Transfers.Callbacks.pfnOnUnregistered = shClSvcX11OnTransferUnregisteredCallback;
     176#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    148177
    149178                rc = ShClX11ThreadStart(&pCtx->X11, true /* grab shared clipboard */);
     
    352381}
    353382
     383#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     384/**
     385 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnInitialized
     386 *
     387 * This starts the HTTP server if not done yet and registers the transfer with it.
     388 *
     389 * @thread Service main thread.
     390 */
     391static DECLCALLBACK(void) shClSvcX11OnTransferInitCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     392{
     393    RT_NOREF(pCbCtx);
     394
     395#if 1
     396    LogFlowFuncEnter();
     397
     398    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     399    AssertPtr(pCtx);
     400
     401    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     402    AssertPtr(pTransfer);
     403
     404    switch (ShClTransferGetDir(pTransfer))
     405    {
     406        case SHCLTRANSFERDIR_FROM_REMOTE: /* G->H */
     407        {
     408# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     409            /* We only need to start the HTTP server when we actually receive data from the remote (host). */
     410            ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx);
     411# endif
     412            break;
     413        }
     414
     415        case SHCLTRANSFERDIR_TO_REMOTE: /* H->G */
     416        {
     417            PSHCLEVENT pEvent;
     418            int rc = ShClEventSourceGenerateAndRegisterEvent(&pCtx->pClient->EventSrc, &pEvent);
     419            if (RT_SUCCESS(rc))
     420            {
     421                rc = ShClX11ReadDataFromX11Async(&pCtx->X11, VBOX_SHCL_FMT_URI_LIST, UINT32_MAX, pEvent);
     422                if (RT_SUCCESS(rc))
     423                {
     424                    /* X supplies the data asynchronously, so we need to wait for data to arrive first. */
     425                    PSHCLEVENTPAYLOAD pPayload;
     426                    rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     427                    if (RT_SUCCESS(rc))
     428                    {
     429                        if (pPayload)
     430                        {
     431                            Assert(pPayload->cbData == sizeof(SHCLX11RESPONSE));
     432                            AssertPtr(pPayload->pvData);
     433                            PSHCLX11RESPONSE pResp = (PSHCLX11RESPONSE)pPayload->pvData;
     434
     435                            rc = ShClTransferRootsInitFromStringList(pTransfer,
     436                                                                     (char *)pResp->Read.pvData, pResp->Read.cbData + 1 /* Include zero terminator */);
     437                            //if (RT_SUCCESS(rc))
     438                            //    rc = ShClTransferRootListRead(pTransfer);
     439
     440                            if (RT_SUCCESS(rc))
     441                                LogRel2(("Shared Clipboard: Host reported %RU64 X11 root entries for transfer to guest\n", ShClTransferRootsCount(pTransfer)));
     442
     443                            RTMemFree(pResp->Read.pvData);
     444                            pResp->Read.cbData = 0;
     445
     446                            ShClPayloadFree(pPayload);
     447                            pPayload = NULL;
     448                        }
     449                        else
     450                            rc = VERR_NO_DATA; /* No payload. */
     451                    }
     452                }
     453
     454                ShClEventRelease(pEvent);
     455            }
     456            else
     457                rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
     458            break;
     459        }
     460
     461        default:
     462            break;
     463    }
     464
     465    LogFlowFuncLeave();
     466}
     467
     468/**
     469 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnDestroy
     470 *
     471 * This stops the HTTP server if not done yet.
     472 *
     473 * @thread Service main thread.
     474 */
     475static DECLCALLBACK(void) shClSvcX11OnTransferDestroyCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx)
     476{
     477    LogFlowFuncEnter();
     478
     479# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     480    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pCbCtx->pvUser;
     481    AssertPtr(pCtx);
     482
     483    PSHCLTRANSFER pTransfer = pCbCtx->pTransfer;
     484    AssertPtr(pTransfer);
     485
     486    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
     487        ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx);
     488# else
     489    RT_NOREF(pCbCtx);
     490# endif
     491
     492    LogFlowFuncLeave();
     493}
     494
     495/**
     496 * Unregisters a transfer from a HTTP server.
     497 *
     498 * This also stops the HTTP server if no active transfers are found anymore.
     499 *
     500 * @param   pCtx                Shared clipboard context to unregister transfer for.
     501 * @param   pTransfer           Transfer to unregister.
     502 *
     503 * @thread Clipboard main thread.
     504 */
     505static void shClSvcX11HttpTransferUnregister(PSHCLCONTEXT pCtx, PSHCLTRANSFER pTransfer)
     506{
     507    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
     508    {
     509# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     510        if (ShClTransferHttpServerIsInitialized(&pCtx->X11.HttpCtx.HttpServer))
     511        {
     512            ShClTransferHttpServerUnregisterTransfer(&pCtx->X11.HttpCtx.HttpServer, pTransfer);
     513            ShClTransferHttpServerMaybeStop(&pCtx->X11.HttpCtx);
     514        }
     515# else
     516        RT_NOREF(pCtx);
     517# endif
     518    }
     519
     520    //ShClTransferRelease(pTransfer);
     521}
     522
     523/**
     524 * @copydoc SHCLTRANSFERCALLBACKS::pfnOnUnregistered
     525 *
     526 * Unregisters a (now) unregistered transfer from the HTTP server.
     527 *
     528 * @thread Clipboard main thread.
     529 */
     530static DECLCALLBACK(void) shClSvcX11OnTransferUnregisteredCallback(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx)
     531{
     532    RT_NOREF(pTransferCtx);
     533    shClSvcX11HttpTransferUnregister((PSHCLCONTEXT)pCbCtx->pvUser, pCbCtx->pTransfer);
     534}
     535#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
     536
    354537/**
    355538 * @copydoc SHCLCALLBACKS::pfnOnRequestDataFromSource
     
    373556    }
    374557
    375     int rc = VINF_SUCCESS;
    376 
    377 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     558    PSHCLCLIENT const pClient = pCtx->pClient;
     559    int rc = ShClSvcReadDataFromGuest(pClient, uFmt, ppv, pcb);
     560    if (RT_FAILURE(rc))
     561        return rc;
     562
    378563    /*
    379      * Note: We always return a generic URI list here.
     564     * Note: We always return a generic URI list (as HTTP links) here.
    380565     *       As we don't know which Atom target format was requested by the caller, the X11 clipboard codes needs
    381566     *       to decide & transform the list into the actual clipboard Atom target format the caller wanted.
    382567     */
     568#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    383569    if (uFmt == VBOX_SHCL_FMT_URI_LIST)
    384570    {
    385         PSHCLTRANSFER pTransfer = ShClTransferHttpServerGetTransferFirst(&pCtx->X11.HttpCtx.HttpServer);
    386         if (pTransfer)
    387         {
    388             if (RT_SUCCESS(rc))
    389                 rc = ShClTransferRootListRead(pTransfer);
    390         }
    391 
    392         /** @todo BUGBUG IMPLEMENT THIS! */
    393 
    394         *ppv = NULL;
    395         *pcb = 0;
    396 
    397         rc = VERR_NO_DATA;
    398     }
    399 #endif
    400 
    401     if (RT_SUCCESS(rc))
    402     {
    403         /* Request data from the guest and for data to arrive. */
    404         PSHCLEVENT pEvent;
    405         rc = ShClSvcReadDataFromGuestAsync(pCtx->pClient, uFmt, &pEvent);
     571        PSHCLTRANSFER pTransfer;
     572        rc = ShClSvcTransferCreate(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE,
     573                                   NIL_SHCLTRANSFERID /* Creates a new transfer ID */, &pTransfer);
    406574        if (RT_SUCCESS(rc))
    407575        {
    408             PSHCLEVENTPAYLOAD pPayload;
    409             rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     576            /* Initialize the transfer on the host side. */
     577            rc = ShClSvcTransferInit(pClient, pTransfer);
     578            if (RT_FAILURE(rc))
     579                 ShClSvcTransferDestroy(pClient, pTransfer);
     580        }
     581
     582        if (RT_SUCCESS(rc))
     583        {
     584            /* We have to wait for the guest reporting the transfer as being initialized.
     585             * Only then we can start reading stuff. */
     586            rc = ShClTransferWaitForStatus(pTransfer, SHCL_TIMEOUT_DEFAULT_MS, SHCLTRANSFERSTATUS_INITIALIZED);
    410587            if (RT_SUCCESS(rc))
    411588            {
    412                 if (   !pPayload
    413                     || !pPayload->cbData)
     589                rc = ShClTransferRootListRead(pTransfer);
     590                if (RT_SUCCESS(rc))
    414591                {
    415                     rc = VERR_NO_DATA;
    416                 }
    417                 else
    418                 {
    419                     *ppv = pPayload->pvData;
    420                     *pcb = pPayload->cbData;
     592# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     593                    /* As soon as we register the transfer with the HTTP server, the transfer needs to have its roots set. */
     594                    PSHCLHTTPSERVER const pHttpSrv = &pCtx->X11.HttpCtx.HttpServer;
     595                    rc = ShClTransferHttpServerRegisterTransfer(pHttpSrv, pTransfer);
     596                    if (RT_SUCCESS(rc))
     597                    {
     598                        char *pszURL = ShClTransferHttpServerGetUrlA(pHttpSrv, pTransfer->State.uID);
     599                        if (pszURL)
     600                        {
     601                            *ppv = pszURL;
     602                            *pcb = strlen(pszURL) + 1 /* Include terminator */;
     603
     604                            LogFlowFunc(("URL is '%s'\n", pszURL));
     605
     606                            /* ppv has ownership of pszURL. */
     607
     608                            rc = VINF_SUCCESS;
     609                        }
     610                        else
     611                            rc = VERR_NO_MEMORY;
     612                    }
     613# else
     614                    rc = VERR_NOT_SUPPORTED;
     615# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
    421616                }
    422617            }
    423 
    424             ShClEventRelease(pEvent);
    425         }
    426     }
     618        }
     619    }
     620#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    427621
    428622    if (RT_FAILURE(rc))
    429         LogRel(("Shared Clipboard: Requesting data in format %#x for X11 host failed with %Rrc\n", uFmt, rc));
     623        LogRel(("Shared Clipboard: Requesting X11 data in format %#x from guest failed with %Rrc\n", uFmt, rc));
    430624
    431625    LogFlowFuncLeaveRC(rc);
     
    434628
    435629#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    436 
    437 int ShClBackendTransferCreate(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
     630/**
     631 * Handles transfer status replies from the guest.
     632 */
     633int ShClBackendTransferHandleStatusReply(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer, SHCLSOURCE enmSource, SHCLTRANSFERSTATUS enmStatus, int rcStatus)
     634{
     635    RT_NOREF(pBackend, pClient, enmSource, rcStatus);
     636
     637    PSHCLCONTEXT pCtx = pClient->State.pCtx; RT_NOREF(pCtx);
     638
     639    if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE) /* Guest -> Host */
     640    {
     641        switch (enmStatus)
     642        {
     643            case SHCLTRANSFERSTATUS_INITIALIZED:
     644            {
     645#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
     646                int rc2 = ShClTransferHttpServerMaybeStart(&pCtx->X11.HttpCtx);
     647                if (RT_SUCCESS(rc2))
     648                {
     649
     650                }
     651
     652                if (RT_FAILURE(rc2))
     653                    LogRel(("Shared Clipboard: Registering HTTP transfer failed: %Rrc\n", rc2));
     654#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
     655                break;
     656            }
     657
     658            default:
     659                break;
     660        }
     661    }
     662
     663    return VINF_SUCCESS;
     664}
     665
     666int ShClBackendTransferHGRootListRead(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    438667{
    439668    RT_NOREF(pBackend);
    440 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    441     /* We only need to start the HTTP server (and register the transfer to it) when we actually receive data from the guest. */
    442     if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    443         return ShClTransferHttpServerMaybeStart(&pClient->State.pCtx->X11.HttpCtx);
     669
     670#if 1
     671    RT_NOREF(pClient, pTransfer);
     672    int rc = 0;
    444673#else
    445     RT_NOREF(pClient, pTransfer);
    446 #endif
    447     return VINF_SUCCESS;
    448 }
    449 
    450 int ShClBackendTransferDestroy(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    451 {
    452     RT_NOREF(pBackend);
    453 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
    454     /* See comment in ShClBackendTransferCreate(). */
    455     if (ShClTransferGetDir(pTransfer) == SHCLTRANSFERDIR_FROM_REMOTE)
    456         return ShClTransferHttpServerMaybeStop(&pClient->State.pCtx->X11.HttpCtx);
    457 #else
    458     RT_NOREF(pClient, pTransfer);
    459 #endif
    460     return VINF_SUCCESS;
    461 }
    462 
    463 int ShClBackendTransferGetRoots(PSHCLBACKEND pBackend, PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
    464 {
    465     RT_NOREF(pBackend);
    466 
    467674    LogFlowFuncEnter();
    468675
     
    508715    else
    509716        rc = VERR_SHCLPB_MAX_EVENTS_REACHED;
     717#endif
    510718
    511719    LogFlowFuncLeaveRC(rc);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r100204 r100367  
    614614
    615615    /* Make sure to send a quit message to the guest so that it can terminate gracefully. */
    616     RTCritSectEnter(&pClient->CritSect);
     616    shClSvcClientLock(pClient);
     617
    617618    if (pClient->Pending.uType)
    618619    {
     
    627628        pClient->Pending.paParms = NULL;
    628629    }
    629     RTCritSectLeave(&pClient->CritSect);
     630
     631#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     632    shClSvcTransferDestroyAll(pClient);
     633    ShClTransferCtxDestroy(&pClient->Transfers.Ctx);
     634#endif
    630635
    631636    ShClEventSourceDestroy(&pClient->EventSrc);
     637
     638    shClSvcClientUnlock(pClient);
    632639
    633640    shClSvcClientStateDestroy(&pClient->State);
     
    635642    PSHCLCLIENTLEGACYCID pCidIter, pCidIterNext;
    636643    RTListForEachSafe(&pClient->Legacy.lstCID, pCidIter, pCidIterNext, SHCLCLIENTLEGACYCID, Node)
    637     {
    638644        RTMemFree(pCidIter);
    639     }
    640645
    641646    int rc2 = RTCritSectDelete(&pClient->CritSect);
     
    686691
    687692#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    688     shClSvcClientTransfersReset(pClient);
     693    shClSvcTransferDestroyAll(pClient);
    689694#endif
    690695
     
    12201225
    12211226/**
    1222  * Requests to read clipboard data from the guest.
     1227 * Reads clipboard data from the guest, asynchronous version.
    12231228 *
    12241229 * @returns VBox status code.
     
    13301335                }
    13311336
    1332 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     1337#if 0 /* ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    13331338                /*
    13341339                 * When the host wants to read URI data from the guest:
    13351340                 *   - Initialize a transfer locally.
    13361341                 *   - Request URI data from the guest; this tells the guest to initialize a transfer on the guest side.
    1337                  *   - Start the transfer locally once we receive the transfer STARTED status from the guest via VBOX_SHCL_GUEST_FN_REPLY.
     1342                 *   - Start the transfer locally once we receive the transfer INITIALIZED status from the guest via VBOX_SHCL_GUEST_FN_REPLY.
     1343                 *
     1344                 * When this function returns, the X11 clipboard will try reading the data, so we need to make sure that
     1345                 *   - the local HTTP server is up and running (will be done in ShClBackendTransferCreate() on X11)
     1346                 *   - the right (HTTP) URL data is filled into the clipboard
     1347                 * by then.
    13381348                 */
    13391349                if (   RT_SUCCESS(rc)
    1340                     && fFormat == VBOX_SHCL_FMT_URI_LIST)
     1350                    && (fFormat & VBOX_SHCL_FMT_URI_LIST))
    13411351                {
    1342                     rc = shClSvcTransferInit(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE,
    1343                                              NULL /* pTransfer */);
     1352                    PSHCLTRANSFER pTransfer;
     1353                    rc = ShClSvcTransferInit(pClient, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_REMOTE, &pTransfer);
    13441354                    if (RT_SUCCESS(rc))
    13451355                        rc = shClSvcSetSource(pClient, SHCLSOURCE_REMOTE);
     
    13811391
    13821392/**
     1393 * Reads clipboard data from the guest.
     1394 *
     1395 * @returns VBox status code.
     1396 * @param   pClient             Client to request to read data form.
     1397 * @param   fFormats            The formats being requested, OR'ed together (VBOX_SHCL_FMT_XXX).
     1398 * @param   ppv                 Where to return the allocated data read.
     1399 *                              Must be free'd by the caller.
     1400 * @param   pcb                 Where to return number of bytes read.
     1401 */
     1402int ShClSvcReadDataFromGuest(PSHCLCLIENT pClient, SHCLFORMAT fFormats, void **ppv, uint32_t *pcb)
     1403{
     1404    LogFlowFuncEnter();
     1405
     1406    /* Request data from the guest and wait for data to arrive. */
     1407    PSHCLEVENT pEvent;
     1408    int rc = ShClSvcReadDataFromGuestAsync(pClient, fFormats, &pEvent);
     1409    if (RT_SUCCESS(rc))
     1410    {
     1411        PSHCLEVENTPAYLOAD pPayload;
     1412        rc = ShClEventWait(pEvent, SHCL_TIMEOUT_DEFAULT_MS, &pPayload);
     1413        if (RT_SUCCESS(rc))
     1414        {
     1415            if (   !pPayload
     1416                || !pPayload->cbData)
     1417            {
     1418                rc = VERR_NO_DATA;
     1419            }
     1420            else
     1421            {
     1422                *ppv = pPayload->pvData;
     1423                *pcb = pPayload->cbData;
     1424            }
     1425        }
     1426
     1427        ShClEventRelease(pEvent);
     1428    }
     1429
     1430    if (RT_FAILURE(rc))
     1431        LogRel(("Shared Clipboard: Reading data from guest failed with %Rrc\n", rc));
     1432
     1433    LogFlowFuncLeaveRC(rc);
     1434    return rc;
     1435}
     1436
     1437/**
    13831438 * Signals the host that clipboard data from the guest has been received.
    13841439 *
     
    15751630     */
    15761631    int rc;
    1577     if (!fFormats && pClient->State.enmSource != SHCLSOURCE_REMOTE)
     1632    if (!fFormats)
    15781633        rc = VINF_SUCCESS;
    15791634    else
    15801635    {
    1581         rc = shClSvcSetSource(pClient, SHCLSOURCE_REMOTE);
     1636        rc = RTCritSectEnter(&g_CritSect);
    15821637        if (RT_SUCCESS(rc))
    15831638        {
    1584             rc = RTCritSectEnter(&g_CritSect);
    1585             if (RT_SUCCESS(rc))
     1639            if (g_ExtState.pfnExtension)
    15861640            {
    1587                 if (g_ExtState.pfnExtension)
    1588                 {
    1589                     SHCLEXTPARMS parms;
    1590                     RT_ZERO(parms);
    1591                     parms.uFormat = fFormats;
    1592 
    1593                     g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof(parms));
    1594                 }
    1595                 else
    1596                 {
    1597 #ifdef LOG_ENABLED
    1598                     char *pszFmts = ShClFormatsToStrA(fFormats);
    1599                     if (pszFmts)
    1600                     {
    1601                         LogRel2(("Shared Clipboard: Guest reported formats '%s' to host\n", pszFmts));
    1602                         RTStrFree(pszFmts);
    1603                     }
    1604 #endif
    1605                     rc = ShClBackendReportFormats(&g_ShClBackend, pClient, fFormats);
    1606                     if (RT_FAILURE(rc))
    1607                         LogRel(("Shared Clipboard: Reporting guest clipboard formats to the host failed with %Rrc\n", rc));
    1608                 }
    1609 
    1610                 RTCritSectLeave(&g_CritSect);
     1641                SHCLEXTPARMS parms;
     1642                RT_ZERO(parms);
     1643                parms.uFormat = fFormats;
     1644
     1645                g_ExtState.pfnExtension(g_ExtState.pvExtension, VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE, &parms, sizeof(parms));
    16111646            }
    16121647            else
    1613                 LogRel2(("Shared Clipboard: Unable to take internal lock while receiving guest clipboard announcement: %Rrc\n", rc));
    1614         }
     1648            {
     1649#ifdef LOG_ENABLED
     1650                char *pszFmts = ShClFormatsToStrA(fFormats);
     1651                if (pszFmts)
     1652                {
     1653                    LogRel2(("Shared Clipboard: Guest reported formats '%s' to host\n", pszFmts));
     1654                    RTStrFree(pszFmts);
     1655                }
     1656#endif
     1657                rc = ShClBackendReportFormats(&g_ShClBackend, pClient, fFormats);
     1658                if (RT_FAILURE(rc))
     1659                    LogRel(("Shared Clipboard: Reporting guest clipboard formats to the host failed with %Rrc\n", rc));
     1660            }
     1661
     1662            RTCritSectLeave(&g_CritSect);
     1663        }
     1664        else
     1665            LogRel2(("Shared Clipboard: Unable to take internal lock while receiving guest clipboard announcement: %Rrc\n", rc));
    16151666    }
    16161667
     
    17621813        else
    17631814            LogRel(("Shared Clipboard: Reading host clipboard data failed with %Rrc\n", rc));
    1764 
    1765 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    1766         /*
    1767          * When we receive a read request for URI data:
    1768          *   - Initialize a transfer locally.
    1769          *   - Tell the guest to initialize a transfer on the guest side.
    1770          *   - Start the transfer locally once we receive the transfer STARTED status from the guest via VBOX_SHCL_GUEST_FN_REPLY.
    1771          */
    1772         if (uFormat == VBOX_SHCL_FMT_URI_LIST) /* Only init a transfer if we supply an URI list. */
    1773         {
    1774             shClSvcClientLock(pClient);
    1775 
    1776             rc = shClSvcTransferInit(pClient, SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL,
    1777                                      NULL /* pTransfer */);
    1778             if (RT_SUCCESS(rc))
    1779                 rc = shClSvcSetSource(pClient, SHCLSOURCE_LOCAL);
    1780 
    1781             if (RT_FAILURE(rc))
    1782                 LogRel(("Shared Clipboard: Initializing host -> guest transfer failed with %Rrc\n", rc));
    1783 
    1784             shClSvcClientUnlock(pClient);
    1785         }
    1786 #endif
    17871815    }
    17881816
     
    19982026}
    19992027
    2000 /**
    2001  * Sets the transfer source type of a Shared Clipboard client.
    2002  *
    2003  * @returns VBox status code.
    2004  * @param   pClient             Client to set transfer source type for.
    2005  * @param   enmSource           Source type to set.
    2006  */
    2007 int shClSvcSetSource(PSHCLCLIENT pClient, SHCLSOURCE enmSource)
    2008 {
    2009     if (!pClient) /* If no client connected (anymore), bail out. */
    2010         return VINF_SUCCESS;
    2011 
    2012     int rc = VINF_SUCCESS;
    2013 
    2014     pClient->State.enmSource = enmSource;
    2015 
    2016     LogFlowFunc(("Source of client %RU32 is now %RU32\n", pClient->State.uClientID, pClient->State.enmSource));
    2017 
    2018     LogFlowFuncLeaveRC(rc);
    2019     return rc;
    2020 }
    2021 
    20222028static int svcInit(VBOXHGCMSVCFNTABLE *pTable)
    20232029{
     
    20692075        g_ExtState.uClientID = 0;
    20702076    }
    2071 
    2072 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    2073     shClSvcClientTransfersReset(pClient);
    2074 #endif
    20752077
    20762078    ShClBackendDisconnect(&g_ShClBackend, pClient);
     
    22502252
    22512253#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    2252                 shClSvcClientTransfersReset(pClient);
     2254                /* Reset transfer state. */
     2255                shClSvcTransferDestroyAll(pClient);
    22532256#endif
    22542257                shClSvcClientUnlock(pClient);
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardServiceHost.cpp

    r100204 r100367  
    330330
    331331#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
    332 int ShClBackendTransferCreate(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
    333 int ShClBackendTransferDestroy(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
    334 int ShClBackendTransferGetRoots(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
     332int ShClBackendTransferHandleStatusReply(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER, SHCLSOURCE, SHCLTRANSFERSTATUS, int) { return VINF_SUCCESS; }
     333int ShClBackendTransferHGRootListRead(PSHCLBACKEND, PSHCLCLIENT, PSHCLTRANSFER) { return VINF_SUCCESS; }
    335334#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
    336335
  • trunk/src/VBox/HostServices/SharedClipboard/testcase/tstClipboardTransfers.cpp

    r100204 r100367  
    212212{
    213213    PSHCLTRANSFER pTransfer;
    214     int rc = ShClTransferCreate(&pTransfer);
     214    int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer);
    215215    RTTESTI_CHECK_RC_OK(rc);
    216216
    217217    SHCLTXPROVIDER Provider;
    218     RTTESTI_CHECK(VBClTransferProviderLocalQueryInterface(&Provider) != NULL);
     218    RTTESTI_CHECK(ShClTransferProviderLocalQueryInterface(&Provider) != NULL);
    219219    RTTESTI_CHECK_RC_OK(ShClTransferSetProvider(pTransfer, &Provider));
    220220
     
    246246
    247247    PSHCLTRANSFER pTransfer;
    248     int rc = ShClTransferCreate(&pTransfer);
     248    int rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer);
    249249    RTTESTI_CHECK_RC_OK(rc);
    250250
    251251    SHCLTXPROVIDER Provider;
    252     VBClTransferProviderLocalQueryInterface(&Provider);
     252    ShClTransferProviderLocalQueryInterface(&Provider);
    253253
    254254    rc = ShClTransferSetProvider(pTransfer, &Provider);
    255255    RTTESTI_CHECK_RC_OK(rc);
    256256
    257     rc = ShClTransferInit(pTransfer, SHCLTRANSFERDIR_FROM_REMOTE, SHCLSOURCE_LOCAL);
     257    rc = ShClTransferInit(pTransfer);
    258258    RTTESTI_CHECK_RC_OK(rc);
    259259
     
    309309    RTTESTI_CHECK_RC_OK(rc);
    310310    PSHCLTRANSFER pTransfer;
    311     rc = ShClTransferCreate(&pTransfer);
     311    rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer);
    312312    RTTESTI_CHECK_RC_OK(rc);
    313313    rc = ShClTransferDestroy(pTransfer);
     
    318318    PSHCLLIST pList = ShClTransferListAlloc();
    319319    RTTESTI_CHECK(pList != NULL);
    320     rc = ShClTransferCreate(&pTransfer);
     320    rc = ShClTransferCreate(SHCLTRANSFERDIR_TO_REMOTE, SHCLSOURCE_LOCAL, &pTransfer);
    321321    RTTESTI_CHECK_RC_OK(rc);
    322322    ShClTransferListFree(pList);
  • trunk/src/VBox/Runtime/r3/http-server.cpp

    r100250 r100367  
    689689        case VERR_IS_A_DIRECTORY:       return RTHTTPSTATUS_FORBIDDEN;
    690690        case VERR_NOT_FOUND:            return RTHTTPSTATUS_NOTFOUND;
     691        case VERR_INTERNAL_ERROR:       return RTHTTPSTATUS_INTERNALSERVERERROR;
    691692        default:
    692693            break;
     
    713714    LogFlowFuncEnter();
    714715
    715     int rc = VINF_SUCCESS;
    716 
    717716    /* If a low-level GET request handler is defined, call it and return. */
    718717    RTHTTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnGetRequest, pReq);
     
    723722    char *pszMIMEHint = NULL;
    724723
     724    RTHTTPSTATUS enmStsResponse = RTHTTPSTATUS_OK;
     725
     726    int rc;
     727
    725728    RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, &pszMIMEHint);
    726729    if (RT_FAILURE(rc))
    727         return rc;
     730         enmStsResponse = rtHttpServerRcToStatus(rc);
    728731
    729732    void *pvHandle = NULL;
    730     RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle);
    731 
    732     if (RT_SUCCESS(rc))
    733     {
    734         size_t cbBuf = _64K;
    735         void  *pvBuf = RTMemAlloc(cbBuf);
    736         AssertPtrReturn(pvBuf, VERR_NO_MEMORY);
    737 
    738         for (;;)
    739         {
    740             RTHTTPHEADERLIST HdrLst;
    741             rc = RTHttpHeaderListInit(&HdrLst);
     733    if (RT_SUCCESS(rc)) /* Only call open if querying information above succeeded. */
     734        RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle);
     735
     736    size_t cbBuf = _64K;
     737    void  *pvBuf = RTMemAlloc(cbBuf);
     738    AssertPtrReturn(pvBuf, VERR_NO_MEMORY);
     739
     740    for (;;)
     741    {
     742        RTHTTPHEADERLIST HdrLst;
     743        rc = RTHttpHeaderListInit(&HdrLst);
     744        AssertRCReturn(rc, rc);
     745
     746        char szVal[16];
     747
     748        /* Note: For directories fsObj.cbObject contains the actual size (in bytes)
     749         *       of the body data for the directory listing. */
     750
     751        ssize_t cch = RTStrPrintf2(szVal, sizeof(szVal), "%RU64", fsObj.cbObject);
     752        AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     753        rc = RTHttpHeaderListAdd(HdrLst, "Content-Length", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
     754        AssertRCBreak(rc);
     755
     756        cch = RTStrPrintf2(szVal, sizeof(szVal), "identity");
     757        AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     758        rc = RTHttpHeaderListAdd(HdrLst, "Content-Encoding", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
     759        AssertRCBreak(rc);
     760
     761        if (pszMIMEHint == NULL)
     762        {
     763            const char *pszMIME = rtHttpServerGuessMIMEType(RTPathSuffix(pReq->pszUrl));
     764            rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIME, strlen(pszMIME), RTHTTPHEADERLISTADD_F_BACK);
     765        }
     766        else
     767        {
     768            rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIMEHint, strlen(pszMIMEHint), RTHTTPHEADERLISTADD_F_BACK);
     769            RTStrFree(pszMIMEHint);
     770            pszMIMEHint = NULL;
     771        }
     772        AssertRCBreak(rc);
     773
     774        if (pClient->State.msKeepAlive)
     775        {
     776            /* If the client requested to keep alive the connection,
     777             * always override this with 30s and report this back to the client. */
     778            pClient->State.msKeepAlive = RT_MS_30SEC; /** @todo Make this configurable. */
     779#ifdef DEBUG_andy
     780            pClient->State.msKeepAlive = 5000;
     781#endif
     782            cch = RTStrPrintf2(szVal, sizeof(szVal), "timeout=%RU64", pClient->State.msKeepAlive / RT_MS_1SEC); /** @todo No pipelining support here yet. */
     783            AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
     784            rc = RTHttpHeaderListAdd(HdrLst, "Keep-Alive", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    742785            AssertRCReturn(rc, rc);
    743 
    744             char szVal[16];
    745 
    746             /* Note: For directories fsObj.cbObject contains the actual size (in bytes)
    747              *       of the body data for the directory listing. */
    748 
    749             ssize_t cch = RTStrPrintf2(szVal, sizeof(szVal), "%RU64", fsObj.cbObject);
    750             AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    751             rc = RTHttpHeaderListAdd(HdrLst, "Content-Length", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    752             AssertRCBreak(rc);
    753 
    754             cch = RTStrPrintf2(szVal, sizeof(szVal), "identity");
    755             AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    756             rc = RTHttpHeaderListAdd(HdrLst, "Content-Encoding", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    757             AssertRCBreak(rc);
    758 
    759             if (pszMIMEHint == NULL)
     786        }
     787
     788        rc = rtHttpServerSendResponseEx(pClient, enmStsResponse, &HdrLst);
     789
     790        RTHttpHeaderListDestroy(HdrLst);
     791
     792        if (rc == VERR_BROKEN_PIPE) /* Could happen on fast reloads. */
     793            break;
     794        AssertRCReturn(rc, rc);
     795
     796        size_t cbToRead  = fsObj.cbObject;
     797        size_t cbRead    = 0; /* Shut up GCC. */
     798        size_t cbWritten = 0; /* Ditto. */
     799        while (cbToRead)
     800        {
     801            RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);
     802            if (RT_FAILURE(rc))
     803                break;
     804            rc = rtHttpServerSendResponseBody(pClient, pvBuf, cbRead, &cbWritten);
     805            AssertBreak(cbToRead >= cbWritten);
     806            cbToRead -= cbWritten;
     807            if (rc == VERR_NET_CONNECTION_RESET_BY_PEER) /* Clients often apruptly abort the connection when done. */
    760808            {
    761                 const char *pszMIME = rtHttpServerGuessMIMEType(RTPathSuffix(pReq->pszUrl));
    762                 rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIME, strlen(pszMIME), RTHTTPHEADERLISTADD_F_BACK);
    763             }
    764             else
    765             {
    766                 rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", pszMIMEHint, strlen(pszMIMEHint), RTHTTPHEADERLISTADD_F_BACK);
    767                 RTStrFree(pszMIMEHint);
    768                 pszMIMEHint = NULL;
     809                rc = VINF_SUCCESS;
     810                break;
    769811            }
    770812            AssertRCBreak(rc);
    771 
    772             if (pClient->State.msKeepAlive)
    773             {
    774                 /* If the client requested to keep alive the connection,
    775                  * always override this with 30s and report this back to the client. */
    776                 pClient->State.msKeepAlive = RT_MS_30SEC; /** @todo Make this configurable. */
    777 #ifdef DEBUG_andy
    778                 pClient->State.msKeepAlive = 5000;
    779 #endif
    780                 cch = RTStrPrintf2(szVal, sizeof(szVal), "timeout=%RU64", pClient->State.msKeepAlive / RT_MS_1SEC); /** @todo No pipelining support here yet. */
    781                 AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW);
    782                 rc = RTHttpHeaderListAdd(HdrLst, "Keep-Alive", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK);
    783                 AssertRCReturn(rc, rc);
    784             }
    785 
    786             rc = rtHttpServerSendResponseEx(pClient, RTHTTPSTATUS_OK, &HdrLst);
    787 
    788             RTHttpHeaderListDestroy(HdrLst);
    789 
    790             if (rc == VERR_BROKEN_PIPE) /* Could happen on fast reloads. */
    791                 break;
    792             AssertRCReturn(rc, rc);
    793 
    794             size_t cbToRead  = fsObj.cbObject;
    795             size_t cbRead    = 0; /* Shut up GCC. */
    796             size_t cbWritten = 0; /* Ditto. */
    797             while (cbToRead)
    798             {
    799                 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pReq, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead);
    800                 if (RT_FAILURE(rc))
    801                     break;
    802                 rc = rtHttpServerSendResponseBody(pClient, pvBuf, cbRead, &cbWritten);
    803                 AssertBreak(cbToRead >= cbWritten);
    804                 cbToRead -= cbWritten;
    805                 if (rc == VERR_NET_CONNECTION_RESET_BY_PEER) /* Clients often apruptly abort the connection when done. */
    806                 {
    807                     rc = VINF_SUCCESS;
    808                     break;
    809                 }
    810                 AssertRCBreak(rc);
    811             }
    812 
    813             break;
    814         } /* for (;;) */
    815 
    816         RTMemFree(pvBuf);
    817 
    818         int rc2 = rc; /* Save rc. */
    819 
     813        }
     814
     815        break;
     816    } /* for (;;) */
     817
     818    RTMemFree(pvBuf);
     819
     820    int rc2 = rc; /* Save rc. */
     821
     822    if (pvHandle)
    820823        RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pReq, pvHandle);
    821824
    822         if (RT_FAILURE(rc2)) /* Restore original rc on failure. */
    823             rc = rc2;
    824     }
     825    if (RT_FAILURE(rc2)) /* Restore original rc on failure. */
     826        rc = rc2;
    825827
    826828    LogFlowFuncLeaveRC(rc);
     
    12241226                if (RT_FAILURE(rcMethod))
    12251227                    LogFunc(("Request %s %s failed with %Rrc\n", RTHttpMethodToStr(pReq->enmMethod), pReq->pszUrl, rcMethod));
    1226 
    1227                 enmSts = rtHttpServerRcToStatus(rcMethod);
    12281228                break;
    12291229            }
     
    12421242    /* Make sure to return at least *something* to the client, to prevent hangs. */
    12431243    if (enmSts == RTHTTPSTATUS_INTERNAL_NOT_SET)
    1244         enmSts = RTHTTPSTATUS_INTERNALSERVERERROR;
     1244        enmSts = rtHttpServerRcToStatus(VERR_INTERNAL_ERROR);
    12451245
    12461246    int rc2 = rtHttpServerSendResponseSimple(pClient, enmSts);
     
    12571257 * @returns VBox status code.
    12581258 * @param   pClient             Client to process requests for.
    1259  */
    1260 static int rtHttpServerClientMain(PRTHTTPSERVERCLIENT pClient)
     1259 * @param   msTimeout           Timeout to wait for reading data.
     1260 *                              Gets renewed for a each reading round.
     1261 */
     1262static int rtHttpServerClientMain(PRTHTTPSERVERCLIENT pClient, RTMSINTERVAL msTimeout)
    12611263{
    12621264    int rc;
     
    12691271    pClient->State.msKeepAlive = 0;
    12701272
    1271     RTMSINTERVAL cWaitMs      = RT_INDEFINITE_WAIT; /* The first wait always waits indefinitely. */
     1273    RTMSINTERVAL cWaitMs      = msTimeout;
    12721274    uint64_t     tsLastReadMs = 0;
    12731275
    1274     for (;;)
     1276    for (;;) /* For keep-alive handling. */
    12751277    {
    12761278        rc = RTTcpSelectOne(pClient->hSocket, cWaitMs);
     
    13491351            rc = rtHttpServerProcessRequest(pClient, szReq, cbReadTotal);
    13501352        }
    1351         else
    1352             break;
     1353
     1354        break;
    13531355
    13541356    } /* for */
     
    13951397    Client.hSocket = hSocket;
    13961398
    1397     return rtHttpServerClientMain(&Client);
     1399    return rtHttpServerClientMain(&Client, RT_MS_30SEC /* Timeout */);
    13981400}
    13991401
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette