Return 0 instead of crashing when a NULL source string is passed
[kamenim/samba-autobuild/.git] / source / lib / util_unistr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-2001
5    Copyright (C) Simo Sorce 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 #ifndef MAXUNI
25 #define MAXUNI 1024
26 #endif
27
28 /* these 3 tables define the unicode case handling.  They are loaded
29    at startup either via mmap() or read() from the lib directory */
30 static smb_ucs2_t *upcase_table;
31 static smb_ucs2_t *lowcase_table;
32 static uint8 *valid_table;
33
34
35 /*******************************************************************
36 load the case handling tables
37 ********************************************************************/
38 void load_case_tables(void)
39 {
40         static int initialised;
41         int i;
42
43         if (initialised) return;
44         initialised = 1;
45
46         upcase_table = map_file(lib_path("upcase.dat"), 0x20000);
47         lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000);
48
49         /* we would like Samba to limp along even if these tables are
50            not available */
51         if (!upcase_table) {
52                 DEBUG(1,("creating lame upcase table\n"));
53                 upcase_table = malloc(0x20000);
54                 for (i=0;i<0x10000;i++) {
55                         smb_ucs2_t v;
56                         SSVAL(&v, 0, i);
57                         upcase_table[v] = i;
58                 }
59                 for (i=0;i<256;i++) {
60                         smb_ucs2_t v;
61                         SSVAL(&v, 0, UCS2_CHAR(i));
62                         upcase_table[v] = UCS2_CHAR(islower(i)?toupper(i):i);
63                 }
64         }
65
66         if (!lowcase_table) {
67                 DEBUG(1,("creating lame lowcase table\n"));
68                 lowcase_table = malloc(0x20000);
69                 for (i=0;i<0x10000;i++) {
70                         smb_ucs2_t v;
71                         SSVAL(&v, 0, i);
72                         lowcase_table[v] = i;
73                 }
74                 for (i=0;i<256;i++) {
75                         smb_ucs2_t v;
76                         SSVAL(&v, 0, UCS2_CHAR(i));
77                         lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i);
78                 }
79         }
80 }
81
82 /*
83   see if a ucs2 character can be mapped correctly to a dos character
84   and mapped back to the same character in ucs2
85 */
86 static int check_dos_char(smb_ucs2_t c)
87 {
88         char buf[10];
89         smb_ucs2_t c2 = 0;
90         int len1, len2;
91         len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf));
92         if (len1 == 0) return 0;
93         len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2);
94         if (len2 != 2) return 0;
95         return (c == c2);
96 }
97
98 /*******************************************************************
99 load the valid character map table
100 ********************************************************************/
101 void init_valid_table(void)
102 {
103         static int initialised;
104         static int mapped_file;
105         int i;
106         const char *allowed = ".!#$%&'()_-@^`~";
107
108         if (initialised && mapped_file) return;
109         initialised = 1;
110
111         valid_table = map_file(lib_path("valid.dat"), 0x10000);
112         if (valid_table) {
113                 mapped_file = 1;
114                 return;
115         }
116
117         if (valid_table) free(valid_table);
118
119         DEBUG(2,("creating default valid table\n"));
120         valid_table = malloc(0x10000);
121         for (i=0;i<128;i++) valid_table[i] = isalnum(i) || 
122                                     strchr(allowed,i);
123         for (;i<0x10000;i++) {
124                 smb_ucs2_t c;
125                 SSVAL(&c, 0, i);
126                 valid_table[i] = check_dos_char(c);
127         }
128 }
129
130
131 /*******************************************************************
132  Write a string in (little-endian) unicode format. src is in
133  the current DOS codepage. len is the length in bytes of the
134  string pointed to by dst.
135
136  if null_terminate is True then null terminate the packet (adds 2 bytes)
137
138  the return value is the length in bytes consumed by the string, including the
139  null termination if applied
140 ********************************************************************/
141
142 size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
143 {
144         return push_ucs2(NULL, dst, src, len, 
145                          STR_UNICODE|STR_NOALIGN | (null_terminate?STR_TERMINATE:0));
146 }
147
148
149 /*******************************************************************
150  Skip past a unicode string, but not more than len. Always move
151  past a terminating zero if found.
152 ********************************************************************/
153
154 char *skip_unibuf(char *src, size_t len)
155 {
156     char *srcend = src + len;
157
158     while (src < srcend && SVAL(src,0))
159         src += 2;
160
161     if(!SVAL(src,0))
162         src += 2;
163
164     return src;
165 }
166
167 /* Copy a string from little-endian or big-endian unicode source (depending
168  * on flags) to internal samba format destination
169  */ 
170 int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags)
171 {
172         if (!src) return 0;
173         if(dest_len==-1) dest_len=MAXUNI-3;
174         return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN);
175 }
176
177 /* Copy a string from a unistr2 source to internal samba format
178    destination.  Use this instead of direct calls to rpcstr_pull() to avoid
179    having to determine whether the source string is null terminated. */
180
181 int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
182 {
183         return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring),
184                          src->uni_str_len * 2, 0);
185 }
186
187 /* Converts a string from internal samba format to unicode
188  */ 
189 int rpcstr_push(void* dest, const char *src, int dest_len, int flags)
190 {
191         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
192 }
193
194 /*******************************************************************
195  Return a DOS codepage version of a little-endian unicode string.
196  len is the filename length (ignoring any terminating zero) in uin16
197  units. Always null terminates.
198  Hack alert: uses fixed buffer(s).
199 ********************************************************************/
200 char *dos_unistrn2(const uint16 *src, int len)
201 {
202         static char lbufs[8][MAXUNI];
203         static int nexti;
204         char *lbuf = lbufs[nexti];
205         nexti = (nexti+1)%8;
206         pull_ucs2(NULL, lbuf, src, MAXUNI-3, len*2, STR_NOALIGN);
207         return lbuf;
208 }
209
210 /*******************************************************************
211  Convert a (little-endian) UNISTR2 structure to an ASCII string
212 ********************************************************************/
213 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
214 {
215         if (str == NULL) {
216                 *dest='\0';
217                 return;
218         }
219         pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
220 }
221
222 /*******************************************************************
223 give a static string for displaying a UNISTR2
224 ********************************************************************/
225 const char *unistr2_static(const UNISTR2 *str)
226 {
227         static pstring ret;
228         unistr2_to_ascii(ret, str, sizeof(ret));
229         return ret;
230 }
231
232
233 /*******************************************************************
234  duplicate a UNISTR2 string into a null terminated char*
235  using a talloc context
236 ********************************************************************/
237 char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str)
238 {
239         char *s;
240         int maxlen = (str->uni_str_len+1)*4;
241         if (!str->buffer) return NULL;
242         s = (char *)talloc(ctx, maxlen); /* convervative */
243         if (!s) return NULL;
244         pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, 
245                   STR_NOALIGN);
246         return s;
247 }
248
249
250 /*******************************************************************
251 Return a number stored in a buffer
252 ********************************************************************/
253
254 uint32 buffer2_to_uint32(BUFFER2 *str)
255 {
256         if (str->buf_len == 4)
257                 return IVAL(str->buffer, 0);
258         else
259                 return 0;
260 }
261
262 /*******************************************************************
263  Convert a wchar to upper case.
264 ********************************************************************/
265
266 smb_ucs2_t toupper_w(smb_ucs2_t val)
267 {
268         return upcase_table[SVAL(&val,0)];
269 }
270
271 /*******************************************************************
272  Convert a wchar to lower case.
273 ********************************************************************/
274
275 smb_ucs2_t tolower_w( smb_ucs2_t val )
276 {
277         return lowcase_table[SVAL(&val,0)];
278
279 }
280
281 /*******************************************************************
282 determine if a character is lowercase
283 ********************************************************************/
284 BOOL islower_w(smb_ucs2_t c)
285 {
286         return upcase_table[SVAL(&c,0)] != c;
287 }
288
289 /*******************************************************************
290 determine if a character is uppercase
291 ********************************************************************/
292 BOOL isupper_w(smb_ucs2_t c)
293 {
294         return lowcase_table[SVAL(&c,0)] != c;
295 }
296
297
298 /*******************************************************************
299 determine if a character is valid in a 8.3 name
300 ********************************************************************/
301 BOOL isvalid83_w(smb_ucs2_t c)
302 {
303         return valid_table[SVAL(&c,0)] != 0;
304 }
305
306 /*******************************************************************
307  Count the number of characters in a smb_ucs2_t string.
308 ********************************************************************/
309 size_t strlen_w(const smb_ucs2_t *src)
310 {
311         size_t len;
312
313         for(len = 0; *src++; len++) ;
314
315         return len;
316 }
317
318 /*******************************************************************
319  Count up to max number of characters in a smb_ucs2_t string.
320 ********************************************************************/
321 size_t strnlen_w(const smb_ucs2_t *src, size_t max)
322 {
323         size_t len;
324
325         for(len = 0; *src++ && (len < max); len++) ;
326
327         return len;
328 }
329
330 /*******************************************************************
331 wide strchr()
332 ********************************************************************/
333 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
334 {
335         while (*s != 0) {
336                 if (c == *s) return (smb_ucs2_t *)s;
337                 s++;
338         }
339         if (c == *s) return (smb_ucs2_t *)s;
340
341         return NULL;
342 }
343
344 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
345 {
346         return strchr_w(s, UCS2_CHAR(c));
347 }
348
349 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
350 {
351         const smb_ucs2_t *p = s;
352         int len = strlen_w(s);
353         if (len == 0) return NULL;
354         p += (len - 1);
355         do {
356                 if (c == *p) return (smb_ucs2_t *)p;
357         } while (p-- != s);
358         return NULL;
359 }
360
361 /*******************************************************************
362 wide strstr()
363 ********************************************************************/
364 smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
365 {
366         smb_ucs2_t *r;
367         size_t slen, inslen;
368
369         if (!s || !*s || !ins || !*ins) return NULL;
370         slen = strlen_w(s);
371         inslen = strlen_w(ins);
372         r = (smb_ucs2_t *)s;
373         while ((r = strchr_w(r, *ins))) {
374                 if (strncmp_w(r, ins, inslen) == 0) return r;
375                 r++;
376         }
377         return NULL;
378 }
379
380 /*******************************************************************
381  Convert a string to lower case.
382  return True if any char is converted
383 ********************************************************************/
384 BOOL strlower_w(smb_ucs2_t *s)
385 {
386         BOOL ret = False;
387         while (*s) {
388                 smb_ucs2_t v = tolower_w(*s);
389                 if (v != *s) {
390                         *s = v;
391                         ret = True;
392                 }
393                 s++;
394         }
395         return ret;
396 }
397
398 /*******************************************************************
399  Convert a string to upper case.
400  return True if any char is converted
401 ********************************************************************/
402 BOOL strupper_w(smb_ucs2_t *s)
403 {
404         BOOL ret = False;
405         while (*s) {
406                 smb_ucs2_t v = toupper_w(*s);
407                 if (v != *s) {
408                         *s = v;
409                         ret = True;
410                 }
411                 s++;
412         }
413         return ret;
414 }
415
416 /*******************************************************************
417   convert a string to "normal" form
418 ********************************************************************/
419 void strnorm_w(smb_ucs2_t *s)
420 {
421   extern int case_default;
422   if (case_default == CASE_UPPER)
423     strupper_w(s);
424   else
425     strlower_w(s);
426 }
427
428 int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
429 {
430         while (*b && *a == *b) { a++; b++; }
431         return (*a - *b);
432         /* warning: if *a != *b and both are not 0 we retrun a random
433                 greater or lesser than 0 number not realted to which
434                 string is longer */
435 }
436
437 int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
438 {
439         size_t n = 0;
440         while ((n < len) && *b && *a == *b) { a++; b++; n++;}
441         return (len - n)?(*a - *b):0;   
442 }
443
444 /*******************************************************************
445 case insensitive string comparison
446 ********************************************************************/
447 int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
448 {
449         while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; }
450         return (tolower_w(*a) - tolower_w(*b));
451 }
452
453 /*******************************************************************
454 case insensitive string comparison, lenght limited
455 ********************************************************************/
456 int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
457 {
458         size_t n = 0;
459         while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; }
460         return (len - n)?(tolower_w(*a) - tolower_w(*b)):0;
461 }
462
463 /*******************************************************************
464   compare 2 strings 
465 ********************************************************************/
466 BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
467 {
468         if (s1 == s2) return(True);
469         if (!s1 || !s2) return(False);
470   
471         return(strcasecmp_w(s1,s2)==0);
472 }
473
474 /*******************************************************************
475   compare 2 strings up to and including the nth char.
476   ******************************************************************/
477 BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
478 {
479   if (s1 == s2) return(True);
480   if (!s1 || !s2 || !n) return(False);
481   
482   return(strncasecmp_w(s1,s2,n)==0);
483 }
484
485 /*******************************************************************
486 duplicate string
487 ********************************************************************/
488 smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
489 {
490         return strndup_w(src, 0);
491 }
492
493 /* if len == 0 then duplicate the whole string */
494 smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len)
495 {
496         smb_ucs2_t *dest;
497         
498         if (!len) len = strlen_w(src);
499         dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t));
500         if (!dest) {
501                 DEBUG(0,("strdup_w: out of memory!\n"));
502                 return NULL;
503         }
504
505         memcpy(dest, src, len * sizeof(smb_ucs2_t));
506         dest[len] = 0;
507         
508         return dest;
509 }
510
511 /*******************************************************************
512 copy a string with max len
513 ********************************************************************/
514
515 smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
516 {
517         size_t len;
518         
519         if (!dest || !src) return NULL;
520         
521         for (len = 0; (src[len] != 0) && (len < max); len++)
522                 dest[len] = src[len];
523         while (len < max)
524                 dest[len++] = 0;
525         
526         return dest;
527 }
528
529
530 /*******************************************************************
531 append a string of len bytes and add a terminator
532 ********************************************************************/
533
534 smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
535 {       
536         size_t start;
537         size_t len;     
538         
539         if (!dest || !src) return NULL;
540         
541         start = strlen_w(dest);
542         len = strnlen_w(src, max);
543
544         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
545         dest[start+len] = 0;
546         
547         return dest;
548 }
549
550 smb_ucs2_t *strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src)
551 {       
552         size_t start;
553         size_t len;     
554         
555         if (!dest || !src) return NULL;
556         
557         start = strlen_w(dest);
558         len = strlen_w(src);
559
560         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
561         dest[start+len] = 0;
562         
563         return dest;
564 }
565
566
567 /*******************************************************************
568 replace any occurence of oldc with newc in unicode string
569 ********************************************************************/
570
571 void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
572 {
573         for(;*s;s++) {
574                 if(*s==oldc) *s=newc;
575         }
576 }
577
578 /*******************************************************************
579 trim unicode string
580 ********************************************************************/
581
582 BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
583                                   const smb_ucs2_t *back)
584 {
585         BOOL ret = False;
586         size_t len, front_len, back_len;
587
588         if (!s || !*s) return False;
589
590         len = strlen_w(s);
591
592         if (front && *front) {
593                 front_len = strlen_w(front);
594                 while (len && strncmp_w(s, front, front_len) == 0) {
595                         memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t));
596                         len -= front_len;
597                         ret = True;
598                 }
599         }
600         
601         if (back && *back) {
602                 back_len = strlen_w(back);
603                 while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) {
604                         s[len - back_len] = 0;
605                         len -= back_len;
606                         ret = True;
607                 }
608         }
609
610         return ret;
611 }
612
613 /*
614   The *_wa() functions take a combination of 7 bit ascii
615   and wide characters They are used so that you can use string
616   functions combining C string constants with ucs2 strings
617
618   The char* arguments must NOT be multibyte - to be completely sure
619   of this only pass string constants */
620
621
622 void pstrcpy_wa(smb_ucs2_t *dest, const char *src)
623 {
624         int i;
625         for (i=0;i<PSTRING_LEN;i++) {
626                 dest[i] = UCS2_CHAR(src[i]);
627                 if (src[i] == 0) return;
628         }
629 }
630
631 int strcmp_wa(const smb_ucs2_t *a, const char *b)
632 {
633         while (*b && *a == UCS2_CHAR(*b)) { a++; b++; }
634         return (*a - UCS2_CHAR(*b));
635 }
636
637 int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len)
638 {
639         size_t n = 0;
640         while ((n < len) && *b && *a == UCS2_CHAR(*b)) { a++; b++; n++;}
641         return (len - n)?(*a - UCS2_CHAR(*b)):0;
642 }
643
644 smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
645 {
646         while (*s != 0) {
647                 int i;
648                 for (i=0; p[i] && *s != UCS2_CHAR(p[i]); i++) 
649                         ;
650                 if (p[i]) return (smb_ucs2_t *)s;
651                 s++;
652         }
653         return NULL;
654 }
655
656 smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
657 {
658         smb_ucs2_t *r;
659         size_t slen, inslen;
660
661         if (!s || !*s || !ins || !*ins) return NULL;
662         slen = strlen_w(s);
663         inslen = strlen(ins);
664         r = (smb_ucs2_t *)s;
665         while ((r = strchr_w(r, UCS2_CHAR(*ins)))) {
666                 if (strncmp_wa(r, ins, inslen) == 0) return r;
667                 r++;
668         }
669         return NULL;
670 }
671
672 /*******************************************************************
673 copy a string with max len
674 ********************************************************************/
675
676 smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max)
677 {
678         smb_ucs2_t *ucs2_src;
679
680         if (!dest || !src) return NULL;
681         if (!(ucs2_src = acnv_uxu2(src)))
682                 return NULL;
683         
684         strncpy_w(dest, ucs2_src, max);
685         SAFE_FREE(ucs2_src);
686         return dest;
687 }
688
689 /*******************************************************************
690 convert and duplicate an ascii string
691 ********************************************************************/
692 smb_ucs2_t *strdup_wa(const char *src)
693 {
694         return strndup_wa(src, 0);
695 }
696
697 /* if len == 0 then duplicate the whole string */
698 smb_ucs2_t *strndup_wa(const char *src, size_t len)
699 {
700         smb_ucs2_t *dest, *s;
701
702         s = acnv_dosu2(src);    
703         if (!len) len = strlen_w(s);
704         dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t));
705         if (!dest) {
706                 DEBUG(0,("strdup_w: out of memory!\n"));
707                 SAFE_FREE(s);
708                 return NULL;
709         }
710
711         memcpy(dest, src, len * sizeof(smb_ucs2_t));
712         dest[len] = 0;
713
714         SAFE_FREE(s);
715         return dest;
716 }
717
718 /*******************************************************************
719 append a string of len bytes and add a terminator
720 ********************************************************************/
721
722 smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max)
723 {
724         smb_ucs2_t *ucs2_src;
725
726         if (!dest || !src) return NULL;
727         if (!(ucs2_src = acnv_uxu2(src)))
728                 return NULL;
729         
730         strncat_w(dest, ucs2_src, max);
731         SAFE_FREE(ucs2_src);
732         return dest;
733 }
734
735 smb_ucs2_t *strcat_wa(smb_ucs2_t *dest, const char *src)
736 {       
737         smb_ucs2_t *ucs2_src;
738         
739         if (!dest || !src) return NULL;
740         if (!(ucs2_src = acnv_uxu2(src)))
741                 return NULL;
742         
743         strcat_w(dest, ucs2_src);
744         SAFE_FREE(ucs2_src);
745         return dest;
746 }
747
748 BOOL trim_string_wa(smb_ucs2_t *s, const char *front,
749                                   const char *back)
750 {
751         wpstring f, b;
752
753         if (front) push_ucs2(NULL, f, front, sizeof(wpstring) - 1, STR_TERMINATE);
754         else *f = 0;
755         if (back) push_ucs2(NULL, b, back, sizeof(wpstring) - 1, STR_TERMINATE);
756         else *b = 0;
757         return trim_string_w(s, f, b);
758 }
759
760 /*******************************************************************
761  returns the length in number of wide characters
762  ******************************************************************/
763 int unistrlen(uint16 *s)
764 {
765         int len;
766
767         if (!s)
768                 return -1;
769
770         for (len=0; *s; s++,len++);
771
772         return len;
773 }
774
775 /*******************************************************************
776  Strcpy for unicode strings.  returns length (in num of wide chars)
777 ********************************************************************/
778
779 int unistrcpy(uint16 *dst, uint16 *src)
780 {
781         int num_wchars = 0;
782
783         while (*src) {
784                 *dst++ = *src++;
785                 num_wchars++;
786         }
787         *dst = 0;
788
789         return num_wchars;
790 }
791
792 /**
793  * Samba ucs2 type to UNISTR2 conversion
794  *
795  * @param ctx Talloc context to create the dst strcture (if null) and the 
796  *            contents of the unicode string.
797  * @param dst UNISTR2 destination. If equals null, then it's allocated.
798  * @param src smb_ucs2_t source.
799  * @param max_len maximum number of unicode characters to copy. If equals
800  *        null, then null-termination of src is taken
801  *
802  * @return copied UNISTR2 destination
803  **/
804 UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src)
805 {
806         size_t len;
807
808         if (!src) return NULL;
809         len = strlen_w(src);
810         
811         /* allocate UNISTR2 destination if not given */
812         if (!dst) {
813                 dst = (UNISTR2*) talloc(ctx, sizeof(UNISTR2));
814                 if (!dst) return NULL;
815         }
816         if (!dst->buffer) {
817                 dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1));
818                 if (!dst->buffer) return NULL;
819         }
820         
821         /* set UNISTR2 parameters */
822         dst->uni_max_len = len + 1;
823         dst->undoc = 0;
824         dst->uni_str_len = len;
825         
826         /* copy the actual unicode string */
827         strncpy_w(dst->buffer, src, dst->uni_max_len);
828         
829         return dst;
830 };
831