VirtualBox

source: vbox/trunk/src/VBox/Additions/darwin/VBoxClient/VBoxClientClipboardHostToGuest.cpp@ 86649

Last change on this file since 86649 was 85845, checked in by vboxsync, 4 years ago

Shared Clipboard/X11: Fixes for empty strings (was too strict before), don't include the terminating zeros when return string lengths to match IPRT. Also should fix the testcases.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/** $Id: VBoxClientClipboardHostToGuest.cpp 85845 2020-08-20 14:28:33Z vboxsync $ */
2/** @file
3 * VBoxClient - Shared Clipboard Host -> Guest copying, Darwin.
4 */
5
6/*
7 * Copyright (C) 2007-2020 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#include <Carbon/Carbon.h>
23#include <signal.h>
24#include <stdlib.h>
25
26#include <iprt/initterm.h>
27#include <iprt/mem.h>
28#include <iprt/message.h>
29#include <iprt/stream.h>
30#include <iprt/thread.h>
31#include <iprt/utf16.h>
32#include <VBox/VBoxGuestLib.h>
33#include <VBox/GuestHost/SharedClipboard.h>
34#include <VBox/HostServices/VBoxClipboardSvc.h>
35#include <VBox/GuestHost/clipboard-helper.h>
36#include "VBoxClientInternal.h"
37
38/**
39 * Allocate memory for host buffer and receive it.
40 *
41 * @param u32ClientId Host connection.
42 * @param fFormat Buffer data format.
43 * @param pData Where to store received data.
44 * @param cbDataSize The size of the received data.
45 * @param cbMemSize The actual size of memory occupied by *pData.
46 *
47 * @returns IPRT status code.
48 */
49static int vbclClipboardReadHostData(uint32_t u32ClientId, uint32_t fFormat, void **pData, uint32_t *cbDataSize, uint32_t *cbMemSize)
50{
51 int rc;
52
53 AssertReturn(pData && cbDataSize && cbMemSize, VERR_INVALID_PARAMETER);
54
55 uint32_t cbDataSizeInternal = _4K;
56 uint32_t cbMemSizeInternal = cbDataSizeInternal;
57 void *pDataInternal = RTMemPageAllocZ(cbDataSizeInternal);
58
59 if (!pDataInternal)
60 return VERR_NO_MEMORY;
61
62 rc = VbglR3ClipboardReadData(u32ClientId, fFormat, pDataInternal, cbMemSizeInternal, &cbDataSizeInternal);
63 if (rc == VINF_BUFFER_OVERFLOW)
64 {
65 /* Reallocate bigger buffer and receive all the data */
66 RTMemPageFree(pDataInternal, cbMemSizeInternal);
67 cbDataSizeInternal = cbMemSizeInternal = RT_ALIGN_32(cbDataSizeInternal, PAGE_SIZE);
68 pDataInternal = RTMemPageAllocZ(cbMemSizeInternal);
69 if (!pDataInternal)
70 return VERR_NO_MEMORY;
71
72 rc = VbglR3ClipboardReadData(u32ClientId, fFormat, pDataInternal, cbMemSizeInternal, &cbDataSizeInternal);
73 }
74
75 /* Error occurred of zero-sized buffer */
76 if (RT_FAILURE(rc))
77 {
78 RTMemPageFree(pDataInternal, cbMemSizeInternal);
79 return VERR_NO_MEMORY;
80 }
81
82 *pData = pDataInternal;
83 *cbDataSize = cbDataSizeInternal;
84 *cbMemSize = cbMemSizeInternal;
85
86 return rc;
87}
88
89/**
90 * Release memory occupied by host buffer.
91 *
92 * @param pData Pointer to memory occupied by host buffer.
93 * @param cbMemSize The actual size of memory occupied by *pData.
94 */
95static void vbclClipboardReleaseHostData(void **pData, uint32_t cbMemSize)
96{
97 AssertReturnVoid(pData && cbMemSize > 0);
98 RTMemPageFree(*pData, cbMemSize);
99}
100
101/**
102 * Paste buffer into guest clipboard.
103 *
104 * @param pPasteboard Guest PasteBoard reference.
105 * @param pData Data to be pasted.
106 * @param cbDataSize The size of *pData.
107 * @param fFormat Buffer data format.
108 * @param fClear Whether or not clear guest clipboard before insert data.
109 *
110 * @returns IPRT status code.
111 */
112static int vbclClipboardGuestPasteData(PasteboardRef pPasteboard, UInt8 *pData, CFIndex cbDataSize, CFStringRef sFormat, bool fClear)
113{
114 PasteboardItemID itemId = (PasteboardItemID)1;
115 CFDataRef textData = NULL;
116 OSStatus rc;
117
118 /* Ignoring sunchronization flags here */
119 PasteboardSynchronize(pPasteboard);
120
121 if (fClear)
122 {
123 rc = PasteboardClear(pPasteboard);
124 AssertReturn(rc == noErr, VERR_NOT_SUPPORTED);
125 }
126
127 /* Create a CData object which we could pass to the pasteboard */
128 if ((textData = CFDataCreate(kCFAllocatorDefault, pData, cbDataSize)))
129 {
130 /* Put the Utf-8 version to the pasteboard */
131 rc = PasteboardPutItemFlavor(pPasteboard, itemId, sFormat, textData, 0);
132 CFRelease(textData);
133 if (rc != noErr)
134 {
135 VBoxClientVerbose(3, "unable to put data into guest's clipboard: %d\n", rc);
136 return VERR_GENERAL_FAILURE;
137 }
138 }
139 else
140 return VERR_NO_MEMORY;
141
142 /* Synchronize updated content */
143 PasteboardSynchronize(pPasteboard);
144
145 return VINF_SUCCESS;
146}
147
148/**
149 * Paste text data into guest clipboard.
150 *
151 * @param pPasteboard Guest PasteBoard reference.
152 * @param pData Data to be pasted.
153 * @param cbDataSize Size of *pData.
154 */
155static int vbclClipboardGuestPasteText(PasteboardRef pPasteboard, void *pData, uint32_t cbDataSize)
156{
157 AssertReturn(pData, VERR_INVALID_PARAMETER);
158
159 /* Skip zero-sized buffer */
160 AssertReturn(cbDataSize > 0, VINF_SUCCESS);
161
162 /* If buffer content is Unicode text, then deliver
163 it in both formats UTF16 (original) and UTF8. */
164
165 /* Convert END-OF-LINE */
166 size_t cwcDst;
167 int rc = ShClUtf16CRLFLenUtf8((RTUTF16 *)pData, cbDataSize / sizeof(RTUTF16), &cwcDst);
168 AssertRCReturn(rc, rc);
169
170 cwcDst++; /* Add space for terminator. */
171
172 PRTUTF16 pwszDst = (RTUTF16 *)RTMemAlloc(cwcDst * sizeof(RTUTF16));
173 AssertPtrReturn(pwszDst, VERR_NO_MEMORY);
174
175 rc = ShClConvUtf16CRLFToLF((RTUTF16 *)pData, cbDataSize / sizeof(RTUTF16), pwszDst, cwcDst);
176 if (RT_SUCCESS(rc))
177 {
178 /* Paste UTF16 */
179 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pwszDst, cwcDst * sizeof(RTUTF16), kUTTypeUTF16PlainText, true);
180 if (RT_SUCCESS(rc))
181 {
182 /* Paste UTF8 */
183 char *pszDst;
184 rc = RTUtf16ToUtf8((PRTUTF16)pwszDst, &pszDst);
185 if (RT_SUCCESS(rc))
186 {
187 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pszDst, strlen(pszDst), kUTTypeUTF8PlainText, false);
188 RTStrFree(pszDst);
189 }
190 }
191
192 }
193
194 RTMemFree(pwszDst);
195
196 return rc;
197}
198
199/**
200 * Paste picture data into guest clipboard.
201 *
202 * @param pPasteboard Guest PasteBoard reference.
203 * @param pData Data to be pasted.
204 * @param cbDataSize The size of *pData.
205 *
206 * @returns IPRT status code.
207 */
208static int vbclClipboardGuestPastePicture(PasteboardRef pPasteboard, void *pData, uint32_t cbDataSize)
209{
210 int rc;
211 void *pBmp;
212 size_t cbBmpSize;
213
214 AssertReturn(pData, VERR_INVALID_PARAMETER);
215 /* Skip zero-sized buffer */
216 AssertReturn(cbDataSize > 0, VINF_SUCCESS);
217
218 rc = ShClDibToBmp(pData, cbDataSize, &pBmp, &cbBmpSize);
219 AssertReturn(RT_SUCCESS(rc), rc);
220
221 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pBmp, cbBmpSize, kUTTypeBMP, true);
222 RTMemFree(pBmp);
223
224 return rc;
225}
226
227/**
228 * Read host's clipboard buffer and put its content to guest clipboard.
229 *
230 * @param u32ClientId Host connection.
231 * @param pPasteboard Guest PasteBoard reference.
232 * @param fFormats List of data formats (bit field) received from host.
233 *
234 * @returns IPRT status code.
235 */
236int vbclClipboardForwardToGuest(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats)
237{
238 int rc = VERR_INVALID_PARAMETER;
239 void *pData;
240 uint32_t cbDataSize, cbMemSize;
241 uint32_t fFormatsInternal = fFormats;
242
243 /* Walk across all item(s) formats */
244 while (fFormatsInternal)
245 {
246 if (fFormatsInternal & VBOX_SHCL_FMT_UNICODETEXT)
247 {
248 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_UNICODETEXT: %d\n", fFormatsInternal);
249
250 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_UNICODETEXT, &pData, &cbDataSize, &cbMemSize);
251 if (RT_SUCCESS(rc))
252 {
253 /* Store data in guest buffer */
254 rc = vbclClipboardGuestPasteText(pPasteboard, pData, cbDataSize);
255
256 /* Release occupied resources */
257 vbclClipboardReleaseHostData(&pData, cbMemSize);
258 }
259
260 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_UNICODETEXT);
261 }
262
263 else if (fFormatsInternal & VBOX_SHCL_FMT_BITMAP)
264 {
265 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_BITMAP: %d\n", fFormatsInternal);
266
267 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_BITMAP, &pData, &cbDataSize, &cbMemSize);
268 if (RT_SUCCESS(rc))
269 {
270 /* Store data in guest buffer */
271 rc = vbclClipboardGuestPastePicture(pPasteboard, pData, cbDataSize);
272
273 /* Release occupied resources */
274 vbclClipboardReleaseHostData(&pData, cbMemSize);
275 }
276
277 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_BITMAP);
278 }
279
280 else if (fFormatsInternal & VBOX_SHCL_FMT_HTML)
281 {
282 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_HTML: %d\n", fFormatsInternal);
283
284 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_HTML, &pData, &cbDataSize, &cbMemSize);
285 if (RT_SUCCESS(rc))
286 {
287 /* Store data in guest buffer */
288 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pData, cbDataSize, kUTTypeHTML, true);
289
290 /* Release occupied resources */
291 vbclClipboardReleaseHostData(&pData, cbMemSize);
292 }
293
294 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_HTML);
295 }
296
297 else
298 {
299 VBoxClientVerbose(3, "received data in unsupported format: %d\n", fFormats);
300 break;
301 }
302 }
303
304 return rc;
305}
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