VirtualBox

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

Last change on this file since 41423 was 41210, checked in by vboxsync, 13 years ago

GuestHost, HostService: darwin bitmap support, copyright header and some cleanups.

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