2 Unix SMB/CIFS implementation.
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.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
32 #define NDR_BASE_MARSHALL_SIZE 1024
34 /* this guid indicates NDR encoding in a protocol tower */
35 const struct dcerpc_syntax_id ndr_transfer_syntax
= {
36 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
40 const struct dcerpc_syntax_id ndr64_transfer_syntax
= {
41 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
46 work out the number of bytes needed to align on a n byte boundary
48 size_t ndr_align_size(uint32_t offset
, size_t n
)
50 if ((offset
& (n
-1)) == 0) return 0;
51 return n
- (offset
& (n
-1));
55 initialise a ndr parse structure from a data blob
57 struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
61 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
62 if (!ndr
) return NULL
;
63 ndr
->current_mem_ctx
= mem_ctx
;
65 ndr
->data
= blob
->data
;
66 ndr
->data_size
= blob
->length
;
72 advance by 'size' bytes
74 NTSTATUS
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
77 if (ndr
->offset
> ndr
->data_size
) {
78 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
79 "ndr_pull_advance by %u failed",
86 set the parse offset to 'ofs'
88 static NTSTATUS
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
91 if (ndr
->offset
> ndr
->data_size
) {
92 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
93 "ndr_pull_set_offset %u failed",
99 /* save the offset/size of the current ndr state */
100 void ndr_pull_save(struct ndr_pull
*ndr
, struct ndr_pull_save
*save
)
102 save
->offset
= ndr
->offset
;
103 save
->data_size
= ndr
->data_size
;
106 /* restore the size/offset of a ndr structure */
107 void ndr_pull_restore(struct ndr_pull
*ndr
, struct ndr_pull_save
*save
)
109 ndr
->offset
= save
->offset
;
110 ndr
->data_size
= save
->data_size
;
114 /* create a ndr_push structure, ready for some marshalling */
115 struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
117 struct ndr_push
*ndr
;
119 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
125 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
126 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
135 /* create a ndr_push structure, ready for some marshalling */
136 struct ndr_push
*ndr_push_init(void)
138 return ndr_push_init_ctx(NULL
);
141 /* free a ndr_push structure */
142 void ndr_push_free(struct ndr_push
*ndr
)
148 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
149 DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
152 blob
.data
= ndr
->data
;
153 blob
.length
= ndr
->offset
;
155 if (ndr
->alloc_size
> ndr
->offset
) {
156 ndr
->data
[ndr
->offset
] = 0;
163 expand the available space in the buffer to ndr->offset + extra_size
165 NTSTATUS
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
167 uint32_t size
= extra_size
+ ndr
->offset
;
169 if (size
< ndr
->offset
) {
170 /* extra_size overflowed the offset */
171 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %u",
175 if (ndr
->alloc_size
> size
) {
179 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
180 if (size
+1 > ndr
->alloc_size
) {
181 ndr
->alloc_size
= size
+1;
183 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
185 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
192 void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...) _PRINTF_ATTRIBUTE(2,3)
198 va_start(ap
, format
);
199 vasprintf(&s
, format
, ap
);
202 for (i
=0;i
<ndr
->depth
;i
++) {
206 DEBUG(0,("%s\n", s
));
210 static void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...) _PRINTF_ATTRIBUTE(2,3)
215 for (i
=0;i
<ndr
->depth
;i
++) {
216 ndr
->private_data
= talloc_asprintf_append(
217 (char *)ndr
->private_data
, " ");
220 va_start(ap
, format
);
221 ndr
->private_data
= talloc_vasprintf_append(
222 (char *)ndr
->private_data
, format
, ap
);
224 ndr
->private_data
= talloc_asprintf_append(
225 (char *)ndr
->private_data
, "\n");
229 a useful helper function for printing idl structures via DEBUG()
231 void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
233 struct ndr_print
*ndr
;
235 ndr
= talloc_zero(NULL
, struct ndr_print
);
237 ndr
->print
= ndr_print_debug_helper
;
245 a useful helper function for printing idl unions via DEBUG()
247 void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
249 struct ndr_print
*ndr
;
251 ndr
= talloc_zero(NULL
, struct ndr_print
);
253 ndr
->print
= ndr_print_debug_helper
;
256 ndr_print_set_switch_value(ndr
, ptr
, level
);
262 a useful helper function for printing idl function calls via DEBUG()
264 void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
266 struct ndr_print
*ndr
;
268 ndr
= talloc_zero(NULL
, struct ndr_print
);
270 ndr
->print
= ndr_print_debug_helper
;
273 fn(ndr
, name
, flags
, ptr
);
279 a useful helper function for printing idl function calls to a string
281 char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
282 ndr_print_function_t fn
, const char *name
,
283 int flags
, void *ptr
)
285 struct ndr_print
*ndr
;
288 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
289 if (!ndr
) return NULL
;
290 if (!(ndr
->private_data
= talloc_strdup(mem_ctx
, ""))) {
294 ndr
->print
= ndr_print_string_helper
;
297 fn(ndr
, name
, flags
, ptr
);
298 ret
= (char *)ndr
->private_data
;
303 void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
305 /* the big/little endian flags are inter-dependent */
306 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
307 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
309 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
310 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
312 if (new_flags
& LIBNDR_FLAG_REMAINING
) {
313 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
315 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
316 (*pflags
) &= ~LIBNDR_FLAG_REMAINING
;
318 (*pflags
) |= new_flags
;
321 static NTSTATUS
ndr_map_error(enum ndr_err_code ndr_err
)
324 case NDR_ERR_BUFSIZE
:
325 return NT_STATUS_BUFFER_TOO_SMALL
;
327 return NT_STATUS_INTERNAL_ERROR
;
329 return NT_STATUS_NO_MEMORY
;
330 case NDR_ERR_ARRAY_SIZE
:
331 return NT_STATUS_ARRAY_BOUNDS_EXCEEDED
;
336 /* we should map all error codes to different status codes */
337 return NT_STATUS_INVALID_PARAMETER
;
341 return and possibly log an NDR error
343 NTSTATUS
ndr_pull_error(struct ndr_pull
*ndr
,
344 enum ndr_err_code ndr_err
,
345 const char *format
, ...) _PRINTF_ATTRIBUTE(3,4)
350 va_start(ap
, format
);
351 vasprintf(&s
, format
, ap
);
354 DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err
, s
));
358 return ndr_map_error(ndr_err
);
362 return and possibly log an NDR error
364 NTSTATUS
ndr_push_error(struct ndr_push
*ndr
,
365 enum ndr_err_code ndr_err
,
366 const char *format
, ...) _PRINTF_ATTRIBUTE(3,4)
371 va_start(ap
, format
);
372 vasprintf(&s
, format
, ap
);
375 DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err
, s
));
379 return ndr_map_error(ndr_err
);
383 handle subcontext buffers, which in midl land are user-marshalled, but
384 we use magic in pidl to make them easier to cope with
386 NTSTATUS
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
387 struct ndr_pull
**_subndr
,
391 struct ndr_pull
*subndr
;
392 uint32_t r_content_size
;
394 switch (header_size
) {
396 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
398 content_size
= size_is
;
400 r_content_size
= content_size
;
405 uint16_t content_size
;
406 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
407 if (size_is
>= 0 && size_is
!= content_size
) {
408 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
409 (int)size_is
, (int)content_size
);
411 r_content_size
= content_size
;
416 uint32_t content_size
;
417 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
418 if (size_is
>= 0 && size_is
!= content_size
) {
419 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
420 (int)size_is
, (int)content_size
);
422 r_content_size
= content_size
;
426 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
430 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
432 subndr
= talloc_zero(ndr
, struct ndr_pull
);
433 NT_STATUS_HAVE_NO_MEMORY(subndr
);
434 subndr
->flags
= ndr
->flags
;
435 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
437 subndr
->data
= ndr
->data
+ ndr
->offset
;
439 subndr
->data_size
= r_content_size
;
445 NTSTATUS
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
446 struct ndr_pull
*subndr
,
453 } else if (header_size
> 0) {
454 advance
= subndr
->data_size
;
456 advance
= subndr
->offset
;
458 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
462 NTSTATUS
ndr_push_subcontext_start(struct ndr_push
*ndr
,
463 struct ndr_push
**_subndr
,
467 struct ndr_push
*subndr
;
469 subndr
= ndr_push_init_ctx(ndr
);
470 NT_STATUS_HAVE_NO_MEMORY(subndr
);
471 subndr
->flags
= ndr
->flags
;
478 push a subcontext header
480 NTSTATUS
ndr_push_subcontext_end(struct ndr_push
*ndr
,
481 struct ndr_push
*subndr
,
486 ssize_t padding_len
= size_is
- subndr
->offset
;
487 if (padding_len
> 0) {
488 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
489 } else if (padding_len
< 0) {
490 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
491 (int)subndr
->offset
, (int)size_is
);
495 switch (header_size
) {
500 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
504 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
508 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
512 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
517 store a token in the ndr context, for later retrieval
519 NTSTATUS
ndr_token_store(TALLOC_CTX
*mem_ctx
,
520 struct ndr_token_list
**list
,
524 struct ndr_token_list
*tok
;
525 tok
= talloc(mem_ctx
, struct ndr_token_list
);
527 return NT_STATUS_NO_MEMORY
;
531 DLIST_ADD((*list
), tok
);
536 retrieve a token from a ndr context, using cmp_fn to match the tokens
538 NTSTATUS
ndr_token_retrieve_cmp_fn(struct ndr_token_list
**list
, const void *key
, uint32_t *v
,
539 comparison_fn_t _cmp_fn
, BOOL _remove_tok
)
541 struct ndr_token_list
*tok
;
542 for (tok
=*list
;tok
;tok
=tok
->next
) {
543 if (_cmp_fn
&& _cmp_fn(tok
->key
,key
)==0) goto found
;
544 else if (!_cmp_fn
&& tok
->key
== key
) goto found
;
546 return ndr_map_error(NDR_ERR_TOKEN
);
550 DLIST_REMOVE((*list
), tok
);
557 retrieve a token from a ndr context
559 NTSTATUS
ndr_token_retrieve(struct ndr_token_list
**list
, const void *key
, uint32_t *v
)
561 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, True
);
565 peek at but don't removed a token from a ndr context
567 uint32_t ndr_token_peek(struct ndr_token_list
**list
, const void *key
)
571 status
= ndr_token_retrieve_cmp_fn(list
, key
, &v
, NULL
, False
);
572 if (NT_STATUS_IS_OK(status
)) return v
;
577 pull an array size field and add it to the array_size_list token list
579 NTSTATUS
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
582 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &size
));
583 return ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
587 get the stored array size field
589 uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
591 return ndr_token_peek(&ndr
->array_size_list
, p
);
595 check the stored array size field
597 NTSTATUS
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
600 stored
= ndr_token_peek(&ndr
->array_size_list
, p
);
601 if (stored
!= size
) {
602 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
603 "Bad array size - got %u expected %u\n",
610 pull an array length field and add it to the array_length_list token list
612 NTSTATUS
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
614 uint32_t length
, offset
;
615 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &offset
));
617 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
618 "non-zero array offset %u\n", offset
);
620 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &length
));
621 return ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
625 get the stored array length field
627 uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
629 return ndr_token_peek(&ndr
->array_length_list
, p
);
633 check the stored array length field
635 NTSTATUS
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
638 stored
= ndr_token_peek(&ndr
->array_length_list
, p
);
639 if (stored
!= length
) {
640 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
641 "Bad array length - got %u expected %u\n",
650 NTSTATUS
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
652 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
655 NTSTATUS
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
657 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
660 NTSTATUS
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
662 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
666 retrieve a switch value
668 uint32_t ndr_push_get_switch_value(struct ndr_push
*ndr
, const void *p
)
670 return ndr_token_peek(&ndr
->switch_list
, p
);
673 uint32_t ndr_pull_get_switch_value(struct ndr_pull
*ndr
, const void *p
)
675 return ndr_token_peek(&ndr
->switch_list
, p
);
678 uint32_t ndr_print_get_switch_value(struct ndr_print
*ndr
, const void *p
)
680 return ndr_token_peek(&ndr
->switch_list
, p
);
684 pull a struct from a blob using NDR
686 NTSTATUS
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
687 ndr_pull_flags_fn_t fn
)
689 struct ndr_pull
*ndr
;
690 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
692 return NT_STATUS_NO_MEMORY
;
694 return fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
698 pull a struct from a blob using NDR - failing if all bytes are not consumed
700 NTSTATUS
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
701 ndr_pull_flags_fn_t fn
)
703 struct ndr_pull
*ndr
;
706 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
708 return NT_STATUS_NO_MEMORY
;
710 status
= fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
711 if (!NT_STATUS_IS_OK(status
)) return status
;
712 if (ndr
->offset
!= ndr
->data_size
) {
713 return NT_STATUS_BUFFER_TOO_SMALL
;
719 pull a union from a blob using NDR, given the union discriminator
721 NTSTATUS
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
722 uint32_t level
, ndr_pull_flags_fn_t fn
)
724 struct ndr_pull
*ndr
;
727 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
729 return NT_STATUS_NO_MEMORY
;
731 ndr_pull_set_switch_value(ndr
, p
, level
);
732 status
= fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
733 if (!NT_STATUS_IS_OK(status
)) return status
;
734 if (ndr
->offset
!= ndr
->data_size
) {
735 return NT_STATUS_BUFFER_TOO_SMALL
;
741 push a struct to a blob using NDR
743 NTSTATUS
ndr_push_struct_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, const void *p
,
744 ndr_push_flags_fn_t fn
)
747 struct ndr_push
*ndr
;
748 ndr
= ndr_push_init_ctx(mem_ctx
);
750 return NT_STATUS_NO_MEMORY
;
752 status
= fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
753 if (!NT_STATUS_IS_OK(status
)) {
757 *blob
= ndr_push_blob(ndr
);
763 push a union to a blob using NDR
765 NTSTATUS
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
766 uint32_t level
, ndr_push_flags_fn_t fn
)
769 struct ndr_push
*ndr
;
770 ndr
= ndr_push_init_ctx(mem_ctx
);
772 return NT_STATUS_NO_MEMORY
;
774 ndr_push_set_switch_value(ndr
, p
, level
);
775 status
= fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
776 if (!NT_STATUS_IS_OK(status
)) {
780 *blob
= ndr_push_blob(ndr
);
786 generic ndr_size_*() handler for structures
788 size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
790 struct ndr_push
*ndr
;
794 /* avoid recursion */
795 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
797 ndr
= ndr_push_init_ctx(NULL
);
799 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
800 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
801 if (!NT_STATUS_IS_OK(status
)) {
810 generic ndr_size_*() handler for unions
812 size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
814 struct ndr_push
*ndr
;
818 /* avoid recursion */
819 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
821 ndr
= ndr_push_init_ctx(NULL
);
823 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
824 ndr_push_set_switch_value(ndr
, p
, level
);
825 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
826 if (!NT_STATUS_IS_OK(status
)) {
835 get the current base for relative pointers for the push
837 uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
839 return ndr
->relative_base_offset
;
843 restore the old base for relative pointers for the push
845 void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
847 ndr
->relative_base_offset
= offset
;
851 setup the current base for relative pointers for the push
852 called in the NDR_SCALAR stage
854 NTSTATUS
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
856 ndr
->relative_base_offset
= offset
;
857 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
861 setup the current base for relative pointers for the push
862 called in the NDR_BUFFERS stage
864 NTSTATUS
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
866 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
870 push a relative object - stage1
871 this is called during SCALARS processing
873 NTSTATUS
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
876 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
879 NDR_CHECK(ndr_push_align(ndr
, 4));
880 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
881 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
885 push a relative object - stage2
886 this is called during buffers processing
888 NTSTATUS
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
890 struct ndr_push_save save
;
891 uint32_t ptr_offset
= 0xFFFFFFFF;
895 ndr_push_save(ndr
, &save
);
896 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
897 if (ptr_offset
> ndr
->offset
) {
898 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
899 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
900 ptr_offset
, ndr
->offset
);
902 ndr
->offset
= ptr_offset
;
903 if (save
.offset
< ndr
->relative_base_offset
) {
904 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
905 "ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u)",
906 save
.offset
, ndr
->relative_base_offset
);
908 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save
.offset
- ndr
->relative_base_offset
));
909 ndr_push_restore(ndr
, &save
);
914 get the current base for relative pointers for the pull
916 uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
918 return ndr
->relative_base_offset
;
922 restore the old base for relative pointers for the pull
924 void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
926 ndr
->relative_base_offset
= offset
;
930 setup the current base for relative pointers for the pull
931 called in the NDR_SCALAR stage
933 NTSTATUS
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
935 ndr
->relative_base_offset
= offset
;
936 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
940 setup the current base for relative pointers for the pull
941 called in the NDR_BUFFERS stage
943 NTSTATUS
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
945 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
949 pull a relative object - stage1
950 called during SCALARS processing
952 NTSTATUS
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
954 rel_offset
+= ndr
->relative_base_offset
;
955 if (rel_offset
> ndr
->data_size
) {
956 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
957 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
958 rel_offset
, ndr
->data_size
);
960 return ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
964 pull a relative object - stage2
965 called during BUFFERS processing
967 NTSTATUS
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
970 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
971 return ndr_pull_set_offset(ndr
, rel_offset
);