r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text
[kai/samba.git] / source3 / librpc / ndr / ndr_string.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    routines for marshalling/unmarshalling string types
5
6    Copyright (C) Andrew Tridgell 2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23
24 /**
25   pull a general string from the wire
26 */
27 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
28 {
29         char *as=NULL;
30         uint32_t len1, ofs, len2;
31         uint16_t len3;
32         int ret;
33         charset_t chset = CH_UTF16LE;
34         unsigned byte_mul = 2;
35         unsigned flags = ndr->flags;
36         unsigned c_len_term = 0;
37
38         if (!(ndr_flags & NDR_SCALARS)) {
39                 return NT_STATUS_OK;
40         }
41
42         if (NDR_BE(ndr)) {
43                 chset = CH_UTF16BE;
44         }
45
46         if (flags & LIBNDR_FLAG_STR_ASCII) {
47                 chset = CH_DOS;
48                 byte_mul = 1;
49                 flags &= ~LIBNDR_FLAG_STR_ASCII;
50         }
51
52         if (flags & LIBNDR_FLAG_STR_UTF8) {
53                 chset = CH_UTF8;
54                 byte_mul = 1;
55                 flags &= ~LIBNDR_FLAG_STR_UTF8;
56         }
57
58         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
59         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
60                 c_len_term = 1;
61                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
62         }
63
64         switch (flags & LIBNDR_STRING_FLAGS) {
65         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
66         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
67                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
68                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
69                 if (ofs != 0) {
70                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
71                                               ndr->flags & LIBNDR_STRING_FLAGS);
72                 }
73                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
74                 if (len2 > len1) {
75                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
76                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
77                                               len1, ofs, len2);
78                 }
79                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
80                 if (len2 == 0) {
81                         as = talloc_strdup(ndr->current_mem_ctx, "");
82                 } else {
83                         ret = convert_string_talloc(ndr->current_mem_ctx,
84                                                     chset, CH_UNIX, 
85                                                     ndr->data+ndr->offset, 
86                                                     (len2 + c_len_term)*byte_mul,
87                                                     &as, True);
88                         if (ret == -1) {
89                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
90                                                       "Bad character conversion");
91                         }
92                 }
93                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
94
95                 if (len1 != len2) {
96                         DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
97                 }
98
99                 /* this is a way of detecting if a string is sent with the wrong
100                    termination */
101                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
102                         if (strlen(as) < (len2 + c_len_term)) {
103                                 DEBUG(6,("short string '%s'\n", as));
104                         }
105                 } else {
106                         if (strlen(as) == (len2 + c_len_term)) {
107                                 DEBUG(6,("long string '%s'\n", as));
108                         }
109                 }
110                 *s = as;
111                 break;
112
113         case LIBNDR_FLAG_STR_SIZE4:
114         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
115                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
116                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
117                 if (len1 == 0) {
118                         as = talloc_strdup(ndr->current_mem_ctx, "");
119                 } else {
120                         ret = convert_string_talloc(ndr->current_mem_ctx,
121                                                     chset, CH_UNIX, 
122                                                     ndr->data+ndr->offset, 
123                                                     (len1 + c_len_term)*byte_mul,
124                                                     &as, False);
125                         if (ret == -1) {
126                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
127                                                       "Bad character conversion");
128                         }
129                 }
130                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
131
132                 /* this is a way of detecting if a string is sent with the wrong
133                    termination */
134                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
135                         if (strlen(as) < (len1 + c_len_term)) {
136                                 DEBUG(6,("short string '%s'\n", as));
137                         }
138                 } else {
139                         if (strlen(as) == (len1 + c_len_term)) {
140                                 DEBUG(6,("long string '%s'\n", as));
141                         }
142                 }
143                 *s = as;
144                 break;
145
146         case LIBNDR_FLAG_STR_LEN4:
147         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
148                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
149                 if (ofs != 0) {
150                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
151                                               ndr->flags & LIBNDR_STRING_FLAGS);
152                 }
153                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
154                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
155                 if (len1 == 0) {
156                         as = talloc_strdup(ndr->current_mem_ctx, "");
157                 } else {
158                         ret = convert_string_talloc(ndr->current_mem_ctx,
159                                                     chset, CH_UNIX, 
160                                                     ndr->data+ndr->offset, 
161                                                     (len1 + c_len_term)*byte_mul,
162                                                     &as, False);
163                         if (ret == -1) {
164                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
165                                                       "Bad character conversion");
166                         }
167                 }
168                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
169
170                 /* this is a way of detecting if a string is sent with the wrong
171                    termination */
172                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
173                         if (strlen(as) < (len1 + c_len_term)) {
174                                 DEBUG(6,("short string '%s'\n", as));
175                         }
176                 } else {
177                         if (strlen(as) == (len1 + c_len_term)) {
178                                 DEBUG(6,("long string '%s'\n", as));
179                         }
180                 }
181                 *s = as;
182                 break;
183
184
185         case LIBNDR_FLAG_STR_SIZE2:
186         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
187                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
188                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
189                 if (len3 == 0) {
190                         as = talloc_strdup(ndr->current_mem_ctx, "");
191                 } else {
192                         ret = convert_string_talloc(ndr->current_mem_ctx,
193                                                     chset, CH_UNIX, 
194                                                     ndr->data+ndr->offset, 
195                                                     (len3 + c_len_term)*byte_mul,
196                                                     &as, False);
197                         if (ret == -1) {
198                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
199                                                       "Bad character conversion");
200                         }
201                 }
202                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
203
204                 /* this is a way of detecting if a string is sent with the wrong
205                    termination */
206                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
207                         if (strlen(as) < (len3 + c_len_term)) {
208                                 DEBUG(6,("short string '%s'\n", as));
209                         }
210                 } else {
211                         if (strlen(as) == (len3 + c_len_term)) {
212                                 DEBUG(6,("long string '%s'\n", as));
213                         }
214                 }
215                 *s = as;
216                 break;
217
218         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
219                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
220                 NDR_PULL_NEED_BYTES(ndr, len3);
221                 if (len3 == 0) {
222                         as = talloc_strdup(ndr->current_mem_ctx, "");
223                 } else {
224                         ret = convert_string_talloc(ndr->current_mem_ctx,
225                                                     chset, CH_UNIX, 
226                                                     ndr->data+ndr->offset, 
227                                                     len3, &as, False);
228                         if (ret == -1) {
229                                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
230                                                       "Bad character conversion");
231                         }
232                 }
233                 NDR_CHECK(ndr_pull_advance(ndr, len3));
234                 *s = as;
235                 break;
236
237         case LIBNDR_FLAG_STR_NULLTERM:
238                 if (byte_mul == 1) {
239                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
240                 } else {
241                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
242                 }
243                 ret = convert_string_talloc(ndr->current_mem_ctx,
244                                             chset, CH_UNIX, 
245                                             ndr->data+ndr->offset, 
246                                             len1, &as, False);
247                 if (ret == -1) {
248                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
249                                               "Bad character conversion");
250                 }
251                 NDR_CHECK(ndr_pull_advance(ndr, len1));
252                 *s = as;
253                 break;
254
255         case LIBNDR_FLAG_STR_FIXLEN15:
256         case LIBNDR_FLAG_STR_FIXLEN32:
257                 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
258                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
259                 ret = convert_string_talloc(ndr->current_mem_ctx,
260                                             chset, CH_UNIX, 
261                                             ndr->data+ndr->offset, 
262                                             len1*byte_mul, &as, False);
263                 if (ret == -1) {
264                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
265                                               "Bad character conversion");
266                 }
267                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
268                 *s = as;
269                 break;
270
271         default:
272                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
273                                       ndr->flags & LIBNDR_STRING_FLAGS);
274         }
275
276         return NT_STATUS_OK;
277 }
278
279
280 /**
281   push a general string onto the wire
282 */
283 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
284 {
285         ssize_t s_len, c_len, d_len;
286         charset_t chset = CH_UTF16LE;
287         unsigned flags = ndr->flags;
288         unsigned byte_mul = 2;
289         uint8_t *dest = NULL;
290
291         if (!(ndr_flags & NDR_SCALARS)) {
292                 return NT_STATUS_OK;
293         }
294
295         if (NDR_BE(ndr)) {
296                 chset = CH_UTF16BE;
297         }
298         
299         s_len = s?strlen(s):0;
300
301         if (flags & LIBNDR_FLAG_STR_ASCII) {
302                 chset = CH_DOS;
303                 byte_mul = 1;
304                 flags &= ~LIBNDR_FLAG_STR_ASCII;
305         }
306
307         if (flags & LIBNDR_FLAG_STR_UTF8) {
308                 chset = CH_UTF8;
309                 byte_mul = 1;
310                 flags &= ~LIBNDR_FLAG_STR_UTF8;
311         }
312
313         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
314
315         if (!(flags & 
316               (LIBNDR_FLAG_STR_NOTERM |
317                LIBNDR_FLAG_STR_FIXLEN15 |
318                LIBNDR_FLAG_STR_FIXLEN32))) {
319                 s_len++;
320         }
321         d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest,
322                                       False);
323         if (d_len == -1) {
324                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
325                                       "Bad character conversion");
326         }
327
328         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
329                 c_len = d_len;
330                 flags &= ~LIBNDR_FLAG_STR_BYTESIZE;
331         } else if (flags & LIBNDR_FLAG_STR_CHARLEN) {
332                 c_len = (d_len / byte_mul)-1;
333                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
334         } else {
335                 c_len = d_len / byte_mul;
336         }
337
338         switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) {
339         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
340                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
341                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
342                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
343                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
344                 break;
345
346         case LIBNDR_FLAG_STR_LEN4:
347                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
348                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
349                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
350                 break;
351
352         case LIBNDR_FLAG_STR_SIZE4:
353                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
354                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
355                 break;
356
357         case LIBNDR_FLAG_STR_SIZE2:
358                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len));
359                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
360                 break;
361
362         case LIBNDR_FLAG_STR_NULLTERM:
363                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
364                 break;
365
366         case LIBNDR_FLAG_STR_FIXLEN15:
367         case LIBNDR_FLAG_STR_FIXLEN32: {
368                 ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
369                 uint32_t pad_len = fix_len - d_len;
370                 if (d_len > fix_len) {
371                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
372                                               "Bad character conversion");
373                 }
374                 NDR_CHECK(ndr_push_bytes(ndr, dest, d_len));
375                 if (pad_len != 0) {
376                         NDR_CHECK(ndr_push_zero(ndr, pad_len));
377                 }
378                 break;
379         }
380
381         default:
382                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
383                                       ndr->flags & LIBNDR_STRING_FLAGS);
384         }
385
386         talloc_free(dest);
387
388         return NT_STATUS_OK;
389 }
390
391 /**
392   push a general string onto the wire
393 */
394 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
395 {
396         size_t c_len;
397         unsigned flags = ndr->flags;
398         unsigned byte_mul = 2;
399         unsigned c_len_term = 1;
400
401         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
402                 return 32;
403         }
404         if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
405                 return 15;
406         }
407         
408         c_len = s?strlen(s):0;
409
410         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
411                 byte_mul = 1;
412         }
413
414         if (flags & LIBNDR_FLAG_STR_NOTERM) {
415                 c_len_term = 0;
416         }
417
418         c_len = c_len + c_len_term;
419
420         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
421                 c_len = c_len * byte_mul;
422         }
423
424         return c_len;
425 }
426
427 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
428 {
429         if (s) {
430                 ndr->print(ndr, "%-25s: '%s'", name, s);
431         } else {
432                 ndr->print(ndr, "%-25s: NULL", name);
433         }
434 }
435
436 uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
437 {
438         /* FIXME: Is this correct for all strings ? */
439         if(!(*string)) return ret;
440         return ret+strlen(*string)+1;
441 }
442
443 /**
444   pull a general string array from the wire
445 */
446 NTSTATUS ndr_pull_string_array(struct ndr_pull *ndr, int ndr_flags, const char ***_a)
447 {
448         const char **a = *_a;
449         uint32_t count;
450
451         if (!(ndr_flags & NDR_SCALARS)) {
452                 return NT_STATUS_OK;
453         }
454
455         for (count = 0;; count++) {
456                 TALLOC_CTX *tmp_ctx;
457                 const char *s = NULL;
458                 a = talloc_realloc(ndr->current_mem_ctx, a, const char *, count + 2);
459                 NT_STATUS_HAVE_NO_MEMORY(a);
460                 a[count]   = NULL;
461                 a[count+1]   = NULL;
462
463                 tmp_ctx = ndr->current_mem_ctx;
464                 ndr->current_mem_ctx = a;
465                 NDR_CHECK(ndr_pull_string(ndr, ndr_flags, &s));
466                 ndr->current_mem_ctx = tmp_ctx;
467                 if (strcmp("", s)==0) {
468                         a[count] = NULL;
469                         break;
470                 } else {
471                         a[count] = s;
472                 }
473         }
474
475         *_a =a;
476         return NT_STATUS_OK;
477 }
478
479 /**
480   push a general string array onto the wire
481 */
482 NTSTATUS ndr_push_string_array(struct ndr_push *ndr, int ndr_flags, const char **a)
483 {
484         uint32_t count;
485
486         if (!(ndr_flags & NDR_SCALARS)) {
487                 return NT_STATUS_OK;
488         }
489
490         for (count = 0; a && a[count]; count++) {
491                 NDR_CHECK(ndr_push_string(ndr, ndr_flags, a[count]));
492         }
493
494         NDR_CHECK(ndr_push_string(ndr, ndr_flags, ""));
495
496         return NT_STATUS_OK;
497 }
498
499 void ndr_print_string_array(struct ndr_print *ndr, const char *name, const char **a)
500 {
501         uint32_t count;
502         uint32_t i;
503
504         for (count = 0; a && a[count]; count++) {}
505
506         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
507         ndr->depth++;
508         for (i=0;i<count;i++) {
509                 char *idx=NULL;
510                 asprintf(&idx, "[%d]", i);
511                 if (idx) {
512                         ndr_print_string(ndr, idx, a[i]);
513                         free(idx);
514                 }
515         }
516         ndr->depth--;
517 }
518
519 /**
520  * Return number of elements in a string including the last (zeroed) element 
521  */
522 uint32_t ndr_string_length(const void *_var, uint32_t element_size)
523 {
524         uint32_t i;
525         uint8_t zero[4] = {0,0,0,0};
526         const char *var = (const char *)_var;
527
528         for (i = 0; memcmp(var+i*element_size,zero,element_size) != 0; i++);
529
530         return i+1;
531 }
532
533 NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
534 {
535         uint32_t i;
536         struct ndr_pull_save save_offset;
537
538         ndr_pull_save(ndr, &save_offset);
539         ndr_pull_advance(ndr, (count - 1) * element_size);
540         NDR_PULL_NEED_BYTES(ndr, element_size);
541
542         for (i = 0; i < element_size; i++) {
543                  if (ndr->data[ndr->offset+i] != 0) {
544                         ndr_pull_restore(ndr, &save_offset);
545
546                         return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
547                  }
548         }
549
550         ndr_pull_restore(ndr, &save_offset);
551
552         return NT_STATUS_OK;
553 }
554
555 NTSTATUS ndr_pull_charset(struct ndr_pull *ndr, int ndr_flags, const char **var, uint32_t length, uint8_t byte_mul, charset_t chset)
556 {
557         int ret;
558         if (length == 0) {
559                 *var = talloc_strdup(ndr->current_mem_ctx, "");
560                 return NT_STATUS_OK;
561         }
562
563         if (NDR_BE(ndr) && chset == CH_UTF16) {
564                 chset = CH_UTF16BE;
565         }
566
567         NDR_PULL_NEED_BYTES(ndr, length*byte_mul);
568
569         ret = convert_string_talloc(ndr->current_mem_ctx,
570                                     chset, CH_UNIX, 
571                                     ndr->data+ndr->offset, 
572                                     length*byte_mul,
573                                     var, False);
574         if (ret == -1) {
575                 return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
576                                       "Bad character conversion");
577         }
578         NDR_CHECK(ndr_pull_advance(ndr, length*byte_mul));
579
580         return NT_STATUS_OK;
581 }
582
583 NTSTATUS ndr_push_charset(struct ndr_push *ndr, int ndr_flags, const char *var,
584                           uint32_t length, uint8_t byte_mul, charset_t chset)
585 {
586         ssize_t ret, required;
587
588         if (NDR_BE(ndr) && chset == CH_UTF16) {
589                 chset = CH_UTF16BE;
590         }
591
592         required = byte_mul * length;
593         
594         NDR_PUSH_NEED_BYTES(ndr, required);
595         ret = convert_string(CH_UNIX, chset, 
596                              var, strlen(var),
597                              ndr->data+ndr->offset, required, False);
598         if (ret == -1) {
599                 return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
600                                       "Bad character conversion");
601         }
602
603         /* Make sure the remaining part of the string is filled with zeroes */
604         if (ret < required) {
605                 memset(ndr->data+ndr->offset+ret, 0, required-ret);
606         }
607
608         ndr->offset += required;
609
610         return NT_STATUS_OK;
611 }
612
613 /* Return number of elements in a string in the specified charset */
614 uint32_t ndr_charset_length(const void *var, int chset)
615 {
616         /* FIXME: Treat special chars special here, taking chset into account */
617         /* Also include 0 byte */
618         return strlen((const char *)var)+1;
619 }