VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-common.cpp@ 78406

Last change on this file since 78406 was 78161, checked in by vboxsync, 6 years ago

Shared Clipboard: Unified naming of shared guest/host files; too many similarly named files in different directories otherwise, can be confusing.

  • Property eol-style set to native
  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 11.1 KB
Line 
1/* $Id: clipboard-common.cpp 78161 2019-04-17 13:52:43Z vboxsync $ */
2/** @file
3 * Shared Clipboard: Some helper function for converting between the various eol.
4 */
5
6/*
7 * Includes contributions from François Revol
8 *
9 * Copyright (C) 2006-2019 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include <iprt/alloc.h>
21#include <iprt/assert.h>
22#include <iprt/errcore.h>
23#include <VBox/log.h>
24#include <VBox/GuestHost/clipboard-helper.h>
25
26/** @todo use const where appropriate; delinuxify the code (*Lin* -> *Host*); use AssertLogRel*. */
27
28int vboxClipboardUtf16GetWinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
29{
30 size_t cwDest, i;
31
32 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
33 AssertLogRelMsgReturn(pwszSrc != NULL, ("vboxClipboardUtf16GetWinSize: received a null Utf16 string, returning VERR_INVALID_PARAMETER\n"), VERR_INVALID_PARAMETER);
34 if (cwSrc == 0)
35 {
36 *pcwDest = 0;
37 LogFlowFunc(("empty source string, returning\n"));
38 return VINF_SUCCESS;
39 }
40/** @todo convert the remainder of the Assert stuff to AssertLogRel. */
41 /* We only take little endian Utf16 */
42 if (pwszSrc[0] == UTF16BEMARKER)
43 {
44 LogRel(("vboxClipboardUtf16GetWinSize: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
45 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
46 }
47 cwDest = 0;
48 /* Calculate the size of the destination text string. */
49 /* Is this Utf16 or Utf16-LE? */
50 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0); i < cwSrc; ++i, ++cwDest)
51 {
52 /* Check for a single line feed */
53 if (pwszSrc[i] == LINEFEED)
54 ++cwDest;
55#ifdef RT_OS_DARWIN
56 /* Check for a single carriage return (MacOS) */
57 if (pwszSrc[i] == CARRIAGERETURN)
58 ++cwDest;
59#endif
60 if (pwszSrc[i] == 0)
61 {
62 /* Don't count this, as we do so below. */
63 break;
64 }
65 }
66 /* Count the terminating null byte. */
67 ++cwDest;
68 LogFlowFunc(("returning VINF_SUCCESS, %d 16bit words\n", cwDest));
69 *pcwDest = cwDest;
70 return VINF_SUCCESS;
71}
72
73int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
74 size_t cwDest)
75{
76 size_t i, j;
77 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
78 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
79 {
80 LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
81 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
82 }
83 if (cwSrc == 0)
84 {
85 if (cwDest == 0)
86 {
87 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
88 return VERR_BUFFER_OVERFLOW;
89 }
90 pu16Dest[0] = 0;
91 LogFlowFunc(("empty source string, returning\n"));
92 return VINF_SUCCESS;
93 }
94 /* We only take little endian Utf16 */
95 if (pwszSrc[0] == UTF16BEMARKER)
96 {
97 LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
98 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
99 }
100 /* Don't copy the endian marker. */
101 for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
102 {
103 /* Don't copy the null byte, as we add it below. */
104 if (pwszSrc[i] == 0)
105 break;
106 if (j == cwDest)
107 {
108 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
109 return VERR_BUFFER_OVERFLOW;
110 }
111 if (pwszSrc[i] == LINEFEED)
112 {
113 pu16Dest[j] = CARRIAGERETURN;
114 ++j;
115 if (j == cwDest)
116 {
117 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
118 return VERR_BUFFER_OVERFLOW;
119 }
120 }
121#ifdef RT_OS_DARWIN
122 /* Check for a single carriage return (MacOS) */
123 else if (pwszSrc[i] == CARRIAGERETURN)
124 {
125 /* set cr */
126 pu16Dest[j] = CARRIAGERETURN;
127 ++j;
128 if (j == cwDest)
129 {
130 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
131 return VERR_BUFFER_OVERFLOW;
132 }
133 /* add the lf */
134 pu16Dest[j] = LINEFEED;
135 continue;
136 }
137#endif
138 pu16Dest[j] = pwszSrc[i];
139 }
140 /* Add the trailing null. */
141 if (j == cwDest)
142 {
143 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
144 return VERR_BUFFER_OVERFLOW;
145 }
146 pu16Dest[j] = 0;
147 LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
148 return VINF_SUCCESS;
149}
150
151int vboxClipboardUtf16GetLinSize(PRTUTF16 pwszSrc, size_t cwSrc, size_t *pcwDest)
152{
153 size_t cwDest;
154
155 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
156 if (!VALID_PTR(pwszSrc))
157 {
158 LogRel(("vboxClipboardUtf16GetLinSize: received an invalid Utf16 string %p. Returning VERR_INVALID_PARAMETER.\n", pwszSrc));
159 AssertReturn(VALID_PTR(pwszSrc), VERR_INVALID_PARAMETER);
160 }
161 if (cwSrc == 0)
162 {
163 LogFlowFunc(("empty source string, returning VINF_SUCCESS\n"));
164 *pcwDest = 0;
165 return VINF_SUCCESS;
166 }
167 /* We only take little endian Utf16 */
168 if (pwszSrc[0] == UTF16BEMARKER)
169 {
170 LogRel(("vboxClipboardUtf16GetLinSize: received a big endian Utf16 string. Returning VERR_INVALID_PARAMETER.\n"));
171 AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
172 }
173 /* Calculate the size of the destination text string. */
174 /* Is this Utf16 or Utf16-LE? */
175 if (pwszSrc[0] == UTF16LEMARKER)
176 cwDest = 0;
177 else
178 cwDest = 1;
179 for (size_t i = 0; i < cwSrc; ++i, ++cwDest)
180 {
181 if ( (i + 1 < cwSrc)
182 && (pwszSrc[i] == CARRIAGERETURN)
183 && (pwszSrc[i + 1] == LINEFEED))
184 {
185 ++i;
186 }
187 if (pwszSrc[i] == 0)
188 {
189 break;
190 }
191 }
192 /* Terminating zero */
193 ++cwDest;
194 LogFlowFunc(("returning %d\n", cwDest));
195 *pcwDest = cwDest;
196 return VINF_SUCCESS;
197}
198
199int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
200 size_t cwDest)
201{
202 size_t cwDestPos;
203
204 LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u, pu16Dest=%p, cwDest=%u\n",
205 cwSrc, pwszSrc, cwSrc, pu16Dest, cwDest));
206 /* A buffer of size 0 may not be an error, but it is not a good idea either. */
207 Assert(cwDest > 0);
208 if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
209 {
210 LogRel(("vboxClipboardUtf16WinToLin: received an invalid ptr, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
211 AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
212 }
213 /* We only take little endian Utf16 */
214 if (pwszSrc[0] == UTF16BEMARKER)
215 {
216 LogRel(("vboxClipboardUtf16WinToLin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
217 AssertMsgFailedReturn(("received a big endian string\n"), VERR_INVALID_PARAMETER);
218 }
219 if (cwDest == 0)
220 {
221 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
222 return VERR_BUFFER_OVERFLOW;
223 }
224 if (cwSrc == 0)
225 {
226 pu16Dest[0] = 0;
227 LogFlowFunc(("received empty string. Returning VINF_SUCCESS\n"));
228 return VINF_SUCCESS;
229 }
230 /* Prepend the Utf16 byte order marker if it is missing. */
231 if (pwszSrc[0] == UTF16LEMARKER)
232 {
233 cwDestPos = 0;
234 }
235 else
236 {
237 pu16Dest[0] = UTF16LEMARKER;
238 cwDestPos = 1;
239 }
240 for (size_t i = 0; i < cwSrc; ++i, ++cwDestPos)
241 {
242 if (pwszSrc[i] == 0)
243 {
244 break;
245 }
246 if (cwDestPos == cwDest)
247 {
248 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
249 return VERR_BUFFER_OVERFLOW;
250 }
251 if ( (i + 1 < cwSrc)
252 && (pwszSrc[i] == CARRIAGERETURN)
253 && (pwszSrc[i + 1] == LINEFEED))
254 {
255 ++i;
256 }
257 pu16Dest[cwDestPos] = pwszSrc[i];
258 }
259 /* Terminating zero */
260 if (cwDestPos == cwDest)
261 {
262 LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
263 return VERR_BUFFER_OVERFLOW;
264 }
265 pu16Dest[cwDestPos] = 0;
266 LogFlowFunc(("set string %ls. Returning\n", pu16Dest + 1));
267 return VINF_SUCCESS;
268}
269
270int vboxClipboardDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDest, size_t *pcbDest)
271{
272 size_t cb = sizeof(BMFILEHEADER) + cbSrc;
273 PBMFILEHEADER pFileHeader = NULL;
274 void *pvDest = NULL;
275 size_t offPixel = 0;
276
277 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
278 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
279 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
280
281 PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pvSrc;
282 /** @todo Support all the many versions of the DIB headers. */
283 if ( cbSrc < sizeof(BMINFOHEADER)
284 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) < sizeof(BMINFOHEADER)
285 || RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
286 {
287 Log(("vboxClipboardDibToBmp: invalid or unsupported bitmap data.\n"));
288 return VERR_INVALID_PARAMETER;
289 }
290
291 offPixel = sizeof(BMFILEHEADER)
292 + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
293 + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
294 if (cbSrc < offPixel)
295 {
296 Log(("vboxClipboardDibToBmp: invalid bitmap data.\n"));
297 return VERR_INVALID_PARAMETER;
298 }
299
300 pvDest = RTMemAlloc(cb);
301 if (!pvDest)
302 {
303 Log(("writeToPasteboard: cannot allocate memory for bitmap.\n"));
304 return VERR_NO_MEMORY;
305 }
306
307 pFileHeader = (PBMFILEHEADER)pvDest;
308 pFileHeader->u16Type = BITMAPHEADERMAGIC;
309 pFileHeader->u32Size = RT_H2LE_U32(cb);
310 pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
311 pFileHeader->u32OffBits = RT_H2LE_U32(offPixel);
312 memcpy((uint8_t *)pvDest + sizeof(BMFILEHEADER), pvSrc, cbSrc);
313 *ppvDest = pvDest;
314 *pcbDest = cb;
315 return VINF_SUCCESS;
316}
317
318int vboxClipboardBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDest, size_t *pcbDest)
319{
320 AssertPtrReturn(pvSrc, VERR_INVALID_PARAMETER);
321 AssertPtrReturn(ppvDest, VERR_INVALID_PARAMETER);
322 AssertPtrReturn(pcbDest, VERR_INVALID_PARAMETER);
323
324 PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pvSrc;
325 if ( cbSrc < sizeof(BMFILEHEADER)
326 || pFileHeader->u16Type != BITMAPHEADERMAGIC
327 || RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
328 {
329 Log(("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
330 return VERR_INVALID_PARAMETER;
331 }
332
333 *ppvDest = ((uint8_t *)pvSrc) + sizeof(BMFILEHEADER);
334 *pcbDest = cbSrc - sizeof(BMFILEHEADER);
335 return VINF_SUCCESS;
336}
337
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