VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp@ 79257

Last change on this file since 79257 was 79174, checked in by vboxsync, 6 years ago

Shared Clipboard/URI: Update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/* $Id: VBoxSharedClipboardSvc-x11.cpp 79174 2019-06-17 10:30:49Z vboxsync $ */
2/** @file
3 * Shared Clipboard Service - Linux host.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
23#include <iprt/assert.h>
24#include <iprt/critsect.h>
25#include <iprt/env.h>
26#include <iprt/mem.h>
27#include <iprt/semaphore.h>
28#include <iprt/string.h>
29
30#include <VBox/GuestHost/SharedClipboard.h>
31#include <VBox/HostServices/VBoxClipboardSvc.h>
32#include <VBox/err.h>
33
34#include "VBoxSharedClipboardSvc-internal.h"
35
36
37/*********************************************************************************************************************************
38* Structures and Typedefs *
39*********************************************************************************************************************************/
40struct _VBOXCLIPBOARDREQFROMVBOX;
41typedef struct _VBOXCLIPBOARDREQFROMVBOX VBOXCLIPBOARDREQFROMVBOX;
42
43/** Global context information used by the host glue for the X11 clipboard
44 * backend */
45struct _VBOXCLIPBOARDCONTEXT
46{
47 /** This mutex is grabbed during any critical operations on the clipboard
48 * which might clash with others. */
49 RTCRITSECT clipboardMutex;
50 /** The currently pending request for data from VBox. NULL if there is
51 * no request pending. The protocol for completing a request is to grab
52 * the critical section, check that @a pReq is not NULL, fill in the data
53 * fields and set @a pReq to NULL. The protocol for cancelling a pending
54 * request is to grab the critical section and set pReq to NULL.
55 * It is an error if a request arrives while another one is pending, and
56 * the backend is responsible for ensuring that this does not happen. */
57 VBOXCLIPBOARDREQFROMVBOX *pReq;
58 /** Pointer to the opaque X11 backend structure */
59 CLIPBACKEND *pBackend;
60 /** Pointer to the VBox host client data structure. */
61 PVBOXCLIPBOARDCLIENTDATA pClientData;
62 /** We set this when we start shutting down as a hint not to post any new
63 * requests. */
64 bool fShuttingDown;
65};
66
67
68
69/**
70 * Report formats available in the X11 clipboard to VBox.
71 * @param pCtx Opaque context pointer for the glue code
72 * @param u32Formats The formats available
73 * @note Host glue code
74 */
75void ClipReportX11Formats(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Formats)
76{
77 LogFlowFunc(("pCtx=%p, u32Formats=%02X\n", pCtx, u32Formats));
78
79 vboxSvcClipboardReportMsg(pCtx->pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, u32Formats);
80}
81
82/**
83 * Initialise the host side of the shared clipboard.
84 * @note Host glue code
85 */
86int VBoxClipboardSvcImplInit(void)
87{
88 return VINF_SUCCESS;
89}
90
91/**
92 * Terminate the host side of the shared clipboard.
93 * @note host glue code
94 */
95void VBoxClipboardSvcImplDestroy(void)
96{
97
98}
99
100/**
101 * Connect a guest to the shared clipboard.
102 * @note host glue code
103 * @note on the host, we assume that some other application already owns
104 * the clipboard and leave ownership to X11.
105 */
106int VBoxClipboardSvcImplConnect(PVBOXCLIPBOARDCLIENTDATA pClientData, bool fHeadless)
107{
108 int rc = VINF_SUCCESS;
109
110 LogRel(("Starting host clipboard service\n"));
111
112 PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)RTMemAllocZ(sizeof(VBOXCLIPBOARDCONTEXT));
113 if (!pCtx)
114 {
115 rc = VERR_NO_MEMORY;
116 }
117 else
118 {
119 RTCritSectInit(&pCtx->clipboardMutex);
120 CLIPBACKEND *pBackend = ClipConstructX11(pCtx, fHeadless);
121 if (!pBackend)
122 {
123 rc = VERR_NO_MEMORY;
124 }
125 else
126 {
127 pCtx->pBackend = pBackend;
128 pClientData->State.pCtx = pCtx;
129 pCtx->pClientData = pClientData;
130
131 rc = ClipStartX11(pBackend, true /* grab shared clipboard */);
132 if (RT_FAILURE(rc))
133 ClipDestructX11(pBackend);
134 }
135
136 if (RT_FAILURE(rc))
137 {
138 RTCritSectDelete(&pCtx->clipboardMutex);
139 RTMemFree(pCtx);
140 }
141 }
142
143 if (RT_FAILURE(rc))
144 LogRel(("Failed to initialize the Shared Clipboard host service, rc=%Rrc\n", rc));
145
146 LogFlowFuncLeaveRC(rc);
147 return rc;
148}
149
150/**
151 * Synchronise the contents of the host clipboard with the guest, called
152 * after a save and restore of the guest.
153 * @note Host glue code
154 */
155int VBoxClipboardSvcImplSync(PVBOXCLIPBOARDCLIENTDATA pClientData)
156{
157 LogFlowFuncEnter();
158
159 /* Tell the guest we have no data in case X11 is not available. If
160 * there is data in the host clipboard it will automatically be sent to
161 * the guest when the clipboard starts up. */
162 return vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS, 0);
163}
164
165/**
166 * Shut down the shared clipboard service and "disconnect" the guest.
167 * @note Host glue code
168 */
169int VBoxClipboardSvcImplDisconnect(PVBOXCLIPBOARDCLIENTDATA pClientData)
170{
171 LogFlowFuncEnter();
172
173 LogRel(("Stopping the host clipboard service\n"));
174
175 PVBOXCLIPBOARDCONTEXT pCtx = pClientData->State.pCtx;
176
177 /* Drop the reference to the client, in case it is still there. This
178 * will cause any outstanding clipboard data requests from X11 to fail
179 * immediately. */
180 pCtx->fShuttingDown = true;
181
182 /* If there is a currently pending request, release it immediately. */
183 VBoxClipboardSvcImplWriteData(pClientData, NULL, 0, 0);
184
185 int rc = ClipStopX11(pCtx->pBackend);
186 /** @todo handle this slightly more reasonably, or be really sure
187 * it won't go wrong. */
188 AssertRC(rc);
189
190 if (RT_SUCCESS(rc)) /* And if not? */
191 {
192 ClipDestructX11(pCtx->pBackend);
193 RTCritSectDelete(&pCtx->clipboardMutex);
194 RTMemFree(pCtx);
195 }
196
197 LogFlowFuncLeaveRC(rc);
198 return rc;
199}
200
201/**
202 * VBox is taking possession of the shared clipboard.
203 *
204 * @param pClientData Context data for the guest system
205 * @param u32Formats Clipboard formats the guest is offering
206 * @note Host glue code
207 */
208int VBoxClipboardSvcImplFormatAnnounce(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t u32Formats)
209{
210 LogFlowFunc(("pClientData=%p, u32Formats=%02X\n", pClientData, u32Formats));
211
212 ClipAnnounceFormatToX11(pClientData->State.pCtx->pBackend, u32Formats);
213
214 return VINF_SUCCESS;
215}
216
217/** Structure describing a request for clipoard data from the guest. */
218struct _CLIPREADCBREQ
219{
220 /** Where to write the returned data to. */
221 void *pv;
222 /** The size of the buffer in pv */
223 uint32_t cb;
224 /** The actual size of the data written */
225 uint32_t *pcbActual;
226};
227
228/**
229 * Called when VBox wants to read the X11 clipboard.
230 *
231 * @returns VINF_SUCCESS on successful completion
232 * @returns VINF_HGCM_ASYNC_EXECUTE if the operation will complete
233 * asynchronously
234 * @returns iprt status code on failure
235 * @param pClientData Context information about the guest VM
236 * @param u32Format The format that the guest would like to receive the data in
237 * @param pv Where to write the data to
238 * @param cb The size of the buffer to write the data to
239 * @param pcbActual Where to write the actual size of the written data
240 *
241 * @note We always fail or complete asynchronously
242 * @note On success allocates a CLIPREADCBREQ structure which must be
243 * freed in ClipCompleteDataRequestFromX11 when it is called back from
244 * the backend code.
245 *
246 */
247int VBoxClipboardSvcImplReadData(PVBOXCLIPBOARDCLIENTDATA pClientData,
248 uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual)
249{
250 LogFlowFunc(("pClientData=%p, u32Format=%02X, pv=%p, cb=%u, pcbActual=%p\n",
251 pClientData, u32Format, pv, cb, pcbActual));
252
253 int rc = VINF_SUCCESS;
254 CLIPREADCBREQ *pReq = (CLIPREADCBREQ *)RTMemAlloc(sizeof(CLIPREADCBREQ));
255 if (!pReq)
256 {
257 rc = VERR_NO_MEMORY;
258 }
259 else
260 {
261 pReq->pv = pv;
262 pReq->cb = cb;
263 pReq->pcbActual = pcbActual;
264 rc = ClipRequestDataFromX11(pClientData->State.pCtx->pBackend, u32Format, pReq);
265 if (RT_SUCCESS(rc))
266 rc = VINF_HGCM_ASYNC_EXECUTE;
267 }
268
269 LogFlowFuncLeaveRC(rc);
270 return rc;
271}
272
273/**
274 * Complete a request from VBox for the X11 clipboard data. The data should
275 * be written to the buffer provided in the initial request.
276 * @param pCtx request context information
277 * @param rc the completion status of the request
278 * @param pReq request
279 * @param pv address
280 * @param cb size
281 *
282 * @todo change this to deal with the buffer issues rather than offloading
283 * them onto the caller
284 */
285void ClipCompleteDataRequestFromX11(VBOXCLIPBOARDCONTEXT *pCtx, int rc,
286 CLIPREADCBREQ *pReq, void *pv, uint32_t cb)
287{
288 if (cb <= pReq->cb && cb != 0)
289 memcpy(pReq->pv, pv, cb);
290
291 RTMemFree(pReq);
292
293 vboxSvcClipboardCompleteReadData(pCtx->pClientData, rc, cb);
294}
295
296/** A request for clipboard data from VBox */
297struct _VBOXCLIPBOARDREQFROMVBOX
298{
299 /** Data received */
300 void *pv;
301 /** The size of the data */
302 uint32_t cb;
303 /** Format of the data */
304 uint32_t format;
305 /** A semaphore for waiting for the data */
306 RTSEMEVENT finished;
307};
308
309/** Wait for clipboard data requested from VBox to arrive. */
310static int clipWaitForDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx,
311 VBOXCLIPBOARDREQFROMVBOX *pReq,
312 uint32_t u32Format)
313{
314 int rc = VINF_SUCCESS;
315
316 LogFlowFunc(("pCtx=%p, pReq=%p, u32Format=%02X\n", pCtx, pReq, u32Format));
317
318 /* Request data from VBox */
319 vboxSvcClipboardReportMsg(pCtx->pClientData,
320 VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA,
321 u32Format);
322 /* Which will signal us when it is ready. We use a timeout here
323 * because we can't be sure that the guest will behave correctly.
324 */
325 rc = RTSemEventWait(pReq->finished, CLIPBOARD_TIMEOUT);
326
327 /* If the request hasn't yet completed then we cancel it. We use
328 * the critical section to prevent these operations colliding. */
329 RTCritSectEnter(&pCtx->clipboardMutex);
330
331 /* The data may have arrived between the semaphore timing out and
332 * our grabbing the mutex. */
333 if (rc == VERR_TIMEOUT && pReq->pv != NULL)
334 rc = VINF_SUCCESS;
335 if (pCtx->pReq == pReq)
336 pCtx->pReq = NULL;
337 Assert(pCtx->pReq == NULL);
338
339 RTCritSectLeave(&pCtx->clipboardMutex);
340
341 if (RT_SUCCESS(rc) && (pReq->pv == NULL))
342 rc = VERR_NO_DATA;
343
344 LogFlowFuncLeaveRC(rc);
345 return rc;
346}
347
348/** Post a request for clipboard data to VBox/the guest and wait for it to be
349 * completed. */
350static int clipRequestDataFromVBox(VBOXCLIPBOARDCONTEXT *pCtx, VBOXCLIPBOARDREQFROMVBOX *pReq, uint32_t u32Format)
351{
352 int rc = VINF_SUCCESS;
353
354 LogFlowFunc(("pCtx=%p, pReq=%p, u32Format=%02X\n", pCtx, pReq, u32Format));
355
356 /* Start by "posting" the request for the next invocation of
357 * vboxClipboardWriteData. */
358 RTCritSectEnter(&pCtx->clipboardMutex);
359
360 if (pCtx->pReq != NULL)
361 {
362 /* This would be a violation of the protocol, see the comments in the
363 * context structure definition. */
364 Assert(false);
365 rc = VERR_WRONG_ORDER;
366 }
367 else
368 pCtx->pReq = pReq;
369
370 RTCritSectLeave(&pCtx->clipboardMutex);
371
372 if (RT_SUCCESS(rc))
373 rc = clipWaitForDataFromVBox(pCtx, pReq, u32Format);
374
375 LogFlowFuncLeaveRC(rc);
376 return rc;
377}
378
379/**
380 * Send a request to VBox to transfer the contents of its clipboard to X11.
381 *
382 * @param pCtx Pointer to the host clipboard structure
383 * @param u32Format The format in which the data should be transferred
384 * @param ppv On success and if pcb > 0, this will point to a buffer
385 * to be freed with RTMemFree containing the data read.
386 * @param pcb On success, this contains the number of bytes of data
387 * returned
388 * @note Host glue code.
389 */
390int ClipRequestDataForX11(VBOXCLIPBOARDCONTEXT *pCtx, uint32_t u32Format, void **ppv, uint32_t *pcb)
391{
392 VBOXCLIPBOARDREQFROMVBOX request = { NULL, 0, 0, NIL_RTSEMEVENT };
393
394 LogFlowFunc(("pCtx=%p, u32Format=%02X, ppv=%p, pcb=%p\n", pCtx, u32Format, ppv, pcb));
395
396 if (pCtx->fShuttingDown)
397 {
398 /* The shared clipboard is disconnecting. */
399 LogRel(("Clipboard: Host requested guest clipboard data after guest had disconnected\n"));
400 return VERR_WRONG_ORDER;
401 }
402
403 int rc = RTSemEventCreate(&request.finished);
404 if (RT_SUCCESS(rc))
405 {
406 rc = clipRequestDataFromVBox(pCtx, &request, u32Format);
407 RTSemEventDestroy(request.finished);
408 }
409
410 if (RT_SUCCESS(rc))
411 {
412 *ppv = request.pv;
413 *pcb = request.cb;
414 }
415
416 LogFlowFuncLeaveRC(rc);
417 return rc;
418}
419
420/**
421 * Called when we have requested data from VBox and that data has arrived.
422 *
423 * @param pClientData Context information about the guest VM
424 * @param pv Buffer to which the data was written
425 * @param cb The size of the data written
426 * @param u32Format The format of the data written
427 * @note Host glue code
428 */
429int VBoxClipboardSvcImplWriteData(PVBOXCLIPBOARDCLIENTDATA pClientData,
430 void *pv, uint32_t cb, uint32_t u32Format)
431{
432 LogFlowFunc(("pClientData=%p, pv=%p (%.*ls), cb=%u, u32Format=%02X\n", pClientData, pv, cb / 2, pv, cb, u32Format));
433
434 VBOXCLIPBOARDCONTEXT *pCtx = pClientData->State.pCtx;
435
436 /* Grab the mutex and check whether there is a pending request for data. */
437 RTCritSectEnter(&pCtx->clipboardMutex);
438
439 VBOXCLIPBOARDREQFROMVBOX *pReq = pCtx->pReq;
440 if (pReq != NULL)
441 {
442 if (cb > 0)
443 {
444 pReq->pv = RTMemDup(pv, cb);
445 if (pReq->pv != NULL) /* NULL may also mean no memory... */
446 {
447 pReq->cb = cb;
448 pReq->format = u32Format;
449 }
450 }
451 /* Signal that the request has been completed. */
452 RTSemEventSignal(pReq->finished);
453 pCtx->pReq = NULL;
454 }
455
456 RTCritSectLeave(&pCtx->clipboardMutex);
457
458 return VINF_SUCCESS;
459}
460
461#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
462int VBoxClipboardSvcImplURIReadDir(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDDIRDATA pDirData)
463{
464 RT_NOREF(pClientData, pDirData);
465 return VERR_NOT_IMPLEMENTED;
466}
467
468int VBoxClipboardSvcImplURIWriteDir(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDDIRDATA pDirData)
469{
470 RT_NOREF(pClientData, pDirData);
471 return VERR_NOT_IMPLEMENTED;
472}
473
474int VBoxClipboardSvcImplURIReadFileHdr(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDFILEHDR pFileHdr)
475{
476 RT_NOREF(pClientData, pFileHdr);
477 return VERR_NOT_IMPLEMENTED;
478}
479
480int VBoxClipboardSvcImplURIWriteFileHdr(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDFILEHDR pFileHdr)
481{
482 RT_NOREF(pClientData, pFileHdr);
483 return VERR_NOT_IMPLEMENTED;
484}
485
486int VBoxClipboardSvcImplURIReadFileData(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDFILEDATA pFileData)
487{
488 RT_NOREF(pClientData, pFileData);
489 return VERR_NOT_IMPLEMENTED;
490}
491
492int VBoxClipboardSvcImplURIWriteFileData(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDFILEDATA pFileData)
493{
494 RT_NOREF(pClientData, pFileData);
495 return VERR_NOT_IMPLEMENTED;
496}
497#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
498
499#ifdef TESTCASE
500# include <iprt/initterm.h>
501# include <iprt/stream.h>
502
503# define TEST_NAME "tstClipboardX11-2"
504
505struct _CLIPBACKEND
506{
507 uint32_t formats;
508 struct _READDATA
509 {
510 uint32_t format;
511 int rc;
512 CLIPREADCBREQ *pReq;
513 } readData;
514 struct _COMPLETEREAD
515 {
516 int rc;
517 uint32_t cbActual;
518 } completeRead;
519 struct _WRITEDATA
520 {
521 void *pv;
522 uint32_t cb;
523 uint32_t format;
524 bool timeout;
525 } writeData;
526 struct _REPORTDATA
527 {
528 uint32_t format;
529 } reportData;
530};
531
532int vboxSvcClipboardReportMsg(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t uMsg, uint32_t uFormats)
533{
534 RT_NOREF(uFormats);
535 CLIPBACKEND *pBackend = pClientData->State.pCtx->pBackend;
536
537 int rc;
538
539 if ( (uMsg == VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA)
540 && !pBackend->writeData.timeout)
541 {
542 rc = VBoxClipboardSvcImplWriteData(pClientData, pBackend->writeData.pv, pBackend->writeData.cb, pBackend->writeData.format);
543 }
544 else
545 rc = VERR_NOT_SUPPORTED;
546
547 return rc;
548}
549
550int vboxSvcClipboardCompleteReadData(PVBOXCLIPBOARDCLIENTDATA pClientData, int rc, uint32_t cbActual)
551{
552 CLIPBACKEND *pBackend = pClientData->State.pCtx->pBackend;
553 pBackend->completeRead.rc = rc;
554 pBackend->completeRead.cbActual = cbActual;
555
556 return VINF_SUCCESS;
557}
558
559CLIPBACKEND* ClipConstructX11(VBOXCLIPBOARDCONTEXT *pFrontend, bool)
560{
561 RT_NOREF(pFrontend);
562 return (CLIPBACKEND *)RTMemAllocZ(sizeof(CLIPBACKEND));
563}
564
565void ClipDestructX11(CLIPBACKEND *pBackend)
566{
567 RTMemFree(pBackend);
568}
569
570int ClipStartX11(CLIPBACKEND *pBackend, bool)
571{
572 RT_NOREF(pBackend);
573 return VINF_SUCCESS;
574}
575
576int ClipStopX11(CLIPBACKEND *pBackend)
577{
578 RT_NOREF1(pBackend);
579 return VINF_SUCCESS;
580}
581
582int ClipAnnounceFormatToX11(CLIPBACKEND *pBackend, VBOXCLIPBOARDFORMATS vboxFormats)
583{
584 pBackend->formats = vboxFormats;
585 return VINF_SUCCESS;
586}
587
588extern int ClipRequestDataFromX11(CLIPBACKEND *pBackend, VBOXCLIPBOARDFORMAT vboxFormat,
589 CLIPREADCBREQ *pReq)
590{
591 pBackend->readData.format = vboxFormat;
592 pBackend->readData.pReq = pReq;
593 return pBackend->readData.rc;
594}
595
596int main()
597{
598 VBOXCLIPBOARDCLIENTDATA client;
599 unsigned cErrors = 0;
600 int rc = RTR3InitExeNoArguments(0);
601 RTPrintf(TEST_NAME ": TESTING\n");
602 AssertRCReturn(rc, 1);
603 rc = VBoxClipboardSvcImplConnect(&client, false);
604 CLIPBACKEND *pBackend = client.State.pCtx->pBackend;
605 AssertRCReturn(rc, 1);
606 VBoxClipboardSvcImplFormatAnnounce(&client,
607 VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT);
608 if (pBackend->formats != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
609 {
610 RTPrintf(TEST_NAME ": vboxClipboardFormatAnnounce failed with VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n");
611 ++cErrors;
612 }
613 pBackend->readData.rc = VINF_SUCCESS;
614 client.State.asyncRead.callHandle = (VBOXHGCMCALLHANDLE)pBackend;
615 client.State.asyncRead.paParms = (VBOXHGCMSVCPARM *)&client;
616 uint32_t u32Dummy;
617 rc = VBoxClipboardSvcImplReadData(&client, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
618 &u32Dummy, 42, &u32Dummy);
619 if (rc != VINF_HGCM_ASYNC_EXECUTE)
620 {
621 RTPrintf(TEST_NAME ": vboxClipboardReadData returned %Rrc\n", rc);
622 ++cErrors;
623 }
624 else
625 {
626 if ( pBackend->readData.format != VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT
627 || pBackend->readData.pReq->pv != &u32Dummy
628 || pBackend->readData.pReq->cb != 42
629 || pBackend->readData.pReq->pcbActual != &u32Dummy)
630 {
631 RTPrintf(TEST_NAME ": format=%u, pReq->pv=%p, pReq->cb=%u, pReq->pcbActual=%p\n",
632 pBackend->readData.format, pBackend->readData.pReq->pv,
633 pBackend->readData.pReq->cb,
634 pBackend->readData.pReq->pcbActual);
635 ++cErrors;
636 }
637 else
638 {
639 ClipCompleteDataRequestFromX11(client.State.pCtx, VERR_NO_DATA,
640 pBackend->readData.pReq, NULL, 43);
641 if ( pBackend->completeRead.rc != VERR_NO_DATA
642 || pBackend->completeRead.cbActual != 43)
643 {
644 RTPrintf(TEST_NAME ": rc=%Rrc, cbActual=%u\n",
645 pBackend->completeRead.rc,
646 pBackend->completeRead.cbActual);
647 ++cErrors;
648 }
649 }
650 }
651 void *pv;
652 uint32_t cb;
653 pBackend->writeData.pv = (void *)"testing";
654 pBackend->writeData.cb = sizeof("testing");
655 pBackend->writeData.format = 1234;
656 pBackend->reportData.format = 4321; /* XX this should be handled! */
657 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb);
658 if ( rc != VINF_SUCCESS
659 || strcmp((const char *)pv, "testing") != 0
660 || cb != sizeof("testing"))
661 {
662 RTPrintf("rc=%Rrc, pv=%p, cb=%u\n", rc, pv, cb);
663 ++cErrors;
664 }
665 else
666 RTMemFree(pv);
667 pBackend->writeData.timeout = true;
668 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb);
669 if (rc != VERR_TIMEOUT)
670 {
671 RTPrintf("rc=%Rrc, expected VERR_TIMEOUT\n", rc);
672 ++cErrors;
673 }
674 pBackend->writeData.pv = NULL;
675 pBackend->writeData.cb = 0;
676 pBackend->writeData.timeout = false;
677 rc = ClipRequestDataForX11(client.State.pCtx, 23, &pv, &cb);
678 if (rc != VERR_NO_DATA)
679 {
680 RTPrintf("rc=%Rrc, expected VERR_NO_DATA\n", rc);
681 ++cErrors;
682 }
683 /* Data arriving after a timeout should *not* cause any segfaults or
684 * memory leaks. Check with Valgrind! */
685 VBoxClipboardSvcImplWriteData(&client, (void *)"tested", sizeof("tested"), 999);
686 VBoxClipboardSvcImplDisconnect(&client);
687 if (cErrors > 0)
688 RTPrintf(TEST_NAME ": errors: %u\n", cErrors);
689 return cErrors > 0 ? 1 : 0;
690}
691#endif /* TESTCASE */
692
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