VirtualBox

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

Last change on this file since 85416 was 82968, checked in by vboxsync, 5 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.0 KB
Line 
1/** $Id: VBoxClientClipboardHostToGuest.cpp 82968 2020-02-04 10:35:17Z 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 size_t cbActualLen;
158 int rc;
159 char *pszUtf8Buf;
160 RTUTF16 *pDataInternal;
161
162 AssertReturn(pData, VERR_INVALID_PARAMETER);
163
164 /* Skip zero-sized buffer */
165 AssertReturn(cbDataSize > 0, VINF_SUCCESS);
166
167 /* If buffer content is Unicode text, then deliver
168 it in both formats UTF16 (original) and UTF8. */
169
170 /* Convert END-OF-LINE */
171 rc = ShClUtf16GetLinSize((RTUTF16 *)pData, cbDataSize / 2, &cbActualLen);
172 AssertReturn(RT_SUCCESS(rc), rc);
173 pDataInternal = (RTUTF16 *)RTMemAlloc(cbActualLen * 2);
174 AssertReturn(pDataInternal, VERR_NO_MEMORY);
175 rc = ShClUtf16WinToLin((RTUTF16 *)pData, cbDataSize / 2, pDataInternal, cbActualLen);
176
177 /* Do actual paste */
178 if (RT_SUCCESS(rc))
179 {
180 /* Paste UTF16 */
181 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pDataInternal, cbActualLen * 2, kUTTypeUTF16PlainText, true);
182 if (RT_SUCCESS(rc))
183 {
184 /* Paste UTF8 */
185 rc = RTUtf16ToUtf8((RTUTF16 *)pDataInternal, &pszUtf8Buf);
186 if (RT_SUCCESS(rc))
187 {
188 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pszUtf8Buf, strlen(pszUtf8Buf), kUTTypeUTF8PlainText, false);
189 RTStrFree(pszUtf8Buf);
190 }
191 }
192
193 }
194
195 RTMemFree(pDataInternal);
196
197 return rc;
198}
199
200/**
201 * Paste picture data into guest clipboard.
202 *
203 * @param pPasteboard Guest PasteBoard reference.
204 * @param pData Data to be pasted.
205 * @param cbDataSize The size of *pData.
206 *
207 * @returns IPRT status code.
208 */
209static int vbclClipboardGuestPastePicture(PasteboardRef pPasteboard, void *pData, uint32_t cbDataSize)
210{
211 int rc;
212 void *pBmp;
213 size_t cbBmpSize;
214
215 AssertReturn(pData, VERR_INVALID_PARAMETER);
216 /* Skip zero-sized buffer */
217 AssertReturn(cbDataSize > 0, VINF_SUCCESS);
218
219 rc = ShClDibToBmp(pData, cbDataSize, &pBmp, &cbBmpSize);
220 AssertReturn(RT_SUCCESS(rc), rc);
221
222 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pBmp, cbBmpSize, kUTTypeBMP, true);
223 RTMemFree(pBmp);
224
225 return rc;
226}
227
228/**
229 * Read host's clipboard buffer and put its content to guest clipboard.
230 *
231 * @param u32ClientId Host connection.
232 * @param pPasteboard Guest PasteBoard reference.
233 * @param fFormats List of data formats (bit field) received from host.
234 *
235 * @returns IPRT status code.
236 */
237int vbclClipboardForwardToGuest(uint32_t u32ClientId, PasteboardRef pPasteboard, uint32_t fFormats)
238{
239 int rc = VERR_INVALID_PARAMETER;
240 void *pData;
241 uint32_t cbDataSize, cbMemSize;
242 uint32_t fFormatsInternal = fFormats;
243
244 /* Walk across all item(s) formats */
245 while (fFormatsInternal)
246 {
247 if (fFormatsInternal & VBOX_SHCL_FMT_UNICODETEXT)
248 {
249 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_UNICODETEXT: %d\n", fFormatsInternal);
250
251 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_UNICODETEXT, &pData, &cbDataSize, &cbMemSize);
252 if (RT_SUCCESS(rc))
253 {
254 /* Store data in guest buffer */
255 rc = vbclClipboardGuestPasteText(pPasteboard, pData, cbDataSize);
256
257 /* Release occupied resources */
258 vbclClipboardReleaseHostData(&pData, cbMemSize);
259 }
260
261 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_UNICODETEXT);
262 }
263
264 else if (fFormatsInternal & VBOX_SHCL_FMT_BITMAP)
265 {
266 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_BITMAP: %d\n", fFormatsInternal);
267
268 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_BITMAP, &pData, &cbDataSize, &cbMemSize);
269 if (RT_SUCCESS(rc))
270 {
271 /* Store data in guest buffer */
272 rc = vbclClipboardGuestPastePicture(pPasteboard, pData, cbDataSize);
273
274 /* Release occupied resources */
275 vbclClipboardReleaseHostData(&pData, cbMemSize);
276 }
277
278 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_BITMAP);
279 }
280
281 else if (fFormatsInternal & VBOX_SHCL_FMT_HTML)
282 {
283 VBoxClientVerbose(3, "found VBOX_SHCL_FMT_HTML: %d\n", fFormatsInternal);
284
285 rc = vbclClipboardReadHostData(u32ClientId, VBOX_SHCL_FMT_HTML, &pData, &cbDataSize, &cbMemSize);
286 if (RT_SUCCESS(rc))
287 {
288 /* Store data in guest buffer */
289 rc = vbclClipboardGuestPasteData(pPasteboard, (UInt8 *)pData, cbDataSize, kUTTypeHTML, true);
290
291 /* Release occupied resources */
292 vbclClipboardReleaseHostData(&pData, cbMemSize);
293 }
294
295 fFormatsInternal &= ~((uint32_t)VBOX_SHCL_FMT_HTML);
296 }
297
298 else
299 {
300 VBoxClientVerbose(3, "received data in unsupported format: %d\n", fFormats);
301 break;
302 }
303 }
304
305 return rc;
306}
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