VirtualBox

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

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

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