VirtualBox

Changeset 78151 in vbox


Ignore:
Timestamp:
Apr 17, 2019 12:03:42 PM (5 years ago)
Author:
vboxsync
Message:

Shared Clipboard: Got rid of a lot of duplicated code between Windows hosts / guests, plus a lot of renaming / cleanup, some more documentation.

Location:
trunk
Files:
2 added
8 edited

Legend:

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

    r76585 r78151  
    3333#include <iprt/types.h>
    3434
     35/**
     36 * Supported data formats for Shared Clipboard. Bit mask.
     37 */
     38/** Shared Clipboard format is an Unicode text. */
     39#define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT   UINT32_C(0x01)
     40/** Shared Clipboard format is bitmap (BMP / DIB). */
     41#define VBOX_SHARED_CLIPBOARD_FMT_BITMAP        UINT32_C(0x02)
     42/** Shared Clipboard format is HTML. */
     43#define VBOX_SHARED_CLIPBOARD_FMT_HTML          UINT32_C(0x04)
     44
     45/**
     46 * The host messages for the guest.
     47 */
     48#define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT        1
     49#define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA   2
     50#define VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS     3
     51
    3552enum
    3653{
     
    4663struct _VBOXCLIPBOARDCONTEXT;
    4764typedef struct _VBOXCLIPBOARDCONTEXT VBOXCLIPBOARDCONTEXT;
     65typedef struct _VBOXCLIPBOARDCONTEXT *PVBOXCLIPBOARDCONTEXT;
    4866
    4967/** Opaque data structure for the X11/VBox backend code. */
  • trunk/include/VBox/HostServices/VBoxClipboardSvc.h

    r76585 r78151  
    4343
    4444/*
    45  * Supported data formats. Bit mask.
    46  */
    47 #define VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT   UINT32_C(0x01)
    48 #define VBOX_SHARED_CLIPBOARD_FMT_BITMAP        UINT32_C(0x02)
    49 #define VBOX_SHARED_CLIPBOARD_FMT_HTML          UINT32_C(0x04)
    50 
    51 /*
    5245 * The service functions which are callable by host.
    5346 */
     
    6760/* Send data in requested format to host. */
    6861#define VBOX_SHARED_CLIPBOARD_FN_WRITE_DATA        4
    69 
    70 /*
    71  * The host messages for the guest.
    72  */
    73 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT        1
    74 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA   2
    75 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS     3
    7662
    7763/*
  • trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk

    r76553 r78151  
    3737        VBoxDispIf.cpp \
    3838        VBoxSeamless.cpp \
    39         VBoxClipboard.cpp \
    4039        VBoxDisplay.cpp \
    4140        VBoxVRDP.cpp \
     
    4645VBoxTray_VBOX_IMPORT_CHECKER.win.x86 = nt4 #nt350
    4746VBoxTray_VBOX_IMPORT_CHECKER.win.amd64 = xp64
     47ifdef VBOX_WITH_SHARED_CLIPBOARD
     48 VBoxTray_DEFS     += \
     49        VBOX_WITH_SHARED_CLIPBOARD
     50 VBoxTray_SOURCES  += \
     51        VBoxClipboard.cpp \
     52        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
     53endif
    4854ifdef VBOX_WITH_DRAG_AND_DROP
    4955 VBoxTray_DEFS     += \
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp

    r78142 r78151  
    2727#include <iprt/ldr.h>
    2828
    29 #include <VBox/HostServices/VBoxClipboardSvc.h>
     29#include <VBox/GuestHost/SharedClipboard.h>
     30#include <VBox/GuestHost/SharedClipboard-win.h>
    3031#include <strsafe.h>
    3132
     
    3637*   Structures and Typedefs                                                                                                      *
    3738*********************************************************************************************************************************/
    38 /* Dynamically load clipboard functions from User32.dll. */
    39 typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
    40 typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
    41 
    42 typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
    43 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
    44 
    45 #ifndef WM_CLIPBOARDUPDATE
    46 #define WM_CLIPBOARDUPDATE 0x031D
    47 #endif
    48 
    49 /** Sets announced clipboard formats from the host. */
    50 #define VBOX_WM_SHCLPB_SET_FORMATS      WM_USER
    51 /** Reads data from the clipboard and sends it to the host. */
    52 #define VBOX_WM_SHCLPB_READ_DATA        WM_USER + 1
    53 
    54 typedef struct _VBOXCLIPBOARDCONTEXT
    55 {
    56     const VBOXSERVICEENV *pEnv;
    57     uint32_t              u32ClientID;
    58     ATOM                  wndClass;
    59     HWND                  hwnd;
    60     HWND                  hwndNextInChain;
    61     UINT                  timerRefresh;
    62     bool                  fCBChainPingInProcess;
    63     PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener;
    64     PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
    65 } VBOXCLIPBOARDCONTEXT, *PVBOXCLIPBOARDCONTEXT;
    66 
    67 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
    68 
     39
     40struct _VBOXCLIPBOARDCONTEXT
     41{
     42    /** Pointer to the VBoxClient service environment. */
     43    const VBOXSERVICEENV    *pEnv;
     44    /** Client ID the service is connected to the HGCM service with. */
     45    uint32_t                 u32ClientID;
     46    /** Windows-specific context data. */
     47    VBOXCLIPBOARDWINCTX      Win;
     48};
    6949
    7050/*********************************************************************************************************************************
    71 *   Header Files                                                                                                                 *
     51*   Static variables                                                                                                             *
    7252*********************************************************************************************************************************/
    73 /** Static since it is the single instance. Directly used in the windows proc. */
     53/** Static clipboard context (since it is the single instance). Directly used in the windows proc. */
    7454static VBOXCLIPBOARDCONTEXT g_Ctx = { NULL };
    75 
    76 static char s_szClipWndClassName[] = "VBoxSharedClipboardClass";
    77 
    78 
    79 static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
    80 {
    81     RTLDRMOD hUser32 = NIL_RTLDRMOD;
    82     int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);
    83     if (RT_SUCCESS(rc))
    84     {
    85         rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);
    86         if (RT_SUCCESS(rc))
    87         {
    88             rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);
    89         }
    90 
    91         RTLdrClose(hUser32);
    92     }
    93 
    94     if (RT_SUCCESS(rc))
    95     {
    96         Log(("New Clipboard API is enabled\n"));
    97     }
    98     else
    99     {
    100         pCtx->pfnAddClipboardFormatListener = NULL;
    101         pCtx->pfnRemoveClipboardFormatListener = NULL;
    102         Log(("New Clipboard API is not available. rc = %Rrc\n", rc));
    103     }
    104 }
    105 
    106 static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
    107 {
    108     return pCtx->pfnAddClipboardFormatListener != NULL;
    109 }
    110 
    111 
    112 static int vboxOpenClipboard(HWND hWnd)
    113 {
    114     /* "OpenClipboard fails if another window has the clipboard open."
    115      * So try a few times and wait up to 1 second.
    116      */
    117     BOOL fOpened = FALSE;
    118 
    119     LogFlowFunc(("hWnd=%p\n", hWnd));
    120 
    121     int i = 0;
    122     for (;;)
    123     {
    124         if (OpenClipboard(hWnd))
    125         {
    126             fOpened = TRUE;
    127             break;
    128         }
    129 
    130         if (i >= 10) /* sleep interval = [1..512] ms */
    131             break;
    132 
    133         RTThreadSleep(1 << i);
    134         ++i;
    135     }
    136 
    137 #ifdef LOG_ENABLED
    138     if (i > 0)
    139         LogFlowFunc(("%d times tried to open clipboard\n", i + 1));
    140 #endif
    141 
    142     int rc;
    143     if (fOpened)
    144         rc = VINF_SUCCESS;
    145     else
    146     {
    147         const DWORD dwLastErr = GetLastError();
    148         rc = RTErrConvertFromWin32(dwLastErr);
    149         LogRel(("Clipboard: Failed to open clipboard! Error=%ld (%Rrc)\n", dwLastErr, rc));
    150     }
    151 
    152     return rc;
    153 }
    154 
    155 
    156 static int vboxClipboardChanged(PVBOXCLIPBOARDCONTEXT pCtx)
     55/** Static window class name. */
     56static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME;
     57
     58
     59static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    15760{
    15861    AssertPtr(pCtx);
    15962
    160     /* Query list of available formats and report to host. */
    161     int rc = vboxOpenClipboard(pCtx->hwnd);
    162     if (RT_SUCCESS(rc))
    163     {
    164         uint32_t u32Formats = 0;
    165         UINT format = 0;
    166 
    167         while ((format = EnumClipboardFormats(format)) != 0)
    168         {
    169             LogFlowFunc(("vboxClipboardChanged: format = 0x%08X\n", format));
    170             switch (format)
    171             {
    172                 case CF_UNICODETEXT:
    173                 case CF_TEXT:
    174                     u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    175                     break;
    176 
    177                 case CF_DIB:
    178                 case CF_BITMAP:
    179                     u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    180                     break;
    181 
    182                 default:
    183                 {
    184                     if (format >= 0xC000)
    185                     {
    186                         TCHAR szFormatName[256];
    187 
    188                         int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
    189                         if (cActual)
    190                         {
    191                             if (strcmp (szFormatName, "HTML Format") == 0)
    192                             {
    193                                 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
    194                             }
    195                         }
    196                     }
    197                     break;
    198                 }
    199             }
    200         }
    201 
    202         CloseClipboard();
    203         rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, u32Formats);
    204     }
    205     return rc;
    206 }
    207 
    208 /* Add ourselves into the chain of cliboard listeners */
    209 static void vboxClipboardAddToCBChain(PVBOXCLIPBOARDCONTEXT pCtx)
    210 {
    211     AssertPtrReturnVoid(pCtx);
    212     if (vboxClipboardIsNewAPI(pCtx))
    213         pCtx->pfnAddClipboardFormatListener(pCtx->hwnd);
    214     else
    215         pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);
    216     /** @todo r=andy Return code?? */
    217 }
    218 
    219 /* Remove ourselves from the chain of cliboard listeners */
    220 static void vboxClipboardRemoveFromCBChain(PVBOXCLIPBOARDCONTEXT pCtx)
    221 {
    222     AssertPtrReturnVoid(pCtx);
    223 
    224     if (vboxClipboardIsNewAPI(pCtx))
    225     {
    226         pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd);
    227     }
    228     else
    229     {
    230         ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);
    231         pCtx->hwndNextInChain = NULL;
    232     }
    233     /** @todo r=andy Return code?? */
    234 }
    235 
    236 /* Callback which is invoked when we have successfully pinged ourselves down the
    237  * clipboard chain.  We simply unset a boolean flag to say that we are responding.
    238  * There is a race if a ping returns after the next one is initiated, but nothing
    239  * very bad is likely to happen. */
    240 VOID CALLBACK vboxClipboardChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
    241 {
    242     NOREF(hWnd);
    243     NOREF(uMsg);
    244     NOREF(lResult);
    245 
    246     /** @todo r=andy Why not using SetWindowLongPtr for keeping the context? */
    247     PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)dwData;
    248     AssertPtr(pCtx);
    249 
    250     pCtx->fCBChainPingInProcess = FALSE;
    251 }
    252 
    253 static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    254 {
    255     AssertPtr(pCtx);
     63    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
    25664
    25765    LRESULT rc = 0;
     
    26674            {
    26775                /* Clipboard was updated by another application. */
    268                 vboxClipboardChanged(pCtx);
     76                uint32_t uFormats;
     77                int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
     78                if (RT_SUCCESS(vboxrc))
     79                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
    26980            }
    27081        } break;
     
    27283        case WM_CHANGECBCHAIN:
    27384        {
    274             if (vboxClipboardIsNewAPI(pCtx))
     85            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    27586            {
    27687                rc = DefWindowProc(hwnd, msg, wParam, lParam);
     
    27889            }
    27990
    280             HWND hwndRemoved = (HWND)wParam;
    281             HWND hwndNext    = (HWND)lParam;
    282 
    283             LogFlowFunc(("WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
    284 
    285             if (hwndRemoved == pCtx->hwndNextInChain)
     91            HWND hWndRemoved = (HWND)wParam;
     92            HWND hWndNext    = (HWND)lParam;
     93
     94            LogFlowFunc(("WM_CHANGECBCHAIN: hWndRemoved=%p, hWndNext=%p, hWnd=%p\n", hWndRemoved, hWndNext, pWinCtx->hWnd));
     95
     96            if (hWndRemoved == pWinCtx->hWndNextInChain)
    28697            {
    28798                /* The window that was next to our in the chain is being removed.
    28899                 * Relink to the new next window. */
    289                 pCtx->hwndNextInChain = hwndNext;
     100                pWinCtx->hWndNextInChain = hWndNext;
    290101            }
    291102            else
    292103            {
    293                 if (pCtx->hwndNextInChain)
     104                if (pWinCtx->hWndNextInChain)
    294105                {
    295106                    /* Pass the message further. */
    296107                    DWORD_PTR dwResult;
    297                     rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
     108                    rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
     109                                            VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
    298110                    if (!rc)
    299111                        rc = (LRESULT) dwResult;
     
    304116        case WM_DRAWCLIPBOARD:
    305117        {
    306             LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
     118            LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));
    307119
    308120            if (GetClipboardOwner() != hwnd)
     
    310122                /* Clipboard was updated by another application. */
    311123                /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
    312                 int vboxrc = vboxClipboardChanged(pCtx);
    313                 if (RT_FAILURE(vboxrc))
    314                     LogFlowFunc(("vboxClipboardChanged failed, rc = %Rrc\n", vboxrc));
    315             }
    316 
    317             if (pCtx->hwndNextInChain)
     124                uint32_t uFormats;
     125                int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats);
     126                if (RT_SUCCESS(vboxrc))
     127                    vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
     128            }
     129
     130            if (pWinCtx->hWndNextInChain)
    318131            {
    319132                /* Pass the message to next windows in the clipboard chain. */
    320                 SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
     133                SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL);
    321134            }
    322135        } break;
     
    324137        case WM_TIMER:
    325138        {
    326             if (vboxClipboardIsNewAPI(pCtx))
     139            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
    327140                break;
    328141
     
    331144            /* Re-register ourselves in the clipboard chain if our last ping
    332145             * timed out or there seems to be no valid chain. */
    333             if (!hViewer || pCtx->fCBChainPingInProcess)
    334             {
    335                 vboxClipboardRemoveFromCBChain(pCtx);
    336                 vboxClipboardAddToCBChain(pCtx);
    337             }
     146            if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
     147            {
     148                VBoxClipboardWinRemoveFromCBChain(pWinCtx);
     149                VBoxClipboardWinAddToCBChain(pWinCtx);
     150            }
     151
    338152            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
    339153             * processed by ourselves to the chain. */
    340             pCtx->fCBChainPingInProcess = TRUE;
     154            pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;
     155
    341156            hViewer = GetClipboardViewer();
    342157            if (hViewer)
    343                 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, vboxClipboardChainPingProc, (ULONG_PTR)pCtx);
     158                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
     159                                    VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
    344160        } break;
    345161
     
    387203                /* Unsupported clipboard format is requested. */
    388204                LogFlowFunc(("Unsupported clipboard format requested: %ld\n", u32Format));
    389                 EmptyClipboard();
     205                VBoxClipboardWinClear();
    390206            }
    391207            else
     
    518334
    519335                /* Something went wrong. */
    520                 EmptyClipboard();
     336                VBoxClipboardWinClear();
    521337            }
    522338        } break;
     
    527343             * windows is to be destroyed and therefore the guest side becomes inactive.
    528344             */
    529             int vboxrc = vboxOpenClipboard(hwnd);
     345            int vboxrc = VBoxClipboardWinOpen(hwnd);
    530346            if (RT_SUCCESS(vboxrc))
    531347            {
    532                 EmptyClipboard();
    533                 CloseClipboard();
    534             }
    535         } break;
    536 
    537         case VBOX_WM_SHCLPB_SET_FORMATS:
     348                VBoxClipboardWinClear();
     349                VBoxClipboardWinClose();
     350            }
     351        } break;
     352
     353        case VBOX_CLIPBOARD_WM_SET_FORMATS:
    538354        {
    539355            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
     
    542358            LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: u32Formats=0x%x\n", u32Formats));
    543359
    544             int vboxrc = vboxOpenClipboard(hwnd);
     360            int vboxrc = VBoxClipboardWinOpen(hwnd);
    545361            if (RT_SUCCESS(vboxrc))
    546362            {
    547                 EmptyClipboard();
     363                VBoxClipboardWinClear();
    548364
    549365                HANDLE hClip = NULL;
     
    562378                }
    563379
    564                 CloseClipboard();
     380                VBoxClipboardWinClose();
    565381
    566382                LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));
     
    568384        } break;
    569385
    570         case VBOX_WM_SHCLPB_READ_DATA:
     386        case VBOX_CLIPBOARD_WM_READ_DATA:
    571387        {
    572388            /* Send data in the specified format to the host. */
     
    576392            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
    577393
    578             int vboxrc = vboxOpenClipboard(hwnd);
     394            int vboxrc = VBoxClipboardWinOpen(hwnd);
    579395            if (RT_SUCCESS(vboxrc))
    580396            {
     
    642458                }
    643459
    644                 CloseClipboard();
     460                VBoxClipboardWinClose();
    645461            }
    646462
     
    654470        case WM_DESTROY:
    655471        {
    656             vboxClipboardRemoveFromCBChain(pCtx);
    657             if (pCtx->timerRefresh)
    658                 KillTimer(pCtx->hwnd, 0);
     472            VBoxClipboardWinRemoveFromCBChain(pWinCtx);
     473            if (pWinCtx->oldAPI.timerRefresh)
     474                KillTimer(pWinCtx->hWnd, 0);
    659475            /*
    660476             * don't need to call PostQuitMessage cause
     
    699515        wc.lpszClassName = s_szClipWndClassName;
    700516
    701         pCtx->wndClass = RegisterClassEx(&wc);
    702         if (pCtx->wndClass == 0)
     517        ATOM wndClass = RegisterClassEx(&wc);
     518        if (wndClass == 0)
    703519            rc = RTErrConvertFromWin32(GetLastError());
    704520    }
     
    706522    if (RT_SUCCESS(rc))
    707523    {
     524        const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
     525
    708526        /* Create the window. */
    709         pCtx->hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
    710                                     s_szClipWndClassName, s_szClipWndClassName,
    711                                     WS_POPUPWINDOW,
    712                                     -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
    713         if (pCtx->hwnd == NULL)
     527        pWinCtx->hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
     528                                       s_szClipWndClassName, s_szClipWndClassName,
     529                                       WS_POPUPWINDOW,
     530                                       -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
     531        if (pWinCtx->hWnd == NULL)
    714532        {
    715533            rc = VERR_NOT_SUPPORTED;
     
    717535        else
    718536        {
    719             SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
     537            SetWindowPos(pWinCtx->hWnd, HWND_TOPMOST, -200, -200, 0, 0,
    720538                         SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
    721539
    722             vboxClipboardAddToCBChain(pCtx);
    723             if (!vboxClipboardIsNewAPI(pCtx))
    724                 pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
     540            VBoxClipboardWinAddToCBChain(pWinCtx);
     541            if (!VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
     542                pWinCtx->oldAPI.timerRefresh = SetTimer(pWinCtx->hWnd, 0, 10 * 1000 /* 10s */, NULL);
    725543        }
    726544    }
     
    734552    AssertPtrReturnVoid(pCtx);
    735553
    736     if (pCtx->hwnd)
     554    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
     555
     556    if (pWinCtx->hWnd)
    737557    {
    738         DestroyWindow(pCtx->hwnd);
    739         pCtx->hwnd = NULL;
     558        DestroyWindow(pWinCtx->hWnd);
     559        pWinCtx->hWnd = NULL;
    740560    }
    741561
    742     if (pCtx->wndClass != 0)
    743     {
    744         UnregisterClass(s_szClipWndClassName, pCtx->pEnv->hInstance);
    745         pCtx->wndClass = 0;
    746     }
     562    UnregisterClass(s_szClipWndClassName, pCtx->pEnv->hInstance);
    747563}
    748564
     
    777593
    778594    RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
     595
    779596    pCtx->pEnv = pEnv;
    780597
    781598    /* Check that new Clipboard API is available */
    782     vboxClipboardInitNewAPI(pCtx);
     599    VBoxClipboardWinCheckAndInitNewAPI(&pCtx->Win.newAPI);
    783600
    784601    int rc = VbglR3ClipboardConnect(&pCtx->u32ClientID);
     
    811628    RTThreadUserSignal(RTThreadSelf());
    812629
    813     PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance;
     630    const PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance;
    814631    AssertPtr(pCtx);
     632
     633    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
    815634
    816635    int rc;
     
    846665                     * Forward the information to the window, so it can later
    847666                     * respond to WM_RENDERFORMAT message. */
    848                     ::PostMessage(pCtx->hwnd, VBOX_WM_SHCLPB_SET_FORMATS, 0, u32Formats);
     667                    ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 0, u32Formats);
    849668                } break;
    850669
     
    852671                {
    853672                    /* The host needs data in the specified format. */
    854                     ::PostMessage(pCtx->hwnd, VBOX_WM_SHCLPB_READ_DATA, 0, u32Formats);
     673                    ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_READ_DATA, 0, u32Formats);
    855674                } break;
    856675
     
    927746    VBoxClipboardDestroy
    928747};
     748
  • trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk

    r76970 r78151  
    3535VBoxSharedClipboard_SOURCES.win = \
    3636        VBoxClipboard-win.cpp \
     37        $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp \
    3738        VBoxSharedClipboardSvc.rc
    3839VBoxSharedClipboard_SOURCES.darwin = \
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp

    r76553 r78151  
    2424
    2525#include <VBox/HostServices/VBoxClipboardSvc.h>
     26#include <VBox/GuestHost/SharedClipboard-win.h>
    2627
    2728#include <iprt/alloc.h>
     
    3536#include "VBoxClipboard.h"
    3637
    37 #define dprintf Log
    38 
    39 static char gachWindowClassName[] = "VBoxSharedClipboardClass";
    40 
    41 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
    42 
    43 /* Dynamically load clipboard functions from User32.dll. */
    44 typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
    45 typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
    46 
    47 typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
    48 typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
    49 
     38/** Static window class name. */
     39static char s_szClipWndClassName[] = VBOX_CLIPBOARD_WNDCLASS_NAME;
    5040
    5141/*********************************************************************************************************************************
     
    5545static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
    5646static bool IsWindowsHTML(const char *source);
    57 
    58 
    59 #ifndef WM_CLIPBOARDUPDATE
    60 #define WM_CLIPBOARDUPDATE 0x031D
    61 #endif
     47static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
    6248
    6349struct _VBOXCLIPBOARDCONTEXT
    6450{
    65     HWND    hwnd;
    66     HWND    hwndNextInChain;
    67 
    68     UINT     timerRefresh;
    69 
    70     bool     fCBChainPingInProcess;
    71 
    72     RTTHREAD thread;
    73 
    74     HANDLE hRenderEvent;
    75 
    76     VBOXCLIPBOARDCLIENTDATA *pClient;
    77 
    78     PFNADDCLIPBOARDFORMATLISTENER    pfnAddClipboardFormatListener;
    79     PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
    80 
     51    /** Handle for window message handling thread. */
     52    RTTHREAD                 hThread;
     53    /** Event which gets triggered if the host clipboard needs to render its data. */
     54    HANDLE                   hRenderEvent;
     55    /** Structure for keeping and communicating with client data (from the guest). */
     56    PVBOXCLIPBOARDCLIENTDATA pClient;
     57    /** Windows-specific context data. */
     58    VBOXCLIPBOARDWINCTX      Win;
    8159};
    8260
     
    8664
    8765#ifdef LOG_ENABLED
    88 void vboxClipboardDump(const void *pv, size_t cb, uint32_t u32Format)
     66static void vboxClipboardDump(const void *pv, size_t cb, uint32_t u32Format)
    8967{
    9068    if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    9169    {
    92         Log(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));
     70        LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT:\n"));
    9371        if (pv && cb)
    94             Log(("%ls\n", pv));
     72            LogFunc(("%ls\n", pv));
    9573        else
    96             Log(("%p %d\n", pv, cb));
     74            LogFunc(("%p %zu\n", pv, cb));
    9775    }
    9876    else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    99         dprintf(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
     77        LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
    10078    else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    10179    {
    102         Log(("DUMP: VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));
     80        LogFunc(("VBOX_SHARED_CLIPBOARD_FMT_HTML:\n"));
    10381        if (pv && cb)
    10482        {
    105             Log(("%s\n", pv));
     83            LogFunc(("%s\n", pv));
    10684
    10785            //size_t cb = RTStrNLen(pv, );
     
    11492            }
    11593
    116             Log(("%s\n", pszBuf));
     94            LogFunc(("%s\n", pszBuf));
    11795            RTMemFree(pszBuf);
    11896        }
    11997        else
    120             Log(("%p %d\n", pv, cb));
     98            LogFunc(("%p %zu\n", pv, cb));
    12199    }
    122100    else
    123         dprintf(("DUMP: invalid format %02X\n", u32Format));
     101        LogFunc(("Invalid format %02X\n", u32Format));
    124102}
    125103#else  /* !LOG_ENABLED */
     
    127105#endif /* !LOG_ENABLED */
    128106
    129 
    130 static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
    131 {
    132     RTLDRMOD hUser32 = NIL_RTLDRMOD;
    133     int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);
    134     if (RT_SUCCESS(rc))
    135     {
    136         rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);
    137         if (RT_SUCCESS(rc))
    138         {
    139             rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);
    140         }
    141 
    142         RTLdrClose(hUser32);
    143     }
    144 
    145     if (RT_SUCCESS(rc))
    146     {
    147         Log(("New Clipboard API is enabled\n"));
    148     }
    149     else
    150     {
    151         pCtx->pfnAddClipboardFormatListener = NULL;
    152         pCtx->pfnRemoveClipboardFormatListener = NULL;
    153         Log(("New Clipboard API is not available. rc = %Rrc\n", rc));
    154     }
    155 }
    156 
    157 static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
    158 {
    159     return pCtx->pfnAddClipboardFormatListener != NULL;
    160 }
    161 
    162 
    163 static int vboxOpenClipboard(HWND hwnd)
    164 {
    165     /* "OpenClipboard fails if another window has the clipboard open."
    166      * So try a few times and wait up to 1 second.
    167      */
    168     BOOL fOpened = FALSE;
    169 
    170     int i = 0;
    171     for (;;)
    172     {
    173         if (OpenClipboard(hwnd))
    174         {
    175             fOpened = TRUE;
    176             break;
    177         }
    178 
    179         if (i >= 10) /* sleep interval = [1..512] ms */
    180             break;
    181 
    182         RTThreadSleep(1 << i);
    183         ++i;
    184     }
    185 
    186 #ifdef LOG_ENABLED
    187     if (i > 0)
    188         LogFlowFunc(("%d times tried to open clipboard.\n", i + 1));
    189 #endif
    190 
    191     int rc;
    192     if (fOpened)
    193         rc = VINF_SUCCESS;
    194     else
    195     {
    196         const DWORD err = GetLastError();
    197         LogFlowFunc(("error %d\n", err));
    198         rc = RTErrConvertFromWin32(err);
    199     }
    200 
    201     return rc;
    202 }
    203 
    204 
    205107/** @todo Someone please explain the protocol wrt overflows...  */
    206108static void vboxClipboardGetData (uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,
    207109                                  void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)
    208110{
    209     dprintf (("vboxClipboardGetData.\n"));
    210 
    211111    LogFlow(("vboxClipboardGetData cbSrc = %d, cbDst = %d\n", cbSrc, cbDst));
    212112
     
    270170}
    271171
    272 static void vboxClipboardChanged (VBOXCLIPBOARDCONTEXT *pCtx)
    273 {
    274     LogFlow(("vboxClipboardChanged\n"));
    275 
    276     if (pCtx->pClient == NULL)
    277     {
    278         return;
    279     }
    280 
    281     /* Query list of available formats and report to host. */
    282     int rc = vboxOpenClipboard(pCtx->hwnd);
    283     if (RT_SUCCESS(rc))
    284     {
    285         uint32_t u32Formats = 0;
    286 
    287         UINT format = 0;
    288 
    289         while ((format = EnumClipboardFormats (format)) != 0)
    290         {
    291             LogFlow(("vboxClipboardChanged format %#x\n", format));
    292             switch (format)
    293             {
    294                 case CF_UNICODETEXT:
    295                 case CF_TEXT:
    296                     u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
    297                     break;
    298 
    299                 case CF_DIB:
    300                 case CF_BITMAP:
    301                     u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
    302                     break;
    303 
    304                 default:
    305                     if (format >= 0xC000)
    306                     {
    307                         TCHAR szFormatName[256];
    308 
    309                         int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
    310 
    311                         if (cActual)
    312                         {
    313                             if (strcmp (szFormatName, "HTML Format") == 0)
    314                             {
    315                                 u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
    316                             }
    317                         }
    318                     }
    319                     break;
    320             }
    321         }
    322 
    323         CloseClipboard ();
    324 
    325         LogFlow(("vboxClipboardChanged u32Formats %02X\n", u32Formats));
    326 
    327         vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, u32Formats);
    328     }
    329     else
    330     {
    331         LogFlow(("vboxClipboardChanged: error in open clipboard. hwnd: %x. err: %Rrc\n", pCtx->hwnd, rc));
    332     }
    333 }
    334 
    335 /* Add ourselves into the chain of cliboard listeners */
    336 static void addToCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
    337 {
    338     if (vboxClipboardIsNewAPI(pCtx))
    339         pCtx->pfnAddClipboardFormatListener(pCtx->hwnd);
    340     else
    341         pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);
    342 }
    343 
    344 /* Remove ourselves from the chain of cliboard listeners */
    345 static void removeFromCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
    346 {
    347     if (vboxClipboardIsNewAPI(pCtx))
    348     {
    349         pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd);
    350     }
    351     else
    352     {
    353         ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);
    354         pCtx->hwndNextInChain = NULL;
    355     }
    356 }
    357 
    358 /* Callback which is invoked when we have successfully pinged ourselves down the
    359  * clipboard chain.  We simply unset a boolean flag to say that we are responding.
    360  * There is a race if a ping returns after the next one is initiated, but nothing
    361  * very bad is likely to happen. */
    362 VOID CALLBACK CBChainPingProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
    363 {
    364     (void) hwnd;
    365     (void) uMsg;
    366     (void) lResult;
    367     VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)dwData;
    368     pCtx->fCBChainPingInProcess = FALSE;
    369 }
    370 
    371172static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    372173{
    373174    LRESULT rc = 0;
    374175
    375     VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;
     176    PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx;
    376177
    377178    switch (msg)
     
    383184            if (GetClipboardOwner() != hwnd)
    384185            {
    385                 /* Clipboard was updated by another application. */
    386                 vboxClipboardChanged(pCtx);
     186                /* Clipboard was updated by another application, retrieve formats and report back. */
     187                int vboxrc = vboxClipboardSyncInternal(pCtx);
     188                AssertRC(vboxrc);
    387189            }
    388190        } break;
     
    392194            Log(("WM_CHANGECBCHAIN\n"));
    393195
    394             if (vboxClipboardIsNewAPI(pCtx))
     196            if (VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI))
    395197            {
    396198                rc = DefWindowProc(hwnd, msg, wParam, lParam);
     
    401203            HWND hwndNext    = (HWND)lParam;
    402204
    403             if (hwndRemoved == pCtx->hwndNextInChain)
     205            if (hwndRemoved == pCtx->Win.hWndNextInChain)
    404206            {
    405207                /* The window that was next to our in the chain is being removed.
    406208                 * Relink to the new next window.
    407209                 */
    408                 pCtx->hwndNextInChain = hwndNext;
     210                pCtx->Win.hWndNextInChain = hwndNext;
    409211            }
    410212            else
    411213            {
    412                 if (pCtx->hwndNextInChain)
     214                if (pCtx->Win.hWndNextInChain)
    413215                {
    414216                    /* Pass the message further. */
    415217                    DWORD_PTR dwResult;
    416                     rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
     218                    rc = SendMessageTimeout(pCtx->Win.hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
     219                                            VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
     220                                            &dwResult);
    417221                    if (!rc)
    418222                        rc = (LRESULT)dwResult;
     
    425229            Log(("WM_DRAWCLIPBOARD\n"));
    426230
    427             if (GetClipboardOwner () != hwnd)
    428             {
    429                 /* Clipboard was updated by another application. */
    430                 vboxClipboardChanged (pCtx);
    431             }
    432 
    433             if (pCtx->hwndNextInChain)
    434             {
    435                 Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->hwndNextInChain));
     231            if (GetClipboardOwner() != hwnd)
     232            {
     233                /* Clipboard was updated by another application, retrieve formats and report back. */
     234                int vboxrc = vboxClipboardSyncInternal(pCtx);
     235                AssertRC(vboxrc);
     236            }
     237
     238            if (pCtx->Win.hWndNextInChain)
     239            {
     240                Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->Win.hWndNextInChain));
    436241                /* Pass the message to next windows in the clipboard chain. */
    437242                DWORD_PTR dwResult;
    438                 rc = SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
     243                rc = SendMessageTimeout(pCtx->Win.hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
     244                                        &dwResult);
    439245                if (!rc)
    440246                    rc = dwResult;
     
    444250        case WM_TIMER:
    445251        {
    446             if (vboxClipboardIsNewAPI(pCtx))
     252            if (VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI))
    447253                break;
    448254
     
    451257            /* Re-register ourselves in the clipboard chain if our last ping
    452258             * timed out or there seems to be no valid chain. */
    453             if (!hViewer || pCtx->fCBChainPingInProcess)
    454             {
    455                 removeFromCBChain(pCtx);
    456                 addToCBChain(pCtx);
    457             }
     259            if (!hViewer || pCtx->Win.oldAPI.fCBChainPingInProcess)
     260            {
     261                VBoxClipboardWinRemoveFromCBChain(&pCtx->Win);
     262                VBoxClipboardWinAddToCBChain(&pCtx->Win);
     263            }
     264
    458265            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
    459266             * processed by ourselves to the chain. */
    460             pCtx->fCBChainPingInProcess = TRUE;
     267            pCtx->Win.oldAPI.fCBChainPingInProcess = TRUE;
     268
    461269            hViewer = GetClipboardViewer();
    462270            if (hViewer)
    463                 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
     271                SendMessageCallback(hViewer, WM_CHANGECBCHAIN,
     272                                    (WPARAM)pCtx->Win.hWndNextInChain, (LPARAM)pCtx->Win.hWndNextInChain,
     273                                    VBoxClipboardWinChainPingProc, (ULONG_PTR)pCtx);
    464274        } break;
    465275
     
    511321                int vboxrc = vboxClipboardReadDataFromClient (pCtx, u32Format);
    512322
    513                 dprintf(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",
     323                LogFunc(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",
    514324                          vboxrc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));
    515325
     
    521331                    HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, pCtx->pClient->data.cb);
    522332
    523                     dprintf(("hMem %p\n", hMem));
     333                    LogFunc(("hMem %p\n", hMem));
    524334
    525335                    if (hMem)
     
    527337                        void *pMem = GlobalLock (hMem);
    528338
    529                         dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
     339                        LogFunc(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));
    530340
    531341                        if (pMem)
     
    552362                            HANDLE hClip = SetClipboardData (format, hMem);
    553363
    554                             dprintf(("vboxClipboardHostEvent hClip %p\n", hClip));
     364                            LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip));
    555365
    556366                            if (hClip)
     
    571381
    572382                /* Something went wrong. */
    573                 EmptyClipboard ();
     383                VBoxClipboardWinClear();
    574384            }
    575385        } break;
     
    582392             * windows is to be destroyed and therefore the guest side becomes inactive.
    583393             */
    584             int vboxrc = vboxOpenClipboard(hwnd);
     394            int vboxrc = VBoxClipboardWinOpen(hwnd);
    585395            if (RT_SUCCESS(vboxrc))
    586396            {
    587                 EmptyClipboard();
    588 
    589                 CloseClipboard();
     397                VBoxClipboardWinClear();
     398                VBoxClipboardWinClose();
    590399            }
    591400            else
     
    595404        } break;
    596405
    597         case WM_USER:
     406        case VBOX_CLIPBOARD_WM_SET_FORMATS:
    598407        {
    599408            if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats)
     
    602411                 * because host clipboard has more priority.
    603412                 */
    604                 Log(("WM_USER ignored\n"));
     413                Log(("VBOX_CLIPBOARD_WM_SET_FORMATS ignored\n"));
    605414                break;
    606415            }
     
    609418            uint32_t u32Formats = (uint32_t)lParam;
    610419
    611             Log(("WM_USER u32Formats = %02X\n", u32Formats));
    612 
    613             int vboxrc = vboxOpenClipboard(hwnd);
     420            Log(("VBOX_CLIPBOARD_WM_SET_FORMATS: u32Formats=%02X\n", u32Formats));
     421
     422            int vboxrc = VBoxClipboardWinOpen(hwnd);
    614423            if (RT_SUCCESS(vboxrc))
    615424            {
    616                 EmptyClipboard();
    617 
    618                 Log(("WM_USER emptied clipboard\n"));
     425                VBoxClipboardWinClear();
     426
     427                Log(("VBOX_CLIPBOARD_WM_SET_FORMATS emptied clipboard\n"));
    619428
    620429                HANDLE hClip = NULL;
    621430
    622431                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
    623                 {
    624                     dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
    625 
    626                     hClip = SetClipboardData (CF_UNICODETEXT, NULL);
    627                 }
     432                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
    628433
    629434                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
    630                 {
    631                     dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
    632 
    633                     hClip = SetClipboardData (CF_DIB, NULL);
    634                 }
     435                    hClip = SetClipboardData(CF_DIB, NULL);
    635436
    636437                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
    637438                {
    638439                    UINT format = RegisterClipboardFormat ("HTML Format");
    639                     dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
    640440                    if (format != 0)
    641441                    {
     
    644444                }
    645445
    646                 CloseClipboard();
    647 
    648                 dprintf(("window proc WM_USER: hClip %p, err %d\n", hClip, GetLastError ()));
    649             }
    650             else
    651             {
    652                 dprintf(("window proc WM_USER: failed to open clipboard. rc: %Rrc\n", vboxrc));
     446                VBoxClipboardWinClose();
     447
     448                LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError ()));
    653449            }
    654450        } break;
     
    656452        case WM_DESTROY:
    657453        {
    658             /* MS recommends to remove from Clipboard chain in this callback */
    659             Assert(pCtx->hwnd);
    660             removeFromCBChain(pCtx);
    661             if (pCtx->timerRefresh)
    662                 KillTimer(pCtx->hwnd, 0);
     454            /* MS recommends to remove from Clipboard chain in this callback. */
     455            VBoxClipboardWinRemoveFromCBChain(&pCtx->Win);
     456            if (pCtx->Win.oldAPI.timerRefresh)
     457            {
     458                Assert(pCtx->Win.hWnd);
     459                KillTimer(pCtx->Win.hWnd, 0);
     460            }
    663461            PostQuitMessage(0);
    664462        } break;
     
    683481    LogFlow(("VBoxClipboardThread\n"));
    684482
    685     VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;
     483    const PVBOXCLIPBOARDCONTEXT pCtx = &g_ctx;
    686484
    687485    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
     
    695493    wc.hInstance     = hInstance;
    696494    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
    697     wc.lpszClassName = gachWindowClassName;
     495    wc.lpszClassName = s_szClipWndClassName;
    698496
    699497    ATOM atomWindowClass = RegisterClass(&wc);
     
    707505    {
    708506        /* Create the window. */
    709         pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
    710                                      gachWindowClassName, gachWindowClassName,
    711                                      WS_POPUPWINDOW,
    712                                      -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
    713 
    714         if (pCtx->hwnd == NULL)
     507        pCtx->Win.hWnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
     508                                         s_szClipWndClassName, s_szClipWndClassName,
     509                                         WS_POPUPWINDOW,
     510                                         -200, -200, 100, 100, NULL, NULL, hInstance, NULL);
     511        if (pCtx->Win.hWnd == NULL)
    715512        {
    716513            Log(("Failed to create window\n"));
     
    719516        else
    720517        {
    721             SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
     518            SetWindowPos(pCtx->Win.hWnd, HWND_TOPMOST, -200, -200, 0, 0,
    722519                         SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
    723520
    724             addToCBChain(pCtx);
    725             if (!vboxClipboardIsNewAPI(pCtx))
    726                 pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
     521            VBoxClipboardWinAddToCBChain(&pCtx->Win);
     522            if (!VBoxClipboardWinIsNewAPI(&pCtx->Win.newAPI))
     523                pCtx->Win.oldAPI.timerRefresh = SetTimer(pCtx->Win.hWnd, 0, 10 * 1000, NULL);
    727524
    728525            MSG msg;
     
    743540    }
    744541
    745     pCtx->hwnd = NULL;
     542    pCtx->Win.hWnd = NULL;
    746543
    747544    if (atomWindowClass != 0)
    748545    {
    749         UnregisterClass (gachWindowClassName, hInstance);
     546        UnregisterClass (s_szClipWndClassName, hInstance);
    750547        atomWindowClass = 0;
    751548    }
    752549
    753550    return 0;
     551}
     552
     553/**
     554 * Synchronizes the host and the guest clipboard formats by sending all supported host clipboard
     555 * formats to the guest.
     556 *
     557 * @returns VBox status code.
     558 * @param   pCtx                Clipboard context to synchronize.
     559 */
     560static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
     561{
     562    uint32_t uFormats;
     563    int rc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
     564    if (RT_SUCCESS(rc))
     565        vboxSvcClipboardReportMsg(pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS, uFormats);
     566
     567    return rc;
    754568}
    755569
     
    763577    RT_ZERO(g_ctx);
    764578
    765     /* Check that new Clipboard API is available */
    766     vboxClipboardInitNewAPI(&g_ctx);
     579    /* Check that new Clipboard API is available. */
     580    VBoxClipboardWinCheckAndInitNewAPI(&g_ctx.Win.newAPI);
    767581
    768582    g_ctx.hRenderEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    769583
    770     rc = RTThreadCreate (&g_ctx.thread, VBoxClipboardThread, NULL, 65536,
     584    rc = RTThreadCreate (&g_ctx.hThread, VBoxClipboardThread, NULL, 65536,
    771585                         RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SHCLIP");
    772586
     
    783597    Log(("vboxClipboardDestroy\n"));
    784598
    785     if (g_ctx.hwnd)
    786     {
    787         PostMessage (g_ctx.hwnd, WM_CLOSE, 0, 0);
     599    if (g_ctx.Win.hWnd)
     600    {
     601        PostMessage (g_ctx.Win.hWnd, WM_CLOSE, 0, 0);
    788602    }
    789603
     
    791605
    792606    /* Wait for the window thread to terminate. */
    793     RTThreadWait (g_ctx.thread, RT_INDEFINITE_WAIT, NULL);
    794 
    795     g_ctx.thread = NIL_RTTHREAD;
     607    RTThreadWait (g_ctx.hThread, RT_INDEFINITE_WAIT, NULL);
     608
     609    g_ctx.hThread = NIL_RTTHREAD;
    796610}
    797611
     
    820634{
    821635    /* Sync the host clipboard content with the client. */
    822     vboxClipboardChanged (pClient->pCtx);
    823 
    824     return VINF_SUCCESS;
     636    return vboxClipboardSyncInternal(pClient->pCtx);
    825637}
    826638
     
    838650     * The guest announces formats. Forward to the window thread.
    839651     */
    840     PostMessage (pClient->pCtx->hwnd, WM_USER, 0, u32Formats);
     652    PostMessage (pClient->pCtx->Win.hWnd, WM_USER, 0, u32Formats);
    841653}
    842654
     
    880692     * The guest wants to read data in the given format.
    881693     */
    882     int rc = vboxOpenClipboard(pClient->pCtx->hwnd);
     694    int rc = VBoxClipboardWinOpen(pClient->pCtx->Win.hWnd);
    883695    if (RT_SUCCESS(rc))
    884696    {
    885         dprintf(("Clipboard opened.\n"));
     697        LogFunc(("Clipboard opened.\n"));
    886698
    887699        if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
     
    895707                if (lp != NULL)
    896708                {
    897                     dprintf(("CF_DIB\n"));
     709                    LogFunc(("CF_DIB\n"));
    898710
    899711                    vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_BITMAP, lp, GlobalSize (hClip),
     
    918730                if (uniString != NULL)
    919731                {
    920                     dprintf(("CF_UNICODETEXT\n"));
     732                    LogFunc(("CF_UNICODETEXT\n"));
    921733
    922734                    vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT, uniString, (lstrlenW (uniString) + 1) * 2,
     
    945757                    if (lp != NULL)
    946758                    {
    947                         dprintf(("CF_HTML\n"));
     759                        LogFunc(("CF_HTML\n"));
    948760
    949761                        vboxClipboardGetData (VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize (hClip),
     
    961773        }
    962774
    963         CloseClipboard ();
     775        VBoxClipboardWinClose();
    964776    }
    965777    else
    966778    {
    967         dprintf(("vboxClipboardReadData: failed to open clipboard, rc: %Rrc\n", rc));
     779        LogFunc(("vboxClipboardReadData: failed to open clipboard, rc: %Rrc\n", rc));
    968780    }
    969781
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h

    r76570 r78151  
    2525#include <VBox/log.h>
    2626
    27 struct _VBOXCLIPBOARDCONTEXT;
    28 typedef struct _VBOXCLIPBOARDCONTEXT VBOXCLIPBOARDCONTEXT;
    29 
     27#include <VBox/GuestHost/SharedClipboard.h>
    3028
    3129typedef struct _VBOXCLIPBOARDCLIENTDATA
     
    6462    uint32_t u32RequestedFormat;
    6563
    66 } VBOXCLIPBOARDCLIENTDATA;
     64} VBOXCLIPBOARDCLIENTDATA, *PVBOXCLIPBOARDCLIENTDATA;
    6765
    6866/*
    6967 * The service functions. Locking is between the service thread and the platform dependent windows thread.
    7068 */
    71 bool vboxSvcClipboardLock (void);
    72 void vboxSvcClipboardUnlock (void);
    73 
    7469void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
    75 
    7670void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual);
    77 
    78 bool vboxSvcClipboardGetHeadless(void);
    7971
    8072/*
     
    8678int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
    8779void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient);
    88 
    8980void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
    90 
    9181int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
    92 
    9382void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
    9483
  • trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp

    r76970 r78151  
    109109static bool g_fHeadless = false;
    110110
     111static bool vboxSvcClipboardGetHeadless(void);
     112static bool vboxSvcClipboardLock(void);
     113static void vboxSvcClipboardUnlock(void);
     114
    111115
    112116static void VBoxHGCMParmUInt32Set (VBOXHGCMSVCPARM *pParm, uint32_t u32)
     
    163167
    164168/** Getter for headless setting */
    165 bool vboxSvcClipboardGetHeadless(void)
     169static bool vboxSvcClipboardGetHeadless(void)
    166170{
    167171    return g_fHeadless;
     
    184188}
    185189
    186 bool vboxSvcClipboardLock (void)
     190static bool vboxSvcClipboardLock (void)
    187191{
    188192    return RT_SUCCESS(RTCritSectEnter (&critsect));
    189193}
    190194
    191 void vboxSvcClipboardUnlock (void)
     195static void vboxSvcClipboardUnlock(void)
    192196{
    193197    RTCritSectLeave (&critsect);
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