Now that Volker fixed the real issues with ldapsam and adding null attributes
[Samba.git] / source / lib / charcnv.c
blob7acb7147fd64f0d4fb48faab39adf43e6e8652f7
1 /*
2 Unix SMB/CIFS implementation.
3 Character set conversion Extensions
4 Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5 Copyright (C) Andrew Tridgell 2001
6 Copyright (C) Simo Sorce 2001
7 Copyright (C) Martin Pool 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 /**
27 * @file
29 * @brief Character-set conversion routines built on our iconv.
31 * @note Samba's internal character set (at least in the 3.0 series)
32 * is always the same as the one for the Unix filesystem. It is
33 * <b>not</b> necessarily UTF-8 and may be different on machines that
34 * need i18n filenames to be compatible with Unix software. It does
35 * have to be a superset of ASCII. All multibyte sequences must start
36 * with a byte with the high bit set.
38 * @sa lib/iconv.c
42 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
45 /**
46 * Return the name of a charset to give to iconv().
47 **/
48 static const char *charset_name(charset_t ch)
50 const char *ret = NULL;
52 if (ch == CH_UCS2) ret = "UCS-2LE";
53 else if (ch == CH_UNIX) ret = lp_unix_charset();
54 else if (ch == CH_DOS) ret = lp_dos_charset();
55 else if (ch == CH_DISPLAY) ret = lp_display_charset();
56 else if (ch == CH_UTF8) ret = "UTF8";
58 if (!ret || !*ret) ret = "ASCII";
59 return ret;
62 void lazy_initialize_conv(void)
64 static int initialized = False;
66 if (!initialized) {
67 initialized = True;
68 load_case_tables();
69 init_iconv();
73 /**
74 * Initialize iconv conversion descriptors.
76 * This is called the first time it is needed, and also called again
77 * every time the configuration is reloaded, because the charset or
78 * codepage might have changed.
79 **/
80 void init_iconv(void)
82 int c1, c2;
83 BOOL did_reload = False;
85 /* so that charset_name() works we need to get the UNIX<->UCS2 going
86 first */
87 if (!conv_handles[CH_UNIX][CH_UCS2])
88 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
90 if (!conv_handles[CH_UCS2][CH_UNIX])
91 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
93 for (c1=0;c1<NUM_CHARSETS;c1++) {
94 for (c2=0;c2<NUM_CHARSETS;c2++) {
95 const char *n1 = charset_name((charset_t)c1);
96 const char *n2 = charset_name((charset_t)c2);
97 if (conv_handles[c1][c2] &&
98 strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
99 strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
100 continue;
102 did_reload = True;
104 if (conv_handles[c1][c2])
105 smb_iconv_close(conv_handles[c1][c2]);
107 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
108 if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
109 DEBUG(0,("Conversion from %s to %s not supported\n",
110 charset_name((charset_t)c1), charset_name((charset_t)c2)));
111 conv_handles[c1][c2] = NULL;
116 if (did_reload) {
117 /* XXX: Does this really get called every time the dos
118 * codepage changes? */
119 /* XXX: Is the did_reload test too strict? */
120 init_doschar_table();
121 init_valid_table();
126 * Convert string from one encoding to another, making error checking etc
128 * @param src pointer to source string (multibyte or singlebyte)
129 * @param srclen length of the source string in bytes
130 * @param dest pointer to destination string (multibyte or singlebyte)
131 * @param destlen maximal length allowed for string
132 * @returns the number of bytes occupied in the destination
134 size_t convert_string(charset_t from, charset_t to,
135 void const *src, size_t srclen,
136 void *dest, size_t destlen)
138 size_t i_len, o_len;
139 size_t retval;
140 const char* inbuf = (const char*)src;
141 char* outbuf = (char*)dest;
142 smb_iconv_t descriptor;
144 if (srclen == (size_t)-1)
145 srclen = strlen(src)+1;
147 lazy_initialize_conv();
149 descriptor = conv_handles[from][to];
151 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
152 /* conversion not supported, use as is */
153 size_t len = MIN(srclen,destlen);
154 memcpy(dest,src,len);
155 return len;
158 i_len=srclen;
159 o_len=destlen;
160 retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
161 if(retval==(size_t)-1) {
162 const char *reason="unknown error";
163 switch(errno) {
164 case EINVAL:
165 reason="Incomplete multibyte sequence";
166 break;
167 case E2BIG:
168 reason="No more room";
169 DEBUG(0, ("convert_string: Required %d, available %d\n",
170 srclen, destlen));
171 /* we are not sure we need srclen bytes,
172 may be more, may be less.
173 We only know we need more than destlen
174 bytes ---simo */
175 break;
176 case EILSEQ:
177 reason="Illegal multibyte sequence";
178 break;
180 /* smb_panic(reason); */
182 return destlen-o_len;
186 * Convert between character sets, allocating a new buffer for the result.
188 * @param srclen length of source buffer.
189 * @param dest always set at least to NULL
190 * @note -1 is not accepted for srclen.
192 * @returns Size in bytes of the converted string; or -1 in case of error.
195 size_t convert_string_allocate(charset_t from, charset_t to,
196 void const *src, size_t srclen, void **dest)
198 size_t i_len, o_len, destlen;
199 size_t retval;
200 const char *inbuf = (const char *)src;
201 char *outbuf, *ob;
202 smb_iconv_t descriptor;
204 *dest = NULL;
206 if (src == NULL || srclen == (size_t)-1)
207 return (size_t)-1;
209 lazy_initialize_conv();
211 descriptor = conv_handles[from][to];
213 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
214 /* conversion not supported, return -1*/
215 DEBUG(3, ("convert_string_allocate: conversion not supported!\n"));
216 return -1;
219 destlen = MAX(srclen, 512);
220 outbuf = NULL;
221 convert:
222 destlen = destlen * 2;
223 ob = (char *)Realloc(outbuf, destlen);
224 if (!ob) {
225 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
226 SAFE_FREE(outbuf);
227 return (size_t)-1;
228 } else {
229 outbuf = ob;
231 i_len = srclen;
232 o_len = destlen;
233 retval = smb_iconv(descriptor,
234 &inbuf, &i_len,
235 &outbuf, &o_len);
236 if(retval == (size_t)-1) {
237 const char *reason="unknown error";
238 switch(errno) {
239 case EINVAL:
240 reason="Incomplete multibyte sequence";
241 break;
242 case E2BIG:
243 goto convert;
244 case EILSEQ:
245 reason="Illegal multibyte sequence";
246 break;
248 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
249 /* smb_panic(reason); */
250 return (size_t)-1;
253 destlen = destlen - o_len;
254 *dest = (char *)Realloc(ob,destlen);
255 if (!*dest) {
256 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
257 SAFE_FREE(ob);
258 return (size_t)-1;
261 return destlen;
266 * Convert between character sets, allocating a new buffer using talloc for the result.
268 * @param srclen length of source buffer.
269 * @param dest always set at least to NULL
270 * @note -1 is not accepted for srclen.
272 * @returns Size in bytes of the converted string; or -1 in case of error.
274 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
275 void const *src, size_t srclen, void **dest)
277 void *alloced_string;
278 size_t dest_len;
280 /* FIXME: Ridiculous to allocate two buffers and then copy the string! */
282 *dest = NULL;
283 dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
284 if (dest_len == (size_t)-1)
285 return (size_t)-1;
286 *dest = talloc_memdup(ctx, alloced_string, dest_len);
287 SAFE_FREE(alloced_string);
288 if (*dest == NULL)
289 return (size_t)-1;
290 return dest_len;
293 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
295 size_t size;
296 smb_ucs2_t *buffer;
298 size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
299 (void **) &buffer);
300 if (size == -1) {
301 smb_panic("failed to create UCS2 buffer");
303 if (!strupper_w(buffer) && (dest == src)) {
304 free(buffer);
305 return srclen;
308 size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
309 free(buffer);
310 return size;
313 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
315 size_t size;
316 smb_ucs2_t *buffer;
318 size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
319 (void **) &buffer);
320 if (size == -1) {
321 smb_panic("failed to create UCS2 buffer");
323 if (!strlower_w(buffer) && (dest == src)) {
324 free(buffer);
325 return srclen;
327 size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
328 free(buffer);
329 return size;
333 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
335 if (flags & (STR_NOALIGN|STR_ASCII))
336 return 0;
337 return PTR_DIFF(p, base_ptr) & 1;
342 * Copy a string from a char* unix src to a dos codepage string destination.
344 * @return the number of bytes occupied by the string in the destination.
346 * @param flags can include
347 * <dl>
348 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
349 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
350 * </dl>
352 * @param dest_len the maximum length in bytes allowed in the
353 * destination. If @p dest_len is -1 then no maximum is used.
355 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
357 size_t src_len = strlen(src);
358 pstring tmpbuf;
360 /* treat a pstring as "unlimited" length */
361 if (dest_len == (size_t)-1)
362 dest_len = sizeof(pstring);
364 if (flags & STR_UPPER) {
365 pstrcpy(tmpbuf, src);
366 strupper(tmpbuf);
367 src = tmpbuf;
370 if (flags & STR_TERMINATE)
371 src_len++;
373 return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
376 size_t push_ascii_fstring(void *dest, const char *src)
378 return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
381 size_t push_ascii_pstring(void *dest, const char *src)
383 return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
387 * Copy a string from a dos codepage source to a unix char* destination.
389 * The resulting string in "dest" is always null terminated.
391 * @param flags can have:
392 * <dl>
393 * <dt>STR_TERMINATE</dt>
394 * <dd>STR_TERMINATE means the string in @p src
395 * is null terminated, and src_len is ignored.</dd>
396 * </dl>
398 * @param src_len is the length of the source area in bytes.
399 * @returns the number of bytes occupied by the string in @p src.
401 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
403 size_t ret;
405 if (dest_len == (size_t)-1)
406 dest_len = sizeof(pstring);
408 if (flags & STR_TERMINATE) {
409 if (src_len == (size_t)-1) {
410 src_len = strlen(src) + 1;
411 } else {
412 size_t len = strnlen(src, src_len);
413 if (len < src_len)
414 len++;
415 src_len = len;
419 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
421 if (dest_len)
422 dest[MIN(ret, dest_len-1)] = 0;
424 return src_len;
427 size_t pull_ascii_pstring(char *dest, const void *src)
429 return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
432 size_t pull_ascii_fstring(char *dest, const void *src)
434 return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
438 * Copy a string from a char* src to a unicode destination.
440 * @returns the number of bytes occupied by the string in the destination.
442 * @param flags can have:
444 * <dl>
445 * <dt>STR_TERMINATE <dd>means include the null termination.
446 * <dt>STR_UPPER <dd>means uppercase in the destination.
447 * <dt>STR_NOALIGN <dd>means don't do alignment.
448 * </dl>
450 * @param dest_len is the maximum length allowed in the
451 * destination. If dest_len is -1 then no maxiumum is used.
453 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
455 size_t len=0;
456 size_t src_len = strlen(src);
457 pstring tmpbuf;
459 /* treat a pstring as "unlimited" length */
460 if (dest_len == (size_t)-1)
461 dest_len = sizeof(pstring);
463 if (flags & STR_UPPER) {
464 pstrcpy(tmpbuf, src);
465 strupper(tmpbuf);
466 src = tmpbuf;
469 if (flags & STR_TERMINATE)
470 src_len++;
472 if (ucs2_align(base_ptr, dest, flags)) {
473 *(char *)dest = 0;
474 dest = (void *)((char *)dest + 1);
475 if (dest_len) dest_len--;
476 len++;
479 /* ucs2 is always a multiple of 2 bytes */
480 dest_len &= ~1;
482 len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
483 return len;
488 * Copy a string from a unix char* src to a UCS2 destination,
489 * allocating a buffer using talloc().
491 * @param dest always set at least to NULL
493 * @returns The number of bytes occupied by the string in the destination
494 * or -1 in case of error.
496 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
498 size_t src_len = strlen(src)+1;
500 *dest = NULL;
501 return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
506 * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
508 * @param dest always set at least to NULL
510 * @returns The number of bytes occupied by the string in the destination
511 * or -1 in case of error.
514 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
516 size_t src_len = strlen(src)+1;
518 *dest = NULL;
519 return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
523 Copy a string from a char* src to a UTF-8 destination.
524 Return the number of bytes occupied by the string in the destination
525 Flags can have:
526 STR_TERMINATE means include the null termination
527 STR_UPPER means uppercase in the destination
528 dest_len is the maximum length allowed in the destination. If dest_len
529 is -1 then no maxiumum is used.
532 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
534 size_t src_len = strlen(src);
535 pstring tmpbuf;
537 /* treat a pstring as "unlimited" length */
538 if (dest_len == (size_t)-1)
539 dest_len = sizeof(pstring);
541 if (flags & STR_UPPER) {
542 pstrcpy(tmpbuf, src);
543 strupper(tmpbuf);
544 src = tmpbuf;
547 if (flags & STR_TERMINATE)
548 src_len++;
550 return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
553 size_t push_utf8_fstring(void *dest, const char *src)
555 return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
559 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
561 * @param dest always set at least to NULL
563 * @returns The number of bytes occupied by the string in the destination
566 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
568 size_t src_len = strlen(src)+1;
570 *dest = NULL;
571 return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
575 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
577 * @param dest always set at least to NULL
579 * @returns The number of bytes occupied by the string in the destination
582 size_t push_utf8_allocate(char **dest, const char *src)
584 size_t src_len = strlen(src)+1;
586 *dest = NULL;
587 return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
591 Copy a string from a ucs2 source to a unix char* destination.
592 Flags can have:
593 STR_TERMINATE means the string in src is null terminated.
594 STR_NOALIGN means don't try to align.
595 if STR_TERMINATE is set then src_len is ignored if it is -1.
596 src_len is the length of the source area in bytes
597 Return the number of bytes occupied by the string in src.
598 The resulting string in "dest" is always null terminated.
601 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
603 size_t ret;
605 if (dest_len == (size_t)-1)
606 dest_len = sizeof(pstring);
608 if (ucs2_align(base_ptr, src, flags)) {
609 src = (const void *)((const char *)src + 1);
610 if (src_len > 0)
611 src_len--;
614 if (flags & STR_TERMINATE) {
615 if (src_len == (size_t)-1) {
616 src_len = strlen_w(src)*2 + 2;
617 } else {
618 size_t len = strnlen_w(src, src_len/2);
619 if (len < src_len/2)
620 len++;
621 src_len = len*2;
625 /* ucs2 is always a multiple of 2 bytes */
626 if (src_len != (size_t)-1)
627 src_len &= ~1;
629 ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
630 if (dest_len)
631 dest[MIN(ret, dest_len-1)] = 0;
633 return src_len;
636 size_t pull_ucs2_pstring(char *dest, const void *src)
638 return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
641 size_t pull_ucs2_fstring(char *dest, const void *src)
643 return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
647 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
649 * @param dest always set at least to NULL
651 * @returns The number of bytes occupied by the string in the destination
654 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
656 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
657 *dest = NULL;
658 return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
662 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
664 * @param dest always set at least to NULL
666 * @returns The number of bytes occupied by the string in the destination
669 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
671 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
672 *dest = NULL;
673 return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
677 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
679 * @param dest always set at least to NULL
681 * @returns The number of bytes occupied by the string in the destination
684 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
686 size_t src_len = strlen(src)+1;
687 *dest = NULL;
688 return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
692 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
694 * @param dest always set at least to NULL
696 * @returns The number of bytes occupied by the string in the destination
699 size_t pull_utf8_allocate(void **dest, const char *src)
701 size_t src_len = strlen(src)+1;
702 *dest = NULL;
703 return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);
707 Copy a string from a char* src to a unicode or ascii
708 dos codepage destination choosing unicode or ascii based on the
709 flags in the SMB buffer starting at base_ptr.
710 Return the number of bytes occupied by the string in the destination.
711 flags can have:
712 STR_TERMINATE means include the null termination.
713 STR_UPPER means uppercase in the destination.
714 STR_ASCII use ascii even with unicode packet.
715 STR_NOALIGN means don't do alignment.
716 dest_len is the maximum length allowed in the destination. If dest_len
717 is -1 then no maxiumum is used.
720 size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
722 if (dest_len != (size_t)-1)
723 clobber_region(function, line, dest, dest_len);
725 if (!(flags & STR_ASCII) && \
726 ((flags & STR_UNICODE || \
727 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
728 return push_ucs2(base_ptr, dest, src, dest_len, flags);
730 return push_ascii(dest, src, dest_len, flags);
735 Copy a string from a unicode or ascii source (depending on
736 the packet flags) to a char* destination.
737 Flags can have:
738 STR_TERMINATE means the string in src is null terminated.
739 STR_UNICODE means to force as unicode.
740 STR_ASCII use ascii even with unicode packet.
741 STR_NOALIGN means don't do alignment.
742 if STR_TERMINATE is set then src_len is ignored is it is -1
743 src_len is the length of the source area in bytes.
744 Return the number of bytes occupied by the string in src.
745 The resulting string in "dest" is always null terminated.
748 size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
750 if (dest_len != (size_t)-1)
751 clobber_region(function, line, dest, dest_len);
753 if (!(flags & STR_ASCII) && \
754 ((flags & STR_UNICODE || \
755 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
756 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
758 return pull_ascii(dest, src, dest_len, src_len, flags);
761 size_t align_string(const void *base_ptr, const char *p, int flags)
763 if (!(flags & STR_ASCII) && \
764 ((flags & STR_UNICODE || \
765 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
766 return ucs2_align(base_ptr, p, flags);
768 return 0;
772 Convert from unix to ucs2 charset and return the
773 allocated and converted string or NULL if an error occurred.
774 You must provide a zero terminated string.
775 The returning string will be zero terminated.
778 smb_ucs2_t *acnv_uxu2(const char *src)
780 size_t slen;
781 size_t dlen;
782 void *dest;
784 slen = strlen(src) + 1;
785 dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest);
786 if (dlen == (size_t)-1)
787 return NULL;
788 else
789 return dest;
793 Convert from dos to ucs2 charset and return the
794 allocated and converted string or NULL if an error occurred.
795 You must provide a zero terminated string.
796 The returning string will be zero terminated.
799 smb_ucs2_t *acnv_dosu2(const char *src)
801 size_t slen;
802 size_t dlen;
803 void *dest;
805 slen = strlen(src) + 1;
806 dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest);
807 if (dlen == (size_t)-1)
808 return NULL;
809 else
810 return dest;