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