VirtualBox

Changeset 1103 in vbox


Ignore:
Timestamp:
Feb 28, 2007 1:03:10 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
18999
Message:

Shared clipboard. Changelog update.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/HostServices/VBoxClipboardSvc.h

    r1 r1103  
    2828#include <VBox/hgcmsvc.h>
    2929
    30 #define VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE   1
    31 
     30/*
     31 * The mode of operations.
     32 */
    3233#define VBOX_SHARED_CLIPBOARD_MODE_OFF           0
    3334#define VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST 1
     
    3536#define VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL 3
    3637
    37 #define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT 0
    38 #define VBOX_SHARED_CLIPBOARD_FMT_BITMAP      1
     38/*
     39 * Supported data formats. Bit mask.
     40 */
     41#define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT 0x01
     42#define VBOX_SHARED_CLIPBOARD_FMT_BITMAP      0x02
    3943
    40 #define VBOX_SHARED_CLIPBOARD_FN_QUERY_MODE        1
    41 #define VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_CANCEL 2
    42 #define VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_QUERY  3
    43 #define VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_READ   4
    44 #define VBOX_SHARED_CLIPBOARD_FN_SEND_DATA         5
     44/*
     45 * The service functions which are callable by host.
     46 */
     47#define VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE   1
    4548
     49/*
     50 * The service functions which are called by guest.
     51 */
     52/* Call host and wait blocking for an host event VBOX_SHARED_CLIPBOARD_HOST_MSG_* */
     53#define VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG      1
     54/* Send list of available formats to host. */
     55#define VBOX_SHARED_CLIPBOARD_FN_FORMATS           2
     56/* Obtain data in specified format from host. */
     57#define VBOX_SHARED_CLIPBOARD_FN_READ_DATA         3
     58/* Send data in requested format to host. */
     59#define VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA        4
     60
     61/*
     62 * The host messages for the guest.
     63 */
     64#define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT        1
     65#define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA   2
     66#define VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS     3
     67
     68/*
     69 * HGCM parameter structures.
     70 */
    4671#pragma pack (1)
    47 typedef struct _VBoxClipboardQueryMode
     72typedef struct _VBoxClipboardGetHostMsg
    4873{
    4974    VBoxGuestHGCMCallInfo hdr;
    5075
    51     HGCMFunctionParameter mode; /* OUT uint32_t */
     76    /* VBOX_SHARED_CLIPBOARD_HOST_MSG_* */
     77    HGCMFunctionParameter msg;     /* OUT uint32_t */
    5278
    53 } VBoxClipboardQueryMode;
     79    /* VBOX_SHARED_CLIPBOARD_FMT_*, depends on the 'msg'. */
     80    HGCMFunctionParameter formats; /* OUT uint32_t */
     81} VBoxClipboardGetHostMsg;
    5482
    55 typedef struct _VBoxClipboardHostEventCancel
     83typedef struct _VBoxClipboardFormats
    5684{
    5785    VBoxGuestHGCMCallInfo hdr;
    58 } VBoxClipboardHostEventCancel;
    5986
    60 typedef struct _VBoxClipboardHostEventQuery
     87    /* VBOX_SHARED_CLIPBOARD_FMT_* */
     88    HGCMFunctionParameter formats; /* OUT uint32_t */
     89} VBoxClipboardFormats;
     90
     91typedef struct _VBoxClipboardReadData
    6192{
    6293    VBoxGuestHGCMCallInfo hdr;
    6394   
    64     HGCMFunctionParameter format; /* OUT uint32_t */
     95    /* Requested format. */
     96    HGCMFunctionParameter format; /* IN uint32_t */
    6597   
     98    /* The data buffer. */
     99    HGCMFunctionParameter ptr;    /* IN linear pointer. */
     100   
     101    /* Size of returned data, if > ptr->cb, then no data was
     102     * actually transferred and the guest must repeat the call.
     103     */
    66104    HGCMFunctionParameter size;   /* OUT uint32_t */
    67 } VBoxClipboardHostEventQuery;
     105   
     106} VBoxClipboardReadData;
    68107
    69 typedef struct _VBoxClipboardHostEventRead
     108typedef struct _VBoxClipboardWriteData
    70109{
    71110    VBoxGuestHGCMCallInfo hdr;
    72111   
    73     HGCMFunctionParameter ptr;    /* OUT linear pointer. */
    74 } VBoxClipboardHostEventRead;
    75 
    76 typedef struct _VBoxClipboardSendData
    77 {
    78     VBoxGuestHGCMCallInfo hdr;
    79    
     112    /* Returned format as requested in the VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA message. */
    80113    HGCMFunctionParameter format; /* IN uint32_t */
    81114   
     115    /* Data.  */
    82116    HGCMFunctionParameter ptr;    /* IN linear pointer. */
    83 } VBoxClipboardSendData;
     117} VBoxClipboardWriteData;
    84118#pragma pack ()
    85119
  • trunk/src/VBox/Additions/WINNT/VBoxService/VBoxClipboard.cpp

    r9 r1103  
    2222#include <VBox/HostServices/VBoxClipboardSvc.h>
    2323
    24 #include <iprt/crc64.h>
    25 
    26 // #define LOG_ENABLED
     24// #include <iprt/crc64.h>
     25
     26#define LOG_ENABLED
    2727
    2828#ifdef LOG_ENABLED
     
    5555#endif /* LOG_ENABLED */
    5656
     57
    5758typedef struct _VBOXCLIPBOARDCONTEXT
    5859{
     
    6162    uint32_t u32ClientID;
    6263
    63     uint32_t u32Mode;
    64 
    6564    ATOM     atomWindowClass;
    6665
     
    6968    HWND     hwndNextInChain;
    7069
    71     HANDLE   hHostEvent;
    72 
    73     bool     fOperational;
    74 
    75     uint32_t u32LastSentFormat;
    76     uint64_t u64LastSentCRC64;
     70//    bool     fOperational;
     71
     72//    uint32_t u32LastSentFormat;
     73//    uint64_t u64LastSentCRC64;
     74   
     75    bool     fAnnouncing;
    7776
    7877} VBOXCLIPBOARDCONTEXT;
    7978
     79
    8080static char gachWindowClassName[] = "VBoxSharedClipboardClass";
    8181
    82 #define VBOX_INIT_CALL(a, b) do {                                                             \
    83     (a)->hdr.result      = VINF_SUCCESS;                                                      \
    84     (a)->hdr.u32ClientID = pCtx->u32ClientID;                                                 \
    85     (a)->hdr.u32Function = b;                                                                 \
    86     (a)->hdr.cParms      = (sizeof (*a) - sizeof ((a)->hdr)) / sizeof (HGCMFunctionParameter); \
     82
     83#define VBOX_INIT_CALL(__a, __b, __c) do {                                                             \
     84    (__a)->hdr.result      = VINF_SUCCESS;                                                             \
     85    (__a)->hdr.u32ClientID = (__c)->u32ClientID;                                                       \
     86    (__a)->hdr.u32Function = (__b);                                                                    \
     87    (__a)->hdr.cParms      = (sizeof (*(__a)) - sizeof ((__a)->hdr)) / sizeof (HGCMFunctionParameter); \
    8788} while (0)
    8889
    89 static bool vboxClipboardIsSameAsLastSent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
    90                                           void *pv, uint32_t cb)
    91 {
    92     uint64_t u64CRC = RTCrc64 (pv, cb);
    93 
    94     if (   pCtx->u32LastSentFormat == u32Format
    95         && pCtx->u64LastSentCRC64 == u64CRC)
    96     {
    97         return true;
    98     }
    99 
    100     pCtx->u64LastSentCRC64 = u64CRC;
    101     pCtx->u32LastSentFormat = u32Format;
    102 
    103     return false;
    104 }
     90
     91//static bool vboxClipboardIsSameAsLastSent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
     92//                                           void *pv, uint32_t cb)
     93//{
     94//    uint64_t u64CRC = RTCrc64 (pv, cb);
     95//
     96//    if (   pCtx->u32LastSentFormat == u32Format
     97//        && pCtx->u64LastSentCRC64 == u64CRC)
     98//    {
     99//        return true;
     100//    }
     101//
     102//    pCtx->u64LastSentCRC64 = u64CRC;
     103//    pCtx->u32LastSentFormat = u32Format;
     104//
     105//    return false;
     106//}
    105107
    106108static int vboxClipboardConnect (VBOXCLIPBOARDCONTEXT *pCtx)
     
    204206}
    205207
    206 static int vboxClipboardQueryMode (VBOXCLIPBOARDCONTEXT *pCtx)
    207 {
    208     VBoxClipboardQueryMode parms;
    209 
    210     VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_QUERY_MODE);
    211 
    212     VBoxHGCMParmUInt32Set (&parms.mode, 0);
     208static int vboxClipboardReportFormats (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Formats)
     209{
     210    VBoxClipboardFormats parms;
     211
     212    VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_FORMATS, pCtx);
     213
     214    VBoxHGCMParmUInt32Set (&parms.formats, u32Formats);
    213215
    214216    int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
     
    217219    {
    218220        rc = parms.hdr.result;
    219 
    220         if (VBOX_SUCCESS (rc))
    221         {
    222             rc = VBoxHGCMParmUInt32Get (&parms.mode, &pCtx->u32Mode);
    223 
    224             dprintf (("vboxClipboardQueryMode: Mode = %d, rc = %d\n", pCtx->u32Mode, rc));
    225         }
    226221    }
    227222
     
    229224}
    230225
    231 static int vboxClipboardHostEventCancel (VBOXCLIPBOARDCONTEXT *pCtx)
    232 {
    233     VBoxClipboardHostEventCancel parms;
    234 
    235     VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_CANCEL);
    236 
    237     int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
    238 
    239     if (VBOX_SUCCESS (rc))
    240     {
    241         rc = parms.hdr.result;
    242     }
    243 
    244     return rc;
    245 }
    246 
    247 static int vboxClipboardHostEventRead (VBOXCLIPBOARDCONTEXT *pCtx, void *pv, uint32_t cb)
    248 {
    249     if (!VirtualLock (pv, cb))
     226static int vboxClipboardReadData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual)
     227{
     228    if (cb > 0 && !VirtualLock (pv, cb))
    250229    {
    251230        dprintf (("vboxClipboardHostEventRead: VirtualLock failed\n"));
     
    253232    }
    254233
    255     VBoxClipboardHostEventRead parms;
    256 
    257     VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_READ);
    258 
    259     VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
     234    VBoxClipboardReadData parms;
     235
     236    VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_READ_DATA, pCtx);
     237
     238    VBoxHGCMParmUInt32Set (&parms.format, u32Format);
     239    VBoxHGCMParmPtrSet    (&parms.ptr, pv, cb);
     240    VBoxHGCMParmUInt32Set (&parms.size, 0);
    260241
    261242    int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
     
    264245    {
    265246        rc = parms.hdr.result;
    266     }
    267 
    268     VirtualUnlock (pv, cb);
    269 
    270     return rc;
    271 }
    272 
    273 static int vboxClipboardSendData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
    274                                   void *pv, uint32_t cb)
    275 {
    276     if (vboxClipboardIsSameAsLastSent (pCtx, u32Format, pv, cb))
    277     {
    278         dprintf (("vboxClipboardSendData: The data to be sent are the same as the last sent.\n"));
    279         return VINF_SUCCESS;
    280     }
    281 
    282     if (!VirtualLock (pv, cb))
    283     {
    284         dprintf (("vboxClipboardSendData: VirtualLock failed\n"));
    285         return VERR_NOT_SUPPORTED;
    286     }
    287 
    288     VBoxClipboardSendData parms;
    289 
    290     VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_SEND_DATA);
    291 
    292     VBoxHGCMParmUInt32Set (&parms.format, u32Format);
    293     VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
    294 
    295     int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
    296 
    297     if (VBOX_SUCCESS (rc))
    298     {
    299         rc = parms.hdr.result;
    300     }
    301 
    302     VirtualUnlock (pv, cb);
    303 
    304     return rc;
    305 }
    306 
    307 
    308 static void vboxClipboardSendDIB (VBOXCLIPBOARDCONTEXT *pCtx)
    309 {
    310     HANDLE hClip = GetClipboardData (CF_DIB);
    311 
    312     if (hClip != NULL)
    313     {
    314         LPVOID lp = GlobalLock (hClip);
    315 
    316         if (lp != NULL)
    317         {
    318             vboxClipboardSendData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
    319                                    lp, GlobalSize (hClip));
    320 
    321             GlobalUnlock(hClip);
    322         }
    323     }
    324 }
    325 
    326 static void vboxClipboardSendBitmap (VBOXCLIPBOARDCONTEXT *pCtx)
    327 {
    328     /* Request DIB format anyway. The system will convert the available CF_BITMAP to CF_DIB. */
    329     vboxClipboardSendDIB (pCtx);
    330 }
    331 
    332 static void vboxClipboardSendUnicodeText (VBOXCLIPBOARDCONTEXT *pCtx)
    333 {
    334     HANDLE hClip = GetClipboardData(CF_UNICODETEXT);
    335 
    336     if (hClip != NULL)
    337     {
    338         LPWSTR uniString = (LPWSTR)GlobalLock (hClip);
    339 
    340         if (uniString != NULL)
    341         {
    342             vboxClipboardSendData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
    343                                    uniString, (lstrlenW (uniString) + 1) * 2);
    344 
    345             GlobalUnlock(hClip);
    346         }
    347     }
    348 }
    349 
    350 static void vboxClipboardSendText (VBOXCLIPBOARDCONTEXT *pCtx)
    351 {
    352     /* Request UNICODE format anyway. The system will convert the available CF_TEXT to CF_UNICODE. */
    353     vboxClipboardSendUnicodeText (pCtx);
    354 }
    355 
    356 static void vboxClipboardGuestEvent (VBOXCLIPBOARDCONTEXT *pCtx)
    357 {
    358     if (   pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST
    359         && pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
    360     {
    361         /* The host will not accept the clipboard data anyway. */
    362         return;
    363     }
    364 
    365     if (OpenClipboard (pCtx->hwnd))
    366     {
    367         int cFormats = CountClipboardFormats ();
    368 
    369         if (cFormats > 0)
    370         {
    371             dprintf (("vboxClipboardGuestEvent: cFormats = %d\n", cFormats));
    372 
    373             static UINT aFormatPriorityList[] =
    374             {
    375                 CF_UNICODETEXT,
    376                 CF_TEXT,
    377                 CF_DIB,
    378                 CF_BITMAP
    379             };
    380 
    381             int iFormat = GetPriorityClipboardFormat (aFormatPriorityList, ELEMENTS (aFormatPriorityList));
    382 
    383             switch (iFormat)
    384             {
    385                 case CF_TEXT:
     247
     248        if (VBOX_SUCCESS (rc))
     249        {
     250            uint32_t u32Size;
     251
     252            rc = VBoxHGCMParmUInt32Get (&parms.size, &u32Size);
     253
     254            dprintf (("vboxClipboardReadData: actual size = %d, rc = %d\n", u32Size, rc));
     255
     256            if (VBOX_SUCCESS (rc))
     257            {
     258                if (pcbActual)
    386259                {
    387                     dprintf(("CF_TEXT\n"));
    388 
    389                     vboxClipboardSendText (pCtx);
    390                 } break;
    391 
    392                 case CF_UNICODETEXT:
    393                 {
    394                     dprintf(("CF_UNICODETEXT\n"));
    395 
    396                     vboxClipboardSendUnicodeText (pCtx);
    397                 } break;
    398 
    399                 case CF_BITMAP:
    400                 {
    401                     dprintf(("CF_BITMAP\n"));
    402 
    403                     vboxClipboardSendBitmap (pCtx);
    404                 } break;
    405 
    406                 case CF_DIB:
    407                 {
    408                     dprintf(("CF_DIB\n"));
    409 
    410                     vboxClipboardSendDIB (pCtx);
    411                 } break;
    412 
    413                 default:
    414                 {
    415                     dprintf(("not supported %d\n", iFormat));
    416                 }
    417             }
    418         }
    419 
    420         CloseClipboard ();
    421     }
    422 }
    423 
    424 static void vboxClipboardHostEvent (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, uint32_t u32Size)
    425 {
    426     if (   pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
    427         && pCtx->u32Mode != VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
    428     {
    429         /* The guest should not accept the clipboard data anyway. */
    430         vboxClipboardHostEventCancel (pCtx);
    431 
    432         return;
    433     }
    434 
    435     dprintf(("vboxClipboardHostEvent u32Size %d\n", u32Size));
    436 
    437     if (u32Size > 0)
    438     {
    439         HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, u32Size);
    440 
    441         dprintf(("vboxClipboardHostEvent hMem %p\n", hMem));
    442 
    443         if (hMem)
    444         {
    445             void *pMem = GlobalLock (hMem);
    446 
    447             dprintf(("vboxClipboardHostEvent pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
    448 
    449             if (pMem)
    450             {
    451                 /* Read the host data and cancel the transaction. */
    452                 int rc = vboxClipboardHostEventRead (pCtx, pMem, u32Size);
    453 
    454                 dprintf(("vboxClipboardHostEvent read %d\n", rc));
    455 
    456                 if (VBOX_SUCCESS (rc))
    457                 {
    458                     /* Data was read from the host and transaction was cancelled.
    459                      * Return from the code branch without calling cancel event.
    460                      */
    461                     HANDLE hClip = 0;
    462 
    463                     /* Remember the last data that goes to the clipboard.
    464                      * That will prevent sending the same data back to the client.
    465                      */
    466                     vboxClipboardIsSameAsLastSent (pCtx, u32Format, pMem, u32Size);
    467 
    468                     /* The memory must be unlocked before the Clipboard is closed. */
    469                     GlobalUnlock (hMem);
    470 
    471                     /* 'pMem' contains the host clipboard data.
    472                      * size is 'u32Size' and format is 'u32Format'.
    473                      */
    474                     if (OpenClipboard (pCtx->hwnd))
    475                     {
    476                         EmptyClipboard();
    477 
    478                         if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    479                         {
    480                             dprintf(("vboxClipboardHostEvent VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
    481                             hClip = SetClipboardData (CF_UNICODETEXT, hMem);
    482                         }
    483                         else if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    484                         {
    485                             dprintf(("vboxClipboardHostEvent VBOX_SHARED_CLIPBOARD_FMT_BiTMAP\n"));
    486                             hClip = SetClipboardData (CF_DIB, hMem);
    487                         }
    488 
    489                         CloseClipboard();
    490 
    491                         dprintf(("vboxClipboardHostEvent hClip %p\n", hClip));
    492                     }
    493                     else
    494                     {
    495                         dprintf(("vboxClipboardHostEvent failed to open clipboard\n"));
    496                     }
    497 
    498                     if (!hClip)
    499                     {
    500                         /* Failed to set the clipboard data. */
    501                         GlobalFree (hMem);
    502                     }
    503                     else
    504                     {
    505                         /* The hMem ownership has gone to the system. Nothing to do. */
    506                     }
    507 
    508                     return;
     260                    *pcbActual = u32Size;
    509261                }
    510262                else
    511263                {
    512                     GlobalUnlock (hMem);
     264                    if (u32Size != cb)
     265                    {
     266                        rc = VERR_INVALID_PARAMETER;
     267                    }
    513268                }
    514269            }
    515 
    516             GlobalFree (hMem);
    517         }
    518     }
    519     else
    520     {
    521         if (OpenClipboard (pCtx->hwnd))
    522         {
    523             EmptyClipboard();
    524             CloseClipboard();
    525         }
    526     }
    527 
    528     vboxClipboardHostEventCancel (pCtx);
    529 
    530     return;
     270        }
     271    }
     272
     273    if (cb > 0)
     274    {
     275        VirtualUnlock (pv, cb);
     276    }
     277
     278    return rc;
     279}
     280
     281static int vboxClipboardWriteData (VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
     282                                  void *pv, uint32_t cb)
     283{
     284//    if (vboxClipboardIsSameAsLastSent (pCtx, u32Format, pv, cb))
     285//    {
     286//        dprintf (("vboxClipboardWriteData: The data to be sent are the same as the last sent.\n"));
     287//        return VINF_SUCCESS;
     288//    }
     289
     290    if (!VirtualLock (pv, cb))
     291    {
     292        dprintf (("vboxClipboardWriteData: VirtualLock failed\n"));
     293        return VERR_NOT_SUPPORTED;
     294    }
     295
     296    VBoxClipboardWriteData parms;
     297
     298    VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA, pCtx);
     299
     300    VBoxHGCMParmUInt32Set (&parms.format, u32Format);
     301    VBoxHGCMParmPtrSet (&parms.ptr, pv, cb);
     302
     303    int rc = vboxCall (pCtx->pEnv->hDriver, &parms, sizeof (parms));
     304
     305    if (VBOX_SUCCESS (rc))
     306    {
     307        rc = parms.hdr.result;
     308    }
     309
     310    VirtualUnlock (pv, cb);
     311
     312    return rc;
     313}
     314
     315static void vboxClipboardChanged (VBOXCLIPBOARDCONTEXT *pCtx)
     316{
     317    /* Query list of available formats and report to host. */
     318    if (OpenClipboard (pCtx->hwnd))
     319    {
     320        uint32_t u32Formats = 0;
     321
     322        UINT format = 0;
     323
     324        while ((format = EnumClipboardFormats (format)) != 0)
     325        {
     326            switch (format)
     327            {
     328                case CF_UNICODETEXT:
     329                case CF_TEXT:
     330                    u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
     331                    break;
     332
     333                case CF_DIB:
     334                case CF_BITMAP:
     335                    u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
     336                    break;
     337
     338                default:
     339                     break;
     340            }
     341        }
     342
     343        CloseClipboard ();
     344       
     345        vboxClipboardReportFormats (pCtx, u32Formats);
     346    }
    531347}
    532348
     
    565381            dprintf (("vboxClipboardProcessMsg: WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
    566382
    567             vboxClipboardGuestEvent (pCtx);
     383            if (!pCtx->fAnnouncing)
     384            {
     385                vboxClipboardChanged (pCtx);
     386            }
    568387
    569388            /* Pass the message to next windows in the clipboard chain. */
     
    574393        {
    575394            /* Do nothing. Ignore the message. */
     395        } break;
     396       
     397        case WM_RENDERFORMAT:
     398        {
     399            /* Insert the requested clipboard format data into the clipboard. */
     400            uint32_t u32Format = 0;
     401
     402            UINT format = (UINT)wParam;
     403
     404            switch (format)
     405            {
     406                case CF_UNICODETEXT:
     407                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
     408                    break;
     409
     410                case CF_DIB:
     411                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
     412                    break;
     413
     414                default:
     415                     break;
     416            }
     417           
     418            if (u32Format == 0)
     419            {
     420                /* Unsupported clipboard format is requested. */
     421                EmptyClipboard ();
     422            }
     423            else
     424            {
     425                /* Query the size of available data. */
     426                uint32_t cb = 0;
     427
     428                int vboxrc = vboxClipboardReadData (pCtx, u32Format, NULL, 0, &cb);
     429
     430                dprintf(("vboxClipboardReadData vboxrc = %d, cb = %d\n", vboxrc, cb));
     431
     432                if (VBOX_SUCCESS (vboxrc) && cb > 0)
     433                {
     434                    HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cb);
     435
     436                    dprintf(("hMem %p\n", hMem));
     437
     438                    if (hMem)
     439                    {
     440                        void *pMem = GlobalLock (hMem);
     441
     442                        dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
     443
     444                        if (pMem)
     445                        {
     446                            /* Read the host data. */
     447                            vboxrc = vboxClipboardReadData (pCtx, u32Format, pMem, cb, NULL);
     448                           
     449                            dprintf(("vboxClipboardReadData vboxrc %d\n",  vboxrc));
     450
     451                            if (VBOX_SUCCESS (vboxrc))
     452                            {
     453//                                /* Remember the which data was transferred. */
     454//                                vboxClipboardIsSameAsLastSent (pCtx, u32Format, pMem, cb);
     455
     456                                /* The memory must be unlocked before inserting to the Clipboard. */
     457                                GlobalUnlock (hMem);
     458
     459                                /* 'hMem' contains the host clipboard data.
     460                                 * size is 'cb' and format is 'format'.
     461                                 */
     462                                HANDLE hClip = SetClipboardData (format, hMem);
     463
     464                                dprintf(("WM_RENDERFORMAT hClip %p\n", hClip));
     465
     466                                if (hClip)
     467                                {
     468                                    /* The hMem ownership has gone to the system. Finish the processsing. */
     469                                    break;
     470                                }
     471                               
     472                                /* Cleanup follows. */
     473                            }
     474                            else
     475                            {
     476                                GlobalUnlock (hMem);
     477                            }
     478                        }
     479
     480                        GlobalFree (hMem);
     481                    }
     482                }
     483               
     484                /* Something went wrong. */
     485                EmptyClipboard ();
     486            }
     487        } break;
     488
     489        case WM_RENDERALLFORMATS:
     490        {
     491            /* Do nothing. The clipboard formats will be unavailable now, because the
     492             * windows is to be destroyed and therefore the guest side becomes inactive.
     493             */
     494            if (OpenClipboard (hwnd))
     495            {
     496                EmptyClipboard();
     497
     498                CloseClipboard();
     499            }
     500        } break;
     501
     502        case WM_USER:
     503        {
     504            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
     505            uint32_t u32Formats = (uint32_t)lParam;
     506           
     507            /* Prevent the WM_DRAWCLIPBOARD processing. */
     508            pCtx->fAnnouncing = true;
     509
     510            if (OpenClipboard (hwnd))
     511            {
     512                EmptyClipboard();
     513               
     514                HANDLE hClip = NULL;
     515
     516                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     517                {
     518                    dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
     519                    hClip = SetClipboardData (CF_UNICODETEXT, NULL);
     520                }
     521
     522                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     523                {
     524                    dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
     525                    hClip = SetClipboardData (CF_DIB, NULL);
     526                }
     527
     528                CloseClipboard();
     529
     530                dprintf(("window proc WM_USER: hClip %p\n", hClip));
     531            }
     532            else
     533            {
     534                dprintf(("window proc WM_USER: failed to open clipboard\n"));
     535            }
     536           
     537            pCtx->fAnnouncing = false;
     538        } break;
     539
     540        case WM_USER + 1:
     541        {
     542            /* Send data in the specified format to the host. */
     543            uint32_t u32Formats = (uint32_t)lParam;
     544
     545            HANDLE hClip = NULL;
     546
     547            if (OpenClipboard (hwnd))
     548            {
     549                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     550                {
     551                    hClip = GetClipboardData (CF_DIB);
     552
     553                    if (hClip != NULL)
     554                    {
     555                        LPVOID lp = GlobalLock (hClip);
     556
     557                        if (lp != NULL)
     558                        {
     559                            dprintf(("CF_DIB\n"));
     560
     561                            vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
     562                                                    lp, GlobalSize (hClip));
     563
     564                            GlobalUnlock(hClip);
     565                        }
     566                        else
     567                        {
     568                            hClip = NULL;
     569                        }
     570                    }
     571                }
     572                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
     573                {
     574                    hClip = GetClipboardData(CF_UNICODETEXT);
     575
     576                    if (hClip != NULL)
     577                    {
     578                        LPWSTR uniString = (LPWSTR)GlobalLock (hClip);
     579
     580                        if (uniString != NULL)
     581                        {
     582                            dprintf(("CF_UNICODETEXT\n"));
     583
     584                            vboxClipboardWriteData (pCtx, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
     585                                                    uniString, (lstrlenW (uniString) + 1) * 2);
     586
     587                            GlobalUnlock(hClip);
     588                        }
     589                        else
     590                        {
     591                            hClip = NULL;
     592                        }
     593                    }
     594                }
     595
     596                CloseClipboard ();
     597            }
     598           
     599            if (hClip == NULL)
     600            {
     601                /* Requested clipboard format is not available, send empty data. */
     602                vboxClipboardWriteData (pCtx, 0, NULL, 0);
     603            }
    576604        } break;
    577605
     
    668696    dprintf (("VboxClipboardInit\n"));
    669697
    670     if (!gCtx.pEnv)
    671     {
    672         memset (&gCtx, 0, sizeof (gCtx));
    673 
    674         gCtx.pEnv = pEnv;
    675 
    676         rc = vboxClipboardConnect (&gCtx);
     698    if (gCtx.pEnv)
     699    {
     700        /* Clipboard was already initialized. 2 or more instances are not supported. */
     701        return VERR_NOT_SUPPORTED;
     702    }
     703
     704    memset (&gCtx, 0, sizeof (gCtx));
     705
     706    gCtx.pEnv = pEnv;
     707
     708    rc = vboxClipboardConnect (&gCtx);
     709
     710    if (VBOX_SUCCESS (rc))
     711    {
     712        rc = vboxClipboardInit (&gCtx);
     713
     714        dprintf (("vboxClipboardInit: rc = %d\n", rc));
    677715
    678716        if (VBOX_SUCCESS (rc))
    679717        {
    680             rc = vboxClipboardQueryMode (&gCtx);
    681 
    682             if (VBOX_SUCCESS (rc))
    683             {
    684                 rc = vboxClipboardInit (&gCtx);
    685 
    686                 dprintf (("vboxClipboardInit: rc = %d\n", rc));
    687 
    688                 if (VBOX_SUCCESS (rc))
    689                 {
    690                     /* Host to Guest direction requires the thread. */
    691                     if (   gCtx.u32Mode == VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST
    692                         || gCtx.u32Mode == VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL)
    693                     {
    694                         *pfStartThread = true;
    695                     }
    696                 }
    697             }
     718            /* Always start the thread for host messages. */
     719            *pfStartThread = true;
    698720        }
    699721    }
     
    716738
    717739    dprintf(("VBoxClipboardThread\n"));
    718 
    719     HANDLE hHostEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    720 
    721     /* The thread waits for incoming data from the host.
    722      * Register an event notification.
    723      */
     740   
     741    /* Open the new driver instance to not interfere with other callers. */
     742    HANDLE hDriver = CreateFile(VBOXGUEST_DEVICE_NAME,
     743                                GENERIC_READ | GENERIC_WRITE,
     744                                FILE_SHARE_READ | FILE_SHARE_WRITE,
     745                                NULL,
     746                                OPEN_EXISTING,
     747                                FILE_ATTRIBUTE_NORMAL,
     748                                NULL);
     749                               
     750    /* The thread waits for incoming messages from the host. */
    724751    for (;;)
    725752    {
    726         uint32_t u32Format;
    727         uint32_t u32Size;
    728 
    729         VBoxClipboardHostEventQuery parms;
    730 
    731         VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_HOST_EVENT_QUERY);
    732 
    733         VBoxHGCMParmUInt32Set (&parms.format, 0);
    734         VBoxHGCMParmUInt32Set (&parms.size, 0);
     753        VBoxClipboardGetHostMsg parms;
     754
     755        VBOX_INIT_CALL(&parms, VBOX_SHARED_CLIPBOARD_FN_GET_HOST_MSG, pCtx);
     756
     757        VBoxHGCMParmUInt32Set (&parms.msg, 0);
     758        VBoxHGCMParmUInt32Set (&parms.formats, 0);
    735759
    736760        DWORD cbReturned;
    737761
    738         if (!DeviceIoControl (pCtx->pEnv->hDriver,
     762        if (!DeviceIoControl (hDriver,
    739763                              IOCTL_VBOXGUEST_HGCM_CALL,
    740764                              &parms, sizeof (parms),
     
    743767                              NULL))
    744768        {
    745             dprintf(("Failed to call the driver for host event\n"));
     769            dprintf(("Failed to call the driver for host message.\n"));
    746770
    747771            /* Wait a bit before retrying. */
     
    758782        if (VBOX_SUCCESS (rc))
    759783        {
    760             rc = VBoxHGCMParmUInt32Get (&parms.format, &u32Format);
     784            uint32_t u32Msg;
     785            uint32_t u32Formats;
     786
     787            rc = VBoxHGCMParmUInt32Get (&parms.msg, &u32Msg);
    761788
    762789            if (VBOX_SUCCESS (rc))
    763790            {
    764                 rc = VBoxHGCMParmUInt32Get (&parms.size, &u32Size);
     791                rc = VBoxHGCMParmUInt32Get (&parms.formats, &u32Formats);
    765792
    766793                if (VBOX_SUCCESS (rc))
    767794                {
    768                     vboxClipboardHostEvent (pCtx, u32Format, u32Size);
     795                    dprintf(("vboxClipboardHostEvent u32Msg %d, u32Formats %d\n", u32Msg, u32Formats));
     796   
     797                    switch (u32Msg)
     798                    {
     799                        case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
     800                        {
     801                            /* The host has announced available clipboard formats.
     802                             * Forward the information to the window, so it can later
     803                             * respond to WM_RENDERFORMAT message.
     804                             */
     805                            ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
     806                        } break;
     807                        case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
     808                        {
     809                            /* The host needs data in the specified format.
     810                             */
     811                            ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
     812                        } break;
     813                        case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
     814                        {
     815                            /* The host is terminating.
     816                             */
     817                            rc = VERR_INTERRUPTED;
     818                        } break;
     819                        default:
     820                        {
     821                            dprintf(("Unsupported message from host!!!"));
     822                        }
     823                    }
    769824                }
    770825            }
    771826        }
     827       
     828        if (rc == VERR_INTERRUPTED)
     829        {
     830            /* Wait for termination event. */
     831            WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
     832            break;
     833        }
     834       
     835        if (VBOX_FAILURE (rc))
     836        {
     837            /* Wait a bit before retrying. */
     838            if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
     839            {
     840                break;
     841            }
     842
     843            continue;
     844        }
    772845
    773846        dprintf(("processed host event rc = %d\n", rc));
    774847    }
     848   
     849    CloseHandle (hDriver);
    775850
    776851    return 0;
Note: See TracChangeset for help on using the changeset viewer.

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