VirtualBox

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

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