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
;
33 size_t conv_src_len
= 0, converted_size
;
34 int do_convert
= 1, 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 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
62 flags
&= ~LIBNDR_FLAG_STR_RAW8
;
65 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
66 if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
68 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
71 switch (flags
& LIBNDR_STRING_FLAGS
) {
72 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
73 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
74 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
75 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
77 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
78 ndr
->flags
& LIBNDR_STRING_FLAGS
);
80 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len2
));
82 return ndr_pull_error(ndr
, NDR_ERR_STRING
,
83 "Bad string lengths len1=%u ofs=%u len2=%u\n",
85 } else if (len1
!= len2
) {
86 DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1
, len2
, as
));
88 conv_src_len
= len2
+ c_len_term
;
91 case LIBNDR_FLAG_STR_SIZE4
:
92 case LIBNDR_FLAG_STR_SIZE4
|LIBNDR_FLAG_STR_NOTERM
:
93 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
94 conv_src_len
= len1
+ c_len_term
;
97 case LIBNDR_FLAG_STR_LEN4
:
98 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_NOTERM
:
99 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &ofs
));
101 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "non-zero array offset with string flags 0x%x\n",
102 ndr
->flags
& LIBNDR_STRING_FLAGS
);
104 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &len1
));
105 conv_src_len
= len1
+ c_len_term
;
108 case LIBNDR_FLAG_STR_SIZE2
:
109 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
:
110 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
111 conv_src_len
= len3
+ c_len_term
;
114 case LIBNDR_FLAG_STR_SIZE2
|LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_STR_BYTESIZE
:
115 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &len3
));
117 byte_mul
= 1; /* the length is now absolute */
120 case LIBNDR_FLAG_STR_NULLTERM
:
122 * We ensure that conv_str_len cannot return 0 by
123 * requiring that there be enough bytes for at least
124 * the NULL terminator
127 NDR_PULL_NEED_BYTES(ndr
, 1);
128 conv_src_len
= ascii_len_n((const char *)(ndr
->data
+ndr
->offset
), ndr
->data_size
- ndr
->offset
);
130 NDR_PULL_NEED_BYTES(ndr
, 2);
131 conv_src_len
= utf16_len_n(ndr
->data
+ndr
->offset
, ndr
->data_size
- ndr
->offset
);
133 byte_mul
= 1; /* the length is now absolute */
136 case LIBNDR_FLAG_STR_NOTERM
:
137 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
138 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
139 ndr
->flags
& LIBNDR_STRING_FLAGS
);
141 conv_src_len
= ndr
->data_size
- ndr
->offset
;
142 byte_mul
= 1; /* the length is now absolute */
146 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
147 ndr
->flags
& LIBNDR_STRING_FLAGS
);
150 NDR_PULL_NEED_BYTES(ndr
, conv_src_len
* byte_mul
);
151 if (conv_src_len
== 0) {
152 as
= talloc_strdup(ndr
->current_mem_ctx
, "");
156 as
= talloc_strndup(ndr
->current_mem_ctx
,
157 (char *)ndr
->data
+ ndr
->offset
,
160 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
,
161 "Failed to talloc_strndup() in RAW8 ndr_string_pull()");
163 converted_size
= MIN(strlen(as
)+1, conv_src_len
);
164 } else if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
,
165 CH_UNIX
, ndr
->data
+ ndr
->offset
,
166 conv_src_len
* byte_mul
,
167 (void **)(void *)&as
,
169 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
170 "Bad character conversion with flags 0x%x", flags
);
174 /* this is a way of detecting if a string is sent with the wrong
176 if (ndr
->flags
& LIBNDR_FLAG_STR_NOTERM
) {
177 if (as
&& converted_size
> 0 && as
[converted_size
-1] == '\0') {
178 DEBUG(6,("short string '%s', sent with NULL termination despite NOTERM flag in IDL\n", as
));
181 if (as
&& converted_size
> 0 && as
[converted_size
-1] != '\0') {
182 DEBUG(6,("long string '%s', send without NULL termination (which was expected)\n", as
));
186 NDR_CHECK(ndr_pull_advance(ndr
, conv_src_len
* byte_mul
));
189 return NDR_ERR_SUCCESS
;
194 push a general string onto the wire
196 _PUBLIC_
enum ndr_err_code
ndr_push_string(struct ndr_push
*ndr
, int ndr_flags
, const char *s
)
198 ssize_t s_len
, c_len
;
200 int do_convert
= 1, chset
= CH_UTF16
;
201 unsigned flags
= ndr
->flags
;
202 unsigned byte_mul
= 2;
203 uint8_t *dest
= NULL
;
205 if (!(ndr_flags
& NDR_SCALARS
)) {
206 return NDR_ERR_SUCCESS
;
213 s_len
= s
?strlen(s
):0;
215 if (flags
& LIBNDR_FLAG_STR_ASCII
) {
218 flags
&= ~LIBNDR_FLAG_STR_ASCII
;
221 if (flags
& LIBNDR_FLAG_STR_UTF8
) {
224 flags
&= ~LIBNDR_FLAG_STR_UTF8
;
227 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
230 flags
&= ~LIBNDR_FLAG_STR_RAW8
;
233 flags
&= ~LIBNDR_FLAG_STR_CONFORMANT
;
235 if (!(flags
& LIBNDR_FLAG_STR_NOTERM
)) {
241 dest
= (uint8_t *)talloc_strdup(ndr
, "");
242 } else if (!do_convert
) {
244 dest
= (uint8_t *)talloc_strndup(ndr
, s
, s_len
);
245 } else if (!convert_string_talloc(ndr
, CH_UNIX
, chset
, s
, s_len
,
246 (void **)(void *)&dest
, &d_len
))
248 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
249 "Bad character push conversion with flags 0x%x", flags
);
252 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
254 flags
&= ~LIBNDR_FLAG_STR_BYTESIZE
;
255 } else if (flags
& LIBNDR_FLAG_STR_CHARLEN
) {
256 c_len
= (d_len
/ byte_mul
)-1;
257 flags
&= ~LIBNDR_FLAG_STR_CHARLEN
;
259 c_len
= d_len
/ byte_mul
;
262 switch ((flags
& LIBNDR_STRING_FLAGS
) & ~LIBNDR_FLAG_STR_NOTERM
) {
263 case LIBNDR_FLAG_STR_LEN4
|LIBNDR_FLAG_STR_SIZE4
:
264 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
265 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
266 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
267 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
270 case LIBNDR_FLAG_STR_LEN4
:
271 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
272 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
273 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
276 case LIBNDR_FLAG_STR_SIZE4
:
277 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, c_len
));
278 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
281 case LIBNDR_FLAG_STR_SIZE2
:
282 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, c_len
));
283 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
286 case LIBNDR_FLAG_STR_NULLTERM
:
287 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
291 if (ndr
->flags
& LIBNDR_FLAG_REMAINING
) {
292 NDR_CHECK(ndr_push_bytes(ndr
, dest
, d_len
));
296 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
297 ndr
->flags
& LIBNDR_STRING_FLAGS
);
302 return NDR_ERR_SUCCESS
;
306 push a general string onto the wire
308 _PUBLIC_
size_t ndr_string_array_size(struct ndr_push
*ndr
, const char *s
)
311 unsigned flags
= ndr
->flags
;
312 unsigned byte_mul
= 2;
313 unsigned c_len_term
= 1;
315 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
316 c_len
= s
?strlen(s
):0;
318 c_len
= s
?strlen_m(s
):0;
321 if (flags
& (LIBNDR_FLAG_STR_ASCII
|LIBNDR_FLAG_STR_RAW8
|LIBNDR_FLAG_STR_UTF8
)) {
325 if (flags
& LIBNDR_FLAG_STR_NOTERM
) {
329 c_len
= c_len
+ c_len_term
;
331 if (flags
& LIBNDR_FLAG_STR_BYTESIZE
) {
332 c_len
= c_len
* byte_mul
;
338 _PUBLIC_
void ndr_print_string(struct ndr_print
*ndr
, const char *name
, const char *s
)
340 if (NDR_HIDE_SECRET(ndr
)) {
341 ndr
->print(ndr
, "%-25s: <REDACTED SECRET VALUE>", name
);
345 ndr
->print(ndr
, "%-25s: '%s'", name
, s
);
347 ndr
->print(ndr
, "%-25s: NULL", name
);
351 _PUBLIC_
uint32_t ndr_size_string(int ret
, const char * const* string
, int flags
)
353 /* FIXME: Is this correct for all strings ? */
354 if(!(*string
)) return ret
;
355 return ret
+strlen(*string
)+1;
358 static uint32_t guess_string_array_size(struct ndr_pull
*ndr
, int ndr_flags
)
361 * Here we could do something clever like count the number of zeros in
362 * the ndr data, but it is probably sufficient to pick a lowish number
363 * (compared to the overhead of the talloc header) and let the
364 * expontential resizing deal with longer arrays.
369 static enum ndr_err_code
extend_string_array(struct ndr_pull
*ndr
,
373 const char **a
= *_a
;
374 uint32_t inc
= *count
/ 4 + 3;
375 uint32_t alloc_size
= *count
+ inc
;
377 if (alloc_size
< *count
) {
379 return NDR_ERR_ALLOC
;
382 * We allocate and zero two more bytes than we report back, so that
383 * the string array will always be NULL terminated.
385 a
= talloc_realloc(ndr
->current_mem_ctx
, a
,
388 NDR_ERR_HAVE_NO_MEMORY(a
);
390 memset(a
+ *count
, 0, inc
* sizeof(a
[0]));
392 *count
= alloc_size
- 2;
393 return NDR_ERR_SUCCESS
;
397 pull a general string array from the wire
399 _PUBLIC_
enum ndr_err_code
ndr_pull_string_array(struct ndr_pull
*ndr
, int ndr_flags
, const char ***_a
)
401 const char **a
= NULL
;
403 unsigned flags
= ndr
->flags
;
404 unsigned saved_flags
= ndr
->flags
;
407 if (!(ndr_flags
& NDR_SCALARS
)) {
408 return NDR_ERR_SUCCESS
;
411 alloc_size
= guess_string_array_size(ndr
, ndr_flags
);
412 a
= talloc_zero_array(ndr
->current_mem_ctx
, const char *, alloc_size
+ 2);
413 NDR_ERR_HAVE_NO_MEMORY(a
);
415 switch (flags
& (LIBNDR_FLAG_STR_NULLTERM
|LIBNDR_FLAG_STR_NOTERM
)) {
416 case LIBNDR_FLAG_STR_NULLTERM
:
418 * here the strings are null terminated
419 * but also the array is null terminated if LIBNDR_FLAG_REMAINING
422 for (count
= 0;; count
++) {
424 const char *s
= NULL
;
425 if (count
== alloc_size
) {
426 NDR_CHECK(extend_string_array(ndr
,
431 tmp_ctx
= ndr
->current_mem_ctx
;
432 ndr
->current_mem_ctx
= a
;
433 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
434 ndr
->current_mem_ctx
= tmp_ctx
;
435 if ((ndr
->data_size
- ndr
->offset
) == 0 && ndr
->flags
& LIBNDR_FLAG_REMAINING
)
440 if (strcmp("", s
)==0) {
451 case LIBNDR_FLAG_STR_NOTERM
:
452 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
453 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
454 ndr
->flags
& LIBNDR_STRING_FLAGS
);
457 * here the strings are not null terminated
458 * but separated by a null terminator
460 * which means the same as:
461 * Every string is null terminated except the last
462 * string is terminated by the end of the buffer
464 * as LIBNDR_FLAG_STR_NULLTERM also end at the end
465 * of the buffer, we can pull each string with this flag
467 * The big difference with the case LIBNDR_FLAG_STR_NOTERM +
468 * LIBNDR_FLAG_REMAINING is that the last string will not be null terminated
470 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
471 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
473 for (count
= 0; ((ndr
->data_size
- ndr
->offset
) > 0); count
++) {
475 const char *s
= NULL
;
476 if (count
== alloc_size
) {
477 NDR_CHECK(extend_string_array(ndr
,
482 tmp_ctx
= ndr
->current_mem_ctx
;
483 ndr
->current_mem_ctx
= a
;
484 NDR_CHECK(ndr_pull_string(ndr
, ndr_flags
, &s
));
485 ndr
->current_mem_ctx
= tmp_ctx
;
489 a
= talloc_realloc(ndr
->current_mem_ctx
, a
, const char *, count
+ 1);
490 NDR_ERR_HAVE_NO_MEMORY(a
);
495 return ndr_pull_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
496 ndr
->flags
& LIBNDR_STRING_FLAGS
);
499 ndr
->flags
= saved_flags
;
500 return NDR_ERR_SUCCESS
;
504 push a general string array onto the wire
506 _PUBLIC_
enum ndr_err_code
ndr_push_string_array(struct ndr_push
*ndr
, int ndr_flags
, const char **a
)
509 unsigned flags
= ndr
->flags
;
510 unsigned saved_flags
= ndr
->flags
;
512 if (!(ndr_flags
& NDR_SCALARS
)) {
513 return NDR_ERR_SUCCESS
;
516 switch (flags
& LIBNDR_STRING_FLAGS
) {
517 case LIBNDR_FLAG_STR_NULLTERM
:
518 for (count
= 0; a
&& a
[count
]; count
++) {
519 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
521 /* If LIBNDR_FLAG_REMAINING then we do not add a null terminator to the array */
522 if (!(flags
& LIBNDR_FLAG_REMAINING
))
524 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
528 case LIBNDR_FLAG_STR_NOTERM
:
529 if (!(ndr
->flags
& LIBNDR_FLAG_REMAINING
)) {
530 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x (missing NDR_REMAINING)\n",
531 ndr
->flags
& LIBNDR_STRING_FLAGS
);
534 for (count
= 0; a
&& a
[count
]; count
++) {
536 ndr
->flags
&= ~(LIBNDR_FLAG_STR_NOTERM
|LIBNDR_FLAG_REMAINING
);
537 ndr
->flags
|= LIBNDR_FLAG_STR_NULLTERM
;
538 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, ""));
539 ndr
->flags
= saved_flags
;
541 NDR_CHECK(ndr_push_string(ndr
, ndr_flags
, a
[count
]));
547 return ndr_push_error(ndr
, NDR_ERR_STRING
, "Bad string flags 0x%x\n",
548 ndr
->flags
& LIBNDR_STRING_FLAGS
);
551 ndr
->flags
= saved_flags
;
552 return NDR_ERR_SUCCESS
;
555 _PUBLIC_
void ndr_print_string_array(struct ndr_print
*ndr
, const char *name
, const char **a
)
560 for (count
= 0; a
&& a
[count
]; count
++) {}
562 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
564 for (i
=0;i
<count
;i
++) {
566 if (asprintf(&idx
, "[%d]", i
) != -1) {
567 ndr_print_string(ndr
, idx
, a
[i
]);
574 _PUBLIC_
size_t ndr_size_string_array(const char **a
, uint32_t count
, int flags
)
580 if (flags
& LIBNDR_FLAG_STR_RAW8
) {
582 flags
&= ~LIBNDR_FLAG_STR_RAW8
;
585 switch (flags
& LIBNDR_STRING_FLAGS
) {
586 case LIBNDR_FLAG_STR_NULLTERM
:
587 for (i
= 0; i
< count
; i
++) {
588 size
+= rawbytes
?strlen(a
[i
]) + 1:strlen_m_term(a
[i
]);
591 case LIBNDR_FLAG_STR_NOTERM
:
592 for (i
= 0; i
< count
; i
++) {
593 size
+= rawbytes
?strlen(a
[i
]):strlen_m(a
[i
]);
604 * Return number of elements in a string including the last (zeroed) element
606 _PUBLIC_
uint32_t ndr_string_length(const void *_var
, uint32_t element_size
)
609 uint8_t zero
[4] = {0,0,0,0};
610 const char *var
= (const char *)_var
;
612 for (i
= 0; memcmp(var
+i
*element_size
,zero
,element_size
) != 0; i
++);
618 * @brief Get the string length including the null terminator if available.
620 * This checks the string length based on the elements. The returned number
621 * includes the terminating null byte(s) if found.
623 * @param[in] _var The string the calculate the length for.
625 * @param[in] length The length of the buffer passed by _var.
627 * @param[in] element_size The element_size of a string char in bytes.
629 * @return The length of the strings or 0.
631 static uint32_t ndr_string_n_length(const void *_var
,
633 uint32_t element_size
)
636 uint8_t zero
[4] = {0,0,0,0};
637 const char *var
= (const char *)_var
;
640 if (element_size
> 4) {
644 for (i
= 0; i
< length
; i
++, var
+= element_size
) {
645 cmp
= memcmp(var
, zero
, element_size
);
658 _PUBLIC_
enum ndr_err_code
ndr_check_string_terminator(struct ndr_pull
*ndr
, uint32_t count
, uint32_t element_size
)
661 uint32_t save_offset
;
663 save_offset
= ndr
->offset
;
664 NDR_CHECK(ndr_pull_advance(ndr
, (count
- 1) * element_size
));
665 NDR_PULL_NEED_BYTES(ndr
, element_size
);
667 for (i
= 0; i
< element_size
; i
++) {
668 if (ndr
->data
[ndr
->offset
+i
] != 0) {
669 ndr
->offset
= save_offset
;
671 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
, "String terminator not present or outside string boundaries");
675 ndr
->offset
= save_offset
;
677 return NDR_ERR_SUCCESS
;
680 _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
)
682 size_t converted_size
;
685 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
686 return NDR_ERR_SUCCESS
;
689 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
693 if ((byte_mul
!= 0) && (length
> UINT32_MAX
/byte_mul
)) {
694 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
, "length overflow");
696 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
698 if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
, CH_UNIX
,
699 ndr
->data
+ndr
->offset
, length
*byte_mul
,
700 discard_const_p(void *, var
),
703 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
704 "Bad character conversion");
706 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
708 return NDR_ERR_SUCCESS
;
711 _PUBLIC_
enum ndr_err_code
ndr_pull_charset_to_null(struct ndr_pull
*ndr
, int ndr_flags
, const char **var
, uint32_t length
, uint8_t byte_mul
, charset_t chset
)
713 size_t converted_size
;
717 *var
= talloc_strdup(ndr
->current_mem_ctx
, "");
718 return NDR_ERR_SUCCESS
;
721 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
725 NDR_PULL_NEED_BYTES(ndr
, length
*byte_mul
);
727 str_len
= ndr_string_n_length(ndr
->data
+ndr
->offset
, length
, byte_mul
);
729 return ndr_pull_error(ndr
, NDR_ERR_LENGTH
,
733 if (!convert_string_talloc(ndr
->current_mem_ctx
, chset
, CH_UNIX
,
734 ndr
->data
+ndr
->offset
, str_len
*byte_mul
,
735 discard_const_p(void *, var
),
738 return ndr_pull_error(ndr
, NDR_ERR_CHARCNV
,
739 "Bad character conversion");
741 NDR_CHECK(ndr_pull_advance(ndr
, length
*byte_mul
));
743 return NDR_ERR_SUCCESS
;
746 _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
)
750 if (NDR_BE(ndr
) && chset
== CH_UTF16
) {
754 if ((byte_mul
!= 0) && (length
> SIZE_MAX
/byte_mul
)) {
755 return ndr_push_error(ndr
, NDR_ERR_LENGTH
, "length overflow");
757 required
= byte_mul
* length
;
759 NDR_PUSH_NEED_BYTES(ndr
, required
);
765 return ndr_push_error(ndr
, NDR_ERR_INVALID_POINTER
, "NULL [ref] pointer");
768 if (!convert_string(CH_UNIX
, chset
,
770 ndr
->data
+ndr
->offset
, required
, &size
)) {
771 return ndr_push_error(ndr
, NDR_ERR_CHARCNV
,
772 "Bad character conversion");
775 /* Make sure the remaining part of the string is filled with zeroes */
776 if (size
< required
) {
777 memset(ndr
->data
+ndr
->offset
+size
, 0, required
-size
);
781 ndr
->offset
+= required
;
783 return NDR_ERR_SUCCESS
;
786 _PUBLIC_
enum ndr_err_code
ndr_push_charset_to_null(struct ndr_push
*ndr
, int ndr_flags
, const char *var
, uint32_t length
, uint8_t byte_mul
, charset_t chset
)
788 const char *str
= var
;
791 str
= "\0"; /* i.e. two zero bytes, for UTF16 null word. */
795 return ndr_push_charset(ndr
, ndr_flags
, str
, length
, byte_mul
, chset
);
798 /* Return number of elements in a string in the specified charset */
799 _PUBLIC_
uint32_t ndr_charset_length(const void *var
, charset_t chset
)
802 /* case CH_UTF16: this has the same value as CH_UTF16LE */
807 return strlen_m_ext_term((const char *)var
, CH_UNIX
, chset
);
810 return strlen((const char *)var
)+1;
813 /* Fallback, this should never happen */
814 return strlen((const char *)var
)+1;