r5765: remove unused var
[samba.git] / source / librpc / ndr / ndr_basic.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    routines for marshalling/unmarshalling basic 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 "system/network.h"
25
26 #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
27 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
28 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
29 #define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
30 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
31 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
32 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
33
34
35 /*
36   check for data leaks from the server by looking for non-zero pad bytes
37   these could also indicate that real structure elements have been
38   mistaken for padding in the IDL
39 */
40 void ndr_check_padding(struct ndr_pull *ndr, size_t n)
41 {
42         size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
43         int i;
44         for (i=ndr->offset;i<ofs2;i++) {
45                 if (ndr->data[i] != 0) {
46                         break;
47                 }
48         }
49         if (i<ofs2) {
50                 DEBUG(0,("WARNING: Non-zero padding to %d: ", n));
51                 for (i=ndr->offset;i<ofs2;i++) {
52                         DEBUG(0,("%02x ", ndr->data[i]));
53                 }
54                 DEBUG(0,("\n"));
55         }
56
57 }
58
59 /*
60   parse a uint8
61 */
62 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
63 {
64         NDR_PULL_NEED_BYTES(ndr, 1);
65         *v = CVAL(ndr->data, ndr->offset);
66         ndr->offset += 1;
67         return NT_STATUS_OK;
68 }
69
70
71 /*
72   parse a uint16
73 */
74 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
75 {
76         NDR_PULL_ALIGN(ndr, 2);
77         NDR_PULL_NEED_BYTES(ndr, 2);
78         *v = NDR_SVAL(ndr, ndr->offset);
79         ndr->offset += 2;
80         return NT_STATUS_OK;
81 }
82
83
84 /*
85   parse a uint32_t
86 */
87 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
88 {
89         NDR_PULL_ALIGN(ndr, 4);
90         NDR_PULL_NEED_BYTES(ndr, 4);
91         *v = NDR_IVAL(ndr, ndr->offset);
92         ndr->offset += 4;
93         return NT_STATUS_OK;
94 }
95
96 /*
97   parse a int32_t
98 */
99 NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
100 {
101         NDR_PULL_ALIGN(ndr, 4);
102         NDR_PULL_NEED_BYTES(ndr, 4);
103         *v = NDR_IVALS(ndr, ndr->offset);
104         ndr->offset += 4;
105         return NT_STATUS_OK;
106 }
107
108 /*
109   parse a pointer referent identifier
110 */
111 NTSTATUS ndr_pull_unique_ptr(struct ndr_pull *ndr, uint32_t *v)
112 {
113         NTSTATUS status;
114         status = ndr_pull_uint32(ndr, NDR_SCALARS, v);
115         if (*v != 0) {
116                 ndr->ptr_count++;
117         }
118         return status;
119 }
120
121 /*
122   parse a ref pointer referent identifier
123 */
124 NTSTATUS ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
125 {
126         NTSTATUS status;
127         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
128         /* ref pointers always point to data */
129         *v = 1;
130         return status;
131 }
132
133 /*
134   parse a udlong
135 */
136 NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
137 {
138         NDR_PULL_ALIGN(ndr, 4);
139         NDR_PULL_NEED_BYTES(ndr, 8);
140         *v = NDR_IVAL(ndr, ndr->offset);
141         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
142         ndr->offset += 8;
143         return NT_STATUS_OK;
144 }
145
146 /*
147   parse a udlongr
148 */
149 NTSTATUS ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
150 {
151         NDR_PULL_ALIGN(ndr, 4);
152         NDR_PULL_NEED_BYTES(ndr, 8);
153         *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
154         *v |= NDR_IVAL(ndr, ndr->offset+4);
155         ndr->offset += 8;
156         return NT_STATUS_OK;
157 }
158
159 /*
160   parse a dlong
161 */
162 NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
163 {
164         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
165 }
166
167 /*
168   parse a hyper
169 */
170 NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
171 {
172         NDR_PULL_ALIGN(ndr, 8);
173         return ndr_pull_udlong(ndr, ndr_flags, v);
174 }
175
176 /*
177   pull a NTSTATUS
178 */
179 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
180 {
181         uint32_t v;
182         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
183         *status = NT_STATUS(v);
184         return NT_STATUS_OK;
185 }
186
187 /*
188   push a NTSTATUS
189 */
190 NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
191 {
192         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
193 }
194
195 void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
196 {
197         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
198 }
199
200 /*
201   pull a WERROR
202 */
203 NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
204 {
205         uint32_t v;
206         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
207         *status = W_ERROR(v);
208         return NT_STATUS_OK;
209 }
210
211 /*
212   push a WERROR
213 */
214 NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
215 {
216         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
217 }
218
219 void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
220 {
221         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
222 }
223
224 /*
225   parse a set of bytes
226 */
227 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
228 {
229         NDR_PULL_NEED_BYTES(ndr, n);
230         memcpy(data, ndr->data + ndr->offset, n);
231         ndr->offset += n;
232         return NT_STATUS_OK;
233 }
234
235 /*
236   pull an array of uint8
237 */
238 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
239 {
240         if (!(ndr_flags & NDR_SCALARS)) {
241                 return NT_STATUS_OK;
242         }
243         return ndr_pull_bytes(ndr, data, n);
244 }
245
246
247 /*
248   pull an array of uint16
249 */
250 NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *data, uint32_t n)
251 {
252         uint32_t i;
253         if (!(ndr_flags & NDR_SCALARS)) {
254                 return NT_STATUS_OK;
255         }
256         for (i=0;i<n;i++) {
257                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &data[i]));
258         }
259         return NT_STATUS_OK;
260 }
261
262 /*
263   pull a const array of uint32_t
264 */
265 NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *data, uint32_t n)
266 {
267         uint32_t i;
268         if (!(ndr_flags & NDR_SCALARS)) {
269                 return NT_STATUS_OK;
270         }
271         for (i=0;i<n;i++) {
272                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &data[i]));
273         }
274         return NT_STATUS_OK;
275 }
276
277 /*
278   pull a const array of hyper
279 */
280 NTSTATUS ndr_pull_array_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *data, uint32_t n)
281 {
282         uint32_t i;
283         if (!(ndr_flags & NDR_SCALARS)) {
284                 return NT_STATUS_OK;
285         }
286         for (i=0;i<n;i++) {
287                 NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &data[i]));
288         }
289         return NT_STATUS_OK;
290 }
291
292 /*
293   pull a const array of WERROR
294 */
295 NTSTATUS ndr_pull_array_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *data, uint32_t n)
296 {
297         uint32_t i;
298         if (!(ndr_flags & NDR_SCALARS)) {
299                 return NT_STATUS_OK;
300         }
301         for (i=0;i<n;i++) {
302                 NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &data[i]));
303         }
304         return NT_STATUS_OK;
305 }
306
307
308
309 /*
310   push a uint8
311 */
312 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
313 {
314         NDR_PUSH_NEED_BYTES(ndr, 1);
315         SCVAL(ndr->data, ndr->offset, v);
316         ndr->offset += 1;
317         return NT_STATUS_OK;
318 }
319
320 /*
321   push a uint16
322 */
323 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
324 {
325         NDR_PUSH_ALIGN(ndr, 2);
326         NDR_PUSH_NEED_BYTES(ndr, 2);
327         NDR_SSVAL(ndr, ndr->offset, v);
328         ndr->offset += 2;
329         return NT_STATUS_OK;
330 }
331
332 /*
333   push a uint32_t
334 */
335 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
336 {
337         NDR_PUSH_ALIGN(ndr, 4);
338         NDR_PUSH_NEED_BYTES(ndr, 4);
339         NDR_SIVAL(ndr, ndr->offset, v);
340         ndr->offset += 4;
341         return NT_STATUS_OK;
342 }
343
344 /*
345   push a int32_t
346 */
347 NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
348 {
349         NDR_PUSH_ALIGN(ndr, 4);
350         NDR_PUSH_NEED_BYTES(ndr, 4);
351         NDR_SIVALS(ndr, ndr->offset, v);
352         ndr->offset += 4;
353         return NT_STATUS_OK;
354 }
355
356 /*
357   push a udlong
358 */
359 NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
360 {
361         NDR_PUSH_ALIGN(ndr, 4);
362         NDR_PUSH_NEED_BYTES(ndr, 8);
363         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
364         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
365         ndr->offset += 8;
366         return NT_STATUS_OK;
367 }
368
369 /*
370   push a udlongr
371 */
372 NTSTATUS ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
373 {
374         NDR_PUSH_ALIGN(ndr, 4);
375         NDR_PUSH_NEED_BYTES(ndr, 8);
376         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
377         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
378         ndr->offset += 8;
379         return NT_STATUS_OK;
380 }
381
382 /*
383   push a int64
384 */
385 NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
386 {
387         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
388 }
389
390 /*
391   push a hyper
392 */
393 NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
394 {
395         NDR_PUSH_ALIGN(ndr, 8);
396         return ndr_push_udlong(ndr, NDR_SCALARS, v);
397 }
398
399 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
400 {
401         NDR_PUSH_ALIGN(ndr, size);
402         return NT_STATUS_OK;
403 }
404
405 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
406 {
407         NDR_PULL_ALIGN(ndr, size);
408         return NT_STATUS_OK;
409 }
410
411 /*
412   push some bytes
413 */
414 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
415 {
416         NDR_PUSH_NEED_BYTES(ndr, n);
417         memcpy(ndr->data + ndr->offset, data, n);
418         ndr->offset += n;
419         return NT_STATUS_OK;
420 }
421
422 /*
423   push some zero bytes
424 */
425 NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
426 {
427         NDR_PUSH_NEED_BYTES(ndr, n);
428         memset(ndr->data + ndr->offset, 0, n);
429         ndr->offset += n;
430         return NT_STATUS_OK;
431 }
432
433 /*
434   push an array of uint8
435 */
436 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
437 {
438         if (!(ndr_flags & NDR_SCALARS)) {
439                 return NT_STATUS_OK;
440         }
441         return ndr_push_bytes(ndr, data, n);
442 }
443
444 /*
445   push an array of uint16
446 */
447 NTSTATUS ndr_push_array_uint16(struct ndr_push *ndr, int ndr_flags, const uint16_t *data, uint32_t n)
448 {
449         int i;
450         if (!(ndr_flags & NDR_SCALARS)) {
451                 return NT_STATUS_OK;
452         }
453         for (i=0;i<n;i++) {
454                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, data[i]));
455         }
456         return NT_STATUS_OK;
457 }
458
459 /*
460   push an array of uint32_t
461 */
462 NTSTATUS ndr_push_array_uint32(struct ndr_push *ndr, int ndr_flags, const uint32_t *data, uint32_t n)
463 {
464         int i;
465         if (!(ndr_flags & NDR_SCALARS)) {
466                 return NT_STATUS_OK;
467         }
468         for (i=0;i<n;i++) {
469                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, data[i]));
470         }
471         return NT_STATUS_OK;
472 }
473
474 /*
475   push an array of hyper
476 */
477 NTSTATUS ndr_push_array_hyper(struct ndr_push *ndr, int ndr_flags, const uint64_t *data, uint32_t n)
478 {
479         int i;
480         if (!(ndr_flags & NDR_SCALARS)) {
481                 return NT_STATUS_OK;
482         }
483         for (i=0;i<n;i++) {
484                 NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, data[i]));
485         }
486         return NT_STATUS_OK;
487 }
488
489 /*
490   push an array of hyper
491 */
492 NTSTATUS ndr_push_array_WERROR(struct ndr_push *ndr, int ndr_flags, const WERROR *data, uint32_t n)
493 {
494         int i;
495         if (!(ndr_flags & NDR_SCALARS)) {
496                 return NT_STATUS_OK;
497         }
498         for (i=0;i<n;i++) {
499                 NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, data[i]));
500         }
501         return NT_STATUS_OK;
502 }
503
504 /*
505   save the current position
506  */
507 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
508 {
509         save->offset = ndr->offset;
510 }
511
512 /*
513   restore the position
514  */
515 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
516 {
517         ndr->offset = save->offset;
518 }
519
520 /*
521   push a unique non-zero value if a pointer is non-NULL, otherwise 0
522 */
523 NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
524 {
525         uint32_t ptr = 0;
526         if (p) {
527                 ndr->ptr_count++;
528                 ptr = ndr->ptr_count;
529         }
530         return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
531 }
532
533 /*
534   push always a 0, if a pointer is NULL it's a fatal error
535 */
536 NTSTATUS ndr_push_ref_ptr(struct ndr_push *ndr, const void *p)
537 {
538         if (p == NULL) {
539                 return NT_STATUS_INVALID_PARAMETER_MIX;
540         }
541         return ndr_push_uint32(ndr, NDR_SCALARS, 0);
542 }
543
544 /*
545   pull a general string from the wire
546 */
547 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
548 {
549         char *as=NULL;
550         uint32_t len1, ofs, len2;
551         uint16_t len3;
552         int ret;
553         int chset = CH_UTF16;
554         unsigned byte_mul = 2;
555         unsigned flags = ndr->flags;
556         unsigned c_len_term = 0;
557
558         if (!(ndr_flags & NDR_SCALARS)) {
559                 return NT_STATUS_OK;
560         }
561
562         if (NDR_BE(ndr)) {
563                 chset = CH_UTF16BE;
564         }
565
566         if (flags & LIBNDR_FLAG_STR_ASCII) {
567                 chset = CH_DOS;
568                 byte_mul = 1;
569                 flags &= ~LIBNDR_FLAG_STR_ASCII;
570         }
571
572         if (flags & LIBNDR_FLAG_STR_UTF8) {
573                 chset = CH_UTF8;
574                 byte_mul = 1;
575                 flags &= ~LIBNDR_FLAG_STR_UTF8;
576         }
577
578         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
579         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
580                 c_len_term = 1;
581                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
582         }
583
584         switch (flags & LIBNDR_STRING_FLAGS) {
585         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
586         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
587                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
588                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
589                 if (ofs != 0) {
590                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
591                                               ndr->flags & LIBNDR_STRING_FLAGS);
592                 }
593                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
594                 if (len2 > len1) {
595                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
596                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
597                                               len1, ofs, len2);
598                 }
599                 if (len2 == 0) {
600                         *s = talloc_strdup(ndr, "");
601                         break;
602                 }
603                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
604                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
605                                             ndr->data+ndr->offset, 
606                                             (len2 + c_len_term)*byte_mul,
607                                             (void **)&as);
608                 if (ret == -1) {
609                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
610                                               "Bad character conversion");
611                 }
612                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
613
614                 /* this is a way of detecting if a string is sent with the wrong
615                    termination */
616                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
617                         if (strlen(as) < (len2 + c_len_term)) {
618                                 DEBUG(6,("short string '%s'\n", as));
619                         }
620                 } else {
621                         if (strlen(as) == (len2 + c_len_term)) {
622                                 DEBUG(6,("long string '%s'\n", as));
623                         }
624                 }
625                 *s = as;
626                 break;
627
628         case LIBNDR_FLAG_STR_SIZE4:
629         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
630                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
631                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
632                 if (len1 == 0) {
633                         *s = talloc_strdup(ndr, "");
634                         break;
635                 }
636                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
637                                             ndr->data+ndr->offset, 
638                                             (len1 + c_len_term)*byte_mul,
639                                             (void **)&as);
640                 if (ret == -1) {
641                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
642                                               "Bad character conversion");
643                 }
644                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
645
646                 /* this is a way of detecting if a string is sent with the wrong
647                    termination */
648                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
649                         if (strlen(as) < (len1 + c_len_term)) {
650                                 DEBUG(6,("short string '%s'\n", as));
651                         }
652                 } else {
653                         if (strlen(as) == (len1 + c_len_term)) {
654                                 DEBUG(6,("long string '%s'\n", as));
655                         }
656                 }
657                 *s = as;
658                 break;
659
660         case LIBNDR_FLAG_STR_LEN4:
661         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
662                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
663                 if (ofs != 0) {
664                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
665                                               ndr->flags & LIBNDR_STRING_FLAGS);
666                 }
667                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
668                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
669                 if (len1 == 0) {
670                         *s = talloc_strdup(ndr, "");
671                         break;
672                 }
673                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
674                                             ndr->data+ndr->offset, 
675                                             (len1 + c_len_term)*byte_mul,
676                                             (void **)&as);
677                 if (ret == -1) {
678                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
679                                               "Bad character conversion");
680                 }
681                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
682
683                 /* this is a way of detecting if a string is sent with the wrong
684                    termination */
685                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
686                         if (strlen(as) < (len1 + c_len_term)) {
687                                 DEBUG(6,("short string '%s'\n", as));
688                         }
689                 } else {
690                         if (strlen(as) == (len1 + c_len_term)) {
691                                 DEBUG(6,("long string '%s'\n", as));
692                         }
693                 }
694                 *s = as;
695                 break;
696
697
698         case LIBNDR_FLAG_STR_SIZE2:
699         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
700                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
701                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
702                 if (len3 == 0) {
703                         *s = talloc_strdup(ndr, "");
704                         break;
705                 }
706                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
707                                             ndr->data+ndr->offset, 
708                                             (len3 + c_len_term)*byte_mul,
709                                             (void **)&as);
710                 if (ret == -1) {
711                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
712                                               "Bad character conversion");
713                 }
714                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
715
716                 /* this is a way of detecting if a string is sent with the wrong
717                    termination */
718                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
719                         if (strlen(as) < (len3 + c_len_term)) {
720                                 DEBUG(6,("short string '%s'\n", as));
721                         }
722                 } else {
723                         if (strlen(as) == (len3 + c_len_term)) {
724                                 DEBUG(6,("long string '%s'\n", as));
725                         }
726                 }
727                 *s = as;
728                 break;
729
730         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
731                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
732                 NDR_PULL_NEED_BYTES(ndr, len3);
733                 if (len3 == 0) {
734                         *s = talloc_strdup(ndr, "");
735                         break;
736                 }
737                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
738                                             ndr->data+ndr->offset, 
739                                             len3,
740                                             (void **)&as);
741                 if (ret == -1) {
742                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
743                                               "Bad character conversion");
744                 }
745                 NDR_CHECK(ndr_pull_advance(ndr, len3));
746                 *s = as;
747                 break;
748
749         case LIBNDR_FLAG_STR_NULLTERM:
750                 if (byte_mul == 1) {
751                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
752                 } else {
753                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
754                 }
755                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
756                                             ndr->data+ndr->offset, 
757                                             len1,
758                                             (void **)&as);
759                 if (ret == -1) {
760                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
761                                               "Bad character conversion");
762                 }
763                 NDR_CHECK(ndr_pull_advance(ndr, len1));
764                 *s = as;
765                 break;
766
767         case LIBNDR_FLAG_STR_FIXLEN15:
768         case LIBNDR_FLAG_STR_FIXLEN32:
769                 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
770                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
771                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
772                                             ndr->data+ndr->offset, 
773                                             len1*byte_mul,
774                                             (void **)&as);
775                 if (ret == -1) {
776                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
777                                               "Bad character conversion");
778                 }
779                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
780                 *s = as;
781                 break;
782
783         default:
784                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
785                                       ndr->flags & LIBNDR_STRING_FLAGS);
786         }
787
788         return NT_STATUS_OK;
789 }
790
791
792 /*
793   push a general string onto the wire
794 */
795 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
796 {
797         ssize_t s_len, c_len, d_len;
798         int ret;
799         int chset = CH_UTF16;
800         unsigned flags = ndr->flags;
801         unsigned byte_mul = 2;
802         unsigned c_len_term = 1;
803
804         if (!(ndr_flags & NDR_SCALARS)) {
805                 return NT_STATUS_OK;
806         }
807
808         if (NDR_BE(ndr)) {
809                 chset = CH_UTF16BE;
810         }
811         
812         s_len = s?strlen(s):0;
813         c_len = s?strlen_m(s):0;
814
815         if (flags & LIBNDR_FLAG_STR_ASCII) {
816                 chset = CH_DOS;
817                 byte_mul = 1;
818                 flags &= ~LIBNDR_FLAG_STR_ASCII;
819         }
820
821         if (flags & LIBNDR_FLAG_STR_UTF8) {
822                 chset = CH_UTF8;
823                 byte_mul = 1;
824                 flags &= ~LIBNDR_FLAG_STR_UTF8;
825         }
826
827         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
828
829         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
830                 c_len_term = 0;
831                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
832         }
833
834         switch (flags & LIBNDR_STRING_FLAGS) {
835         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
836                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len+c_len_term));
837                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
838                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len+c_len_term));
839                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
840                 ret = convert_string(CH_UNIX, chset, 
841                                      s, s_len+1,
842                                      ndr->data+ndr->offset, 
843                                      byte_mul*(c_len+1));
844                 if (ret == -1) {
845                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
846                                               "Bad character conversion");
847                 }
848                 ndr->offset += byte_mul*(c_len+1);
849                 break;
850
851         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
852                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
853                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
854                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
855                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
856                 ret = convert_string(CH_UNIX, chset, 
857                                      s, s_len,
858                                      ndr->data+ndr->offset, c_len*byte_mul);
859                 if (ret == -1) {
860                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
861                                               "Bad character conversion");
862                 }
863                 ndr->offset += c_len*byte_mul;
864                 break;
865
866         case LIBNDR_FLAG_STR_LEN4:
867                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
868                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len + c_len_term));
869                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
870                 ret = convert_string(CH_UNIX, chset, 
871                                      s, s_len + 1,
872                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
873                 if (ret == -1) {
874                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
875                                               "Bad character conversion");
876                 }
877                 ndr->offset += byte_mul*(c_len+1);
878                 break;
879
880         case LIBNDR_FLAG_STR_SIZE4:
881                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len + c_len_term));
882                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
883                 ret = convert_string(CH_UNIX, chset, 
884                                      s, s_len + 1,
885                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
886                 if (ret == -1) {
887                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
888                                               "Bad character conversion");
889                 }
890                 ndr->offset += byte_mul*(c_len+1);
891                 break;
892
893         case LIBNDR_FLAG_STR_SIZE2:
894                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len + c_len_term));
895                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
896                 ret = convert_string(CH_UNIX, chset, 
897                                      s, s_len + 1,
898                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
899                 if (ret == -1) {
900                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
901                                               "Bad character conversion");
902                 }
903                 ndr->offset += byte_mul*(c_len+1);
904                 break;
905
906         case LIBNDR_FLAG_STR_NULLTERM:
907                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
908                 ret = convert_string(CH_UNIX, chset, 
909                                      s, s_len+1,
910                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
911                 if (ret == -1) {
912                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
913                                               "Bad character conversion");
914                 }
915                 ndr->offset += byte_mul*(c_len+1);
916                 break;
917
918         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
919                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len*byte_mul));
920                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
921                 ret = convert_string(CH_UNIX, chset, 
922                                      s, s_len,
923                                      ndr->data+ndr->offset, c_len*byte_mul);
924                 if (ret == -1) {
925                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
926                                               "Bad character conversion");
927                 }
928                 ndr->offset += c_len*byte_mul;
929                 break;
930
931         case LIBNDR_FLAG_STR_FIXLEN15:
932         case LIBNDR_FLAG_STR_FIXLEN32:
933                 d_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
934                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*d_len);
935                 ret = convert_string(CH_UNIX, chset, 
936                                      s, s_len,
937                                      ndr->data+ndr->offset, byte_mul*d_len);
938                 if (ret == -1) {
939                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
940                                               "Bad character conversion");
941                 }
942                 ndr->offset += byte_mul*d_len;
943                 break;
944
945         default:
946                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
947                                       ndr->flags & LIBNDR_STRING_FLAGS);
948         }
949
950         return NT_STATUS_OK;
951 }
952
953 /*
954   push a general string onto the wire
955 */
956 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
957 {
958         size_t c_len;
959         unsigned flags = ndr->flags;
960         unsigned byte_mul = 2;
961         unsigned c_len_term = 1;
962
963         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
964                 return 32;
965         }
966         if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
967                 return 15;
968         }
969         
970         c_len = s?strlen_m(s):0;
971
972         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
973                 byte_mul = 1;
974         }
975
976         if (flags & LIBNDR_FLAG_STR_NOTERM) {
977                 c_len_term = 0;
978         }
979
980         c_len = c_len + c_len_term;
981
982         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
983                 c_len = c_len * byte_mul;
984         }
985
986         return c_len;
987 }
988
989
990 /*
991   push a NTTIME
992 */
993 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
994 {
995         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
996         return NT_STATUS_OK;
997 }
998
999 /*
1000   pull a NTTIME
1001 */
1002 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
1003 {
1004         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
1005         return NT_STATUS_OK;
1006 }
1007
1008 /*
1009   push a NTTIME
1010 */
1011 NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
1012 {
1013         t /= 10000000;
1014         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
1015         return NT_STATUS_OK;
1016 }
1017
1018 /*
1019   pull a NTTIME_1sec
1020 */
1021 NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
1022 {
1023         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
1024         (*t) *= 10000000;
1025         return NT_STATUS_OK;
1026 }
1027
1028 /*
1029   pull a NTTIME_hyper
1030 */
1031 NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
1032 {
1033         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
1034         return NT_STATUS_OK;
1035 }
1036
1037 /*
1038   push a NTTIME_hyper
1039 */
1040 NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
1041 {
1042         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
1043         return NT_STATUS_OK;
1044 }
1045
1046 /*
1047   push a time_t
1048 */
1049 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
1050 {
1051         return ndr_push_uint32(ndr, ndr_flags, t);
1052 }
1053
1054 /*
1055   pull a time_t
1056 */
1057 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
1058 {
1059         uint32_t tt;
1060         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
1061         *t = tt;
1062         return NT_STATUS_OK;
1063 }
1064
1065
1066 /*
1067   pull a ipv4address
1068 */
1069 NTSTATUS ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
1070 {
1071         struct ipv4_addr in;
1072         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &in.addr));
1073         in.addr = htonl(in.addr);
1074         *address = talloc_strdup(ndr, sys_inet_ntoa(in));
1075         NT_STATUS_HAVE_NO_MEMORY(*address);
1076         return NT_STATUS_OK;
1077 }
1078
1079 /*
1080   push a ipv4address
1081 */
1082 NTSTATUS ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
1083 {
1084         uint32_t addr = interpret_addr(address);
1085         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
1086         return NT_STATUS_OK;
1087 }
1088
1089 /*
1090   print a ipv4address
1091 */
1092 void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
1093                            const char *address)
1094 {
1095         ndr->print(ndr, "%-25s: %s", name, address);
1096 }
1097
1098
1099 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
1100 {
1101         ndr->print(ndr, "%s: struct %s", name, type);
1102 }
1103
1104 void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
1105                     const char *val, uint_t value)
1106 {
1107         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
1108                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1109         } else {
1110                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1111         }
1112 }
1113
1114 void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint_t flag, uint_t value)
1115 {
1116         /* this is an attempt to support multi-bit bitmap masks */
1117         value &= flag;
1118
1119         while (!(flag & 1)) {
1120                 flag >>= 1;
1121                 value >>= 1;
1122         }       
1123         if (flag == 1) {
1124                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
1125         } else {
1126                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
1127         }
1128 }
1129
1130 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
1131 {
1132         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
1133 }
1134
1135 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
1136 {
1137         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
1138 }
1139
1140 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
1141 {
1142         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1143 }
1144
1145 void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
1146 {
1147         ndr->print(ndr, "%-25s: %d", name, v);
1148 }
1149
1150 void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
1151 {
1152         ndr->print(ndr, "%-25s: 0x%08x%08x (%llu)", name,
1153                    (uint32_t)(v >> 32),
1154                    (uint32_t)(v & 0xFFFFFFFF),
1155                    v);
1156 }
1157
1158 void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
1159 {
1160         ndr_print_udlong(ndr, name, v);
1161 }
1162
1163 void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
1164 {
1165         ndr->print(ndr, "%-25s: 0x%08x%08x (%lld)", name, 
1166                    (uint32_t)(v >> 32), 
1167                    (uint32_t)(v & 0xFFFFFFFF),
1168                    v);
1169 }
1170
1171 void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
1172 {
1173         ndr_print_dlong(ndr, name, v);
1174 }
1175
1176 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1177 {
1178         if (p) {
1179                 ndr->print(ndr, "%-25s: *", name);
1180         } else {
1181                 ndr->print(ndr, "%-25s: NULL", name);
1182         }
1183 }
1184
1185 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
1186 {
1187         if (s) {
1188                 ndr->print(ndr, "%-25s: '%s'", name, s);
1189         } else {
1190                 ndr->print(ndr, "%-25s: NULL", name);
1191         }
1192 }
1193
1194 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1195 {
1196         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1197 }
1198
1199 void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1200 {
1201         /* this is a standard NTTIME here
1202          * as it's already converted in the pull/push code
1203          */
1204         ndr_print_NTTIME(ndr, name, t);
1205 }
1206
1207 void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
1208 {
1209         ndr_print_NTTIME(ndr, name, t);
1210 }
1211
1212 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1213 {
1214         if (t == (time_t)-1 || t == 0) {
1215                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1216         } else {
1217                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1218         }
1219 }
1220
1221 void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1222 {
1223         ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1224 }
1225
1226 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1227 {
1228         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1229 }
1230
1231 void ndr_print_array_WERROR(struct ndr_print *ndr, const char *name, 
1232                             const WERROR *data, uint32_t count)
1233 {
1234         int i;
1235
1236         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1237         ndr->depth++;
1238         for (i=0;i<count;i++) {
1239                 char *idx=NULL;
1240                 asprintf(&idx, "[%d]", i);
1241                 if (idx) {
1242                         ndr_print_WERROR(ndr, idx, data[i]);
1243                         free(idx);
1244                 }
1245         }
1246         ndr->depth--;   
1247 }
1248
1249 void ndr_print_array_hyper(struct ndr_print *ndr, const char *name, 
1250                             const uint64_t *data, uint32_t count)
1251 {
1252         int i;
1253
1254         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1255         ndr->depth++;
1256         for (i=0;i<count;i++) {
1257                 char *idx=NULL;
1258                 asprintf(&idx, "[%d]", i);
1259                 if (idx) {
1260                         ndr_print_hyper(ndr, idx, data[i]);
1261                         free(idx);
1262                 }
1263         }
1264         ndr->depth--;   
1265 }
1266
1267 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
1268                             const uint32_t *data, uint32_t count)
1269 {
1270         int i;
1271
1272         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1273         ndr->depth++;
1274         for (i=0;i<count;i++) {
1275                 char *idx=NULL;
1276                 asprintf(&idx, "[%d]", i);
1277                 if (idx) {
1278                         ndr_print_uint32(ndr, idx, data[i]);
1279                         free(idx);
1280                 }
1281         }
1282         ndr->depth--;   
1283 }
1284
1285 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
1286                             const uint16_t *data, uint32_t count)
1287 {
1288         int i;
1289
1290         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1291         ndr->depth++;
1292         for (i=0;i<count;i++) {
1293                 char *idx=NULL;
1294                 asprintf(&idx, "[%d]", i);
1295                 if (idx) {
1296                         ndr_print_uint16(ndr, idx, data[i]);
1297                         free(idx);
1298                 }
1299         }
1300         ndr->depth--;   
1301 }
1302
1303 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1304                            const uint8_t *data, uint32_t count)
1305 {
1306         int i;
1307
1308         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1309                 char s[1202];
1310                 for (i=0;i<count;i++) {
1311                         snprintf(&s[i*2], 3, "%02x", data[i]);
1312                 }
1313                 s[i*2] = 0;
1314                 ndr->print(ndr, "%-25s: %s", name, s);
1315                 return;
1316         }
1317
1318         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1319         ndr->depth++;
1320         for (i=0;i<count;i++) {
1321                 char *idx=NULL;
1322                 asprintf(&idx, "[%d]", i);
1323                 if (idx) {
1324                         ndr_print_uint8(ndr, idx, data[i]);
1325                         free(idx);
1326                 }
1327         }
1328         ndr->depth--;   
1329 }
1330
1331 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1332 {
1333         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
1334         if (r.length) {
1335                 dump_data(10, r.data, r.length);
1336         }
1337 }
1338
1339
1340 /*
1341   push a DATA_BLOB onto the wire. 
1342 */
1343 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1344 {
1345         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1346                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1347                         blob.length = NDR_ALIGN(ndr, 2);
1348                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1349                         blob.length = NDR_ALIGN(ndr, 4);
1350                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1351                         blob.length = NDR_ALIGN(ndr, 8);
1352                 }
1353                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1354                 data_blob_clear(&blob);
1355         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1356                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1357         }
1358         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1359         return NT_STATUS_OK;
1360 }
1361
1362 /*
1363   pull a DATA_BLOB from the wire. 
1364 */
1365 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1366 {
1367         uint32_t length;
1368
1369         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1370                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1371                         length = NDR_ALIGN(ndr, 2);
1372                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1373                         length = NDR_ALIGN(ndr, 4);
1374                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1375                         length = NDR_ALIGN(ndr, 8);
1376                 }
1377                 if (ndr->data_size - ndr->offset < length) {
1378                         length = ndr->data_size - ndr->offset;
1379                 }
1380         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1381                 length = ndr->data_size - ndr->offset;
1382         } else {
1383                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1384         }
1385         NDR_PULL_NEED_BYTES(ndr, length);
1386         *blob = data_blob_talloc(ndr, ndr->data+ndr->offset, length);
1387         ndr->offset += length;
1388         return NT_STATUS_OK;
1389 }
1390
1391 uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1392 {
1393         return ret + data->length;
1394 }
1395
1396 uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
1397 {
1398         /* FIXME: Is this correct for all strings ? */
1399         if(!(*string)) return ret;
1400         return ret+strlen(*string)+1;
1401 }