updated the 3.0 branch from the head branch - ready for alpha18
[nivanova/samba-autobuild/.git] / source3 / 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(dest_len==-1) dest_len=MAXUNI-3;
173         return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN);
174 }
175
176 /* Copy a string from a unistr2 source to internal samba format
177    destination.  Use this instead of direct calls to rpcstr_pull() to avoid
178    having to determine whether the source string is null terminated. */
179
180 int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
181 {
182         return pull_ucs2(NULL, dest, src->buffer, sizeof(fstring),
183                          src->uni_str_len * 2, 0);
184 }
185
186 /* Converts a string from internal samba format to unicode
187  */ 
188 int rpcstr_push(void* dest, const char *src, int dest_len, int flags)
189 {
190         return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
191 }
192
193 /*******************************************************************
194  Return a DOS codepage version of a little-endian unicode string.
195  len is the filename length (ignoring any terminating zero) in uin16
196  units. Always null terminates.
197  Hack alert: uses fixed buffer(s).
198 ********************************************************************/
199 char *dos_unistrn2(const uint16 *src, int len)
200 {
201         static char lbufs[8][MAXUNI];
202         static int nexti;
203         char *lbuf = lbufs[nexti];
204         nexti = (nexti+1)%8;
205         pull_ucs2(NULL, lbuf, src, MAXUNI-3, len*2, STR_NOALIGN);
206         return lbuf;
207 }
208
209 /*******************************************************************
210  Convert a (little-endian) UNISTR2 structure to an ASCII string
211 ********************************************************************/
212 void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
213 {
214         if (str == NULL) {
215                 *dest='\0';
216                 return;
217         }
218         pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
219 }
220
221
222 /*******************************************************************
223  duplicate a UNISTR2 string into a null terminated char*
224  using a talloc context
225 ********************************************************************/
226 char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str)
227 {
228         char *s;
229         int maxlen = (str->uni_str_len+1)*4;
230         if (!str->buffer) return NULL;
231         s = (char *)talloc(ctx, maxlen); /* convervative */
232         if (!s) return NULL;
233         pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, 
234                   STR_NOALIGN);
235         return s;
236 }
237
238
239 /*******************************************************************
240 Return a number stored in a buffer
241 ********************************************************************/
242
243 uint32 buffer2_to_uint32(BUFFER2 *str)
244 {
245         if (str->buf_len == 4)
246                 return IVAL(str->buffer, 0);
247         else
248                 return 0;
249 }
250
251 /*******************************************************************
252  Convert a wchar to upper case.
253 ********************************************************************/
254
255 smb_ucs2_t toupper_w(smb_ucs2_t val)
256 {
257         return upcase_table[SVAL(&val,0)];
258 }
259
260 /*******************************************************************
261  Convert a wchar to lower case.
262 ********************************************************************/
263
264 smb_ucs2_t tolower_w( smb_ucs2_t val )
265 {
266         return lowcase_table[SVAL(&val,0)];
267
268 }
269
270 /*******************************************************************
271 determine if a character is lowercase
272 ********************************************************************/
273 BOOL islower_w(smb_ucs2_t c)
274 {
275         return upcase_table[SVAL(&c,0)] != c;
276 }
277
278 /*******************************************************************
279 determine if a character is uppercase
280 ********************************************************************/
281 BOOL isupper_w(smb_ucs2_t c)
282 {
283         return lowcase_table[SVAL(&c,0)] != c;
284 }
285
286
287 /*******************************************************************
288 determine if a character is valid in a 8.3 name
289 ********************************************************************/
290 BOOL isvalid83_w(smb_ucs2_t c)
291 {
292         return valid_table[SVAL(&c,0)] != 0;
293 }
294
295 /*******************************************************************
296  Count the number of characters in a smb_ucs2_t string.
297 ********************************************************************/
298 size_t strlen_w(const smb_ucs2_t *src)
299 {
300         size_t len;
301
302         for(len = 0; *src++; len++) ;
303
304         return len;
305 }
306
307 /*******************************************************************
308  Count up to max number of characters in a smb_ucs2_t string.
309 ********************************************************************/
310 size_t strnlen_w(const smb_ucs2_t *src, size_t max)
311 {
312         size_t len;
313
314         for(len = 0; *src++ && (len < max); len++) ;
315
316         return len;
317 }
318
319 /*******************************************************************
320 wide strchr()
321 ********************************************************************/
322 smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
323 {
324         while (*s != 0) {
325                 if (c == *s) return (smb_ucs2_t *)s;
326                 s++;
327         }
328         return NULL;
329 }
330
331 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
332 {
333         return strchr_w(s, UCS2_CHAR(c));
334 }
335
336 smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
337 {
338         const smb_ucs2_t *p = s;
339         int len = strlen_w(s);
340         if (len == 0) return NULL;
341         p += (len - 1);
342         do {
343                 if (c == *p) return (smb_ucs2_t *)p;
344         } while (p-- != s);
345         return NULL;
346 }
347
348 /*******************************************************************
349 wide strstr()
350 ********************************************************************/
351 smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
352 {
353         smb_ucs2_t *r;
354         size_t slen, inslen;
355
356         if (!s || !*s || !ins || !*ins) return NULL;
357         slen = strlen_w(s);
358         inslen = strlen_w(ins);
359         r = (smb_ucs2_t *)s;
360         while ((r = strchr_w(r, *ins))) {
361                 if (strncmp_w(r, ins, inslen) == 0) return r;
362                 r++;
363         }
364         return NULL;
365 }
366
367 /*******************************************************************
368  Convert a string to lower case.
369  return True if any char is converted
370 ********************************************************************/
371 BOOL strlower_w(smb_ucs2_t *s)
372 {
373         BOOL ret = False;
374         while (*s) {
375                 smb_ucs2_t v = tolower_w(*s);
376                 if (v != *s) {
377                         *s = v;
378                         ret = True;
379                 }
380                 s++;
381         }
382         return ret;
383 }
384
385 /*******************************************************************
386  Convert a string to upper case.
387  return True if any char is converted
388 ********************************************************************/
389 BOOL strupper_w(smb_ucs2_t *s)
390 {
391         BOOL ret = False;
392         while (*s) {
393                 smb_ucs2_t v = toupper_w(*s);
394                 if (v != *s) {
395                         *s = v;
396                         ret = True;
397                 }
398                 s++;
399         }
400         return ret;
401 }
402
403 /*******************************************************************
404   convert a string to "normal" form
405 ********************************************************************/
406 void strnorm_w(smb_ucs2_t *s)
407 {
408   extern int case_default;
409   if (case_default == CASE_UPPER)
410     strupper_w(s);
411   else
412     strlower_w(s);
413 }
414
415 int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
416 {
417         while (*b && *a == *b) { a++; b++; }
418         return (*a - *b);
419         /* warning: if *a != *b and both are not 0 we retrun a random
420                 greater or lesser than 0 number not realted to which
421                 string is longer */
422 }
423
424 int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
425 {
426         size_t n = 0;
427         while ((n < len) && *b && *a == *b) { a++; b++; n++;}
428         return (len - n)?(*a - *b):0;   
429 }
430
431 /*******************************************************************
432 case insensitive string comparison
433 ********************************************************************/
434 int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
435 {
436         while (*b && toupper_w(*a) == toupper_w(*b)) { a++; b++; }
437         return (tolower_w(*a) - tolower_w(*b));
438 }
439
440 /*******************************************************************
441 case insensitive string comparison, lenght limited
442 ********************************************************************/
443 int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
444 {
445         size_t n = 0;
446         while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; }
447         return (len - n)?(tolower_w(*a) - tolower_w(*b)):0;
448 }
449
450 /*******************************************************************
451   compare 2 strings 
452 ********************************************************************/
453 BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
454 {
455         if (s1 == s2) return(True);
456         if (!s1 || !s2) return(False);
457   
458         return(strcasecmp_w(s1,s2)==0);
459 }
460
461 /*******************************************************************
462   compare 2 strings up to and including the nth char.
463   ******************************************************************/
464 BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
465 {
466   if (s1 == s2) return(True);
467   if (!s1 || !s2 || !n) return(False);
468   
469   return(strncasecmp_w(s1,s2,n)==0);
470 }
471
472 /*******************************************************************
473 duplicate string
474 ********************************************************************/
475 smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
476 {
477         return strndup_w(src, 0);
478 }
479
480 /* if len == 0 then duplicate the whole string */
481 smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len)
482 {
483         smb_ucs2_t *dest;
484         
485         if (!len) len = strlen_w(src);
486         dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t));
487         if (!dest) {
488                 DEBUG(0,("strdup_w: out of memory!\n"));
489                 return NULL;
490         }
491
492         memcpy(dest, src, len * sizeof(smb_ucs2_t));
493         dest[len] = 0;
494         
495         return dest;
496 }
497
498 /*******************************************************************
499 copy a string with max len
500 ********************************************************************/
501
502 smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
503 {
504         size_t len;
505         
506         if (!dest || !src) return NULL;
507         
508         for (len = 0; (src[len] != 0) && (len < max); len++)
509                 dest[len] = src[len];
510         while (len < max)
511                 dest[len++] = 0;
512         
513         return dest;
514 }
515
516
517 /*******************************************************************
518 append a string of len bytes and add a terminator
519 ********************************************************************/
520
521 smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
522 {       
523         size_t start;
524         size_t len;     
525         
526         if (!dest || !src) return NULL;
527         
528         start = strlen_w(dest);
529         len = strnlen_w(src, max);
530
531         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
532         dest[start+len] = 0;
533         
534         return dest;
535 }
536
537 smb_ucs2_t *strcat_w(smb_ucs2_t *dest, const smb_ucs2_t *src)
538 {       
539         size_t start;
540         size_t len;     
541         
542         if (!dest || !src) return NULL;
543         
544         start = strlen_w(dest);
545         len = strlen_w(src);
546
547         memcpy(&dest[start], src, len*sizeof(smb_ucs2_t));                      
548         dest[start+len] = 0;
549         
550         return dest;
551 }
552
553
554 /*******************************************************************
555 replace any occurence of oldc with newc in unicode string
556 ********************************************************************/
557
558 void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
559 {
560         for(;*s;s++) {
561                 if(*s==oldc) *s=newc;
562         }
563 }
564
565 /*******************************************************************
566 trim unicode string
567 ********************************************************************/
568
569 BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
570                                   const smb_ucs2_t *back)
571 {
572         BOOL ret = False;
573         size_t len, front_len, back_len;
574
575         if (!s || !*s) return False;
576
577         len = strlen_w(s);
578
579         if (front && *front) {
580                 front_len = strlen_w(front);
581                 while (len && strncmp_w(s, front, front_len) == 0) {
582                         memmove(s, (s + front_len), (len - front_len + 1) * sizeof(smb_ucs2_t));
583                         len -= front_len;
584                         ret = True;
585                 }
586         }
587         
588         if (back && *back) {
589                 back_len = strlen_w(back);
590                 while (len && strncmp_w((s + (len - back_len)), back, back_len) == 0) {
591                         s[len - back_len] = 0;
592                         len -= back_len;
593                         ret = True;
594                 }
595         }
596
597         return ret;
598 }
599
600 /*
601   The *_wa() functions take a combination of 7 bit ascii
602   and wide characters They are used so that you can use string
603   functions combining C string constants with ucs2 strings
604
605   The char* arguments must NOT be multibyte - to be completely sure
606   of this only pass string constants */
607
608
609 void pstrcpy_wa(smb_ucs2_t *dest, const char *src)
610 {
611         int i;
612         for (i=0;i<PSTRING_LEN;i++) {
613                 dest[i] = UCS2_CHAR(src[i]);
614                 if (src[i] == 0) return;
615         }
616 }
617
618 int strcmp_wa(const smb_ucs2_t *a, const char *b)
619 {
620         while (*b && *a == UCS2_CHAR(*b)) { a++; b++; }
621         return (*a - UCS2_CHAR(*b));
622 }
623
624 int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len)
625 {
626         size_t n = 0;
627         while ((n < len) && *b && *a == UCS2_CHAR(*b)) { a++; b++; n++;}
628         return (len - n)?(*a - UCS2_CHAR(*b)):0;
629 }
630
631 smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
632 {
633         while (*s != 0) {
634                 int i;
635                 for (i=0; p[i] && *s != UCS2_CHAR(p[i]); i++) 
636                         ;
637                 if (p[i]) return (smb_ucs2_t *)s;
638                 s++;
639         }
640         return NULL;
641 }
642
643 smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
644 {
645         smb_ucs2_t *r;
646         size_t slen, inslen;
647
648         if (!s || !*s || !ins || !*ins) return NULL;
649         slen = strlen_w(s);
650         inslen = strlen(ins);
651         r = (smb_ucs2_t *)s;
652         while ((r = strchr_w(r, UCS2_CHAR(*ins)))) {
653                 if (strncmp_wa(r, ins, inslen) == 0) return r;
654                 r++;
655         }
656         return NULL;
657 }
658
659 /*******************************************************************
660 copy a string with max len
661 ********************************************************************/
662
663 smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max)
664 {
665         smb_ucs2_t *ucs2_src;
666
667         if (!dest || !src) return NULL;
668         if (!(ucs2_src = acnv_uxu2(src)))
669                 return NULL;
670         
671         strncpy_w(dest, ucs2_src, max);
672         SAFE_FREE(ucs2_src);
673         return dest;
674 }
675
676 /*******************************************************************
677 convert and duplicate an ascii string
678 ********************************************************************/
679 smb_ucs2_t *strdup_wa(const char *src)
680 {
681         return strndup_wa(src, 0);
682 }
683
684 /* if len == 0 then duplicate the whole string */
685 smb_ucs2_t *strndup_wa(const char *src, size_t len)
686 {
687         smb_ucs2_t *dest, *s;
688
689         s = acnv_dosu2(src);    
690         if (!len) len = strlen_w(s);
691         dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t));
692         if (!dest) {
693                 DEBUG(0,("strdup_w: out of memory!\n"));
694                 SAFE_FREE(s);
695                 return NULL;
696         }
697
698         memcpy(dest, src, len * sizeof(smb_ucs2_t));
699         dest[len] = 0;
700
701         SAFE_FREE(s);
702         return dest;
703 }
704
705 /*******************************************************************
706 append a string of len bytes and add a terminator
707 ********************************************************************/
708
709 smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max)
710 {
711         smb_ucs2_t *ucs2_src;
712
713         if (!dest || !src) return NULL;
714         if (!(ucs2_src = acnv_uxu2(src)))
715                 return NULL;
716         
717         strncat_w(dest, ucs2_src, max);
718         SAFE_FREE(ucs2_src);
719         return dest;
720 }
721
722 smb_ucs2_t *strcat_wa(smb_ucs2_t *dest, const char *src)
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         strcat_w(dest, ucs2_src);
731         SAFE_FREE(ucs2_src);
732         return dest;
733 }
734
735 BOOL trim_string_wa(smb_ucs2_t *s, const char *front,
736                                   const char *back)
737 {
738         wpstring f, b;
739
740         if (front) push_ucs2(NULL, f, front, sizeof(wpstring) - 1, STR_TERMINATE);
741         else *f = 0;
742         if (back) push_ucs2(NULL, b, back, sizeof(wpstring) - 1, STR_TERMINATE);
743         else *b = 0;
744         return trim_string_w(s, f, b);
745 }
746
747 /*******************************************************************
748  returns the length in number of wide characters
749  ******************************************************************/
750 int unistrlen(uint16 *s)
751 {
752         int len;
753
754         if (!s)
755                 return -1;
756
757         for (len=0; *s; s++,len++);
758
759         return len;
760 }
761
762 /*******************************************************************
763  Strcpy for unicode strings.  returns length (in num of wide chars)
764 ********************************************************************/
765
766 int unistrcpy(uint16 *dst, uint16 *src)
767 {
768         int num_wchars = 0;
769
770         while (*src) {
771                 *dst++ = *src++;
772                 num_wchars++;
773         }
774         *dst = 0;
775
776         return num_wchars;
777 }
778
779 /**
780  * Samba ucs2 type to UNISTR2 conversion
781  *
782  * @param ctx Talloc context to create the dst strcture (if null) and the 
783  *            contents of the unicode string.
784  * @param dst UNISTR2 destination. If equals null, then it's allocated.
785  * @param src smb_ucs2_t source.
786  * @param max_len maximum number of unicode characters to copy. If equals
787  *        null, then null-termination of src is taken
788  *
789  * @return copied UNISTR2 destination
790  **/
791 UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src)
792 {
793         size_t len;
794
795         if (!src) return NULL;
796         len = strlen_w(src);
797         
798         /* allocate UNISTR2 destination if not given */
799         if (!dst) {
800                 dst = (UNISTR2*) talloc(ctx, sizeof(UNISTR2));
801                 if (!dst) return NULL;
802         }
803         if (!dst->buffer) {
804                 dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1));
805                 if (!dst->buffer) return NULL;
806         }
807         
808         /* set UNISTR2 parameters */
809         dst->uni_max_len = len + 1;
810         dst->undoc = 0;
811         dst->uni_str_len = len;
812         
813         /* copy the actual unicode string */
814         strncpy_w(dst->buffer, src, dst->uni_max_len);
815         
816         return dst;
817 };
818