2 Unix SMB/CIFS implementation.
4 routines for marshalling/unmarshalling basic types
6 Copyright (C) Andrew Tridgell 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, uint8 *v)
30 NDR_PULL_NEED_BYTES(ndr, 1);
31 *v = CVAL(ndr->data, ndr->offset);
40 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, uint16 *v)
42 NDR_PULL_ALIGN(ndr, 2);
43 NDR_PULL_NEED_BYTES(ndr, 2);
44 *v = SVAL(ndr->data, ndr->offset);
53 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, uint32 *v)
55 NDR_PULL_ALIGN(ndr, 4);
56 NDR_PULL_NEED_BYTES(ndr, 4);
57 *v = IVAL(ndr->data, ndr->offset);
65 NTSTATUS ndr_pull_HYPER_T(struct ndr_pull *ndr, HYPER_T *v)
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);
78 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, NTSTATUS *status)
81 NDR_CHECK(ndr_pull_uint32(ndr, &v));
82 *status = NT_STATUS(v);
89 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, char *data, uint32 n)
91 NDR_PULL_NEED_BYTES(ndr, n);
92 memcpy(data, ndr->data + ndr->offset, n);
98 pull an array of uint8
100 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, char *data, uint32 n)
102 return ndr_pull_bytes(ndr, data, n);
107 pull an array of uint16
109 NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, uint16 *data, uint32 n)
113 NDR_CHECK(ndr_pull_uint16(ndr, &data[i]));
119 pull a const array of uint32
121 NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, uint32 *data, uint32 n)
125 NDR_CHECK(ndr_pull_uint32(ndr, &data[i]));
133 NTSTATUS ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, GUID *guid)
135 if (ndr_flags & NDR_SCALARS) {
136 return ndr_pull_bytes(ndr, guid->info, GUID_SIZE);
145 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, uint8 v)
147 NDR_PUSH_NEED_BYTES(ndr, 1);
148 SCVAL(ndr->data, ndr->offset, v);
156 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, uint16 v)
158 NDR_PUSH_ALIGN(ndr, 2);
159 NDR_PUSH_NEED_BYTES(ndr, 2);
160 SSVAL(ndr->data, ndr->offset, v);
168 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, uint32 v)
170 NDR_PUSH_ALIGN(ndr, 4);
171 NDR_PUSH_NEED_BYTES(ndr, 4);
172 SIVAL(ndr->data, ndr->offset, v);
180 NTSTATUS ndr_push_HYPER_T(struct ndr_push *ndr, HYPER_T v)
182 NDR_PUSH_ALIGN(ndr, 8);
183 NDR_PUSH_NEED_BYTES(ndr, 8);
184 SIVAL(ndr->data, ndr->offset, v.low);
185 SIVAL(ndr->data, ndr->offset+4, v.high);
190 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
192 NDR_PUSH_ALIGN(ndr, size);
196 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
198 NDR_PULL_ALIGN(ndr, size);
205 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const char *data, uint32 n)
207 NDR_PUSH_NEED_BYTES(ndr, n);
208 memcpy(ndr->data + ndr->offset, data, n);
214 push an array of uint8
216 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, const char *data, uint32 n)
218 return ndr_push_bytes(ndr, data, n);
222 push an array of uint32
224 NTSTATUS ndr_push_array_uint32(struct ndr_push *ndr, const uint32 *data, uint32 n)
228 NDR_CHECK(ndr_push_uint32(ndr, data[i]));
234 save the current position
236 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
238 save->offset = ndr->offset;
244 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
246 ndr->offset = save->offset;
250 this is used when a packet has a 4 byte length field. We remember the start position
251 and come back to it later to fill in the size
253 NTSTATUS ndr_push_length4_start(struct ndr_push *ndr, struct ndr_push_save *save)
255 NDR_PUSH_ALIGN(ndr, 4);
256 ndr_push_save(ndr, save);
257 return ndr_push_uint32(ndr, 0);
260 NTSTATUS ndr_push_length4_end(struct ndr_push *ndr, struct ndr_push_save *save)
262 struct ndr_push_save save2;
263 ndr_push_save(ndr, &save2);
264 ndr_push_restore(ndr, save);
265 NDR_CHECK(ndr_push_uint32(ndr, save2.offset - ndr->offset));
266 ndr_push_restore(ndr, &save2);
271 push a 1 if a pointer is non-NULL, otherwise 0
273 NTSTATUS ndr_push_ptr(struct ndr_push *ndr, const void *p)
275 return ndr_push_uint32(ndr, p?0xaabbccdd:0);
279 push a comformant, variable ucs2 string onto the wire from a C string
281 NTSTATUS ndr_push_unistr(struct ndr_push *ndr, const char *s)
285 len = push_ucs2_talloc(ndr->mem_ctx, (smb_ucs2_t **)&ws, s);
287 return NT_STATUS_INVALID_PARAMETER;
289 NDR_CHECK(ndr_push_uint32(ndr, len/2));
290 NDR_CHECK(ndr_push_uint32(ndr, 0));
291 NDR_CHECK(ndr_push_uint32(ndr, len/2));
292 NDR_CHECK(ndr_push_bytes(ndr, ws, len));
297 push a comformant, variable ucs2 string onto the wire from a C string
300 NTSTATUS ndr_push_unistr_noterm(struct ndr_push *ndr, const char *s)
304 len = push_ucs2_talloc(ndr->mem_ctx, (smb_ucs2_t **)&ws, s);
306 return NT_STATUS_INVALID_PARAMETER;
308 NDR_CHECK(ndr_push_uint32(ndr, len/2 - 1));
309 NDR_CHECK(ndr_push_uint32(ndr, 0));
310 NDR_CHECK(ndr_push_uint32(ndr, len/2 - 1));
311 NDR_CHECK(ndr_push_bytes(ndr, ws, len - 2));
316 pull a comformant, variable ucs2 string from the wire into a C string
318 NTSTATUS ndr_pull_unistr(struct ndr_pull *ndr, const char **s)
321 uint32 len1, ofs, len2;
323 NDR_CHECK(ndr_pull_uint32(ndr, &len1));
324 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
325 NDR_CHECK(ndr_pull_uint32(ndr, &len2));
327 return NT_STATUS_INVALID_PARAMETER;
329 NDR_ALLOC_N(ndr, ws, (len1+1)*2);
330 NDR_CHECK(ndr_pull_bytes(ndr, ws, len2*2));
331 SSVAL(ws, len1*2, 0);
332 SSVAL(ws, len2*2, 0);
333 pull_ucs2_talloc(ndr->mem_ctx, &as, (const smb_ucs2_t *)ws);
335 return NT_STATUS_INVALID_PARAMETER;
342 pull a comformant, variable ucs2 string from the wire into a C string
344 NTSTATUS ndr_pull_unistr_noterm(struct ndr_pull *ndr, const char **s)
346 return ndr_pull_unistr(ndr, s);
350 push a 4 byte offset pointer, remembering where we are so we can later fill
353 NTSTATUS ndr_push_offset(struct ndr_push *ndr, struct ndr_push_save *ofs)
355 NDR_PUSH_ALIGN(ndr, 4);
356 ndr_push_save(ndr, ofs);
357 return ndr_push_uint32(ndr, 0);
361 fill in the correct offset in a saved offset pointer
362 the offset is taken relative to 'save'
364 NTSTATUS ndr_push_offset_ptr(struct ndr_push *ndr,
365 struct ndr_push_save *ofs,
366 struct ndr_push_save *save)
368 struct ndr_push_save save2;
369 ndr_push_save(ndr, &save2);
370 ndr_push_restore(ndr, ofs);
371 NDR_CHECK(ndr_push_uint32(ndr, save2.offset - save->offset));
372 ndr_push_restore(ndr, &save2);
380 NTSTATUS ndr_push_GUID(struct ndr_push *ndr, int ndr_flags, GUID *guid)
382 if (ndr_flags & NDR_SCALARS) {
383 return ndr_push_bytes(ndr, guid->info, GUID_SIZE);
391 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t)
393 NDR_CHECK(ndr_push_uint32(ndr, t.low));
394 NDR_CHECK(ndr_push_uint32(ndr, t.high));
401 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t)
403 NDR_CHECK(ndr_pull_uint32(ndr, &t->low));
404 NDR_CHECK(ndr_pull_uint32(ndr, &t->high));
409 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
411 ndr->print(ndr, "%s: struct %s", name, type);
414 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8 v)
416 ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
419 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16 v)
421 ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
424 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32 v)
426 ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
429 void ndr_print_HYPER_T(struct ndr_print *ndr, const char *name, HYPER_T v)
431 ndr->print(ndr, "%-25s: 0x%08x%08x", name, v.high, v.low);
434 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
437 ndr->print(ndr, "%-25s: *", name);
439 ndr->print(ndr, "%-25s: NULL", name);
443 void ndr_print_unistr_noterm(struct ndr_print *ndr, const char *name, const char *s)
445 ndr->print(ndr, "%-25s: '%s'", name, s);
448 void ndr_print_unistr(struct ndr_print *ndr, const char *name, const char *s)
450 ndr->print(ndr, "%-25s: '%s'", name, s);
453 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
455 ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr->mem_ctx, &t));
458 void ndr_print_union(struct ndr_print *ndr, const char *name, uint16 level, const char *type)
460 ndr->print(ndr, "%-25s: union %s(case %u)", name, type, level);
463 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16 level)
465 ndr->print(ndr, "UNKNOWN LEVEL %u", level);
468 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name,
469 uint32 *data, uint32 count)
473 ndr->print(ndr, "%s: ARRAY(%d)", name, count);
475 for (i=0;i<count;i++) {
477 asprintf(&idx, "[%d]", i);
479 ndr_print_uint32(ndr, idx, data[i]);
486 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name,
487 uint8 *data, uint32 count)
491 ndr->print(ndr, "%s: ARRAY(%d)", name, count);
493 for (i=0;i<count;i++) {
495 asprintf(&idx, "[%d]", i);
497 ndr_print_uint8(ndr, idx, data[i]);
504 void ndr_print_GUID(struct ndr_print *ndr, const char *name, struct GUID *guid)
506 ndr->print(ndr, "%-25s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
508 IVAL(guid->info, 0), SVAL(guid->info, 4), SVAL(guid->info, 6),
509 guid->info[8], guid->info[9],
510 guid->info[10], guid->info[11], guid->info[12], guid->info[13],
511 guid->info[14], guid->info[15]);
516 pull a spoolss style "relative string"
518 NTSTATUS ndr_pull_relstr(struct ndr_pull *ndr, int ndr_flags, const char **s)
522 struct ndr_pull_save save;
524 if (!(ndr_flags & NDR_SCALARS)) {
528 NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
529 ndr_pull_save(ndr, &save);
530 NDR_CHECK(ndr_pull_set_offset(ndr, ofs));
531 ret = convert_string_talloc(ndr->mem_ctx, CH_UCS2, CH_UNIX,
532 ndr->data+ndr->offset,
533 ndr->data_size - ndr->offset,
536 return ndr_pull_error(ndr, NDR_ERR_RELSTR, "Bad relative string");
538 ndr_pull_restore(ndr, &save);
543 push a spoolss style "relative string"
545 NTSTATUS ndr_push_relstr(struct ndr_push *ndr, int ndr_flags, const char **s)
547 struct ndr_push_save *save;
548 if (ndr_flags & NDR_SCALARS) {
549 save = talloc(ndr->mem_ctx, sizeof(*save));
550 if (!save) return NT_STATUS_NO_MEMORY;
551 NDR_CHECK(ndr_push_align(ndr, 4));
552 ndr_push_save(ndr, save);
553 NDR_CHECK(ndr_push_uint32(ndr, 0xFFFFFFFF));
554 save->next = ndr->relstr_list;
555 ndr->relstr_list = save;
557 if (ndr_flags & NDR_BUFFERS) {
558 struct ndr_push_save save2;
561 save = ndr->relstr_list;
563 return ndr_push_error(ndr, NDR_ERR_RELSTR, "Empty relstr stack");
565 ndr->relstr_list = save->next;
566 NDR_CHECK(ndr_push_align(ndr, 2));
567 ndr_push_save(ndr, &save2);
568 ndr_push_restore(ndr, save);
569 NDR_CHECK(ndr_push_uint32(ndr, save2.offset));
570 ndr_push_restore(ndr, &save2);
571 len = 2*(strlen_m(*s)+1);
572 NDR_PUSH_NEED_BYTES(ndr, len);
573 ret = push_ucs2(NULL, ndr->data + ndr->offset, *s, len, STR_TERMINATE);
575 return ndr_push_error(ndr, NDR_ERR_CHARCNV, "Bad string conversion");
582 void ndr_print_relstr(struct ndr_print *ndr, const char *name, const char **s)
584 ndr_print_unistr(ndr, name, *s);