cde0b52f3beea1855cb15c73fd5d656a55625009
[samba.git] / source4 / 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
25 #define NDR_BE(ndr) ((ndr)->flags & LIBNDR_FLAG_BIGENDIAN)
26 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
27 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
28 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
29 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
30
31 /*
32   parse a uint8
33 */
34 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, uint8 *v)
35 {
36         NDR_PULL_NEED_BYTES(ndr, 1);
37         *v = CVAL(ndr->data, ndr->offset);
38         ndr->offset += 1;
39         return NT_STATUS_OK;
40 }
41
42
43 /*
44   parse a uint16
45 */
46 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, uint16 *v)
47 {
48         NDR_PULL_ALIGN(ndr, 2);
49         NDR_PULL_NEED_BYTES(ndr, 2);
50         *v = NDR_SVAL(ndr, ndr->offset);
51         ndr->offset += 2;
52         return NT_STATUS_OK;
53 }
54
55
56 /*
57   parse a uint32
58 */
59 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, uint32 *v)
60 {
61         NDR_PULL_ALIGN(ndr, 4);
62         NDR_PULL_NEED_BYTES(ndr, 4);
63         *v = NDR_IVAL(ndr, ndr->offset);
64         ndr->offset += 4;
65         return NT_STATUS_OK;
66 }
67
68 /*
69   parse a HYPER_T
70 */
71 NTSTATUS ndr_pull_HYPER_T(struct ndr_pull *ndr, HYPER_T *v)
72 {
73         NDR_PULL_ALIGN(ndr, 8);
74         NDR_PULL_NEED_BYTES(ndr, 8);
75         v->low = NDR_IVAL(ndr, ndr->offset);
76         v->high = NDR_IVAL(ndr, ndr->offset+4);
77         ndr->offset += 8;
78         return NT_STATUS_OK;
79 }
80
81 /*
82   pull a NTSTATUS
83 */
84 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, NTSTATUS *status)
85 {
86         uint32 v;
87         NDR_CHECK(ndr_pull_uint32(ndr, &v));
88         *status = NT_STATUS(v);
89         return NT_STATUS_OK;
90 }
91
92 /*
93   push a NTSTATUS
94 */
95 NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, NTSTATUS status)
96 {
97         return ndr_push_uint32(ndr, NT_STATUS_V(status));
98 }
99
100 void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS *r)
101 {
102         ndr->print(ndr, "%-25s: %s", name, nt_errstr(*r));
103 }
104
105 /*
106   pull a WERROR
107 */
108 NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, WERROR *status)
109 {
110         uint32 v;
111         NDR_CHECK(ndr_pull_uint32(ndr, &v));
112         *status = W_ERROR(v);
113         return NT_STATUS_OK;
114 }
115
116 /*
117   push a WERROR
118 */
119 NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, WERROR status)
120 {
121         return ndr_push_uint32(ndr, W_ERROR_V(status));
122 }
123
124 void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR *r)
125 {
126         ndr->print(ndr, "%-25s: %s", name, win_errstr(*r));
127 }
128
129 /*
130   parse a set of bytes
131 */
132 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, char *data, uint32 n)
133 {
134         NDR_PULL_NEED_BYTES(ndr, n);
135         memcpy(data, ndr->data + ndr->offset, n);
136         ndr->offset += n;
137         return NT_STATUS_OK;
138 }
139
140 /*
141   pull an array of uint8
142 */
143 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, char *data, uint32 n)
144 {
145         if (!(ndr_flags & NDR_SCALARS)) {
146                 return NT_STATUS_OK;
147         }
148         return ndr_pull_bytes(ndr, data, n);
149 }
150
151
152 /*
153   pull an array of uint16
154 */
155 NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags, uint16 *data, uint32 n)
156 {
157         uint32 i;
158         if (!(ndr_flags & NDR_SCALARS)) {
159                 return NT_STATUS_OK;
160         }
161         for (i=0;i<n;i++) {
162                 NDR_CHECK(ndr_pull_uint16(ndr, &data[i]));
163         }
164         return NT_STATUS_OK;
165 }
166
167 /*
168   pull a const array of uint32
169 */
170 NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags, uint32 *data, uint32 n)
171 {
172         uint32 i;
173         if (!(ndr_flags & NDR_SCALARS)) {
174                 return NT_STATUS_OK;
175         }
176         for (i=0;i<n;i++) {
177                 NDR_CHECK(ndr_pull_uint32(ndr, &data[i]));
178         }
179         return NT_STATUS_OK;
180 }
181
182 /*
183   push a uint8
184 */
185 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, uint8 v)
186 {
187         NDR_PUSH_NEED_BYTES(ndr, 1);
188         SCVAL(ndr->data, ndr->offset, v);
189         ndr->offset += 1;
190         return NT_STATUS_OK;
191 }
192
193 /*
194   push a uint16
195 */
196 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, uint16 v)
197 {
198         NDR_PUSH_ALIGN(ndr, 2);
199         NDR_PUSH_NEED_BYTES(ndr, 2);
200         NDR_SSVAL(ndr, ndr->offset, v);
201         ndr->offset += 2;
202         return NT_STATUS_OK;
203 }
204
205 /*
206   push a uint32
207 */
208 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, uint32 v)
209 {
210         NDR_PUSH_ALIGN(ndr, 4);
211         NDR_PUSH_NEED_BYTES(ndr, 4);
212         NDR_SIVAL(ndr, ndr->offset, v);
213         ndr->offset += 4;
214         return NT_STATUS_OK;
215 }
216
217 /*
218   push a HYPER_T
219 */
220 NTSTATUS ndr_push_HYPER_T(struct ndr_push *ndr, HYPER_T v)
221 {
222         NDR_PUSH_ALIGN(ndr, 8);
223         NDR_PUSH_NEED_BYTES(ndr, 8);
224         NDR_SIVAL(ndr, ndr->offset, v.low);
225         NDR_SIVAL(ndr, ndr->offset+4, v.high);
226         ndr->offset += 8;
227         return NT_STATUS_OK;
228 }
229
230 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
231 {
232         NDR_PUSH_ALIGN(ndr, size);
233         return NT_STATUS_OK;
234 }
235
236 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
237 {
238         NDR_PULL_ALIGN(ndr, size);
239         return NT_STATUS_OK;
240 }
241
242 /*
243   push some bytes
244 */
245 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const char *data, uint32 n)
246 {
247         NDR_PUSH_NEED_BYTES(ndr, n);
248         memcpy(ndr->data + ndr->offset, data, n);
249         ndr->offset += n;
250         return NT_STATUS_OK;
251 }
252
253 /*
254   push some zero bytes
255 */
256 NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32 n)
257 {
258         NDR_PUSH_NEED_BYTES(ndr, n);
259         memset(ndr->data + ndr->offset, 0, n);
260         ndr->offset += n;
261         return NT_STATUS_OK;
262 }
263
264 /*
265   push an array of uint8
266 */
267 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const char *data, uint32 n)
268 {
269         if (!(ndr_flags & NDR_SCALARS)) {
270                 return NT_STATUS_OK;
271         }
272         return ndr_push_bytes(ndr, data, n);
273 }
274
275 /*
276   push an array of uint16
277 */
278 NTSTATUS ndr_push_array_uint16(struct ndr_push *ndr, int ndr_flags, const uint16 *data, uint32 n)
279 {
280         int i;
281         if (!(ndr_flags & NDR_SCALARS)) {
282                 return NT_STATUS_OK;
283         }
284         for (i=0;i<n;i++) {
285                 NDR_CHECK(ndr_push_uint16(ndr, data[i]));
286         }
287         return NT_STATUS_OK;
288 }
289
290 /*
291   push an array of uint32
292 */
293 NTSTATUS ndr_push_array_uint32(struct ndr_push *ndr, int ndr_flags, const uint32 *data, uint32 n)
294 {
295         int i;
296         if (!(ndr_flags & NDR_SCALARS)) {
297                 return NT_STATUS_OK;
298         }
299         for (i=0;i<n;i++) {
300                 NDR_CHECK(ndr_push_uint32(ndr, data[i]));
301         }
302         return NT_STATUS_OK;
303 }
304
305 /*
306   save the current position
307  */
308 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
309 {
310         save->offset = ndr->offset;
311 }
312
313 /*
314   restore the position
315  */
316 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
317 {
318         ndr->offset = save->offset;
319 }
320
321 /*
322   push a 1 if a pointer is non-NULL, otherwise 0
323 */
324 NTSTATUS ndr_push_ptr(struct ndr_push *ndr, const void *p)
325 {
326         uint32 ptr = 0;
327         if (p) {
328                 /* we do this to ensure that we generate unique ref ids,
329                    which means we can handle the case where a MS programmer
330                    forgot to mark a pointer as unique */
331                 ndr->ptr_count++;
332                 ptr = ndr->ptr_count;
333         }
334         return ndr_push_uint32(ndr, ptr);
335 }
336
337
338 /*
339   pull a general string from the wire
340 */
341 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
342 {
343         char *as=NULL;
344         uint32 len1, ofs, len2;
345         uint16 len3;
346         int ret;
347         int chset = CH_UCS2;
348
349         if (!(ndr_flags & NDR_SCALARS)) {
350                 return NT_STATUS_OK;
351         }
352
353         if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
354                 chset = CH_UCS2BE;
355         }
356
357         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
358         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
359         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
360                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
361                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
362                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
363                 if (len2 > len1) {
364                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
365                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
366                                               len1, ofs, len2);
367                 }
368                 if (len2 == 0) {
369                         *s = talloc_strdup(ndr->mem_ctx, "");
370                         break;
371                 }
372                 NDR_PULL_NEED_BYTES(ndr, len2*2);
373                 ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
374                                             ndr->data+ndr->offset, 
375                                             len2*2,
376                                             (const void **)&as);
377                 if (ret == -1) {
378                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
379                                               "Bad character conversion");
380                 }
381                 NDR_CHECK(ndr_pull_advance(ndr, len2*2));
382                 *s = as;
383                 break;
384
385         case LIBNDR_FLAG_STR_SIZE4:
386                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
387                 NDR_PULL_NEED_BYTES(ndr, len1*2);
388                 if (len1 == 0) {
389                         *s = talloc_strdup(ndr->mem_ctx, "");
390                         break;
391                 }
392                 ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
393                                             ndr->data+ndr->offset, 
394                                             len1*2,
395                                             (const void **)&as);
396                 if (ret == -1) {
397                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
398                                               "Bad character conversion");
399                 }
400                 NDR_CHECK(ndr_pull_advance(ndr, len1*2));
401                 *s = as;
402                 break;
403
404         case LIBNDR_FLAG_STR_NULLTERM:
405                 len1 = strnlen_w(ndr->data+ndr->offset, 
406                                  (ndr->data_size - ndr->offset)/2);
407                 if (len1*2+2 <= ndr->data_size - ndr->offset) {
408                         len1++;
409                 }
410                 ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, 
411                                             ndr->data+ndr->offset, 
412                                             len1*2,
413                                             (const void **)s);
414                 if (ret == -1) {
415                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
416                                               "Bad character conversion");
417                 }
418                 NDR_CHECK(ndr_pull_advance(ndr, len1*2));
419                 break;
420
421         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
422                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
423                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
424                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
425                 if (len2 > len1) {
426                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
427                                               "Bad ascii string lengths len1=%u ofs=%u len2=%u\n", 
428                                               len1, ofs, len2);
429                 }
430                 NDR_ALLOC_N(ndr, as, (len2+1));
431                 NDR_CHECK(ndr_pull_bytes(ndr, as, len2));
432                 as[len2] = 0;
433                 (*s) = as;
434                 break;
435
436         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
437                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
438                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
439                 NDR_ALLOC_N(ndr, as, (len2+1));
440                 NDR_CHECK(ndr_pull_bytes(ndr, as, len2));
441                 as[len2] = 0;
442                 (*s) = as;
443                 break;
444
445         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2:
446                 NDR_CHECK(ndr_pull_uint16(ndr, &len3));
447                 NDR_ALLOC_N(ndr, as, (len3+1));
448                 NDR_CHECK(ndr_pull_bytes(ndr, as, len3));
449                 as[len3] = 0;
450                 (*s) = as;
451                 break;
452
453         default:
454                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
455                                       ndr->flags & LIBNDR_STRING_FLAGS);
456         }
457
458         return NT_STATUS_OK;
459 }
460
461
462 /*
463   push a general string onto the wire
464 */
465 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
466 {
467         ssize_t s_len, c_len;
468         int ret;
469         int chset = CH_UCS2;
470
471         if (!(ndr_flags & NDR_SCALARS)) {
472                 return NT_STATUS_OK;
473         }
474
475         if (ndr->flags & LIBNDR_FLAG_BIGENDIAN) {
476                 chset = CH_UCS2BE;
477         }
478         
479         s_len = s?strlen(s):0;
480         c_len = s?strlen_m(s):0;
481
482         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
483         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
484                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
485                 NDR_CHECK(ndr_push_uint32(ndr, 0));
486                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
487                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
488                 ret = convert_string(CH_UNIX, chset, 
489                                      s, s_len+1,
490                                      ndr->data+ndr->offset, c_len*2 + 2);
491                 if (ret == -1) {
492                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
493                                               "Bad character conversion");
494                 }
495                 ndr->offset += c_len*2 + 2;
496                 break;
497
498         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
499                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
500                 NDR_CHECK(ndr_push_uint32(ndr, 0));
501                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
502                 NDR_PUSH_NEED_BYTES(ndr, c_len*2);
503                 ret = convert_string(CH_UNIX, chset, 
504                                      s, s_len,
505                                      ndr->data+ndr->offset, c_len*2);
506                 if (ret == -1) {
507                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
508                                               "Bad character conversion");
509                 }
510                 ndr->offset += c_len*2;
511                 break;
512
513         case LIBNDR_FLAG_STR_SIZE4:
514                 NDR_CHECK(ndr_push_uint32(ndr, c_len + 1));
515                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
516                 ret = convert_string(CH_UNIX, chset, 
517                                      s, s_len + 1,
518                                      ndr->data+ndr->offset, c_len*2 + 2);
519                 if (ret == -1) {
520                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
521                                               "Bad character conversion");
522                 }
523                 ndr->offset += c_len*2 + 2;
524                 break;
525
526         case LIBNDR_FLAG_STR_NULLTERM:
527                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
528                 ret = convert_string(CH_UNIX, chset, 
529                                      s, s_len+1,
530                                      ndr->data+ndr->offset, c_len*2 + 2);
531                 if (ret == -1) {
532                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
533                                               "Bad character conversion");
534                 }
535                 ndr->offset += c_len*2 + 2;
536                 break;
537                 
538         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
539                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
540                 NDR_CHECK(ndr_push_uint32(ndr, 0));
541                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
542                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
543                 ret = convert_string(CH_UNIX, CH_DOS, 
544                                      s, s_len + 1,
545                                      ndr->data+ndr->offset, c_len + 1);
546                 if (ret == -1) {
547                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
548                                               "Bad character conversion");
549                 }
550                 ndr->offset += c_len + 1;
551                 break;
552
553         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
554                 NDR_CHECK(ndr_push_uint32(ndr, 0));
555                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
556                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
557                 ret = convert_string(CH_UNIX, CH_DOS, 
558                                      s, s_len + 1,
559                                      ndr->data+ndr->offset, c_len + 1);
560                 if (ret == -1) {
561                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
562                                               "Bad character conversion");
563                 }
564                 ndr->offset += c_len + 1;
565                 break;
566
567         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2:
568                 NDR_CHECK(ndr_push_uint16(ndr, c_len+1));
569                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
570                 ret = convert_string(CH_UNIX, CH_DOS, 
571                                      s, s_len + 1,
572                                      ndr->data+ndr->offset, c_len + 1);
573                 if (ret == -1) {
574                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
575                                               "Bad character conversion");
576                 }
577                 ndr->offset += c_len + 1;
578                 break;
579
580         default:
581                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
582                                       ndr->flags & LIBNDR_STRING_FLAGS);
583         }
584
585         return NT_STATUS_OK;
586 }
587
588 /*
589   push a NTTIME
590 */
591 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t)
592 {
593         NDR_CHECK(ndr_push_uint32(ndr, t.low));
594         NDR_CHECK(ndr_push_uint32(ndr, t.high));
595         return NT_STATUS_OK;
596 }
597
598 /*
599   pull a NTTIME
600 */
601 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t)
602 {
603         NDR_CHECK(ndr_pull_uint32(ndr, &t->low));
604         NDR_CHECK(ndr_pull_uint32(ndr, &t->high));
605         return NT_STATUS_OK;
606 }
607
608 /*
609   push a time_t
610 */
611 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t)
612 {
613         return ndr_push_uint32(ndr, t);
614 }
615
616 /*
617   pull a time_t
618 */
619 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, time_t *t)
620 {
621         uint32 tt;
622         NDR_CHECK(ndr_pull_uint32(ndr, &tt));
623         *t = tt;
624         return NT_STATUS_OK;
625 }
626
627
628 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
629 {
630         ndr->print(ndr, "%s: struct %s", name, type);
631 }
632
633 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8 v)
634 {
635         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
636 }
637
638 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16 v)
639 {
640         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
641 }
642
643 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32 v)
644 {
645         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
646 }
647
648 void ndr_print_HYPER_T(struct ndr_print *ndr, const char *name, HYPER_T v)
649 {
650         ndr->print(ndr, "%-25s: 0x%08x%08x", name, v.high, v.low);
651 }
652
653 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
654 {
655         if (p) {
656                 ndr->print(ndr, "%-25s: *", name);
657         } else {
658                 ndr->print(ndr, "%-25s: NULL", name);
659         }
660 }
661
662 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
663 {
664         if (s) {
665                 ndr->print(ndr, "%-25s: '%s'", name, s);
666         } else {
667                 ndr->print(ndr, "%-25s: NULL", name);
668         }
669 }
670
671 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
672 {
673         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr->mem_ctx, &t));
674 }
675
676 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
677 {
678         if (t == (time_t)-1 || t == 0) {
679                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
680         } else {
681                 ndr->print(ndr, "%-25s: %s", name, http_timestring(ndr->mem_ctx, t));
682         }
683 }
684
685 void ndr_print_union(struct ndr_print *ndr, const char *name, uint16 level, const char *type)
686 {
687         ndr->print(ndr, "%-25s: union %s(case %u)", name, type, level);
688 }
689
690 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16 level)
691 {
692         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
693 }
694
695 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
696                             const uint32 *data, uint32 count)
697 {
698         int i;
699
700         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
701         ndr->depth++;
702         for (i=0;i<count;i++) {
703                 char *idx=NULL;
704                 asprintf(&idx, "[%d]", i);
705                 if (idx) {
706                         ndr_print_uint32(ndr, idx, data[i]);
707                         free(idx);
708                 }
709         }
710         ndr->depth--;   
711 }
712
713 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
714                             const uint16 *data, uint32 count)
715 {
716         int i;
717
718         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
719         ndr->depth++;
720         for (i=0;i<count;i++) {
721                 char *idx=NULL;
722                 asprintf(&idx, "[%d]", i);
723                 if (idx) {
724                         ndr_print_uint16(ndr, idx, data[i]);
725                         free(idx);
726                 }
727         }
728         ndr->depth--;   
729 }
730
731 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
732                            const uint8 *data, uint32 count)
733 {
734         int i;
735
736         if (count <= 32 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
737                 char s[65];
738                 for (i=0;i<count;i++) {
739                         snprintf(&s[i*2], 3, "%02x", data[i]);
740                 }
741                 s[i*2] = 0;
742                 ndr->print(ndr, "%-25s: %s", name, s);
743                 return;
744         }
745
746         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
747         ndr->depth++;
748         for (i=0;i<count;i++) {
749                 char *idx=NULL;
750                 asprintf(&idx, "[%d]", i);
751                 if (idx) {
752                         ndr_print_uint8(ndr, idx, data[i]);
753                         free(idx);
754                 }
755         }
756         ndr->depth--;   
757 }
758
759 /*
760   build a GUID from a string
761 */
762 NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
763 {
764         uint32 time_low;
765         uint32 time_mid, time_hi_and_version;
766         uint32 clock_seq[2];
767         uint32 node[6];
768         int i;
769
770         if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
771                          &time_low, &time_mid, &time_hi_and_version, 
772                          &clock_seq[0], &clock_seq[1],
773                          &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
774                 return NT_STATUS_INVALID_PARAMETER;
775         }
776
777         guid->time_low = time_low;
778         guid->time_mid = time_mid;
779         guid->time_hi_and_version = time_hi_and_version;
780         guid->clock_seq[0] = clock_seq[0];
781         guid->clock_seq[1] = clock_seq[1];
782         for (i=0;i<6;i++) {
783                 guid->node[i] = node[i];
784         }
785
786         return NT_STATUS_OK;
787 }
788
789 /*
790   its useful to be able to display these in debugging messages
791 */
792 const char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
793 {
794         return talloc_asprintf(mem_ctx, 
795                                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
796                                guid->time_low, guid->time_mid,
797                                guid->time_hi_and_version,
798                                guid->clock_seq[0],
799                                guid->clock_seq[1],
800                                guid->node[0], guid->node[1],
801                                guid->node[2], guid->node[3],
802                                guid->node[4], guid->node[5]);
803 }
804
805 void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
806 {
807         ndr->print(ndr, "%-25s: %s", GUID_string(ndr->mem_ctx, guid));
808 }
809
810 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
811 {
812         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
813         if (r.length) {
814                 dump_data(10, r.data, r.length);
815         }
816 }
817
818
819 /*
820   push a DATA_BLOB onto the wire. 
821 */
822 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob)
823 {
824         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
825                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
826                         blob.length = NDR_ALIGN(ndr, 2);
827                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
828                         blob.length = NDR_ALIGN(ndr, 4);
829                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
830                         blob.length = NDR_ALIGN(ndr, 8);
831                 }
832                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
833                 data_blob_clear(&blob);
834         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
835                 NDR_CHECK(ndr_push_uint32(ndr, blob.length));
836         }
837         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
838         return NT_STATUS_OK;
839 }
840
841 /*
842   pull a DATA_BLOB from the wire. 
843 */
844 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob)
845 {
846         uint32 length;
847
848         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
849                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
850                         length = NDR_ALIGN(ndr, 2);
851                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
852                         length = NDR_ALIGN(ndr, 4);
853                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
854                         length = NDR_ALIGN(ndr, 8);
855                 }
856                 if (ndr->data_size - ndr->offset < length) {
857                         length = ndr->data_size - ndr->offset;
858                 }
859         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
860                 length = ndr->data_size - ndr->offset;
861         } else {
862                 NDR_CHECK(ndr_pull_uint32(ndr, &length));
863         }
864         NDR_PULL_NEED_BYTES(ndr, length);
865         *blob = data_blob_talloc(ndr->mem_ctx, ndr->data+ndr->offset, length);
866         ndr->offset += length;
867         return NT_STATUS_OK;
868 }