r275: added IDL and test code for samr_QueryDisplayInfo3(),
[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
25 #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == 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_BE(ndr)) {
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         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
423                 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
424                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
425                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
426                 if (len2 > len1) {
427                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
428                                               "Bad ascii string lengths len1=%u ofs=%u len2=%u\n", 
429                                               len1, ofs, len2);
430                 }
431                 NDR_ALLOC_N(ndr, as, (len2+1));
432                 NDR_CHECK(ndr_pull_bytes(ndr, as, len2));
433                 as[len2] = 0;
434                 (*s) = as;
435                 break;
436
437         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
438                 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
439                 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
440                 NDR_ALLOC_N(ndr, as, (len2+1));
441                 NDR_CHECK(ndr_pull_bytes(ndr, as, len2));
442                 as[len2] = 0;
443                 (*s) = as;
444                 break;
445
446         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2:
447                 NDR_CHECK(ndr_pull_uint16(ndr, &len3));
448                 NDR_ALLOC_N(ndr, as, (len3+1));
449                 NDR_CHECK(ndr_pull_bytes(ndr, as, len3));
450                 as[len3] = 0;
451                 (*s) = as;
452                 break;
453
454         default:
455                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
456                                       ndr->flags & LIBNDR_STRING_FLAGS);
457         }
458
459         return NT_STATUS_OK;
460 }
461
462
463 /*
464   push a general string onto the wire
465 */
466 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
467 {
468         ssize_t s_len, c_len;
469         int ret;
470         int chset = CH_UCS2;
471
472         if (!(ndr_flags & NDR_SCALARS)) {
473                 return NT_STATUS_OK;
474         }
475
476         if (NDR_BE(ndr)) {
477                 chset = CH_UCS2BE;
478         }
479         
480         s_len = s?strlen(s):0;
481         c_len = s?strlen_m(s):0;
482
483         switch (ndr->flags & LIBNDR_STRING_FLAGS) {
484         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
485                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
486                 NDR_CHECK(ndr_push_uint32(ndr, 0));
487                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
488                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
489                 ret = convert_string(CH_UNIX, chset, 
490                                      s, s_len+1,
491                                      ndr->data+ndr->offset, c_len*2 + 2);
492                 if (ret == -1) {
493                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
494                                               "Bad character conversion");
495                 }
496                 ndr->offset += c_len*2 + 2;
497                 break;
498
499         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
500                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
501                 NDR_CHECK(ndr_push_uint32(ndr, 0));
502                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
503                 NDR_PUSH_NEED_BYTES(ndr, c_len*2);
504                 ret = convert_string(CH_UNIX, chset, 
505                                      s, s_len,
506                                      ndr->data+ndr->offset, c_len*2);
507                 if (ret == -1) {
508                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
509                                               "Bad character conversion");
510                 }
511                 ndr->offset += c_len*2;
512                 break;
513
514         case LIBNDR_FLAG_STR_SIZE4:
515                 NDR_CHECK(ndr_push_uint32(ndr, c_len + 1));
516                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
517                 ret = convert_string(CH_UNIX, chset, 
518                                      s, s_len + 1,
519                                      ndr->data+ndr->offset, c_len*2 + 2);
520                 if (ret == -1) {
521                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
522                                               "Bad character conversion");
523                 }
524                 ndr->offset += c_len*2 + 2;
525                 break;
526
527         case LIBNDR_FLAG_STR_NULLTERM:
528                 NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2);
529                 ret = convert_string(CH_UNIX, chset, 
530                                      s, s_len+1,
531                                      ndr->data+ndr->offset, c_len*2 + 2);
532                 if (ret == -1) {
533                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
534                                               "Bad character conversion");
535                 }
536                 ndr->offset += c_len*2 + 2;
537                 break;
538                 
539         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
540                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
541                 NDR_CHECK(ndr_push_uint32(ndr, 0));
542                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
543                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
544                 ret = convert_string(CH_UNIX, CH_DOS, 
545                                      s, s_len + 1,
546                                      ndr->data+ndr->offset, c_len + 1);
547                 if (ret == -1) {
548                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
549                                               "Bad character conversion");
550                 }
551                 ndr->offset += c_len + 1;
552                 break;
553
554         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
555                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
556                 NDR_CHECK(ndr_push_uint32(ndr, 0));
557                 NDR_CHECK(ndr_push_uint32(ndr, c_len));
558                 NDR_PUSH_NEED_BYTES(ndr, c_len);
559                 ret = convert_string(CH_UNIX, CH_DOS, 
560                                      s, s_len,
561                                      ndr->data+ndr->offset, c_len);
562                 if (ret == -1) {
563                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
564                                               "Bad character conversion");
565                 }
566                 ndr->offset += c_len;
567                 break;
568
569         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
570                 NDR_CHECK(ndr_push_uint32(ndr, 0));
571                 NDR_CHECK(ndr_push_uint32(ndr, c_len+1));
572                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
573                 ret = convert_string(CH_UNIX, CH_DOS, 
574                                      s, s_len + 1,
575                                      ndr->data+ndr->offset, c_len + 1);
576                 if (ret == -1) {
577                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
578                                               "Bad character conversion");
579                 }
580                 ndr->offset += c_len + 1;
581                 break;
582
583         case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2:
584                 NDR_CHECK(ndr_push_uint16(ndr, c_len+1));
585                 NDR_PUSH_NEED_BYTES(ndr, c_len + 1);
586                 ret = convert_string(CH_UNIX, CH_DOS, 
587                                      s, s_len + 1,
588                                      ndr->data+ndr->offset, c_len + 1);
589                 if (ret == -1) {
590                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
591                                               "Bad character conversion");
592                 }
593                 ndr->offset += c_len + 1;
594                 break;
595
596         default:
597                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
598                                       ndr->flags & LIBNDR_STRING_FLAGS);
599         }
600
601         return NT_STATUS_OK;
602 }
603
604 /*
605   push a NTTIME
606 */
607 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t)
608 {
609         NDR_CHECK(ndr_push_uint32(ndr, t.low));
610         NDR_CHECK(ndr_push_uint32(ndr, t.high));
611         return NT_STATUS_OK;
612 }
613
614 /*
615   pull a NTTIME
616 */
617 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t)
618 {
619         NDR_CHECK(ndr_pull_uint32(ndr, &t->low));
620         NDR_CHECK(ndr_pull_uint32(ndr, &t->high));
621         return NT_STATUS_OK;
622 }
623
624 /*
625   push a time_t
626 */
627 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t)
628 {
629         return ndr_push_uint32(ndr, t);
630 }
631
632 /*
633   pull a time_t
634 */
635 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, time_t *t)
636 {
637         uint32 tt;
638         NDR_CHECK(ndr_pull_uint32(ndr, &tt));
639         *t = tt;
640         return NT_STATUS_OK;
641 }
642
643
644 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
645 {
646         ndr->print(ndr, "%s: struct %s", name, type);
647 }
648
649 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8 v)
650 {
651         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
652 }
653
654 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16 v)
655 {
656         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
657 }
658
659 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32 v)
660 {
661         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
662 }
663
664 void ndr_print_HYPER_T(struct ndr_print *ndr, const char *name, HYPER_T v)
665 {
666         ndr->print(ndr, "%-25s: 0x%08x%08x", name, v.high, v.low);
667 }
668
669 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
670 {
671         if (p) {
672                 ndr->print(ndr, "%-25s: *", name);
673         } else {
674                 ndr->print(ndr, "%-25s: NULL", name);
675         }
676 }
677
678 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
679 {
680         if (s) {
681                 ndr->print(ndr, "%-25s: '%s'", name, s);
682         } else {
683                 ndr->print(ndr, "%-25s: NULL", name);
684         }
685 }
686
687 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
688 {
689         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr->mem_ctx, &t));
690 }
691
692 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
693 {
694         if (t == (time_t)-1 || t == 0) {
695                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
696         } else {
697                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr->mem_ctx, t));
698         }
699 }
700
701 void ndr_print_union(struct ndr_print *ndr, const char *name, uint16 level, const char *type)
702 {
703         ndr->print(ndr, "%-25s: union %s(case %u)", name, type, level);
704 }
705
706 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16 level)
707 {
708         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
709 }
710
711 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
712                             const uint32 *data, uint32 count)
713 {
714         int i;
715
716         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
717         ndr->depth++;
718         for (i=0;i<count;i++) {
719                 char *idx=NULL;
720                 asprintf(&idx, "[%d]", i);
721                 if (idx) {
722                         ndr_print_uint32(ndr, idx, data[i]);
723                         free(idx);
724                 }
725         }
726         ndr->depth--;   
727 }
728
729 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
730                             const uint16 *data, uint32 count)
731 {
732         int i;
733
734         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
735         ndr->depth++;
736         for (i=0;i<count;i++) {
737                 char *idx=NULL;
738                 asprintf(&idx, "[%d]", i);
739                 if (idx) {
740                         ndr_print_uint16(ndr, idx, data[i]);
741                         free(idx);
742                 }
743         }
744         ndr->depth--;   
745 }
746
747 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
748                            const uint8 *data, uint32 count)
749 {
750         int i;
751
752         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
753                 char s[1202];
754                 for (i=0;i<count;i++) {
755                         snprintf(&s[i*2], 3, "%02x", data[i]);
756                 }
757                 s[i*2] = 0;
758                 ndr->print(ndr, "%-25s: %s", name, s);
759                 return;
760         }
761
762         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
763         ndr->depth++;
764         for (i=0;i<count;i++) {
765                 char *idx=NULL;
766                 asprintf(&idx, "[%d]", i);
767                 if (idx) {
768                         ndr_print_uint8(ndr, idx, data[i]);
769                         free(idx);
770                 }
771         }
772         ndr->depth--;   
773 }
774
775 /*
776   build a GUID from a string
777 */
778 NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
779 {
780         uint32 time_low;
781         uint32 time_mid, time_hi_and_version;
782         uint32 clock_seq[2];
783         uint32 node[6];
784         int i;
785
786         if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
787                          &time_low, &time_mid, &time_hi_and_version, 
788                          &clock_seq[0], &clock_seq[1],
789                          &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) {
790                 return NT_STATUS_INVALID_PARAMETER;
791         }
792
793         guid->time_low = time_low;
794         guid->time_mid = time_mid;
795         guid->time_hi_and_version = time_hi_and_version;
796         guid->clock_seq[0] = clock_seq[0];
797         guid->clock_seq[1] = clock_seq[1];
798         for (i=0;i<6;i++) {
799                 guid->node[i] = node[i];
800         }
801
802         return NT_STATUS_OK;
803 }
804
805 /*
806   its useful to be able to display these in debugging messages
807 */
808 const char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
809 {
810         return talloc_asprintf(mem_ctx, 
811                                "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
812                                guid->time_low, guid->time_mid,
813                                guid->time_hi_and_version,
814                                guid->clock_seq[0],
815                                guid->clock_seq[1],
816                                guid->node[0], guid->node[1],
817                                guid->node[2], guid->node[3],
818                                guid->node[4], guid->node[5]);
819 }
820
821 void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
822 {
823         ndr->print(ndr, "%-25s: %s", name, GUID_string(ndr->mem_ctx, guid));
824 }
825
826 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
827 {
828         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
829         if (r.length) {
830                 dump_data(10, r.data, r.length);
831         }
832 }
833
834
835 /*
836   push a DATA_BLOB onto the wire. 
837 */
838 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, DATA_BLOB blob)
839 {
840         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
841                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
842                         blob.length = NDR_ALIGN(ndr, 2);
843                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
844                         blob.length = NDR_ALIGN(ndr, 4);
845                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
846                         blob.length = NDR_ALIGN(ndr, 8);
847                 }
848                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
849                 data_blob_clear(&blob);
850         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
851                 NDR_CHECK(ndr_push_uint32(ndr, blob.length));
852         }
853         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
854         return NT_STATUS_OK;
855 }
856
857 /*
858   pull a DATA_BLOB from the wire. 
859 */
860 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob)
861 {
862         uint32 length;
863
864         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
865                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
866                         length = NDR_ALIGN(ndr, 2);
867                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
868                         length = NDR_ALIGN(ndr, 4);
869                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
870                         length = NDR_ALIGN(ndr, 8);
871                 }
872                 if (ndr->data_size - ndr->offset < length) {
873                         length = ndr->data_size - ndr->offset;
874                 }
875         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
876                 length = ndr->data_size - ndr->offset;
877         } else {
878                 NDR_CHECK(ndr_pull_uint32(ndr, &length));
879         }
880         NDR_PULL_NEED_BYTES(ndr, length);
881         *blob = data_blob_talloc(ndr->mem_ctx, ndr->data+ndr->offset, length);
882         ndr->offset += length;
883         return NT_STATUS_OK;
884 }