VirtualBox

source: vbox/trunk/src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp@ 53100

Last change on this file since 53100 was 46422, checked in by vboxsync, 12 years ago

GuestHost/SharedClipboard: Utf-8.

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