VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/VBoxClient/clipboard.cpp@ 21077

Last change on this file since 21077 was 21043, checked in by vboxsync, 16 years ago

x11/clipboard: fixed uninitialized variable causing Solaris VBoxClient to exit.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.7 KB
Line 
1/** $Id: clipboard.cpp 21043 2009-06-29 18:54:53Z vboxsync $ */
2/** @file
3 * Guest Additions - X11 Shared Clipboard.
4 */
5
6/*
7 * Copyright (C) 2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/****************************************************************************
23* Header Files *
24****************************************************************************/
25#include <iprt/alloc.h>
26#include <iprt/asm.h>
27#include <iprt/assert.h>
28#include <iprt/initterm.h>
29#include <iprt/mem.h>
30#include <iprt/string.h>
31#include <iprt/process.h>
32#include <iprt/semaphore.h>
33
34#include <VBox/log.h>
35#include <VBox/HostServices/VBoxClipboardSvc.h>
36#include <VBox/GuestHost/SharedClipboard.h>
37
38#include "VBoxClient.h"
39#include "clipboard.h"
40
41/****************************************************************************
42* Global Variables *
43****************************************************************************/
44
45/**
46 * Global clipboard context information.
47 */
48struct _VBOXCLIPBOARDCONTEXT
49{
50 /** Client ID for the clipboard subsystem */
51 uint32_t client;
52
53 /** Pointer to the X11 clipboard backend */
54 CLIPBACKEND *pBackend;
55};
56
57/** Only one client is supported. There seems to be no need for more clients. */
58static VBOXCLIPBOARDCONTEXT g_ctx;
59
60
61/**
62 * Transfer clipboard data from the guest to the host.
63 *
64 * @returns VBox result code
65 * @param u32Format The format of the data being sent
66 * @param pv Pointer to the data being sent
67 * @param cb Size of the data being sent in bytes
68 */
69static int vboxClipboardSendData(uint32_t u32Format, void *pv, uint32_t cb)
70{
71 int rc;
72 LogFlowFunc(("u32Format=%d, pv=%p, cb=%d\n", u32Format, pv, cb));
73 rc = VbglR3ClipboardWriteData(g_ctx.client, u32Format, pv, cb);
74 LogFlowFunc(("rc=%Rrc\n", rc));
75 return rc;
76}
77
78
79/**
80 * Get clipboard data from the host.
81 *
82 * @returns VBox result code
83 * @param u32Format The format of the data being requested
84 * @retval ppv On success and if pcb > 0, this will point to a buffer
85 * to be freed with RTMemFree containing the data read.
86 * @retval pcb On success, this contains the number of bytes of data
87 * returned
88 */
89int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format,
90 void **ppv, uint32_t *pcb)
91{
92 int rc = VINF_SUCCESS;
93 uint32_t cb = 1024;
94 void *pv = RTMemAlloc(cb);
95
96 *ppv = 0;
97 LogFlowFunc(("u32Format=%u\n", u32Format));
98 if (RT_UNLIKELY(!pv))
99 rc = VERR_NO_MEMORY;
100 if (RT_SUCCESS(rc))
101 rc = VbglR3ClipboardReadData(g_ctx.client, u32Format, pv, cb, pcb);
102 if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW))
103 *ppv = pv;
104 /* A return value of VINF_BUFFER_OVERFLOW tells us to try again with a
105 * larger buffer. The size of the buffer needed is placed in *pcb.
106 * So we start all over again. */
107 if (rc == VINF_BUFFER_OVERFLOW)
108 {
109 cb = *pcb;
110 RTMemFree(pv);
111 pv = RTMemAlloc(cb);
112 if (RT_UNLIKELY(!pv))
113 rc = VERR_NO_MEMORY;
114 if (RT_SUCCESS(rc))
115 rc = VbglR3ClipboardReadData(g_ctx.client, u32Format, pv, cb, pcb);
116 if (RT_SUCCESS(rc) && (rc != VINF_BUFFER_OVERFLOW))
117 *ppv = pv;
118 }
119 /* Catch other errors. This also catches the case in which the buffer was
120 * too small a second time, possibly because the clipboard contents
121 * changed half-way through the operation. Since we can't say whether or
122 * not this is actually an error, we just return size 0.
123 */
124 if (RT_FAILURE(rc) || (VINF_BUFFER_OVERFLOW == rc))
125 {
126 *pcb = 0;
127 if (pv != NULL)
128 RTMemFree(pv);
129 }
130 LogFlowFunc(("returning %Rrc\n", rc));
131 if (RT_SUCCESS(rc))
132 LogFlow((" *pcb=%d\n", *pcb));
133 return rc;
134}
135
136/** Opaque data structure describing a request from the host for clipboard
137 * data, passed in when the request is forwarded to the X11 backend so that
138 * it can be completed correctly. */
139struct _CLIPREADCBREQ
140{
141 /** The data format that was requested. */
142 uint32_t u32Format;
143};
144
145/**
146 * Tell the host that new clipboard formats are available.
147 *
148 * @param u32Formats The formats to advertise
149 */
150void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Formats)
151{
152 int rc;
153 LogFlowFunc(("u32Formats=%d\n", u32Formats));
154 rc = VbglR3ClipboardReportFormats(g_ctx.client, u32Formats);
155 LogFlowFunc(("rc=%Rrc\n", rc));
156}
157
158/** This is called by the backend to tell us that a request for data from
159 * X11 has completed.
160 * @param pCtx Our context information
161 * @param rc the iprt result code of the request
162 * @param pReq the request structure that we passed in when we started
163 * the request. We RTMemFree() this in this function.
164 * @param pv the clipboard data returned from X11 if the request
165 * succeeded (see @a rc)
166 * @param cb the size of the data in @a pv
167 */
168void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc,
169 CLIPREADCBREQ *pReq, void *pv,
170 uint32_t cb)
171{
172 if (RT_SUCCESS(rc))
173 vboxClipboardSendData(pReq->u32Format, pv, cb);
174 else
175 vboxClipboardSendData(0, NULL, 0);
176 RTMemFree(pReq);
177}
178
179/**
180 * Connect the guest clipboard to the host.
181 *
182 * @returns VBox status code
183 */
184int vboxClipboardConnect(void)
185{
186 int rc = VINF_SUCCESS;
187 LogFlowFunc(("\n"));
188
189 /* Sanity */
190 AssertReturn(g_ctx.client == 0, VERR_WRONG_ORDER);
191 g_ctx.pBackend = ClipConstructX11(&g_ctx);
192 if (!g_ctx.pBackend)
193 rc = VERR_NO_MEMORY;
194 if (RT_SUCCESS(rc))
195 rc = ClipStartX11(g_ctx.pBackend);
196 if (RT_SUCCESS(rc))
197 {
198 rc = VbglR3ClipboardConnect(&g_ctx.client);
199 if (RT_FAILURE(rc))
200 LogRel(("Error connecting to host. rc=%Rrc\n", rc));
201 else if (!g_ctx.client)
202 {
203 LogRel(("Invalid client ID of 0\n"));
204 rc = VERR_NOT_SUPPORTED;
205 }
206 }
207
208 if (RT_FAILURE(rc) && g_ctx.pBackend)
209 ClipDestructX11(g_ctx.pBackend);
210 LogFlowFunc(("g_ctx.client=%u rc=%Rrc\n", g_ctx.client, rc));
211 return rc;
212}
213
214/**
215 * The main loop of our clipboard reader.
216 */
217int vboxClipboardMain(void)
218{
219 int rc;
220 LogFlowFunc(("Starting guest clipboard service\n"));
221 bool fExiting = false;
222
223 while (!fExiting)
224 {
225 uint32_t Msg;
226 uint32_t fFormats;
227 rc = VbglR3ClipboardGetHostMsg(g_ctx.client, &Msg, &fFormats);
228 if (RT_SUCCESS(rc))
229 {
230 switch (Msg)
231 {
232 case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
233 {
234 /* The host has announced available clipboard formats.
235 * Save the information so that it is available for
236 * future requests from guest applications.
237 */
238 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS fFormats=%x\n", fFormats));
239 ClipAnnounceFormatToX11(g_ctx.pBackend, fFormats);
240 break;
241 }
242
243 case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
244 {
245 /* The host needs data in the specified format. */
246 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA fFormats=%x\n", fFormats));
247 CLIPREADCBREQ *pReq;
248 pReq = (CLIPREADCBREQ *)RTMemAllocZ(sizeof(*pReq));
249 if (!pReq)
250 {
251 rc = VERR_NO_MEMORY;
252 fExiting = true;
253 }
254 else
255 {
256 pReq->u32Format = fFormats;
257 ClipRequestDataFromX11(g_ctx.pBackend, fFormats,
258 pReq);
259 }
260 break;
261 }
262
263 case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
264 {
265 /* The host is terminating. */
266 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT\n"));
267 if (RT_SUCCESS(ClipStopX11(g_ctx.pBackend)))
268 ClipDestructX11(g_ctx.pBackend);
269 fExiting = true;
270 break;
271 }
272
273 default:
274 Log(("Unsupported message from host!!!\n"));
275 }
276 }
277
278 LogFlow(("processed host event rc = %d\n", rc));
279 }
280 LogFlowFunc(("rc=%d\n", rc));
281 return rc;
282}
283
284class ClipboardService : public VBoxClient::Service
285{
286public:
287 virtual const char *getPidFilePath()
288 {
289 return ".vboxclient-clipboard.pid";
290 }
291 virtual int run()
292 {
293 int rc = vboxClipboardConnect();
294 if (RT_SUCCESS(rc))
295 rc = vboxClipboardMain();
296 if (RT_FAILURE(rc))
297 LogFunc(("guest clipboard service terminated annormally: return code %Rrc\n", rc));
298 return rc;
299 }
300 virtual void cleanup()
301 {
302 /* Nothing to do. */
303 }
304};
305
306VBoxClient::Service *VBoxClient::GetClipboardService()
307{
308 return new ClipboardService;
309}
Note: See TracBrowser for help on using the repository browser.

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