VBoxClientClipboard.cpp revision 1a84601801d5bd045712787a3ef59313795389a1
1a84601801d5bd045712787a3ef59313795389a1vboxsync/** $Id$ */
1a84601801d5bd045712787a3ef59313795389a1vboxsync/** @file
1a84601801d5bd045712787a3ef59313795389a1vboxsync * VBoxClient - Shared Slipboard Dispatcher, Darwin.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Copyright (C) 2007-2013 Oracle Corporation
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1a84601801d5bd045712787a3ef59313795389a1vboxsync * available from http://www.virtualbox.org. This file is free software;
1a84601801d5bd045712787a3ef59313795389a1vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1a84601801d5bd045712787a3ef59313795389a1vboxsync * General Public License (GPL) as published by the Free Software
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1a84601801d5bd045712787a3ef59313795389a1vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1a84601801d5bd045712787a3ef59313795389a1vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Header Files *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <Carbon/Carbon.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/asm.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/stream.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/thread.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <iprt/critsect.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/VBoxGuestLib.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/HostServices/VBoxClipboardSvc.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include <VBox/GuestHost/clipboard-helper.h>
1a84601801d5bd045712787a3ef59313795389a1vboxsync#include "VBoxClientInternal.h"
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Global Variables *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/** Host clipboard connection client ID */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic uint32_t g_u32ClientId;
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Guest clipboard reference */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic PasteboardRef g_PasteboardRef;
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Dispatcher tharead handle */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncRTTHREAD g_DispatcherThread;
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Pasteboard polling tharead handle */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncRTTHREAD g_GuestPasteboardThread;
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Flag that indicates whether or not dispatcher and Pasteboard polling threada should stop */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic bool volatile g_fShouldStop;
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Barrier for Pasteboard */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic RTCRITSECT g_critsect;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Local Macros *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync#define VBOXCLIENT_SERVICE_NAME "clipboard"
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/*******************************************************************************
1a84601801d5bd045712787a3ef59313795389a1vboxsync* Local Function Prototypes *
1a84601801d5bd045712787a3ef59313795389a1vboxsync*******************************************************************************/
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardStop(void);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Clipboard dispatcher function.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Forwards cliproard content between host and guest.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param ThreadSelf Unused parameter.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pvUser Unused parameter.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @return IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic DECLCALLBACK(int) vbclClipboardDispatcher(RTTHREAD ThreadSelf, void *pvUser)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync bool fQuit = false;
1a84601801d5bd045712787a3ef59313795389a1vboxsync NOREF(ThreadSelf);
1a84601801d5bd045712787a3ef59313795389a1vboxsync NOREF(pvUser);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "starting host clipboard polling thread\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /*
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Block all signals for this thread. Only the main thread will handle signals.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsync sigset_t signalMask;
1a84601801d5bd045712787a3ef59313795389a1vboxsync sigfillset(&signalMask);
1a84601801d5bd045712787a3ef59313795389a1vboxsync pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync while (!fQuit && !ASMAtomicReadBool(&g_fShouldStop))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t Msg;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t fFormats;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "waiting for new host request\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = VbglR3ClipboardGetHostMsg(g_u32ClientId, &Msg, &fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectEnter(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync switch (Msg)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* The host is terminating */
1a84601801d5bd045712787a3ef59313795389a1vboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "host requested quit\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync fQuit = true;
1a84601801d5bd045712787a3ef59313795389a1vboxsync break;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* The host needs data in the specified format */
1a84601801d5bd045712787a3ef59313795389a1vboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "host requested guest's clipboard read\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardForwardToHost(g_u32ClientId, g_PasteboardRef, fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertMsg(RT_SUCCESS(rc), ("paste to host failed\n"));
1a84601801d5bd045712787a3ef59313795389a1vboxsync break;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* The host has announced available clipboard formats */
1a84601801d5bd045712787a3ef59313795389a1vboxsync case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "host requested guest's clipboard write\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = vbclClipboardForwardToGuest(g_u32ClientId, g_PasteboardRef, fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertMsg(RT_SUCCESS(rc), ("paste to guest failed\n"));
1a84601801d5bd045712787a3ef59313795389a1vboxsync break;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync default:
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "received unknow command from host service\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTThreadSleep(1000);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectLeave(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTThreadSleep(1000);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "host clipboard polling thread stopped\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VINF_SUCCESS;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Clipboard dispatcher function.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Forwards cliproard content between host and guest.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param ThreadSelf Unused parameter.
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @param pvUser Unused parameter.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @return IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic DECLCALLBACK(int) vbclGuestPasteboardPoll(RTTHREAD ThreadSelf, void *pvUser)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync /*
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Block all signals for this thread. Only the main thread will handle signals.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsync sigset_t signalMask;
1a84601801d5bd045712787a3ef59313795389a1vboxsync sigfillset(&signalMask);
1a84601801d5bd045712787a3ef59313795389a1vboxsync pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "starting guest clipboard polling thread\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync while (!ASMAtomicReadBool(&g_fShouldStop))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync PasteboardSyncFlags fSyncFlags;
1a84601801d5bd045712787a3ef59313795389a1vboxsync uint32_t fFormats;
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectEnter(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync fSyncFlags = PasteboardSynchronize(g_PasteboardRef);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (fSyncFlags & kPasteboardModified)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync fFormats = vbclClipboardGetAvailableFormats(g_PasteboardRef);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = VbglR3ClipboardReportFormats(g_u32ClientId, fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "failed to report pasteboard update (%Rrc)\n", rc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "guest clipboard update reported: %d\n", (int)fFormats);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectLeave(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Check pasteboard every 200 ms */
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTThreadSleep(200);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "guest clipboard polling thread stopped\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VINF_SUCCESS;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Initialize host and guest clipboards, start clipboard dispatcher loop.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @return IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardStart(void)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "starting clipboard\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTCritSectInit(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VERR_GENERAL_FAILURE;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = VbglR3ClipboardConnect(&g_u32ClientId);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = PasteboardCreate(kPasteboardClipboard, &g_PasteboardRef);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (rc == noErr)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Start dispatcher loop */
1a84601801d5bd045712787a3ef59313795389a1vboxsync ASMAtomicWriteBool(&g_fShouldStop, false);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTThreadCreate(&g_DispatcherThread,
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardDispatcher,
1a84601801d5bd045712787a3ef59313795389a1vboxsync (void *)NULL,
1a84601801d5bd045712787a3ef59313795389a1vboxsync 0,
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTTHREADTYPE_DEFAULT,
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTTHREADFLAGS_WAITABLE,
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCLIENT_SERVICE_NAME);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Start dispatcher loop */
1a84601801d5bd045712787a3ef59313795389a1vboxsync ASMAtomicWriteBool(&g_fShouldStop, false);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTThreadCreate(&g_GuestPasteboardThread,
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclGuestPasteboardPoll,
1a84601801d5bd045712787a3ef59313795389a1vboxsync (void *)NULL,
1a84601801d5bd045712787a3ef59313795389a1vboxsync 0,
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTTHREADTYPE_DEFAULT,
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTTHREADFLAGS_WAITABLE,
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCLIENT_SERVICE_NAME);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync return VINF_SUCCESS;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Stop dispatcher thread */
1a84601801d5bd045712787a3ef59313795389a1vboxsync ASMAtomicWriteBool(&g_fShouldStop, true);
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "unable create dispatcher thread\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(g_PasteboardRef);
1a84601801d5bd045712787a3ef59313795389a1vboxsync g_PasteboardRef = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = VERR_GENERAL_FAILURE;
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "unable access guest clipboard\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardStop();
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "unable to establish connection to clipboard service: %Rrc\n", rc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectDelete(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/**
1a84601801d5bd045712787a3ef59313795389a1vboxsync * Release host and guest clipboards, stop clipboard dispatcher loop.
1a84601801d5bd045712787a3ef59313795389a1vboxsync *
1a84601801d5bd045712787a3ef59313795389a1vboxsync * @return IPRT status code.
1a84601801d5bd045712787a3ef59313795389a1vboxsync */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncstatic int vbclClipboardStop(void)
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync int rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "stopping clipboard\n");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync AssertReturn(g_u32ClientId != 0, VERR_GENERAL_FAILURE);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync VbglR3ClipboardReportFormats(g_u32ClientId, 0);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = VbglR3ClipboardDisconnect(g_u32ClientId);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_SUCCESS(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync g_u32ClientId = 0;
1a84601801d5bd045712787a3ef59313795389a1vboxsync else
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "unable to close clipboard service connection: %Rrc\n", rc);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (g_PasteboardRef)
1a84601801d5bd045712787a3ef59313795389a1vboxsync {
1a84601801d5bd045712787a3ef59313795389a1vboxsync CFRelease(g_PasteboardRef);
1a84601801d5bd045712787a3ef59313795389a1vboxsync g_PasteboardRef = NULL;
1a84601801d5bd045712787a3ef59313795389a1vboxsync }
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Stop dispatcher thread */
1a84601801d5bd045712787a3ef59313795389a1vboxsync ASMAtomicWriteBool(&g_fShouldStop, true);
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTThreadWait(g_DispatcherThread, 10 * 1000 /* Wait 10 seconds */, NULL);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "failed to stop dispatcher thread");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* Stop Pasteboard polling thread */
1a84601801d5bd045712787a3ef59313795389a1vboxsync rc = RTThreadWait(g_GuestPasteboardThread, 10 * 1000 /* Wait 10 seconds */, NULL);
1a84601801d5bd045712787a3ef59313795389a1vboxsync if (RT_FAILURE(rc))
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBoxClientVerbose(2, "failed to stop pasteboard polling thread");
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync RTCritSectDelete(&g_critsect);
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync return rc;
1a84601801d5bd045712787a3ef59313795389a1vboxsync}
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync/* Clipboard service struct */
1a84601801d5bd045712787a3ef59313795389a1vboxsyncVBOXCLIENTSERVICE g_ClipboardService =
1a84601801d5bd045712787a3ef59313795389a1vboxsync{
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* pszName */
1a84601801d5bd045712787a3ef59313795389a1vboxsync VBOXCLIENT_SERVICE_NAME,
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* pfnStart */
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardStart,
1a84601801d5bd045712787a3ef59313795389a1vboxsync
1a84601801d5bd045712787a3ef59313795389a1vboxsync /* pfnStop */
1a84601801d5bd045712787a3ef59313795389a1vboxsync vbclClipboardStop,
1a84601801d5bd045712787a3ef59313795389a1vboxsync};