VirtualBox

Changeset 78501 in vbox


Ignore:
Timestamp:
May 14, 2019 11:36:25 AM (5 years ago)
Author:
vboxsync
Message:

Shared Clipboard/URI: Update.

Location:
trunk
Files:
2 added
10 edited
1 moved

Legend:

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

    r78440 r78501  
    3232
    3333#include <iprt/assert.h>
     34#include <iprt/critsect.h>
    3435#include <iprt/fs.h>
    3536
     
    3738#include <iprt/cpp/ministring.h>
    3839
    39 /** SharedClipboardDroppedFiles flags. */
    40 typedef uint32_t SHAREDCLIPBOARDDROPPEDFILEFLAGS;
     40/** SharedClipboardCache flags. */
     41typedef uint32_t SHAREDCLIPBOARDCACHEFLAGS;
    4142
    4243/** No flags specified. */
    43 #define SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE                   0
     44#define SHAREDCLIPBOARDCACHE_FLAGS_NONE     0
    4445
    4546/**
    46  * Class for maintaining a "dropped files" directory
     47 * Class for maintaining a Shared Clipboard cache
    4748 * on the host or guest. This will contain all received files & directories
    48  * for a single Shared Clipboard "paste" operation.
     49 * for a single Shared Clipboard operation.
    4950 *
    5051 * In case of a failed Shared Clipboard operation this class can also
    5152 * perform a gentle rollback if required.
    5253 */
    53 class SharedClipboardDroppedFiles
     54class SharedClipboardCache
    5455{
    5556
    5657public:
    5758
    58     SharedClipboardDroppedFiles(void);
    59     SharedClipboardDroppedFiles(const char *pszPath, SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
    60     virtual ~SharedClipboardDroppedFiles(void);
    61 
    62 public:
     59    SharedClipboardCache(void);
     60    SharedClipboardCache(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
     61    virtual ~SharedClipboardCache(void);
     62
     63public:
     64
     65    uint16_t AddRef(void);
     66    uint16_t Release(void);
     67
     68    int Lock(void);
     69    int Unlock(void);
    6370
    6471    int AddFile(const char *pszFile);
     
    6673    int Close(void);
    6774    bool IsOpen(void) const;
    68     int OpenEx(const char *pszPath, SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
    69     int OpenTemp(SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
     75    int OpenEx(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
     76    int OpenTemp(SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
    7077    const char *GetDirAbs(void) const;
    7178    int Reopen(void);
     
    7582protected:
    7683
     84    int initInternal(void);
     85    int destroyInternal(void);
    7786    int closeInternal(void);
    7887
    7988protected:
    8089
     90    /** Number of references to this instance. */
     91    volatile uint16_t            m_cRefs;
     92    /** Critical section for serializing access. */
     93    RTCRITSECT                   m_CritSect;
    8194    /** Open flags. */
    8295    uint32_t                     m_fOpen;
     
    91104};
    92105
    93 int SharedClipboardSanitizeFilename(char *pszPath, size_t cbPath);
     106int SharedClipboardPathSanitizeFilename(char *pszPath, size_t cbPath);
    94107int SharedClipboardPathSanitize(char *pszPath, size_t cbPath);
    95108
  • trunk/include/VBox/GuestHost/SharedClipboard-win.h

    r78474 r78501  
    3737# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    3838#  include <iprt/cpp/ministring.h> /* For RTCString. */
     39#  include <iprt/win/shlobj.h> /* For DROPFILES and friends. */
    3940#  include <oleidl.h>
    4041# endif
     
    4950 *       Do *not* change the name, as this will break compatbility with other (legacy) applications! */
    5051#define VBOX_CLIPBOARD_WIN_REGFMT_HTML       "HTML Format"
    51 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    52 #  define VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST "VBoxURIList"
    53 #endif
    5452
    5553/** Default timeout (in ms) for passing down messages down the clipboard chain. */
     
    127125int VBoxClipboardWinRemoveFromCBChain(PVBOXCLIPBOARDWINCTX pCtx);
    128126VOID CALLBACK VBoxClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
     127
    129128VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat);
    130129int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMAT pfFormats);
    131130
     131#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     132int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, void **ppvData, size_t *pcbData);
     133#endif
     134
     135int VBoxClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
     136bool VBoxClipboardWinIsCFHTML(const char *pszSource);
     137int VBoxClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
     138int VBoxClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
     139
    132140# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    133141class SharedClipboardURIList;
     142#  ifndef FILEGROUPDESCRIPTOR
    134143class FILEGROUPDESCRIPTOR;
     144#  endif
    135145
    136146class VBoxClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r78476 r78501  
    5656 ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    5757 VBoxTray_SOURCES  += \
    58         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
    59         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \
    60         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
     58        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \
    6159        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp \
    6260        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp \
    63         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
     61        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
     62        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp \
     63        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
     64        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp
    6465 endif
    6566endif
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r78474 r78501  
    7979    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
    8080
    81     LRESULT rc = 0;
     81    LRESULT lresultRc = 0;
    8282
    8383    switch (msg)
     
    8787           if (GetClipboardOwner() != hwnd)
    8888           {
    89                Log(("WM_CLIPBOARDUPDATE\n"));
    90 
    91                /* Clipboard was updated by another application. */
     89               /* Clipboard was updated by another application.
     90                * Report available formats to the host. */
    9291               VBOXCLIPBOARDFORMATS fFormats;
    93                int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
    94                if (RT_SUCCESS(vboxrc))
    95                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
     92               int rc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
     93               if (RT_SUCCESS(rc))
     94                   rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
     95
     96               LogFunc(("WM_CLIPBOARDUPDATE: rc=%Rrc, fFormats=0x%x\n", rc, fFormats));
    9697           }
     98           else
     99               LogFlowFunc(("WM_CLIPBOARDUPDATE: No change (VBoxTray is owner)\n"));
    97100        }
    98101        break;
     
    102105           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    103106           {
    104                rc = DefWindowProc(hwnd, msg, wParam, lParam);
     107               lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    105108               break;
    106109           }
     
    123126                   /* Pass the message further. */
    124127                   DWORD_PTR dwResult;
    125                    rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
    126                                            VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
    127                    if (!rc)
    128                        rc = (LRESULT)dwResult;
     128                   lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
     129                                                  VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
     130                   if (!lresultRc)
     131                       lresultRc = (LRESULT)dwResult;
    129132               }
    130133           }
     
    141144               /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
    142145               VBOXCLIPBOARDFORMATS fFormats;
    143                int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
    144                if (RT_SUCCESS(vboxrc))
    145                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
     146               int rc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
     147               if (RT_SUCCESS(rc))
     148                   rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
    146149            }
    147150
     
    197200            LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
    198201
    199             if (fFormat != VBOX_SHARED_CLIPBOARD_FMT_NONE)
     202            if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
     203            {
     204                LogFunc(("WM_RENDERFORMAT: Unsupported format requested\n"));
     205                VBoxClipboardWinClear();
     206            }
     207            else
    200208            {
    201209                const uint32_t cbPrealloc = _4K;
     
    214222                    {
    215223                        /* Read the host data to the preallocated buffer. */
    216                         int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
    217                         LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));
    218 
    219                         if (RT_SUCCESS(vboxrc))
     224                        int rc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
     225                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  rc));
     226
     227                        if (RT_SUCCESS(rc))
    220228                        {
    221229                            if (cb == 0)
     
    245253                                        /* Read the host data to the preallocated buffer. */
    246254                                        uint32_t cbNew = 0;
    247                                         vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
     255                                        rc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
    248256                                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n",
    249                                                      vboxrc, cb, cbNew));
    250 
    251                                         if (RT_SUCCESS(vboxrc)
     257                                                     rc, cb, cbNew));
     258
     259                                        if (RT_SUCCESS(rc)
    252260                                            && cbNew <= cb)
    253261                                        {
     
    335343            * windows is to be destroyed and therefore the guest side becomes inactive.
    336344            */
    337             int vboxrc = VBoxClipboardWinOpen(hwnd);
    338             if (RT_SUCCESS(vboxrc))
     345            int rc = VBoxClipboardWinOpen(hwnd);
     346            if (RT_SUCCESS(rc))
    339347            {
    340348               VBoxClipboardWinClear();
     
    351359           LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
    352360
    353            int vboxrc = VBoxClipboardWinOpen(hwnd);
    354            if (RT_SUCCESS(vboxrc))
     361           int rc = VBoxClipboardWinOpen(hwnd);
     362           if (RT_SUCCESS(rc))
    355363           {
    356364               VBoxClipboardWinClear();
     
    366374                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);
    367375               }
    368 
    369376               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    370377               {
     
    372379                   hClip = SetClipboardData(CF_DIB, NULL);
    373380               }
    374 
    375381               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    376382               {
     
    380386                       hClip = SetClipboardData(cfFormat, NULL);
    381387               }
    382 
    383388#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    384389               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     
    390395                       if (pWinCtx->URI.pDataObj)
    391396                       {
    392                            int vboxrc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
    393                            if (RT_SUCCESS(vboxrc))
     397                           rc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
     398                           if (RT_SUCCESS(rc))
    394399                           {
    395400                               VBoxClipboardWinClose();
     
    429434            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
    430435
    431             int vboxrc = VBoxClipboardWinOpen(hwnd);
    432             if (RT_SUCCESS(vboxrc))
     436            int rc = VBoxClipboardWinOpen(hwnd);
     437            if (RT_SUCCESS(rc))
    433438            {
    434439               if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    435440               {
    436441                   hClip = GetClipboardData(CF_DIB);
    437 
    438442                   if (hClip != NULL)
    439443                   {
     
    441445                       if (lp != NULL)
    442446                       {
    443                            vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
    444                                                              lp, GlobalSize(hClip));
     447                           rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
     448                                                         lp, GlobalSize(hClip));
    445449                           GlobalUnlock(hClip);
    446450                       }
     
    454458               {
    455459                   hClip = GetClipboardData(CF_UNICODETEXT);
    456 
    457460                   if (hClip != NULL)
    458461                   {
    459462                       LPWSTR uniString = (LPWSTR)GlobalLock(hClip);
    460 
    461463                       if (uniString != NULL)
    462464                       {
    463                            vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    464                                                              uniString, (lstrlenW(uniString) + 1) * 2);
     465                           rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     466                                                         uniString, (lstrlenW(uniString) + 1) * 2);
    465467                           GlobalUnlock(hClip);
    466468                       }
     
    483485                           if (lp != NULL)
    484486                           {
    485                                vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
    486                                                                  lp, GlobalSize(hClip));
     487                               rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
     488                                                             lp, GlobalSize(hClip));
    487489                               GlobalUnlock(hClip);
    488490                           }
     
    497499               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    498500               {
    499                    UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST);
    500                    if (format != 0)
     501                   /* The data data in CF_HDROP format, as the files are locally present and don't need to be
     502                    * presented as a IDataObject or IStream. */
     503                   hClip = GetClipboardData(CF_HDROP);
     504                   if (hClip)
    501505                   {
    502                        hClip = GetClipboardData(format);
    503                        if (hClip)
     506                       HDROP hDrop = (HDROP)GlobalLock(hClip);
     507                       if (hDrop)
    504508                       {
    505                            HDROP hDrop = (HDROP)GlobalLock(hClip);
    506                            if (hDrop)
    507                            {
    508             /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
    509                                                                  );*/
    510                                GlobalUnlock(hClip);
    511                            }
    512                            else
    513                            {
    514                                hClip = NULL;
    515                            }
     509        /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
     510                                                             );*/
     511                           GlobalUnlock(hClip);
     512                       }
     513                       else
     514                       {
     515                           hClip = NULL;
    516516                       }
    517517                   }
     
    543543        default:
    544544        {
    545             rc = DefWindowProc(hwnd, msg, wParam, lParam);
     545            lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    546546        }
    547547        break;
     
    549549
    550550#ifndef DEBUG_andy
    551     LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
     551    LogFlowFunc(("vboxClipboardProcessMsg returned with lresultRc=%ld\n", lresultRc));
    552552#endif
    553     return rc;
     553    return lresultRc;
    554554}
    555555
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp

    r78500 r78501  
    11/* $Id$ */
    22/** @file
    3  * Shared Clipboard - Directory handling.
     3 * Shared Clipboard - Cache handling.
    44 */
    55
     
    2323#include <VBox/GuestHost/SharedClipboard-uri.h>
    2424
     25#include <iprt/asm.h>
    2526#include <iprt/assert.h>
    2627#include <iprt/dir.h>
     
    3334#include <VBox/log.h>
    3435
    35 SharedClipboardDroppedFiles::SharedClipboardDroppedFiles(void)
    36     : m_fOpen(0)
    37     , m_hDir(NULL) { }
    38 
    39 SharedClipboardDroppedFiles::SharedClipboardDroppedFiles(const char *pszPath,
    40                                                          SHAREDCLIPBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
    41     : m_fOpen(0)
     36SharedClipboardCache::SharedClipboardCache(void)
     37    : m_cRefs(0)
     38    , m_fOpen(0)
    4239    , m_hDir(NULL)
    4340{
    44     OpenEx(pszPath, fFlags);
    45 }
    46 
    47 SharedClipboardDroppedFiles::~SharedClipboardDroppedFiles(void)
     41    int rc = initInternal();
     42    if (RT_FAILURE(rc))
     43        throw rc;
     44}
     45
     46SharedClipboardCache::SharedClipboardCache(const char *pszPath,
     47                                           SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
     48    : m_cRefs(0)
     49    , m_fOpen(0)
     50    , m_hDir(NULL)
     51{
     52    int rc = initInternal();
     53    if (RT_SUCCESS(rc))
     54        rc = OpenEx(pszPath, fFlags);
     55
     56    if (RT_FAILURE(rc))
     57        throw rc;
     58}
     59
     60SharedClipboardCache::~SharedClipboardCache(void)
    4861{
    4962    /* Only make sure to not leak any handles and stuff, don't delete any
    5063     * directories / files here. */
    5164    closeInternal();
    52 }
    53 
    54 int SharedClipboardDroppedFiles::AddFile(const char *pszFile)
     65
     66    int rc = destroyInternal();
     67    AssertRC(rc);
     68}
     69
     70/**
     71 * Adds a reference to a Shared Clipboard cache.
     72 *
     73 * @returns New reference count.
     74 */
     75uint16_t SharedClipboardCache::AddRef(void)
     76{
     77    return ASMAtomicIncU16(&m_cRefs);
     78}
     79
     80/**
     81 * Removes a reference from a Shared Clipboard cache.
     82 *
     83 * @returns New reference count.
     84 */
     85uint16_t SharedClipboardCache::Release(void)
     86{
     87    Assert(m_cRefs);
     88    return ASMAtomicDecU16(&m_cRefs);
     89}
     90
     91/**
     92 * Locks a Shared Clipboard cache.
     93 *
     94 * @returns VBox status code.
     95 */
     96int SharedClipboardCache::Lock(void)
     97{
     98    return RTCritSectEnter(&m_CritSect);
     99}
     100
     101/**
     102 * Unlocks a Shared Clipboard cache.
     103 *
     104 * @returns VBox status code.
     105 */
     106int SharedClipboardCache::Unlock(void)
     107{
     108    return RTCritSectLeave(&m_CritSect);
     109}
     110
     111int SharedClipboardCache::AddFile(const char *pszFile)
    55112{
    56113    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
     
    61118}
    62119
    63 int SharedClipboardDroppedFiles::AddDir(const char *pszDir)
     120int SharedClipboardCache::AddDir(const char *pszDir)
    64121{
    65122    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
     
    70127}
    71128
    72 int SharedClipboardDroppedFiles::closeInternal(void)
     129int SharedClipboardCache::initInternal(void)
     130{
     131    return RTCritSectInit(&m_CritSect);
     132}
     133
     134int SharedClipboardCache::destroyInternal(void)
     135{
     136    return RTCritSectDelete(&m_CritSect);
     137}
     138
     139int SharedClipboardCache::closeInternal(void)
    73140{
    74141    int rc;
     
    86153}
    87154
    88 int SharedClipboardDroppedFiles::Close(void)
     155int SharedClipboardCache::Close(void)
    89156{
    90157    return closeInternal();
    91158}
    92159
    93 const char *SharedClipboardDroppedFiles::GetDirAbs(void) const
     160const char *SharedClipboardCache::GetDirAbs(void) const
    94161{
    95162    return this->m_strPathAbs.c_str();
    96163}
    97164
    98 bool SharedClipboardDroppedFiles::IsOpen(void) const
     165bool SharedClipboardCache::IsOpen(void) const
    99166{
    100167    return (this->m_hDir != NULL);
    101168}
    102169
    103 int SharedClipboardDroppedFiles::OpenEx(const char *pszPath, SHAREDCLIPBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
     170int SharedClipboardCache::OpenEx(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
    104171{
    105172    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
     
    168235}
    169236
    170 int SharedClipboardDroppedFiles::OpenTemp(SHAREDCLIBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
     237int SharedClipboardCache::OpenTemp(SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
    171238{
    172239    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
     
    185252}
    186253
    187 int SharedClipboardDroppedFiles::Reset(bool fRemoveDropDir)
     254int SharedClipboardCache::Reset(bool fRemoveDropDir)
    188255{
    189256    int rc = closeInternal();
     
    205272}
    206273
    207 int SharedClipboardDroppedFiles::Reopen(void)
     274int SharedClipboardCache::Reopen(void)
    208275{
    209276    if (this->m_strPathAbs.isEmpty())
     
    213280}
    214281
    215 int SharedClipboardDroppedFiles::Rollback(void)
     282int SharedClipboardCache::Rollback(void)
    216283{
    217284    if (this->m_strPathAbs.isEmpty())
  • trunk/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp

    r78390 r78501  
    6464}
    6565
     66/**
     67 * Sanitizes a given path regarding invalid / unhandled characters.
     68 * Currently not implemented.
     69 *
     70 * @returns VBox status code.
     71 * @param   pszPath             Path to sanitize. UTF-8.
     72 * @param   cbPath              Size (in bytes) of the path to sanitize.
     73 */
    6674int SharedClipboardPathSanitize(char *pszPath, size_t cbPath)
    6775{
    6876    /** @todo */
    69     RT_NOREF2(pszPath, cbPath);
     77    RT_NOREF(pszPath, cbPath);
    7078    return VINF_SUCCESS;
    7179}
  • trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp

    r78474 r78501  
    2222#include <iprt/thread.h>
    2323
     24#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     25# include <iprt/utf16.h>
     26#endif
     27
    2428#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
    2529#include <VBox/log.h>
    2630
    2731#include <VBox/GuestHost/SharedClipboard.h>
     32#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     33# include <VBox/GuestHost/SharedClipboard-uri.h>
     34#endif
    2835#include <VBox/GuestHost/SharedClipboard-win.h>
    2936#include <VBox/GuestHost/clipboard-helper.h>
     
    277284}
    278285
     286/**
     287 * Converts a (registered or standard) Windows clipboard format to a VBox clipboard format.
     288 *
     289 * @returns Converted VBox clipboard format, or VBOX_SHARED_CLIPBOARD_FMT_NONE if not found.
     290 * @param   uFormat             Windows clipboard format to convert.
     291 */
    279292VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat)
    280293{
     
    284297    switch (uFormat)
    285298    {
    286       case CF_UNICODETEXT:
    287           vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    288           break;
    289 
    290       case CF_DIB:
    291           vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    292           break;
    293 
    294       default:
    295           if (uFormat >= 0xC000) /** Formats registered with RegisterClipboardFormat() start at this index. */
    296           {
    297               TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
    298               int cActual = GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
    299               if (cActual)
    300               {
    301                   LogFunc(("szFormatName=%s\n", szFormatName));
    302 
    303                   if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0)
    304                       vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
     299        case CF_UNICODETEXT:
     300            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
     301            break;
     302
     303        case CF_DIB:
     304            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
     305            break;
     306
    305307#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    306                   else if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST) == 0)
    307                       vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
     308        /* Handles file system entries which are locally present
     309         * on source for transferring to the target. */
     310        case CF_HDROP:
     311            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
     312            break;
    308313#endif
    309               }
    310           }
    311           break;
    312     }
    313 
     314
     315        default:
     316            if (uFormat >= 0xC000) /** Formats registered with RegisterClipboardFormat() start at this index. */
     317            {
     318                TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
     319                int cActual = GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
     320                if (cActual)
     321                {
     322                    LogFlowFunc(("uFormat=%u -> szFormatName=%s\n", uFormat, szFormatName));
     323
     324                    if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0)
     325                        vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
     326                }
     327            }
     328            break;
     329    }
     330
     331    LogFlowFunc(("uFormat=%u -> vboxFormat=0x%x\n", uFormat, vboxFormat));
    314332    return vboxFormat;
    315333}
     
    354372}
    355373
     374/**
     375 * Extracts a field value from CF_HTML data.
     376 *
     377 * @returns VBox status code.
     378 * @param   pszSrc      source in CF_HTML format.
     379 * @param   pszOption   Name of CF_HTML field.
     380 * @param   puValue     Where to return extracted value of CF_HTML field.
     381 */
     382int VBoxClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)
     383{
     384    AssertPtrReturn(pszSrc, VERR_INVALID_POINTER);
     385    AssertPtrReturn(pszOption, VERR_INVALID_POINTER);
     386
     387    int rc = VERR_INVALID_PARAMETER;
     388
     389    const char *pszOptionValue = RTStrStr(pszSrc, pszOption);
     390    if (pszOptionValue)
     391    {
     392        size_t cchOption = strlen(pszOption);
     393        Assert(cchOption);
     394
     395        rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);
     396    }
     397    return rc;
     398}
     399
     400/**
     401 * Check that the source string contains CF_HTML struct.
     402 *
     403 * @returns @c true if the @a pszSource string is in CF_HTML format.
     404 * @param   pszSource   Source string to check.
     405 */
     406bool VBoxClipboardWinIsCFHTML(const char *pszSource)
     407{
     408    return    RTStrStr(pszSource, "Version:") != NULL
     409           && RTStrStr(pszSource, "StartHTML:") != NULL;
     410}
     411
     412/**
     413 * Converts clipboard data from CF_HTML format to MIME clipboard format.
     414 *
     415 * Returns allocated buffer that contains html converted to text/html mime type
     416 *
     417 * @returns VBox status code.
     418 * @param   pszSource   The input.
     419 * @param   cch         The length of the input.
     420 * @param   ppszOutput  Where to return the result.  Free using RTMemFree.
     421 * @param   pcbOutput   Where to the return length of the result (bytes/chars).
     422 */
     423int VBoxClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)
     424{
     425    Assert(pszSource);
     426    Assert(cch);
     427    Assert(ppszOutput);
     428    Assert(pcbOutput);
     429
     430    uint32_t offStart;
     431    int rc = VBoxClipboardWinGetCFHTMLHeaderValue(pszSource, "StartFragment:", &offStart);
     432    if (RT_SUCCESS(rc))
     433    {
     434        uint32_t offEnd;
     435        rc = VBoxClipboardWinGetCFHTMLHeaderValue(pszSource, "EndFragment:", &offEnd);
     436        if (RT_SUCCESS(rc))
     437        {
     438            if (   offStart > 0
     439                && offEnd > 0
     440                && offEnd > offStart
     441                && offEnd <= cch)
     442            {
     443                uint32_t cchSubStr = offEnd - offStart;
     444                char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);
     445                if (pszResult)
     446                {
     447                    rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);
     448                    if (RT_SUCCESS(rc))
     449                    {
     450                        *ppszOutput = pszResult;
     451                        *pcbOutput  = (uint32_t)(cchSubStr + 1);
     452                        rc = VINF_SUCCESS;
     453                    }
     454                    else
     455                    {
     456                        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
     457                        RTMemFree(pszResult);
     458                    }
     459                }
     460                else
     461                {
     462                    LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));
     463                    rc = VERR_NO_MEMORY;
     464                }
     465            }
     466            else
     467            {
     468                LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));
     469                rc = VERR_INVALID_PARAMETER;
     470            }
     471        }
     472        else
     473        {
     474            LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
     475            rc = VERR_INVALID_PARAMETER;
     476        }
     477    }
     478    else
     479    {
     480        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc\n", rc));
     481        rc = VERR_INVALID_PARAMETER;
     482    }
     483
     484    return rc;
     485}
     486
     487/**
     488 * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.
     489 *
     490 * This is just encapsulation work, slapping a header on the data.
     491 *
     492 * It allocates [..]
     493 *
     494 * Calculations:
     495 *   Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
     496 *   EndHtml       = Header length + fragment length
     497 *   StartHtml     = 105(constant)
     498 *   StartFragment = 141(constant) may vary if the header html content will be extended
     499 *   EndFragment   = Header length + fragment length - 38(ending length)
     500 *
     501 * @param   pszSource   Source buffer that contains utf-16 string in mime html format
     502 * @param   cb          Size of source buffer in bytes
     503 * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
     504 *                      CF_HTML clipboard data.  This function allocates memory for this.
     505 * @param   pcbOutput   Where to return the size of allocated result buffer in bytes/chars, including zero terminator
     506 *
     507 * @note    output buffer should be free using RTMemFree()
     508 * @note    Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
     509 */
     510int VBoxClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
     511{
     512    Assert(ppszOutput);
     513    Assert(pcbOutput);
     514    Assert(pszSource);
     515    Assert(cb);
     516
     517    /* construct CF_HTML formatted string */
     518    char *pszResult = NULL;
     519    size_t cchFragment;
     520    int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
     521    if (!RT_SUCCESS(rc))
     522    {
     523        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));
     524        return VERR_INVALID_PARAMETER;
     525    }
     526
     527    /*
     528    @StartHtml - pos before <html>
     529    @EndHtml - whole size of text excluding ending zero char
     530    @StartFragment - pos after <!--StartFragment-->
     531    @EndFragment - pos before <!--EndFragment-->
     532    @note: all values includes CR\LF inserted into text
     533    Calculations:
     534    Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
     535    EndHtml  = Header length + fragment length
     536    StartHtml = 105(constant)
     537    StartFragment = 143(constant)
     538    EndFragment  = Header length + fragment length - 40(ending length)
     539    */
     540    static const char s_szFormatSample[] =
     541    /*   0:   */ "Version:1.0\r\n"
     542    /*  13:   */ "StartHTML:000000101\r\n"
     543    /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
     544    /*  53:   */ "StartFragment:000000137\r\n"
     545    /*  78:   */ "EndFragment:%0000009u\r\n"
     546    /* 101:   */ "<html>\r\n"
     547    /* 109:   */ "<body>\r\n"
     548    /* 117:   */ "<!--StartFragment-->"
     549    /* 137:   */ "%s"
     550    /* 137+2: */ "<!--EndFragment-->\r\n"
     551    /* 157+2: */ "</body>\r\n"
     552    /* 166+2: */ "</html>\r\n";
     553    /* 175+2: */
     554    AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
     555
     556    /* calculate parameters of CF_HTML header */
     557    size_t cchHeader      = sizeof(s_szFormatSample) - 1;
     558    size_t offEndHtml     = cchHeader + cchFragment;
     559    size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
     560    pszResult = (char *)RTMemAlloc(offEndHtml + 1);
     561    if (pszResult == NULL)
     562    {
     563        LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
     564        return VERR_NO_MEMORY;
     565    }
     566
     567    /* format result CF_HTML string */
     568    size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
     569                                      s_szFormatSample, offEndHtml, offEndFragment, pszSource);
     570    Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
     571
     572#ifdef VBOX_STRICT
     573    /* Control calculations. check consistency.*/
     574    static const char s_szStartFragment[] = "<!--StartFragment-->";
     575    static const char s_szEndFragment[] = "<!--EndFragment-->";
     576
     577    /* check 'StartFragment:' value */
     578    const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
     579    Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
     580
     581    /* check 'EndFragment:' value */
     582    const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
     583    Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
     584#endif
     585
     586    *ppszOutput = pszResult;
     587    *pcbOutput = (uint32_t)cchFormatted + 1;
     588    Assert(*pcbOutput == cchFormatted + 1);
     589
     590    return VINF_SUCCESS;
     591}
     592
     593#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     594/**
     595 * Converts a DROPFILES (HDROP) structure to a string list, separated by \r\n.
     596 *
     597 * @returns VBox status code.
     598 * @param   pDropFiles          Pointer to DROPFILES structure to convert.
     599 * @param   ppvData             Where to return the converted (allocated) data on success.
     600 * @param   pcbData             Size (in bytes) of the allocated data returned.
     601 */
     602int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, void **ppvData, size_t *pcbData)
     603{
     604    AssertPtrReturn(pDropFiles, VERR_INVALID_POINTER);
     605    AssertPtrReturn(ppvData,    VERR_INVALID_POINTER);
     606    AssertPtrReturn(pcbData,    VERR_INVALID_POINTER);
     607
     608    /* Do we need to do Unicode stuff? */
     609    const bool fUnicode = RT_BOOL(pDropFiles->fWide);
     610
     611    /* Get the offset of the file list. */
     612    Assert(pDropFiles->pFiles >= sizeof(DROPFILES));
     613
     614    /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only
     615     *       will work with the plain storage medium pointer! */
     616    HDROP hDrop = (HDROP)(pDropFiles);
     617
     618    int rc = VINF_SUCCESS;
     619
     620    /* First, get the file count. */
     621    /** @todo Does this work on Windows 2000 / NT4? */
     622    char *pszFiles = NULL;
     623    uint32_t cchFiles = 0;
     624    UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */);
     625
     626    LogFlowFunc(("Got %RU16 file(s), fUnicode=%RTbool\n", cFiles, fUnicode));
     627
     628    for (UINT i = 0; i < cFiles; i++)
     629    {
     630        UINT cchFile = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */);
     631        Assert(cchFile);
     632
     633        if (RT_FAILURE(rc))
     634            break;
     635
     636        char *pszFileUtf8 = NULL; /* UTF-8 version. */
     637        UINT cchFileUtf8 = 0;
     638        if (fUnicode)
     639        {
     640            /* Allocate enough space (including terminator). */
     641            WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cchFile + 1) * sizeof(WCHAR));
     642            if (pwszFile)
     643            {
     644                const UINT cwcFileUtf16 = DragQueryFileW(hDrop, i /* File index */,
     645                                                         pwszFile, cchFile + 1 /* Include terminator */);
     646
     647                AssertMsg(cwcFileUtf16 == cchFile, ("cchFileUtf16 (%RU16) does not match cchFile (%RU16)\n",
     648                                                    cwcFileUtf16, cchFile));
     649                RT_NOREF(cwcFileUtf16);
     650
     651                rc = RTUtf16ToUtf8(pwszFile, &pszFileUtf8);
     652                if (RT_SUCCESS(rc))
     653                {
     654                    cchFileUtf8 = (UINT)strlen(pszFileUtf8);
     655                    Assert(cchFileUtf8);
     656                }
     657
     658                RTMemFree(pwszFile);
     659            }
     660            else
     661                rc = VERR_NO_MEMORY;
     662        }
     663        else /* ANSI */
     664        {
     665            /* Allocate enough space (including terminator). */
     666            pszFileUtf8 = (char *)RTMemAlloc((cchFile + 1) * sizeof(char));
     667            if (pszFileUtf8)
     668            {
     669                cchFileUtf8 = DragQueryFileA(hDrop, i /* File index */,
     670                                             pszFileUtf8, cchFile + 1 /* Include terminator */);
     671
     672                AssertMsg(cchFileUtf8 == cchFile, ("cchFileUtf8 (%RU16) does not match cchFile (%RU16)\n",
     673                                                   cchFileUtf8, cchFile));
     674            }
     675            else
     676                rc = VERR_NO_MEMORY;
     677        }
     678
     679        if (RT_SUCCESS(rc))
     680        {
     681            LogFlowFunc(("\tFile: %s (cchFile=%RU16)\n", pszFileUtf8, cchFileUtf8));
     682
     683            LogRel(("DnD: Adding guest file '%s'\n", pszFileUtf8));
     684
     685            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
     686            if (RT_SUCCESS(rc))
     687                cchFiles += cchFileUtf8;
     688        }
     689        else
     690            LogFunc(("Error handling file entry #%u, rc=%Rrc\n", i, rc));
     691
     692        if (pszFileUtf8)
     693            RTStrFree(pszFileUtf8);
     694
     695        if (RT_FAILURE(rc))
     696            break;
     697
     698        /* Add separation between filenames.
     699         * Note: Also do this for the last element of the list. */
     700        rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */);
     701        if (RT_SUCCESS(rc))
     702            cchFiles += 2; /* Include \r\n */
     703    }
     704
     705    if (RT_SUCCESS(rc))
     706    {
     707        cchFiles += 1; /* Add string termination. */
     708        uint32_t cbFiles = cchFiles * sizeof(char);
     709
     710        LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n",
     711                     cFiles, cchFiles, cbFiles, pszFiles));
     712
     713        /* Translate the list into URI elements. */
     714        SharedClipboardURIList lstURI;
     715        rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
     716                                              SHAREDCLIPBOARDURILIST_FLAGS_ABSOLUTE_PATHS);
     717        if (RT_SUCCESS(rc))
     718        {
     719            RTCString strRoot = lstURI.GetRootEntries();
     720            size_t cbRoot = strRoot.length() + 1; /* Include termination */
     721
     722            void *pvData = RTMemAlloc(cbRoot);
     723            if (pvData)
     724            {
     725                memcpy(pvData, strRoot.c_str(), cbRoot);
     726
     727                *ppvData = pvData;
     728                *pcbData = cbRoot;
     729            }
     730            else
     731                rc = VERR_NO_MEMORY;
     732        }
     733    }
     734
     735    LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
     736                 rc, pszFiles, cFiles, cchFiles));
     737
     738    if (pszFiles)
     739        RTStrFree(pszFiles);
     740
     741    return rc;
     742}
     743#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
     744
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r78440 r78501  
    4545ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    4646 VBoxSharedClipboard_SOURCES += \
     47        VBoxSharedClipboardSvc-uri.cpp \
     48        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
     49        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \
    4750        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
    48         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \
    49         $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp
     51        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp
    5052endif
    5153if1of ($(KBUILD_TARGET), linux solaris freebsd) ## @todo X11
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h

    r78151 r78501  
    11/* $Id$ */
    22/** @file
    3  * Shared Clipboard Service - Internal Header.
     3 * Shared Clipboard Service - Internal header.
    44 */
    55
     
    3636    uint32_t u32ClientID;
    3737
    38     bool fAsync;        /* Guest is waiting for a message. */
    39     bool fReadPending;  /* The guest is waiting for data from the host */
    40 
    41     bool fMsgQuit;
    42     bool fMsgReadData;
    43     bool fMsgFormats;
     38    /** The guest is waiting for a message. */
     39    bool fAsync;
     40    /** The guest is waiting for data from the host */
     41    bool fReadPending;
     42    /** Whether the host host has sent a quit message. */
     43    bool fHostMsgQuit;
     44    /** Whether the host host has requested reading clipboard data from the guest. */
     45    bool fHostMsgReadData;
     46    /** Whether the host host has reported its available formats. */
     47    bool fHostMsgFormats;
    4448
    4549    struct {
     
    6771 * The service functions. Locking is between the service thread and the platform dependent windows thread.
    6872 */
    69 void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
     73void vboxSvcClipboardReportMsg(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
    7074void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual);
    7175
     
    7377 * Platform dependent functions.
    7478 */
    75 int vboxClipboardInit (void);
    76 void vboxClipboardDestroy (void);
     79int vboxClipboardInit(void);
     80void vboxClipboardDestroy(void);
    7781
    78 int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
    79 void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient);
    80 void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
    81 int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
    82 void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
     82int vboxClipboardConnect(VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
     83void vboxClipboardDisconnect(VBOXCLIPBOARDCLIENTDATA *pClient);
     84void vboxClipboardFormatAnnounce(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
     85int vboxClipboardReadData(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
     86void vboxClipboardWriteData(VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
    8387
    8488int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient);
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp

    r78440 r78501  
    5252*   Internal Functions                                                                                                           *
    5353*********************************************************************************************************************************/
    54 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pch);
    55 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
    56 static bool IsWindowsHTML(const char *source);
    57 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
     54static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
    5855
    5956struct _VBOXCLIPBOARDCONTEXT
     
    122119
    123120    if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
    124         && IsWindowsHTML((const char *)pvSrc))
     121        && VBoxClipboardWinIsCFHTML((const char *)pvSrc))
    125122    {
    126123        /** @todo r=bird: Why the double conversion? */
    127124        char *pszBuf = NULL;
    128125        uint32_t cbBuf = 0;
    129         int rc = ConvertCFHtmlToMime((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
     126        int rc = VBoxClipboardWinConvertCFHTMLToMIME((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
    130127        if (RT_SUCCESS(rc))
    131128        {
     
    176173static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    177174{
    178     LRESULT rc = 0;
     175    LRESULT lresultRc = 0;
    179176
    180177    const PVBOXCLIPBOARDCONTEXT pCtx    = &g_ctx;
     
    190187            {
    191188                /* Clipboard was updated by another application, retrieve formats and report back. */
    192                 int vboxrc = vboxClipboardSyncInternal(pCtx);
    193                 AssertRC(vboxrc);
     189                int rc = vboxClipboardWinSyncInternal(pCtx);
     190                AssertRC(rc);
    194191            }
    195192        } break;
     
    201198            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    202199            {
    203                 rc = DefWindowProc(hwnd, msg, wParam, lParam);
     200                lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
    204201                break;
    205202            }
     
    221218                    /* Pass the message further. */
    222219                    DWORD_PTR dwResult;
    223                     rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
    224                                             VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
    225                                             &dwResult);
    226                     if (!rc)
    227                         rc = (LRESULT)dwResult;
     220                    lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
     221                                                    VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
     222                                                    &dwResult);
     223                    if (!lresultRc)
     224                        lresultRc = (LRESULT)dwResult;
    228225                }
    229226            }
     
    237234            {
    238235                /* Clipboard was updated by another application, retrieve formats and report back. */
    239                 int vboxrc = vboxClipboardSyncInternal(pCtx);
     236                int vboxrc = vboxClipboardWinSyncInternal(pCtx);
    240237                AssertRC(vboxrc);
    241238            }
     
    244241            {
    245242                LogFunc(("WM_DRAWCLIPBOARD next %p\n", pWinCtx->hWndNextInChain));
     243
    246244                /* Pass the message to next windows in the clipboard chain. */
    247245                DWORD_PTR dwResult;
    248                 rc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
    249                                         &dwResult);
    250                 if (!rc)
    251                     rc = dwResult;
     246                lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
     247                                               &dwResult);
     248                if (!lresultRc)
     249                    lresultRc = dwResult;
    252250            }
    253251        } break;
     
    281279        case WM_RENDERFORMAT:
    282280        {
     281            LogFunc(("WM_RENDERFORMAT\n"));
     282
    283283            /* Insert the requested clipboard format data into the clipboard. */
    284             VBOXCLIPBOARDFORMAT fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
    285 
    286             UINT format = (UINT)wParam;
    287 
    288             LogFunc(("WM_RENDERFORMAT: Format %u\n", format));
    289 
    290             switch (format)
    291             {
    292                 case CF_UNICODETEXT:
    293                     fFormat |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    294                     break;
    295 
    296                 case CF_DIB:
    297                     fFormat |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    298                     break;
    299 
    300                 default:
    301                     if (format >= 0xC000)
    302                     {
    303                         TCHAR szFormatName[256]; /** @todo r=andy Unicode, 256 is enough? */
    304                         int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName) / sizeof (TCHAR));
    305                         if (cActual)
    306                         {
    307                             if (RTStrCmp(szFormatName, "HTML Format") == 0)
    308                                 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
    309 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    310                             if (   RTStrCmp(szFormatName, CFSTR_FILEDESCRIPTOR) == 0
    311                                 || RTStrCmp(szFormatName, CFSTR_FILECONTENTS) == 0)
    312                                 fFormat |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
    313 #endif
    314                         }
    315                     }
    316                     break;
    317             }
     284            const UINT cfFormat = (UINT)wParam;
     285
     286            const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat);
     287
     288            LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
    318289
    319290            if (   fFormat       == VBOX_SHARED_CLIPBOARD_FMT_NONE
     
    322293                /* Unsupported clipboard format is requested. */
    323294                LogFunc(("WM_RENDERFORMAT unsupported format requested or client is not active\n"));
    324                 EmptyClipboard();
     295                VBoxClipboardWinClear();
    325296            }
    326297            else
    327298            {
    328                 int vboxrc = vboxClipboardReadDataFromClient(pCtx, fFormat);
    329 
    330                 LogFunc(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",
    331                           vboxrc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));
    332 
    333                 if (   RT_SUCCESS (vboxrc)
     299                int rc = vboxClipboardReadDataFromClient(pCtx, fFormat);
     300
     301                LogFunc(("vboxClipboardReadDataFromClient rc = %Rrc, pv %p, cb %d, u32Format %d\n",
     302                          rc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));
     303
     304                if (   RT_SUCCESS (rc)
    334305                    && pCtx->pClient->data.pv != NULL
    335306                    && pCtx->pClient->data.cb > 0
     
    367338                             * size is 'cb' and format is 'format'.
    368339                             */
    369                             HANDLE hClip = SetClipboardData(format, hMem);
     340                            HANDLE hClip = SetClipboardData(cfFormat, hMem);
    370341
    371342                            LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip));
     
    399370             * windows is to be destroyed and therefore the guest side becomes inactive.
    400371             */
    401             int vboxrc = VBoxClipboardWinOpen(hwnd);
    402             if (RT_SUCCESS(vboxrc))
     372            int rc = VBoxClipboardWinOpen(hwnd);
     373            if (RT_SUCCESS(rc))
    403374            {
    404375                VBoxClipboardWinClear();
    405376                VBoxClipboardWinClose();
    406377            }
    407             else
    408             {
    409                 LogFlowFunc(("WM_RENDERALLFORMATS: error in open clipboard. hwnd: %x, rc: %Rrc\n", hwnd, vboxrc));
    410             }
    411378        } break;
    412379
    413380        case VBOX_CLIPBOARD_WM_SET_FORMATS:
    414381        {
    415             if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats)
     382            if (   pCtx->pClient == NULL
     383                || pCtx->pClient->fHostMsgFormats)
    416384            {
    417385                /* Host has pending formats message. Ignore the guest announcement,
     
    423391
    424392            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
    425             uint32_t u32Formats = (uint32_t)lParam;
    426 
    427             LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: u32Formats=%02X\n", u32Formats));
    428 
    429             int vboxrc = VBoxClipboardWinOpen(hwnd);
    430             if (RT_SUCCESS(vboxrc))
     393            VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
     394
     395            LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=%02X\n", fFormats));
     396
     397            int rc = VBoxClipboardWinOpen(hwnd);
     398            if (RT_SUCCESS(rc))
    431399            {
    432400                VBoxClipboardWinClear();
    433401
    434                 LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS emptied clipboard\n"));
    435 
    436                 HANDLE hClip = NULL;
    437 
    438                 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     402                HANDLE hClip    = NULL;
     403                UINT   cfFormat = 0;
     404
     405                /** @todo r=andy Only one clipboard format can be set at once, at least on Windows. */
     406
     407                if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     408                {
    439409                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
    440 
    441                 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     410                }
     411                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     412                {
    442413                    hClip = SetClipboardData(CF_DIB, NULL);
    443 
    444                 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    445                 {
    446                     UINT format = RegisterClipboardFormat ("HTML Format");
    447                     if (format != 0)
    448                     {
    449                         hClip = SetClipboardData (format, NULL);
    450                     }
     414                }
     415                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
     416                {
     417                    cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
     418                    if (cfFormat)
     419                        hClip = SetClipboardData(cfFormat, NULL);
    451420                }
    452421
    453422#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
    454                 if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
    455                 {
    456                     UINT format = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
    457                     if (format)
    458                         hClip = SetClipboardData(format, NULL);
    459                 }
     423                /** @todo */
    460424#endif
    461425                VBoxClipboardWinClose();
     
    480444        {
    481445            LogFunc(("WM_ %p\n", msg));
    482             rc = DefWindowProc(hwnd, msg, wParam, lParam);
    483         }
    484     }
    485 
    486     LogFunc(("WM_ rc %d\n", rc));
    487     return rc;
     446            lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
     447        }
     448    }
     449
     450    LogFunc(("WM_ rc %d\n", lresultRc));
     451    return lresultRc;
    488452}
    489453
     
    575539 * @param   pCtx                Clipboard context to synchronize.
    576540 */
    577 static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
     541static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
    578542{
    579543    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     
    663627{
    664628    /* Sync the host clipboard content with the client. */
    665     return vboxClipboardSyncInternal(pClient->pCtx);
     629    return vboxClipboardWinSyncInternal(pClient->pCtx);
    666630}
    667631
     
    783747        else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    784748        {
    785             UINT format = RegisterClipboardFormat("HTML Format");
     749            UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
    786750            if (format != 0)
    787751            {
     
    792756                    if (lp != NULL)
    793757                    {
    794                         LogFunc(("CF_HTML\n"));
    795 
     758                        /** @todo r=andy Add data overflow handling. */
    796759                        vboxClipboardGetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip),
    797760                                             pv, cb, pcbActual);
     
    813776        {
    814777            hClip = GetClipboardData(CF_HDROP);
    815             if (hClip != NULL)
     778            if (hClip != NULL) /* Do we have data in CF_HDROP format? */
    816779            {
    817780                LPVOID lp = GlobalLock(hClip);
    818781                if (lp)
    819782                {
    820                     /* Convert to a string list, separated by \r\n. */
    821                     DROPFILES *pDropFiles = (DROPFILES *)hClip;
    822                     AssertPtr(pDropFiles);
    823 
    824                     /* Do we need to do Unicode stuff? */
    825                     const bool fUnicode = RT_BOOL(pDropFiles->fWide);
    826 
    827                     /* Get the offset of the file list. */
    828                     Assert(pDropFiles->pFiles >= sizeof(DROPFILES));
    829 
    830                     /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only
    831                      *       will work with the plain storage medium pointer! */
    832                     HDROP hDrop = (HDROP)(hClip);
    833 
    834                     /* First, get the file count. */
    835                     /** @todo Does this work on Windows 2000 / NT4? */
    836                     char *pszFiles = NULL;
    837                     uint32_t cchFiles = 0;
    838                     UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */);
    839 
    840                     LogRel(("Shared Clipboard: Got %RU16 file(s), fUnicode=%RTbool\n", cFiles, fUnicode));
    841 
    842                     for (UINT i = 0; i < cFiles; i++)
    843                     {
    844                         UINT cchFile = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */);
    845                         Assert(cchFile);
    846 
    847                         if (RT_FAILURE(rc))
    848                             break;
    849 
    850                         char *pszFileUtf8 = NULL; /* UTF-8 version. */
    851                         UINT cchFileUtf8 = 0;
    852                         if (fUnicode)
    853                         {
    854                             /* Allocate enough space (including terminator). */
    855                             WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cchFile + 1) * sizeof(WCHAR));
    856                             if (pwszFile)
    857                             {
    858                                 const UINT cwcFileUtf16 = DragQueryFileW(hDrop, i /* File index */,
    859                                                                          pwszFile, cchFile + 1 /* Include terminator */);
    860 
    861                                 AssertMsg(cwcFileUtf16 == cchFile, ("cchFileUtf16 (%RU16) does not match cchFile (%RU16)\n",
    862                                                                     cwcFileUtf16, cchFile));
    863                                 RT_NOREF(cwcFileUtf16);
    864 
    865                                 rc = RTUtf16ToUtf8(pwszFile, &pszFileUtf8);
    866                                 if (RT_SUCCESS(rc))
    867                                 {
    868                                     cchFileUtf8 = (UINT)strlen(pszFileUtf8);
    869                                     Assert(cchFileUtf8);
    870                                 }
    871 
    872                                 RTMemFree(pwszFile);
    873                             }
    874                             else
    875                                 rc = VERR_NO_MEMORY;
    876                         }
    877                         else /* ANSI */
    878                         {
    879                             /* Allocate enough space (including terminator). */
    880                             pszFileUtf8 = (char *)RTMemAlloc((cchFile + 1) * sizeof(char));
    881                             if (pszFileUtf8)
    882                             {
    883                                 cchFileUtf8 = DragQueryFileA(hDrop, i /* File index */,
    884                                                              pszFileUtf8, cchFile + 1 /* Include terminator */);
    885 
    886                                 AssertMsg(cchFileUtf8 == cchFile, ("cchFileUtf8 (%RU16) does not match cchFile (%RU16)\n",
    887                                                                    cchFileUtf8, cchFile));
    888                             }
    889                             else
    890                                 rc = VERR_NO_MEMORY;
    891                         }
    892 
    893                         if (RT_SUCCESS(rc))
    894                         {
    895                             LogFlowFunc(("\tFile: %s (cchFile=%RU16)\n", pszFileUtf8, cchFileUtf8));
    896 
    897                             LogRel2(("Shared Clipboard: Adding host file '%s'\n", pszFileUtf8));
    898 
    899                             rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
    900                             if (RT_SUCCESS(rc))
    901                                 cchFiles += cchFileUtf8;
    902                         }
    903                         else
    904                             LogRel(("Shared Clipboard: Error handling file entry #%u, rc=%Rrc\n", i, rc));
    905 
    906                         if (pszFileUtf8)
    907                             RTStrFree(pszFileUtf8);
    908 
    909                         if (RT_FAILURE(rc))
    910                             break;
    911 
    912                         /* Add separation between filenames.
    913                          * Note: Also do this for the last element of the list. */
    914                         rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */);
    915                         if (RT_SUCCESS(rc))
    916                             cchFiles += 2; /* Include \r\n */
    917                     }
    918 
     783                    void *pvTemp;
     784                    size_t cbTemp;
     785                    rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)lp, &pvTemp, &cbTemp);
    919786                    if (RT_SUCCESS(rc))
    920787                    {
    921                         cchFiles += 1; /* Add string termination. */
    922                         uint32_t cbFiles = cchFiles * sizeof(char);
    923 
    924                         LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n",
    925                                      cFiles, cchFiles, cbFiles, pszFiles));
    926 
    927                         /* Translate the list into URI elements. */
    928                         SharedClipboardURIList lstURI;
    929                         rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
    930                                                               SHAREDCLIPBOARDURILIST_FLAGS_ABSOLUTE_PATHS);
    931                         if (RT_SUCCESS(rc))
     788                        if (cbTemp > cb) /** @todo Add overflow handling! */
    932789                        {
    933                             RTCString strRoot = lstURI.GetRootEntries();
    934                             size_t cbRoot = strRoot.length() + 1; /* Include termination */
    935 
    936                             if (cbRoot > cb) /** @todo Add overflow handling! */
    937                                 cbRoot = cb; /* Never copy more than the available buffer supplies. */
    938 
    939                             memcpy(pv, strRoot.c_str(), cbRoot);
    940 
    941                             *pcbActual = (uint32_t)cbRoot;
     790                            AssertMsgFailed(("More data buffer needed -- fix this\n"));
     791                            cbTemp = cb; /* Never copy more than the available buffer supplies. */
    942792                        }
     793
     794                        memcpy(pv, pvTemp, cbTemp);
     795
     796                        RTMemFree(pvTemp);
     797
     798                        *pcbActual = (uint32_t)cbTemp;
    943799                    }
    944 
    945                     LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
    946                                  rc, pszFiles, cFiles, cchFiles));
    947 
    948                     if (pszFiles)
    949                         RTStrFree(pszFiles);
    950800
    951801                    GlobalUnlock(hClip);
     
    982832
    983833        if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
    984             && !IsWindowsHTML((const char*)pv))
     834            && !VBoxClipboardWinIsCFHTML((const char*)pv))
    985835        {
    986836            /* check that this is not already CF_HTML */
    987837            uint32_t cbResult;
    988             int rc = ConvertMimeToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
     838            int rc = VBoxClipboardWinConvertMIMEToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
    989839            if (RT_SUCCESS(rc))
    990840            {
     
    1015865}
    1016866
    1017 
    1018 /**
    1019  * Extracts field value from CF_HTML struct
    1020  *
    1021  * @returns VBox status code
    1022  * @param   pszSrc      source in CF_HTML format
    1023  * @param   pszOption   Name of CF_HTML field
    1024  * @param   puValue     Where to return extracted value of CF_HTML field
    1025  */
    1026 static int GetHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)
    1027 {
    1028     int rc = VERR_INVALID_PARAMETER;
    1029 
    1030     Assert(pszSrc);
    1031     Assert(pszOption);
    1032 
    1033     const char *pszOptionValue = RTStrStr(pszSrc, pszOption);
    1034     if (pszOptionValue)
    1035     {
    1036         size_t cchOption = strlen(pszOption);
    1037         Assert(cchOption);
    1038 
    1039         rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);
    1040     }
    1041     return rc;
    1042 }
    1043 
    1044 
    1045 /**
    1046  * Check that the source string contains CF_HTML struct
    1047  *
    1048  * @param   pszSource   source string.
    1049  *
    1050  * @returns @c true if the @a pszSource string is in CF_HTML format
    1051  */
    1052 static bool IsWindowsHTML(const char *pszSource)
    1053 {
    1054     return    RTStrStr(pszSource, "Version:") != NULL
    1055            && RTStrStr(pszSource, "StartHTML:") != NULL;
    1056 }
    1057 
    1058 
    1059 /**
    1060  * Converts clipboard data from CF_HTML format to MIME clipboard format.
    1061  *
    1062  * Returns allocated buffer that contains html converted to text/html mime type
    1063  *
    1064  * @returns VBox status code.
    1065  * @param   pszSource   The input.
    1066  * @param   cch         The length of the input.
    1067  * @param   ppszOutput  Where to return the result.  Free using RTMemFree.
    1068  * @param   pcbOutput   Where to the return length of the result (bytes/chars).
    1069  */
    1070 static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)
    1071 {
    1072     Assert(pszSource);
    1073     Assert(cch);
    1074     Assert(ppszOutput);
    1075     Assert(pcbOutput);
    1076 
    1077     uint32_t offStart;
    1078     int rc = GetHeaderValue(pszSource, "StartFragment:", &offStart);
    1079     if (RT_SUCCESS(rc))
    1080     {
    1081         uint32_t offEnd;
    1082         rc = GetHeaderValue(pszSource, "EndFragment:", &offEnd);
    1083         if (RT_SUCCESS(rc))
    1084         {
    1085             if (   offStart > 0
    1086                 && offEnd > 0
    1087                 && offEnd > offStart
    1088                 && offEnd <= cch)
    1089             {
    1090                 uint32_t cchSubStr = offEnd - offStart;
    1091                 char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);
    1092                 if (pszResult)
    1093                 {
    1094                     rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);
    1095                     if (RT_SUCCESS(rc))
    1096                     {
    1097                         *ppszOutput = pszResult;
    1098                         *pcbOutput  = (uint32_t)(cchSubStr + 1);
    1099                         rc = VINF_SUCCESS;
    1100                     }
    1101                     else
    1102                     {
    1103                         LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
    1104                         RTMemFree(pszResult);
    1105                     }
    1106                 }
    1107                 else
    1108                 {
    1109                     LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));
    1110                     rc = VERR_NO_MEMORY;
    1111                 }
    1112             }
    1113             else
    1114             {
    1115                 LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));
    1116                 rc = VERR_INVALID_PARAMETER;
    1117             }
    1118         }
    1119         else
    1120         {
    1121             LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
    1122             rc = VERR_INVALID_PARAMETER;
    1123         }
    1124     }
    1125     else
    1126     {
    1127         LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc\n", rc));
    1128         rc = VERR_INVALID_PARAMETER;
    1129     }
    1130 
    1131     return rc;
    1132 }
    1133 
    1134 
    1135 
    1136 /**
    1137  * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.
    1138  *
    1139  * This is just encapsulation work, slapping a header on the data.
    1140  *
    1141  * It allocates
    1142  *
    1143  * Calculations:
    1144  *   Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
    1145  *   EndHtml       = Header length + fragment length
    1146  *   StartHtml     = 105(constant)
    1147  *   StartFragment = 141(constant) may vary if the header html content will be extended
    1148  *   EndFragment   = Header length + fragment length - 38(ending length)
    1149  *
    1150  * @param   pszSource   Source buffer that contains utf-16 string in mime html format
    1151  * @param   cb          Size of source buffer in bytes
    1152  * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
    1153  *                      CF_HTML clipboard data.  This function allocates memory for this.
    1154  * @param   pcbOutput   Where to return the size of allocated result buffer in bytes/chars, including zero terminator
    1155  *
    1156  * @note    output buffer should be free using RTMemFree()
    1157  * @note    Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
    1158  */
    1159 static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
    1160 {
    1161     Assert(ppszOutput);
    1162     Assert(pcbOutput);
    1163     Assert(pszSource);
    1164     Assert(cb);
    1165 
    1166     /* construct CF_HTML formatted string */
    1167     char *pszResult = NULL;
    1168     size_t cchFragment;
    1169     int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
    1170     if (!RT_SUCCESS(rc))
    1171     {
    1172         LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));
    1173         return VERR_INVALID_PARAMETER;
    1174     }
    1175 
    1176     /*
    1177     @StartHtml - pos before <html>
    1178     @EndHtml - whole size of text excluding ending zero char
    1179     @StartFragment - pos after <!--StartFragment-->
    1180     @EndFragment - pos before <!--EndFragment-->
    1181     @note: all values includes CR\LF inserted into text
    1182     Calculations:
    1183     Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
    1184     EndHtml  = Header length + fragment length
    1185     StartHtml = 105(constant)
    1186     StartFragment = 143(constant)
    1187     EndFragment  = Header length + fragment length - 40(ending length)
    1188     */
    1189     static const char s_szFormatSample[] =
    1190     /*   0:   */ "Version:1.0\r\n"
    1191     /*  13:   */ "StartHTML:000000101\r\n"
    1192     /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
    1193     /*  53:   */ "StartFragment:000000137\r\n"
    1194     /*  78:   */ "EndFragment:%0000009u\r\n"
    1195     /* 101:   */ "<html>\r\n"
    1196     /* 109:   */ "<body>\r\n"
    1197     /* 117:   */ "<!--StartFragment-->"
    1198     /* 137:   */ "%s"
    1199     /* 137+2: */ "<!--EndFragment-->\r\n"
    1200     /* 157+2: */ "</body>\r\n"
    1201     /* 166+2: */ "</html>\r\n";
    1202     /* 175+2: */
    1203     AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
    1204 
    1205     /* calculate parameters of CF_HTML header */
    1206     size_t cchHeader      = sizeof(s_szFormatSample) - 1;
    1207     size_t offEndHtml     = cchHeader + cchFragment;
    1208     size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
    1209     pszResult = (char *)RTMemAlloc(offEndHtml + 1);
    1210     if (pszResult == NULL)
    1211     {
    1212         LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
    1213         return VERR_NO_MEMORY;
    1214     }
    1215 
    1216     /* format result CF_HTML string */
    1217     size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
    1218                                       s_szFormatSample, offEndHtml, offEndFragment, pszSource);
    1219     Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
    1220 
    1221 #ifdef VBOX_STRICT
    1222     /* Control calculations. check consistency.*/
    1223     static const char s_szStartFragment[] = "<!--StartFragment-->";
    1224     static const char s_szEndFragment[] = "<!--EndFragment-->";
    1225 
    1226     /* check 'StartFragment:' value */
    1227     const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
    1228     Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
    1229 
    1230     /* check 'EndFragment:' value */
    1231     const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
    1232     Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
    1233 #endif
    1234 
    1235     *ppszOutput = pszResult;
    1236     *pcbOutput = (uint32_t)cchFormatted + 1;
    1237     Assert(*pcbOutput == cchFormatted + 1);
    1238 
    1239     return VINF_SUCCESS;
    1240 }
    1241 
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r78442 r78501  
    8686
    8787#include "VBoxClipboard.h"
     88#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     89# include "VBoxSharedClipboardSvc-uri.h"
     90#endif
    8891
    8992
     
    200203{
    201204    /* Message priority is taken into account. */
    202     if (pClient->fMsgQuit)
     205    if (pClient->fHostMsgQuit)
    203206    {
    204207        LogFlowFunc(("vboxSvcClipboardReturnMsg: Quit\n"));
    205208        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
    206209        VBoxHGCMParmUInt32Set(&paParms[1], 0);
    207         pClient->fMsgQuit = false;
    208     }
    209     else if (pClient->fMsgReadData)
     210        pClient->fHostMsgQuit = false;
     211    }
     212    else if (pClient->fHostMsgReadData)
    210213    {
    211214        uint32_t fFormat = 0;
     
    218221        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    219222            fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
     223#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     224        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
     225            fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
     226#endif
    220227        else
    221             AssertStmt(pClient->u32RequestedFormat == 0, pClient->u32RequestedFormat = 0);
     228        {
     229            LogRel2(("Clipboard: Unsupported format from guest (0x%x), skipping\n", fFormat));
     230            pClient->u32RequestedFormat = 0;
     231        }
    222232        pClient->u32RequestedFormat &= ~fFormat;
    223233        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
    224234        VBoxHGCMParmUInt32Set(&paParms[1], fFormat);
    225235        if (pClient->u32RequestedFormat == 0)
    226             pClient->fMsgReadData = false;
    227     }
    228     else if (pClient->fMsgFormats)
     236            pClient->fHostMsgReadData = false;
     237    }
     238    else if (pClient->fHostMsgFormats)
    229239    {
    230240        LogFlowFunc(("vboxSvcClipboardReturnMsg: Formats %02X\n", pClient->u32AvailableFormats));
    231241        VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
    232242        VBoxHGCMParmUInt32Set(&paParms[1], pClient->u32AvailableFormats);
    233         pClient->fMsgFormats = false;
     243        pClient->fHostMsgFormats = false;
    234244    }
    235245    else
     
    255265            {
    256266                LogFlowFunc(("Quit\n"));
    257                 pClient->fMsgQuit = true;
     267                pClient->fHostMsgQuit = true;
    258268            } break;
    259269            case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
     
    268278                LogFlowFunc(("ReadData %02X\n", u32Formats));
    269279                pClient->u32RequestedFormat = u32Formats;
    270                 pClient->fMsgReadData = true;
     280                pClient->fHostMsgReadData = true;
    271281            } break;
    272282            case VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS:
     
    281291                LogFlowFunc(("Formats %02X\n", u32Formats));
    282292                pClient->u32AvailableFormats = u32Formats;
    283                 pClient->fMsgFormats = true;
     293                pClient->fHostMsgFormats = true;
    284294            } break;
    285295            default:
     
    683693        default:
    684694        {
     695#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     696            rc = vboxClipboardSvcURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival,
     697                                            &fAsynchronousProcessing);
     698#else
    685699            rc = VERR_NOT_IMPLEMENTED;
     700#endif
    686701        }
    687702    }
     
    772787
    773788        default:
    774             break;
     789        {
     790#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
     791            rc = vboxClipboardSvcURIHostHandler(u32Function, cParms, paParms);
     792#endif
     793        } break;
    775794    }
    776795
     
    786805{
    787806    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32ClientID),  /* for validation purposes */
    788     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgQuit),
    789     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgReadData),
    790     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgFormats),
     807    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgQuit),
     808    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgReadData),
     809    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgFormats),
    791810    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32RequestedFormat),
    792811    SSMFIELD_ENTRY_TERM()
     
    843862    bool fAsync: 1; /* Guest is waiting for a message. */
    844863
    845     bool fMsgQuit: 1;
    846     bool fMsgReadData: 1;
    847     bool fMsgFormats: 1;
     864    bool fHostMsgQuit: 1;
     865    bool fHostMsgReadData: 1;
     866    bool fHostMsgFormats: 1;
    848867
    849868    struct
     
    918937        AssertRCReturn(rc, rc);
    919938
    920         pClient->fMsgQuit           = savedState.fMsgQuit;
    921         pClient->fMsgReadData       = savedState.fMsgReadData;
    922         pClient->fMsgFormats        = savedState.fMsgFormats;
     939        pClient->fHostMsgQuit       = savedState.fHostMsgQuit;
     940        pClient->fHostMsgReadData   = savedState.fHostMsgReadData;
     941        pClient->fHostMsgFormats    = savedState.fHostMsgFormats;
    923942        pClient->u32RequestedFormat = savedState.u32RequestedFormat;
    924943    }
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