2 Unix SMB/CIFS implementation.
4 routines for marshalling/unmarshalling string types
6 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
23 #include "librpc/ndr/libndr.h"
26 pull a general string from the wire
28 _PUBLIC_
enum ndr_err_code
ndr_pull_string(struct ndr_pull
*ndr
, int ndr_flags
, const char **s
)
31 uint32_t len1
, ofs
, len2
;
34 charset_t chset
= CH_UTF16
;
35 unsigned byte_mul
= 2;
36 unsigned flags
= ndr
->flags
;
37 unsigned c_len_term
= 0;
39 if (!(ndr_flags
& NDR_SCALARS
)) {
40 return NDR_ERR_SUCCESS
;
47 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
50 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
53 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
56 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
59 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
60 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
62 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
65 switch (flags
& LIBNDR_STRING_FLAGS
) {
66 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
67 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
68 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
69 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
71 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
72 ndr
->flags
& LIBNDR_STRING_FLAGS
);
74 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
76 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
77 "Bad string lengths len1=%u ofs=%u len2=%u\n",
80 NDR_PULL_NEED_BYTES(ndr
, (len2
+ c_len_term
)*byte_mul
);
82 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
84 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
85 ndr
->iconv_convenience
, chset
, CH_UNIX
,
86 ndr
->data
+ndr
->offset
,
87 (len2
+ c_len_term
)*byte_mul
,
88 (void **)&as
, &ret
, false)) {
89 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
90 "Bad character conversion with flags 0x%x", flags
);
93 NDR_CHECK(ndr_pull_advance(ndr
, (len2
+ c_len_term
)*byte_mul
));
96 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1
, len2
, as
));
99 /* this is a way of detecting if a string is sent with the wrong
101 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
102 if (strlen(as
) < (len2
+ c_len_term
)) {
103 DEBUG(6,("short string '%s'\n", as
));
106 if (strlen(as
) == (len2
+ c_len_term
)) {
107 DEBUG(6,("long string '%s'\n", as
));
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
);
118 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
120 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
121 ndr
->iconv_convenience
,
123 ndr
->data
+ndr
->offset
,
124 (len1
+ c_len_term
)*byte_mul
,
125 (void **)&as
, &ret
, false)) {
126 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
127 "Bad character conversion with flags 0x%x", flags
);
130 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
132 /* this is a way of detecting if a string is sent with the wrong
134 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
135 if (strlen(as
) < (len1
+ c_len_term
)) {
136 DEBUG(6,("short string '%s'\n", as
));
139 if (strlen(as
) == (len1
+ c_len_term
)) {
140 DEBUG(6,("long string '%s'\n", as
));
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
));
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
);
153 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
154 NDR_PULL_NEED_BYTES(ndr
, (len1
+ c_len_term
)*byte_mul
);
156 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
158 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
159 ndr
->iconv_convenience
,
161 ndr
->data
+ndr
->offset
,
162 (len1
+ c_len_term
)*byte_mul
,
163 (void **)&as
, &ret
, false)) {
164 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
165 "Bad character conversion with flags 0x%x", flags
);
168 NDR_CHECK(ndr_pull_advance(ndr
, (len1
+ c_len_term
)*byte_mul
));
170 /* this is a way of detecting if a string is sent with the wrong
172 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
173 if (strlen(as
) < (len1
+ c_len_term
)) {
174 DEBUG(6,("short string '%s'\n", as
));
177 if (strlen(as
) == (len1
+ c_len_term
)) {
178 DEBUG(6,("long string '%s'\n", as
));
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
);
190 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
192 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
193 ndr
->iconv_convenience
,
195 ndr
->data
+ndr
->offset
,
196 (len3
+ c_len_term
)*byte_mul
,
197 (void **)&as
, &ret
, false)) {
198 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
199 "Bad character conversion with flags 0x%x", flags
);
202 NDR_CHECK(ndr_pull_advance(ndr
, (len3
+ c_len_term
)*byte_mul
));
204 /* this is a way of detecting if a string is sent with the wrong
206 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
207 if (strlen(as
) < (len3
+ c_len_term
)) {
208 DEBUG(6,("short string '%s'\n", as
));
211 if (strlen(as
) == (len3
+ c_len_term
)) {
212 DEBUG(6,("long string '%s'\n", as
));
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
);
222 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
224 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
225 ndr
->iconv_convenience
,
227 ndr
->data
+ndr
->offset
,
229 (void **)&as
, &ret
, false)) {
230 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
231 "Bad character conversion with flags 0x%x", flags
);
234 NDR_CHECK(ndr_pull_advance(ndr
, len3
));
238 case LIBNDR_FLAG_STR_NULLTERM
:
240 len1
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
242 len1
= utf16_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
244 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
245 ndr
->iconv_convenience
, chset
, CH_UNIX
,
246 ndr
->data
+ndr
->offset
,
248 (void **)&as
, &ret
, false)) {
249 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
250 "Bad character conversion with flags 0x%x", flags
);
252 NDR_CHECK(ndr_pull_advance(ndr
, len1
));
256 case LIBNDR_FLAG_STR_NOTERM
:
257 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
258 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
259 ndr
->flags
& LIBNDR_STRING_FLAGS
);
262 len1
= ndr
->data_size
- ndr
->offset
;
264 NDR_PULL_NEED_BYTES(ndr
, len1
);
266 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
268 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
269 ndr
->iconv_convenience
,
271 ndr
->data
+ndr
->offset
,
273 (void **)&as
, &ret
, false)) {
274 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
275 "Bad character conversion with flags 0x%x", flags
);
278 NDR_CHECK(ndr_pull_advance(ndr
, len1
));
284 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
285 ndr
->flags
& LIBNDR_STRING_FLAGS
);
288 return NDR_ERR_SUCCESS
;
293 push a general string onto the wire
295 _PUBLIC_
enum ndr_err_code
ndr_push_string(struct ndr_push
*ndr
, int ndr_flags
, const char *s
)
297 size_t s_len
, c_len
, d_len
;
298 int chset
= CH_UTF16
;
299 unsigned flags
= ndr
->flags
;
300 unsigned byte_mul
= 2;
301 uint8_t *dest
= NULL
;
303 if (!(ndr_flags
& NDR_SCALARS
)) {
304 return NDR_ERR_SUCCESS
;
311 s_len
= s
?strlen(s
):0;
313 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
316 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
319 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
322 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
325 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
327 if (!(flags
& LIBNDR_FLAG_STR_NOTERM
)) {
330 if (!convert_string_talloc_convenience(ndr
, ndr
->iconv_convenience
, CH_UNIX
, chset
, s
, s_len
, (void **)&dest
, &d_len
, false)) {
331 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
332 "Bad character push conversion with flags 0x%x", flags
);
335 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
337 flags
&= ~LIBNDR_FLAG_STR_BYTESIZE
;
338 } else if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
339 c_len
= (d_len
/ byte_mul
)-1;
340 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
342 c_len
= d_len
/ byte_mul
;
345 switch ((flags
& LIBNDR_STRING_FLAGS
) & ~LIBNDR_FLAG_STR_NOTERM
) {
346 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
347 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
348 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
349 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
350 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
353 case LIBNDR_FLAG_STR_LEN4
:
354 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
355 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
356 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
359 case LIBNDR_FLAG_STR_SIZE4
:
360 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
361 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
364 case LIBNDR_FLAG_STR_SIZE2
:
365 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
));
366 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
369 case LIBNDR_FLAG_STR_NULLTERM
:
370 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
374 if (ndr
->flags
& LIBNDR_FLAG_REMAINING
) {
375 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
379 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
380 ndr
->flags
& LIBNDR_STRING_FLAGS
);
385 return NDR_ERR_SUCCESS
;
389 push a general string onto the wire
391 _PUBLIC_
size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
394 unsigned flags
= ndr
->flags
;
395 unsigned byte_mul
= 2;
396 unsigned c_len_term
= 1;
398 c_len
= s
?strlen_m(s
):0;
400 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_UTF8
)) {
404 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
408 c_len
= c_len
+ c_len_term
;
410 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
411 c_len
= c_len
* byte_mul
;
417 _PUBLIC_
void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
420 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
422 ndr
->print(ndr
, "%-25s: NULL", name
);
426 _PUBLIC_
uint32_t ndr_size_string(int ret
, const char * const* string
, int flags
)
428 /* FIXME: Is this correct for all strings ? */
429 if(!(*string
)) return ret
;
430 return ret
+strlen(*string
)+1;
434 pull a general string array from the wire
436 _PUBLIC_
enum ndr_err_code
ndr_pull_string_array(struct ndr_pull
*ndr
, int ndr_flags
, const char ***_a
)
438 const char **a
= NULL
;
440 unsigned flags
= ndr
->flags
;
441 unsigned saved_flags
= ndr
->flags
;
443 if (!(ndr_flags
& NDR_SCALARS
)) {
444 return NDR_ERR_SUCCESS
;
447 switch (flags
& (LIBNDR_FLAG_STR_NULLTERM
|LIBNDR_FLAG_STR_NOTERM
)) {
448 case LIBNDR_FLAG_STR_NULLTERM
:
450 * here the strings are null terminated
451 * but also the array is null terminated
453 for (count
= 0;; count
++) {
455 const char *s
= NULL
;
456 a
= talloc_realloc(ndr
->current_mem_ctx
, a
, const char *, count
+ 2);
457 NDR_ERR_HAVE_NO_MEMORY(a
);
461 tmp_ctx
= ndr
->current_mem_ctx
;
462 ndr
->current_mem_ctx
= a
;
463 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
464 ndr
->current_mem_ctx
= tmp_ctx
;
465 if (strcmp("", s
)==0) {
476 case LIBNDR_FLAG_STR_NOTERM
:
477 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
478 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
479 ndr
->flags
& LIBNDR_STRING_FLAGS
);
482 * here the strings are not null terminated
483 * but serarated by a null terminator
485 * which means the same as:
486 * very string is null terminated exept the last
487 * string is terminated by the end of the buffer
489 * as LIBNDR_FLAG_STR_NULLTERM also end at the end
490 * of the buffer, we can pull each string with this flag
492 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
493 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
495 for (count
= 0; ((ndr
->data_size
- ndr
->offset
) > 0); count
++) {
497 const char *s
= NULL
;
498 a
= talloc_realloc(ndr
->current_mem_ctx
, a
, const char *, count
+ 2);
499 NDR_ERR_HAVE_NO_MEMORY(a
);
503 tmp_ctx
= ndr
->current_mem_ctx
;
504 ndr
->current_mem_ctx
= a
;
505 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
506 ndr
->current_mem_ctx
= tmp_ctx
;
514 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
515 ndr
->flags
& LIBNDR_STRING_FLAGS
);
518 ndr
->flags
= saved_flags
;
519 return NDR_ERR_SUCCESS
;
523 push a general string array onto the wire
525 _PUBLIC_
enum ndr_err_code
ndr_push_string_array(struct ndr_push
*ndr
, int ndr_flags
, const char **a
)
528 unsigned flags
= ndr
->flags
;
529 unsigned saved_flags
= ndr
->flags
;
531 if (!(ndr_flags
& NDR_SCALARS
)) {
532 return NDR_ERR_SUCCESS
;
535 switch (flags
& LIBNDR_STRING_FLAGS
) {
536 case LIBNDR_FLAG_STR_NULLTERM
:
537 for (count
= 0; a
&& a
[count
]; count
++) {
538 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
541 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
544 case LIBNDR_FLAG_STR_NOTERM
:
545 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
546 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
547 ndr
->flags
& LIBNDR_STRING_FLAGS
);
550 for (count
= 0; a
&& a
[count
]; count
++) {
552 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
553 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
554 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
555 ndr
->flags
= saved_flags
;
557 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
563 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
564 ndr
->flags
& LIBNDR_STRING_FLAGS
);
567 ndr
->flags
= saved_flags
;
568 return NDR_ERR_SUCCESS
;
571 _PUBLIC_
void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
576 for (count
= 0; a
&& a
[count
]; count
++) {}
578 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
580 for (i
=0;i
<count
;i
++) {
582 if (asprintf(&idx
, "[%d]", i
) != -1) {
583 ndr_print_string(ndr
, idx
, a
[i
]);
590 _PUBLIC_
size_t ndr_size_string_array(const char **a
, uint32_t count
, int flags
)
595 switch (flags
& LIBNDR_STRING_FLAGS
) {
596 case LIBNDR_FLAG_STR_NULLTERM
:
597 for (i
= 0; i
< count
; i
++) {
598 size
+= strlen_m_term(a
[i
]);
601 case LIBNDR_FLAG_STR_NOTERM
:
602 for (i
= 0; i
< count
; i
++) {
603 size
+= strlen_m(a
[i
]);
614 * Return number of elements in a string including the last (zeroed) element
616 _PUBLIC_
uint32_t ndr_string_length(const void *_var
, uint32_t element_size
)
619 uint8_t zero
[4] = {0,0,0,0};
620 const char *var
= (const char *)_var
;
622 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
627 _PUBLIC_
enum ndr_err_code
ndr_check_string_terminator(struct ndr_pull
*ndr
, uint32_t count
, uint32_t element_size
)
630 uint32_t save_offset
;
632 save_offset
= ndr
->offset
;
633 ndr_pull_advance(ndr
, (count
- 1) * element_size
);
634 NDR_PULL_NEED_BYTES(ndr
, element_size
);
636 for (i
= 0; i
< element_size
; i
++) {
637 if (ndr
->data
[ndr
->offset
+i
] != 0) {
638 ndr
->offset
= save_offset
;
640 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
, "String terminator not present or outside string boundaries");
644 ndr
->offset
= save_offset
;
646 return NDR_ERR_SUCCESS
;
649 _PUBLIC_
enum ndr_err_code
ndr_pull_charset(struct ndr_pull
*ndr
, int ndr_flags
, const char **var
, uint32_t length
, uint8_t byte_mul
, charset_t chset
)
653 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
654 return NDR_ERR_SUCCESS
;
657 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
661 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
663 if (!convert_string_talloc_convenience(ndr
->current_mem_ctx
,
664 ndr
->iconv_convenience
,
666 ndr
->data
+ndr
->offset
,
668 discard_const_p(void *, var
), &ret
, false)) {
669 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
670 "Bad character conversion");
672 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
674 return NDR_ERR_SUCCESS
;
677 _PUBLIC_
enum ndr_err_code
ndr_push_charset(struct ndr_push
*ndr
, int ndr_flags
, const char *var
, uint32_t length
, uint8_t byte_mul
, charset_t chset
)
679 size_t ret
, required
;
681 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
685 required
= byte_mul
* length
;
687 NDR_PUSH_NEED_BYTES(ndr
, required
);
688 if (!convert_string_convenience(ndr
->iconv_convenience
, CH_UNIX
, chset
,
690 ndr
->data
+ndr
->offset
, required
, &ret
, false)) {
691 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
692 "Bad character conversion");
695 /* Make sure the remaining part of the string is filled with zeroes */
696 if (ret
< required
) {
697 memset(ndr
->data
+ndr
->offset
+ret
, 0, required
-ret
);
700 ndr
->offset
+= required
;
702 return NDR_ERR_SUCCESS
;
705 /* Return number of elements in a string in the specified charset */
706 _PUBLIC_
uint32_t ndr_charset_length(const void *var
, charset_t chset
)
708 /* FIXME: Treat special chars special here, taking chset into account */
709 /* Also include 0 byte */
710 return strlen((const char *)var
)+1;