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
31 #include "dlinklist.h"
33 #define NDR_BASE_MARSHALL_SIZE 1024
36 work out the number of bytes needed to align on a n byte boundary
38 size_t ndr_align_size(uint32_t offset
, size_t n
)
40 if ((offset
& (n
-1)) == 0) return 0;
41 return n
- (offset
& (n
-1));
45 initialise a ndr parse structure from a data blob
47 struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
51 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
52 if (!ndr
) return NULL
;
54 ndr
->data
= blob
->data
;
55 ndr
->data_size
= blob
->length
;
61 create an ndr sub-context based on an existing context. The new context starts
62 at the current offset, with the given size limit
64 NTSTATUS
ndr_pull_subcontext(struct ndr_pull
*ndr
, struct ndr_pull
*ndr2
, uint32_t size
)
66 NDR_PULL_NEED_BYTES(ndr
, size
);
68 ndr2
->data
+= ndr2
->offset
;
70 ndr2
->data_size
= size
;
71 ndr2
->flags
= ndr
->flags
;
77 advance by 'size' bytes
79 NTSTATUS
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
82 if (ndr
->offset
> ndr
->data_size
) {
83 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
84 "ndr_pull_advance by %u failed",
91 set the parse offset to 'ofs'
93 NTSTATUS
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
96 if (ndr
->offset
> ndr
->data_size
) {
97 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
98 "ndr_pull_set_offset %u failed",
104 /* save the offset/size of the current ndr state */
105 void ndr_pull_save(struct ndr_pull
*ndr
, struct ndr_pull_save
*save
)
107 save
->offset
= ndr
->offset
;
108 save
->data_size
= ndr
->data_size
;
111 /* restore the size/offset of a ndr structure */
112 void ndr_pull_restore(struct ndr_pull
*ndr
, struct ndr_pull_save
*save
)
114 ndr
->offset
= save
->offset
;
115 ndr
->data_size
= save
->data_size
;
119 /* create a ndr_push structure, ready for some marshalling */
120 struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
122 struct ndr_push
*ndr
;
124 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
130 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
131 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
140 /* create a ndr_push structure, ready for some marshalling */
141 struct ndr_push
*ndr_push_init(void)
143 return ndr_push_init_ctx(NULL
);
146 /* free a ndr_push structure */
147 void ndr_push_free(struct ndr_push
*ndr
)
153 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
154 DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
157 blob
.data
= ndr
->data
;
158 blob
.length
= ndr
->offset
;
164 expand the available space in the buffer to 'size'
166 NTSTATUS
ndr_push_expand(struct ndr_push
*ndr
, uint32_t size
)
168 if (ndr
->alloc_size
>= size
) {
172 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
173 if (size
> ndr
->alloc_size
) {
174 ndr
->alloc_size
= size
;
176 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
178 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
186 set the push offset to 'ofs'
188 NTSTATUS
ndr_push_set_offset(struct ndr_push
*ndr
, uint32_t ofs
)
190 NDR_CHECK(ndr_push_expand(ndr
, ofs
));
198 NTSTATUS
ndr_push_array(struct ndr_push
*ndr
, int ndr_flags
, void *base
,
199 size_t elsize
, uint32_t count
,
200 NTSTATUS (*push_fn
)(struct ndr_push
*, int, void *))
204 if (!(ndr_flags
& NDR_SCALARS
)) goto buffers
;
205 for (i
=0;i
<count
;i
++) {
206 NDR_CHECK(push_fn(ndr
, NDR_SCALARS
, p
));
209 if (!(ndr_flags
& NDR_BUFFERS
)) goto done
;
212 for (i
=0;i
<count
;i
++) {
213 NDR_CHECK(push_fn(ndr
, NDR_BUFFERS
, p
));
221 pull a constant sized array
223 NTSTATUS
ndr_pull_array(struct ndr_pull
*ndr
, int ndr_flags
, void *base
,
224 size_t elsize
, uint32_t count
,
225 NTSTATUS (*pull_fn
)(struct ndr_pull
*, int, void *))
230 if (!(ndr_flags
& NDR_SCALARS
)) goto buffers
;
231 for (i
=0;i
<count
;i
++) {
232 NDR_CHECK(pull_fn(ndr
, NDR_SCALARS
, p
));
235 if (!(ndr_flags
& NDR_BUFFERS
)) goto done
;
238 for (i
=0;i
<count
;i
++) {
239 NDR_CHECK(pull_fn(ndr
, NDR_BUFFERS
, p
));
247 pull a constant size array of structures
249 NTSTATUS
ndr_pull_struct_array(struct ndr_pull
*ndr
, uint32_t count
,
250 size_t elsize
, void **info
,
251 NTSTATUS (*pull_fn
)(struct ndr_pull
*, int, void *))
256 NDR_ALLOC_N_SIZE(ndr
, *info
, count
, elsize
);
257 base
= (char *)*info
;
259 for (i
= 0; i
< count
; i
++) {
260 ndr
->data
+= ndr
->offset
;
262 NDR_CHECK(pull_fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, &base
[count
* elsize
]));
269 print a generic array
271 void ndr_print_array(struct ndr_print
*ndr
, const char *name
, void *base
,
272 size_t elsize
, uint32_t count
,
273 void (*print_fn
)(struct ndr_print
*, const char *, void *))
277 ndr
->print(ndr
, "%s: ARRAY(%d)", name
, count
);
279 for (i
=0;i
<count
;i
++) {
281 asprintf(&idx
, "[%d]", i
);
283 print_fn(ndr
, idx
, p
);
293 void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...) _PRINTF_ATTRIBUTE(2,3)
299 va_start(ap
, format
);
300 vasprintf(&s
, format
, ap
);
303 for (i
=0;i
<ndr
->depth
;i
++) {
307 DEBUG(0,("%s\n", s
));
312 a useful helper function for printing idl structures via DEBUG()
314 void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
316 struct ndr_print
*ndr
;
318 ndr
= talloc(NULL
, struct ndr_print
);
320 ndr
->print
= ndr_print_debug_helper
;
329 a useful helper function for printing idl unions via DEBUG()
331 void ndr_print_union_debug(ndr_print_union_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
333 struct ndr_print
*ndr
;
335 ndr
= talloc(NULL
, struct ndr_print
);
337 ndr
->print
= ndr_print_debug_helper
;
340 fn(ndr
, name
, level
, ptr
);
345 a useful helper function for printing idl function calls via DEBUG()
347 void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
349 struct ndr_print
*ndr
;
351 ndr
= talloc(NULL
, struct ndr_print
);
353 ndr
->print
= ndr_print_debug_helper
;
356 fn(ndr
, name
, flags
, ptr
);
360 void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
362 /* the big/little endian flags are inter-dependent */
363 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
364 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
366 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
367 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
369 (*pflags
) |= new_flags
;
372 static NTSTATUS
ndr_map_error(enum ndr_err_code err
)
375 case NDR_ERR_BUFSIZE
:
376 return NT_STATUS_BUFFER_TOO_SMALL
;
378 return NT_STATUS_INTERNAL_ERROR
;
380 return NT_STATUS_NO_MEMORY
;
381 case NDR_ERR_ARRAY_SIZE
:
382 return NT_STATUS_ARRAY_BOUNDS_EXCEEDED
;
387 /* we should all error codes to different status codes */
388 return NT_STATUS_INVALID_PARAMETER
;
392 return and possibly log an NDR error
394 NTSTATUS
ndr_pull_error(struct ndr_pull
*ndr
,
395 enum ndr_err_code err
, const char *format
, ...) _PRINTF_ATTRIBUTE(3,4)
400 va_start(ap
, format
);
401 vasprintf(&s
, format
, ap
);
404 DEBUG(3,("ndr_pull_error(%u): %s\n", err
, s
));
408 return ndr_map_error(err
);
412 return and possibly log an NDR error
414 NTSTATUS
ndr_push_error(struct ndr_push
*ndr
, enum ndr_err_code err
, const char *format
, ...) _PRINTF_ATTRIBUTE(3,4)
419 va_start(ap
, format
);
420 vasprintf(&s
, format
, ap
);
423 DEBUG(3,("ndr_push_error(%u): %s\n", err
, s
));
427 return ndr_map_error(err
);
432 handle subcontext buffers, which in midl land are user-marshalled, but
433 we use magic in pidl to make them easier to cope with
435 static NTSTATUS
ndr_pull_subcontext_header(struct ndr_pull
*ndr
,
437 struct ndr_pull
*ndr2
)
439 ndr2
->flags
= ndr
->flags
;
443 uint32_t size
= ndr
->data_size
- ndr
->offset
;
444 NDR_CHECK(ndr_pull_subcontext(ndr
, ndr2
, size
));
450 NDR_CHECK(ndr_pull_uint16(ndr
, &size
));
451 NDR_CHECK(ndr_pull_subcontext(ndr
, ndr2
, size
));
457 NDR_CHECK(ndr_pull_uint32(ndr
, &size
));
458 NDR_CHECK(ndr_pull_subcontext(ndr
, ndr2
, size
));
462 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext size %d",
469 handle subcontext buffers, which in midl land are user-marshalled, but
470 we use magic in pidl to make them easier to cope with
472 NTSTATUS
ndr_pull_subcontext_fn(struct ndr_pull
*ndr
, size_t sub_size
,
473 void *base
, ndr_pull_fn_t fn
)
475 struct ndr_pull
*ndr2
;
476 NDR_ALLOC(ndr
, ndr2
);
477 NDR_CHECK(ndr_pull_subcontext_header(ndr
, sub_size
, ndr2
));
478 NDR_CHECK(fn(ndr2
, base
));
480 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->data_size
));
482 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->offset
));
488 NTSTATUS
ndr_pull_subcontext_flags_fn(struct ndr_pull
*ndr
, size_t sub_size
,
489 void *base
, ndr_pull_flags_fn_t fn
)
491 struct ndr_pull
*ndr2
;
492 NDR_ALLOC(ndr
, ndr2
);
493 NDR_CHECK(ndr_pull_subcontext_header(ndr
, sub_size
, ndr2
));
494 NDR_CHECK(fn(ndr2
, NDR_SCALARS
|NDR_BUFFERS
, base
));
496 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->data_size
));
498 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->offset
));
503 NTSTATUS
ndr_pull_subcontext_union_fn(struct ndr_pull
*ndr
, size_t sub_size
,
504 uint32_t level
, void *base
, ndr_pull_union_fn_t fn
)
506 struct ndr_pull
*ndr2
;
508 NDR_ALLOC(ndr
, ndr2
);
509 NDR_CHECK(ndr_pull_subcontext_header(ndr
, sub_size
, ndr2
));
510 NDR_CHECK(fn(ndr2
, NDR_SCALARS
|NDR_BUFFERS
, level
, base
));
512 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->data_size
));
514 NDR_CHECK(ndr_pull_advance(ndr
, ndr2
->offset
));
521 push a subcontext header
523 static NTSTATUS
ndr_push_subcontext_header(struct ndr_push
*ndr
,
525 struct ndr_push
*ndr2
)
532 NDR_CHECK(ndr_push_uint16(ndr
, ndr2
->offset
));
536 NDR_CHECK(ndr_push_uint32(ndr
, ndr2
->offset
));
540 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext size %d",
547 handle subcontext buffers, which in midl land are user-marshalled, but
548 we use magic in pidl to make them easier to cope with
550 NTSTATUS
ndr_push_subcontext_fn(struct ndr_push
*ndr
, size_t sub_size
,
551 void *base
, ndr_push_fn_t fn
)
553 struct ndr_push
*ndr2
;
555 ndr2
= ndr_push_init_ctx(ndr
);
556 if (!ndr2
) return NT_STATUS_NO_MEMORY
;
558 ndr2
->flags
= ndr
->flags
;
559 NDR_CHECK(fn(ndr2
, base
));
560 NDR_CHECK(ndr_push_subcontext_header(ndr
, sub_size
, ndr2
));
561 NDR_CHECK(ndr_push_bytes(ndr
, ndr2
->data
, ndr2
->offset
));
566 handle subcontext buffers for function that take a flags arg
568 NTSTATUS
ndr_push_subcontext_flags_fn(struct ndr_push
*ndr
, size_t sub_size
,
569 void *base
, ndr_push_flags_fn_t fn
)
571 struct ndr_push
*ndr2
;
573 ndr2
= ndr_push_init_ctx(ndr
);
574 if (!ndr2
) return NT_STATUS_NO_MEMORY
;
576 ndr2
->flags
= ndr
->flags
;
577 NDR_CHECK(fn(ndr2
, NDR_SCALARS
|NDR_BUFFERS
, base
));
578 NDR_CHECK(ndr_push_subcontext_header(ndr
, sub_size
, ndr2
));
579 NDR_CHECK(ndr_push_bytes(ndr
, ndr2
->data
, ndr2
->offset
));
584 handle subcontext buffers for function that take a union
586 NTSTATUS
ndr_push_subcontext_union_fn(struct ndr_push
*ndr
, size_t sub_size
,
587 uint32_t level
, void *base
, ndr_push_union_fn_t fn
)
589 struct ndr_push
*ndr2
;
591 ndr2
= ndr_push_init_ctx(ndr
);
592 if (!ndr2
) return NT_STATUS_NO_MEMORY
;
594 ndr2
->flags
= ndr
->flags
;
595 NDR_CHECK(fn(ndr2
, NDR_SCALARS
|NDR_BUFFERS
, level
, base
));
596 NDR_CHECK(ndr_push_subcontext_header(ndr
, sub_size
, ndr2
));
597 NDR_CHECK(ndr_push_bytes(ndr
, ndr2
->data
, ndr2
->offset
));
603 mark the start of a structure
605 NTSTATUS
ndr_pull_struct_start(struct ndr_pull
*ndr
)
611 mark the end of a structure
613 void ndr_pull_struct_end(struct ndr_pull
*ndr
)
618 mark the start of a structure
620 NTSTATUS
ndr_push_struct_start(struct ndr_push
*ndr
)
626 mark the end of a structure
628 void ndr_push_struct_end(struct ndr_push
*ndr
)
633 store a token in the ndr context, for later retrieval
635 static NTSTATUS
ndr_token_store(TALLOC_CTX
*mem_ctx
,
636 struct ndr_token_list
**list
,
640 struct ndr_token_list
*tok
;
641 tok
= talloc(mem_ctx
, struct ndr_token_list
);
643 return NT_STATUS_NO_MEMORY
;
647 DLIST_ADD((*list
), tok
);
652 retrieve a token from a ndr context
654 static NTSTATUS
ndr_token_retrieve(struct ndr_token_list
**list
, const void *key
, uint32_t *v
)
656 struct ndr_token_list
*tok
;
657 for (tok
=*list
;tok
;tok
=tok
->next
) {
658 if (tok
->key
== key
) {
659 DLIST_REMOVE((*list
), tok
);
664 return ndr_map_error(NDR_ERR_TOKEN
);
668 peek at but don't removed a token from a ndr context
670 static uint32_t ndr_token_peek(struct ndr_token_list
**list
, const void *key
)
672 struct ndr_token_list
*tok
;
673 for (tok
=*list
;tok
;tok
=tok
->next
) {
674 if (tok
->key
== key
) {
682 pull an array size field and add it to the array_size_list token list
684 NTSTATUS
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
687 NDR_CHECK(ndr_pull_uint32(ndr
, &size
));
688 return ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
692 get the stored array size field
694 uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
696 return ndr_token_peek(&ndr
->array_size_list
, p
);
700 check the stored array size field
702 NTSTATUS
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
705 NDR_CHECK(ndr_token_retrieve(&ndr
->array_size_list
, p
, &stored
));
706 if (stored
!= size
) {
707 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
708 "Bad array size - got %u expected %u\n",
715 pull an array length field and add it to the array_length_list token list
717 NTSTATUS
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
719 uint32_t length
, offset
;
720 NDR_CHECK(ndr_pull_uint32(ndr
, &offset
));
722 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
723 "non-zero array offset %u\n", offset
);
725 NDR_CHECK(ndr_pull_uint32(ndr
, &length
));
726 return ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
730 get the stored array length field
732 uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
734 return ndr_token_peek(&ndr
->array_length_list
, p
);
738 check the stored array length field
740 NTSTATUS
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
743 NDR_CHECK(ndr_token_retrieve(&ndr
->array_length_list
, p
, &stored
));
744 if (stored
!= length
) {
745 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
746 "Bad array length - got %u expected %u\n",
753 pull a relative object - stage1
754 called during SCALARS processing
756 NTSTATUS
ndr_pull_relative1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
758 if (ndr
->flags
& LIBNDR_FLAG_RELATIVE_CURRENT
) {
759 return ndr_token_store(ndr
, &ndr
->relative_list
, p
,
760 rel_offset
+ ndr
->offset
- 4);
762 return ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
767 pull a relative object - stage2
768 called during BUFFERS processing
770 NTSTATUS
ndr_pull_relative2(struct ndr_pull
*ndr
, const void *p
)
773 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
774 return ndr_pull_set_offset(ndr
, rel_offset
);
778 push a relative object - stage1
779 this is called during SCALARS processing
781 NTSTATUS
ndr_push_relative1(struct ndr_push
*ndr
, const void *p
)
784 NDR_CHECK(ndr_push_uint32(ndr
, 0));
787 NDR_CHECK(ndr_push_align(ndr
, 4));
788 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
789 return ndr_push_uint32(ndr
, 0xFFFFFFFF);
793 push a relative object - stage2
794 this is called during buffers processing
796 NTSTATUS
ndr_push_relative2(struct ndr_push
*ndr
, const void *p
)
798 struct ndr_push_save save
;
802 NDR_CHECK(ndr_push_align(ndr
, 4));
803 ndr_push_save(ndr
, &save
);
804 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ndr
->offset
));
805 if (ndr
->flags
& LIBNDR_FLAG_RELATIVE_CURRENT
) {
806 NDR_CHECK(ndr_push_uint32(ndr
, save
.offset
- ndr
->offset
));
808 NDR_CHECK(ndr_push_uint32(ndr
, save
.offset
));
810 ndr_push_restore(ndr
, &save
);
816 pull a union from a blob using NDR
818 NTSTATUS
ndr_pull_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, uint32_t level
, void *p
,
819 ndr_pull_union_fn_t fn
)
821 struct ndr_pull
*ndr
;
822 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
824 return NT_STATUS_NO_MEMORY
;
826 return fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, level
, p
);
830 pull a struct from a blob using NDR
832 NTSTATUS
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
833 ndr_pull_flags_fn_t fn
)
835 struct ndr_pull
*ndr
;
836 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
838 return NT_STATUS_NO_MEMORY
;
840 return fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
844 push a struct to a blob using NDR
846 NTSTATUS
ndr_push_struct_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
847 ndr_push_flags_fn_t fn
)
850 struct ndr_push
*ndr
;
851 ndr
= ndr_push_init_ctx(mem_ctx
);
853 return NT_STATUS_NO_MEMORY
;
855 status
= fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
856 if (!NT_STATUS_IS_OK(status
)) {
860 *blob
= ndr_push_blob(ndr
);
866 generic ndr_size_*() handler for structures
868 size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
870 struct ndr_push
*ndr
;
874 ndr
= ndr_push_init_ctx(NULL
);
877 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
878 if (!NT_STATUS_IS_OK(status
)) {
887 generic ndr_size_*() handler for unions
889 size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_union_fn_t push
)
891 struct ndr_push
*ndr
;
895 ndr
= ndr_push_init_ctx(NULL
);
898 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, level
, discard_const(p
));
899 if (!NT_STATUS_IS_OK(status
)) {