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