e62cb87bae732e9968199a3ad153cc94004b7182vboxsync/** @file
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync *
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * VBoxClipboard - Shared clipboard
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync *
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync/*
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync * Copyright (C) 2006-2014 Oracle Corporation
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync *
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * available from http://www.virtualbox.org. This file is free software;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * General Public License (GPL) as published by the Free Software
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync#include "VBoxTray.h"
74804912a237136f06d0b49682a119577135902bvboxsync#include "VBoxHelpers.h"
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync#include <VBox/HostServices/VBoxClipboardSvc.h>
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync#include <strsafe.h>
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync#include <VBox/VMMDev.h>
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync#ifdef DEBUG
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync# define LOG_ENABLED
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync# define LOG_GROUP LOG_GROUP_DEFAULT
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync#endif
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync#include <VBox/log.h>
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsynctypedef struct _VBOXCLIPBOARDCONTEXT
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync const VBOXSERVICEENV *pEnv;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t u32ClientID;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync ATOM atomWindowClass;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HWND hwnd;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HWND hwndNextInChain;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync UINT timerRefresh;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync bool fCBChainPingInProcess;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync// bool fOperational;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync// uint32_t u32LastSentFormat;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync// uint64_t u64LastSentCRC64;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync} VBOXCLIPBOARDCONTEXT;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic char gachWindowClassName[] = "VBoxSharedClipboardClass";
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsyncenum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsyncstatic int vboxClipboardChanged(VBOXCLIPBOARDCONTEXT *pCtx)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync AssertPtr(pCtx);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync /* Query list of available formats and report to host. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int rc = VINF_SUCCESS;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync if (FALSE == OpenClipboard(pCtx->hwnd))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync rc = RTErrConvertFromWin32(GetLastError());
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t u32Formats = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync UINT format = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync while ((format = EnumClipboardFormats (format)) != 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("vboxClipboardChanged: format = 0x%08X\n", format));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync switch (format)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_UNICODETEXT:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_TEXT:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_DIB:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_BITMAP:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync default:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (format >= 0xC000)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync TCHAR szFormatName[256];
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (cActual)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (strcmp (szFormatName, "HTML Format") == 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Formats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync CloseClipboard ();
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, u32Formats);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync return rc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync/* Add ourselves into the chain of cliboard listeners */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsyncstatic void addToCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync{
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync}
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync/* Remove ourselves from the chain of cliboard listeners */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsyncstatic void removeFromCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync{
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync pCtx->hwndNextInChain = NULL;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync}
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync/* Callback which is invoked when we have successfully pinged ourselves down the
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync * clipboard chain. We simply unset a boolean flag to say that we are responding.
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync * There is a race if a ping returns after the next one is initiated, but nothing
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync * very bad is likely to happen. */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsyncVOID CALLBACK CBChainPingProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync{
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync (void) hwnd;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync (void) uMsg;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync (void) lResult;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)dwData;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync pCtx->fCBChainPingInProcess = FALSE;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync}
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync LRESULT rc = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync switch (msg)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_CHANGECBCHAIN:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HWND hwndRemoved = (HWND)wParam;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HWND hwndNext = (HWND)lParam;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hwndRemoved == pCtx->hwndNextInChain)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* The window that was next to our in the chain is being removed.
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync * Relink to the new next window. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx->hwndNextInChain = hwndNext;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx->hwndNextInChain)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Pass the message further. */
b131e6bb7428285210578b64ece7748b4182c58avboxsync DWORD_PTR dwResult;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync if (!rc)
b131e6bb7428285210578b64ece7748b4182c58avboxsync rc = (LRESULT) dwResult;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_DRAWCLIPBOARD:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (GetClipboardOwner () != hwnd)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Clipboard was updated by another application. */
2724514e7078eb3d64e6ee9a2a0e3ec0d7141ca0vboxsync /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
6bfdffcd10c41a57f5b730b072efefc85c850382vboxsync int vboxrc = vboxClipboardChanged(pCtx);
6bfdffcd10c41a57f5b730b072efefc85c850382vboxsync if (RT_FAILURE(vboxrc))
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("vboxClipboardChanged failed, rc = %Rrc\n", vboxrc));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Pass the message to next windows in the clipboard chain. */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync case WM_TIMER:
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync {
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync HWND hViewer = GetClipboardViewer();
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync /* Re-register ourselves in the clipboard chain if our last ping
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync * timed out or there seems to be no valid chain. */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync if (!hViewer || pCtx->fCBChainPingInProcess)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync {
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync removeFromCBChain(pCtx);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync addToCBChain(pCtx);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync }
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync * processed by ourselves to the chain. */
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync pCtx->fCBChainPingInProcess = TRUE;
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync hViewer = GetClipboardViewer();
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync if (hViewer)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync } break;
b35e3948f1287430503b6b432945b8cf4bfd3a23vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_CLOSE:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Do nothing. Ignore the message. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_RENDERFORMAT:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Insert the requested clipboard format data into the clipboard. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t u32Format = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync UINT format = (UINT)wParam;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_RENDERFORMAT, format = %x\n", format));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync switch (format)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_UNICODETEXT:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case CF_DIB:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync default:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (format >= 0xC000)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync TCHAR szFormatName[256];
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (cActual)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (strcmp (szFormatName, "HTML Format") == 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync u32Format |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Format == 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Unsupported clipboard format is requested. */
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Unsupported clipboard format requested: %ld\n", u32Format));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync EmptyClipboard();
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync const uint32_t cbPrealloc = 4096; /* @todo r=andy Make it dynamic for supporting larger text buffers! */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t cb = 0;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Preallocate a buffer, most of small text transfers will fit into it. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync void *pMem = GlobalLock(hMem);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Read the host data to the preallocated buffer. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cbPrealloc, &cb);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n", vboxrc));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync if (RT_SUCCESS(vboxrc))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync if (cb == 0)
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync {
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync /* 0 bytes returned means the clipboard is empty.
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync * Deallocate the memory and set hMem to NULL to get to
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync * the clipboard empty code path. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalFree(hMem);
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync hMem = NULL;
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync }
d6c1ac4cabb20caef17d53c6fd371433a79343d8vboxsync else if (cb > cbPrealloc)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* The preallocated buffer is too small, adjust the size. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hMem = GlobalReAlloc(hMem, cb, 0);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Reallocated hMem = %p\n", hMem));
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync pMem = GlobalLock(hMem);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Read the host data to the preallocated buffer. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t cbNew = 0;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cb, &cbNew);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync if (RT_SUCCESS (vboxrc) && cbNew <= cb)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync cb = cbNew;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalFree(hMem);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hMem = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalFree(hMem);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hMem = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* pMem is the address of the data. cb is the size of returned data. */
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync /* Verify the size of returned text, the memory block for clipboard
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync * must have the exact string size.
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync size_t cbActual = 0;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync if (FAILED (hrc))
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync {
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync /* Discard invalid data. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalFree(hMem);
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync hMem = NULL;
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync }
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync else
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync {
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync /* cbActual is the number of bytes, excluding those used
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync * for the terminating null character.
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync */
dbded28ab93667af3b632833764415d857a30fbcvboxsync cb = (uint32_t)(cbActual + 2);
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync if (hMem)
4ca78a9695174cccd2dc4c0f26da066622ed9d42vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hMem = GlobalReAlloc(hMem, cb, 0);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("Reallocated hMem = %p\n", hMem));
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* 'hMem' contains the host clipboard data.
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync * size is 'cb' and format is 'format'. */
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync HANDLE hClip = SetClipboardData(format, hMem);
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hClip)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* The hMem ownership has gone to the system. Finish the processing. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Cleanup follows. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalUnlock(hMem);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hMem)
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync GlobalFree(hMem);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Something went wrong. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync EmptyClipboard();
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_RENDERALLFORMATS:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Do nothing. The clipboard formats will be unavailable now, because the
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync * windows is to be destroyed and therefore the guest side becomes inactive.
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync */
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync if (OpenClipboard(hwnd))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync EmptyClipboard();
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync CloseClipboard();
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_USER:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t u32Formats = (uint32_t)lParam;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync if (FALSE == OpenClipboard(hwnd))
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync }
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync EmptyClipboard();
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HANDLE hClip = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hClip = SetClipboardData(CF_UNICODETEXT, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hClip = SetClipboardData(CF_DIB, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync UINT format = RegisterClipboardFormat ("HTML Format");
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (format != 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hClip = SetClipboardData(format, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync CloseClipboard();
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: hClip = %p, err = %ld\n", hClip, GetLastError ()));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync case WM_USER + 1:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Send data in the specified format to the host. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync uint32_t u32Formats = (uint32_t)lParam;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync HANDLE hClip = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync if (FALSE == OpenClipboard(hwnd))
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync }
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int vboxrc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync hClip = GetClipboardData(CF_DIB);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hClip != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync LPVOID lp = GlobalLock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (lp != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER + 1: CF_DIB\n"));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync lp, GlobalSize(hClip));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync GlobalUnlock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hClip = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hClip = GetClipboardData(CF_UNICODETEXT);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hClip != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync LPWSTR uniString = (LPWSTR)GlobalLock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (uniString != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER + 1: CF_UNICODETEXT\n"));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync uniString, (lstrlenW(uniString) + 1) * 2);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync GlobalUnlock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hClip = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync UINT format = RegisterClipboardFormat ("HTML Format");
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (format != 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync hClip = GetClipboardData(format);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hClip != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync LPVOID lp = GlobalLock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (lp != NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("WM_USER + 1: CF_HTML\n"));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync lp, GlobalSize(hClip));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync GlobalUnlock(hClip);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync hClip = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync CloseClipboard();
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (hClip == NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Requested clipboard format is not available, send empty data. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync } break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync default:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync rc = DefWindowProc(hwnd, msg, wParam, lParam);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
99f33ab590a3a65e0cd082dd8d67779efb9cc6c9vboxsync#ifndef DEBUG_andy
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
99f33ab590a3a65e0cd082dd8d67779efb9cc6c9vboxsync#endif
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return rc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic int vboxClipboardInit (VBOXCLIPBOARDCONTEXT *pCtx)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Register the Window Class. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync WNDCLASS wc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.style = CS_NOCLOSE;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.lpfnWndProc = vboxClipboardWndProc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.cbClsExtra = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.cbWndExtra = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.hInstance = pCtx->pEnv->hInstance;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.hIcon = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.hCursor = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.lpszMenuName = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync wc.lpszClassName = gachWindowClassName;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx->atomWindowClass = RegisterClass (&wc);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int rc = VINF_SUCCESS;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx->atomWindowClass == 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync rc = VERR_NOT_SUPPORTED;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Create the window. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx->hwnd = CreateWindowEx (WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_TOPMOST,
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync gachWindowClassName, gachWindowClassName,
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync WS_POPUPWINDOW,
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync -200, -200, 100, 100, NULL, NULL, pCtx->pEnv->hInstance, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx->hwnd == NULL)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync rc = VERR_NOT_SUPPORTED;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync SetWindowPos(pCtx->hwnd, HWND_TOPMOST, -200, -200, 0, 0,
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync SWP_NOACTIVATE | SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOSIZE);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync addToCBChain(pCtx);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("vboxClipboardInit returned with rc = %Rrc\n", rc));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return rc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsyncstatic void vboxClipboardDestroy(VBOXCLIPBOARDCONTEXT *pCtx)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx->hwnd)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync removeFromCBChain(pCtx);
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync if (pCtx->timerRefresh)
73b1c18a52f0fc96342349987f5aa1b64b774053vboxsync KillTimer(pCtx->hwnd, 0);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync DestroyWindow (pCtx->hwnd);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx->hwnd = NULL;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx->atomWindowClass != 0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync UnregisterClass(gachWindowClassName, pCtx->pEnv->hInstance);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx->atomWindowClass = 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync/* Static since it is the single instance. Directly used in the windows proc. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic VBOXCLIPBOARDCONTEXT gCtx = { NULL };
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsyncstatic LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Forward with proper context. */
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync return vboxClipboardProcessMsg(&gCtx, hwnd, msg, wParam, lParam);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsyncint VBoxClipboardInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardInit\n"));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (gCtx.pEnv)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Clipboard was already initialized. 2 or more instances are not supported. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return VERR_NOT_SUPPORTED;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync if (VbglR3AutoLogonIsRemoteSession())
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync {
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync /* Do not use clipboard for remote sessions. */
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync LogRel(("VBoxTray: clipboard has been disabled for a remote session.\n"));
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync return VERR_NOT_SUPPORTED;
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync }
f6ee0df7a48d6442c9d6587f4a953ab2df3ecba6vboxsync
48d832e07616531bbb720d9c98103c83b561ebb6vboxsync RT_ZERO (gCtx);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync gCtx.pEnv = pEnv;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int rc = VbglR3ClipboardConnect(&gCtx.u32ClientID);
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync if (RT_SUCCESS (rc))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync rc = vboxClipboardInit(&gCtx);
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync if (RT_SUCCESS (rc))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Always start the thread for host messages. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync *pfStartThread = true;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync else
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync VbglR3ClipboardDisconnect(gCtx.u32ClientID);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
9b4dd8dffe103b4ef000c75fdd22b50d97d93daavboxsync if (RT_SUCCESS(rc))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync *ppInstance = &gCtx;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return rc;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsyncunsigned __stdcall VBoxClipboardThread(void *pInstance)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardThread\n"));
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync AssertPtr(pCtx);
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* The thread waits for incoming messages from the host. */
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync for (;;)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync uint32_t u32Msg;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync uint32_t u32Formats;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync int rc = VbglR3ClipboardGetHostMsg(pCtx->u32ClientID, &u32Msg, &u32Formats);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync if (RT_FAILURE(rc))
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardThread: Failed to call the driver for host message! rc = %Rrc\n", rc));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync if (rc == VERR_INTERRUPTED)
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync /* Wait for termination event. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync break;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync /* Wait a bit before retrying. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync AssertPtr(pCtx->pEnv);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync break;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync continue;
60683d33dcd6c06d56310f709dc979aeeedbfd45vboxsync }
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync else
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardThread: VbglR3ClipboardGetHostMsg u32Msg = %ld, u32Formats = %ld\n", u32Msg, u32Formats));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync switch (u32Msg)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync /* The host has announced available clipboard formats.
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync * Forward the information to the window, so it can later
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync * respond to WM_RENDERFORMAT message. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync } break;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync /* The host needs data in the specified format. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync } break;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync /* The host is terminating. */
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync rc = VERR_INTERRUPTED;
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync } break;
240f7d7012a5f64bcde850bcf048531a710d81cfvboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync default:
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardThread: Unsupported message from host! Message = %ld\n", u32Msg));
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return 0;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsyncvoid VBoxClipboardDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync{
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync if (pCtx != &gCtx)
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync {
a29027bb2378172c7c88610ad5311548b66f96f6vboxsync LogFlowFunc(("VBoxClipboardDestroy: invalid instance %p (our = %p)!\n", pCtx, &gCtx));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync pCtx = &gCtx;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync }
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync vboxClipboardDestroy (pCtx);
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync VbglR3ClipboardDisconnect(pCtx->u32ClientID);
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync memset (pCtx, 0, sizeof (*pCtx));
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync return;
e62cb87bae732e9968199a3ad153cc94004b7182vboxsync}
61e014c7370649a36da3a1ad85efda5d04e9fa3cvboxsync