1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19
20#include "StringServices.h"
21
22#include <DebugServices.h>
23
24
25
26
27
28extern BOOL
29
30BSTRToUTF8
31
32	(
33
34	BSTR			inString,
35
36	std::string	&	outString
37
38	)
39
40{
41
42	USES_CONVERSION;
43
44
45
46	char	*	utf8String	= NULL;
47
48	OSStatus    err			= kNoErr;
49
50
51
52	outString = "";
53
54	if ( inString )
55
56	{
57		TCHAR	*	utf16String	= NULL;
58		size_t      size		= 0;
59
60
61		utf16String = OLE2T( inString );
62
63		require_action( utf16String != NULL, exit, err = kUnknownErr );
64
65
66
67		if ( wcslen( utf16String ) > 0 )
68
69		{
70
71			size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), NULL, 0, NULL, NULL );
72
73			err = translate_errno( size != 0, GetLastError(), kUnknownErr );
74
75			require_noerr( err, exit );
76
77
78
79			try
80
81			{
82
83				utf8String = new char[ size + 1 ];
84
85			}
86
87			catch ( ... )
88
89			{
90
91				utf8String = NULL;
92
93			}
94
95
96
97			require_action( utf8String != NULL, exit, err = kNoMemoryErr );
98
99			size = (size_t) WideCharToMultiByte( CP_UTF8, 0, utf16String, ( int ) wcslen( utf16String ), utf8String, (int) size, NULL, NULL);
100
101			err = translate_errno( size != 0, GetLastError(), kUnknownErr );
102
103			require_noerr( err, exit );
104
105
106
107			// have to add the trailing 0 because WideCharToMultiByte doesn't do it,
108
109			// although it does return the correct size
110
111
112
113			utf8String[size] = '\0';
114
115			outString = utf8String;
116
117		}
118	}
119
120
121
122exit:
123
124
125
126	if ( utf8String != NULL )
127
128	{
129
130		delete [] utf8String;
131
132	}
133
134
135
136	return ( !err ) ? TRUE : FALSE;
137
138}
139
140
141
142
143
144extern BOOL
145
146UTF8ToBSTR
147
148	(
149
150	const char	*	inString,
151
152	CComBSTR	&	outString
153
154	)
155
156{
157
158	wchar_t	*	unicode	= NULL;
159
160	OSStatus	err		= 0;
161
162
163
164	if ( inString )
165
166	{
167		int n;
168
169		n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, NULL, 0 );
170
171
172
173		if ( n > 0 )
174
175		{
176
177			try
178
179			{
180
181				unicode = new wchar_t[ n ];
182
183			}
184
185			catch ( ... )
186
187			{
188
189				unicode = NULL;
190
191			}
192
193
194
195			require_action( unicode, exit, err = ERROR_INSUFFICIENT_BUFFER );
196
197
198
199			n = MultiByteToWideChar( CP_UTF8, 0, inString, -1, unicode, n );
200
201		}
202
203
204
205		outString = unicode;
206
207	}
208
209
210exit:
211
212
213
214    if ( unicode != NULL )
215
216    {
217
218        delete [] unicode;
219
220	}
221
222
223
224	return ( !err ) ? TRUE : FALSE;
225
226}
227
228
229
230
231
232BOOL
233
234ByteArrayToVariant
235
236	(
237
238	const void	*	inArray,
239
240	size_t			inArrayLen,
241
242	VARIANT		*	outVariant
243
244	)
245
246{
247
248	LPBYTE			buf	= NULL;
249
250	HRESULT			hr	= 0;
251
252	BOOL			ok	= TRUE;
253
254
255
256	VariantClear( outVariant );
257
258	outVariant->vt		= VT_ARRAY|VT_UI1;
259
260	outVariant->parray	= SafeArrayCreateVector( VT_UI1, 0, ( ULONG ) inArrayLen );
261
262	require_action( outVariant->parray, exit, ok = FALSE );
263
264	hr = SafeArrayAccessData( outVariant->parray, (LPVOID *)&buf );
265
266	require_action( hr == S_OK, exit, ok = FALSE );
267
268	memcpy( buf, inArray, inArrayLen );
269
270	hr = SafeArrayUnaccessData( outVariant->parray );
271
272	require_action( hr == S_OK, exit, ok = FALSE );
273
274
275
276exit:
277
278
279
280	return ok;
281
282}
283
284
285
286
287
288extern BOOL
289
290VariantToByteArray
291	(
292	VARIANT				*	inVariant,
293	std::vector< BYTE >	&	outArray
294	)
295{
296	BOOL ok = TRUE;
297
298	if ( V_VT( inVariant ) == VT_BSTR )
299	{
300		BSTR bstr = V_BSTR( inVariant );
301		std::string utf8;
302
303		BSTRToUTF8( bstr, utf8 );
304
305		outArray.reserve( utf8.size() );
306		outArray.assign( utf8.begin(), utf8.end() );
307	}
308	else if ( V_VT( inVariant ) == VT_ARRAY )
309	{
310		SAFEARRAY	*	psa			= NULL;
311		BYTE		*	pData		= NULL;
312		ULONG			cElements	= 0;
313		HRESULT			hr;
314
315		psa = V_ARRAY( inVariant );
316
317		require_action( psa, exit, ok = FALSE );
318
319		require_action( SafeArrayGetDim( psa ) == 1, exit, ok = FALSE );
320
321		hr = SafeArrayAccessData( psa, ( LPVOID* )&pData );
322
323		require_action( hr == S_OK, exit, ok = FALSE );
324
325		cElements = psa->rgsabound[0].cElements;
326
327		outArray.reserve( cElements );
328
329		outArray.assign( cElements, 0 );
330
331		memcpy( &outArray[ 0 ], pData, cElements );
332
333		SafeArrayUnaccessData( psa );
334	}
335	else
336	{
337		ok = FALSE;
338	}
339
340exit:
341
342	return ok;
343
344}