summaryrefslogtreecommitdiff
path: root/source4/librpc/ndr/ndr.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-11-16 13:49:14 +0000
committerAndrew Tridgell <tridge@samba.org>2003-11-16 13:49:14 +0000
commitae4cb40100a5c04a4604acfde989ce96ef1801bd (patch)
tree48baadf0d3f5076475025e1f4f52abb4fe62290e /source4/librpc/ndr/ndr.c
parentc4b7585288095cb9459feb237a9581ba30b850d0 (diff)
downloadsamba-ae4cb40100a5c04a4604acfde989ce96ef1801bd.tar.gz
samba-ae4cb40100a5c04a4604acfde989ce96ef1801bd.tar.bz2
samba-ae4cb40100a5c04a4604acfde989ce96ef1801bd.zip
use nstring and [relative] to support levels 1 and 2 of EnumPrinters
fully (This used to be commit 69c6017c945bdd7d1945f22fcad49112ba6a2d2d)
Diffstat (limited to 'source4/librpc/ndr/ndr.c')
-rw-r--r--source4/librpc/ndr/ndr.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c
index 25bfd20006..fb7c602ce8 100644
--- a/source4/librpc/ndr/ndr.c
+++ b/source4/librpc/ndr/ndr.c
@@ -207,8 +207,8 @@ NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32 ofs)
push a generic array
*/
NTSTATUS ndr_push_array(struct ndr_push *ndr, int ndr_flags, void *base,
- size_t elsize, uint32 count,
- NTSTATUS (*push_fn)(struct ndr_push *, int, void *))
+ size_t elsize, uint32 count,
+ NTSTATUS (*push_fn)(struct ndr_push *, int, void *))
{
int i;
char *p = base;
@@ -419,3 +419,75 @@ NTSTATUS ndr_pull_subcontext_union_fn(struct ndr_pull *ndr,
NDR_CHECK(ndr_pull_advance(ndr, size));
return NT_STATUS_OK;
}
+
+
+/*
+ pull a relative structure
+*/
+NTSTATUS ndr_pull_relative(struct ndr_pull *ndr, const void **buf, size_t size,
+ NTSTATUS (*fn)(struct ndr_pull *, int ndr_flags, void *))
+{
+ struct ndr_pull ndr2;
+ uint32 ofs;
+ struct ndr_pull_save save;
+ void *p;
+
+ NDR_CHECK(ndr_pull_uint32(ndr, &ofs));
+ if (ofs == 0) {
+ (*buf) = NULL;
+ return NT_STATUS_OK;
+ }
+ ndr_pull_save(ndr, &save);
+ NDR_CHECK(ndr_pull_set_offset(ndr, ofs));
+ NDR_CHECK(ndr_pull_subcontext(ndr, &ndr2, ndr->data_size - ndr->offset));
+ if (size == 1) {
+ /* oh what a hack! */
+ NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, (void *)&p));
+ } else {
+ NDR_ALLOC_SIZE(ndr, p, size);
+ NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, p));
+ }
+ (*buf) = p;
+ ndr_pull_restore(ndr, &save);
+ return NT_STATUS_OK;
+}
+
+/*
+ push a relative structure
+*/
+NTSTATUS ndr_push_relative(struct ndr_push *ndr, int ndr_flags, const void *p,
+ NTSTATUS (*fn)(struct ndr_push *, int , const void *))
+{
+ struct ndr_push_save *save;
+ if (ndr_flags & NDR_SCALARS) {
+ if (!p) {
+ NDR_CHECK(ndr_push_uint32(ndr, 0));
+ return NT_STATUS_OK;
+ }
+ save = talloc(ndr->mem_ctx, sizeof(*save));
+ if (!save) return NT_STATUS_NO_MEMORY;
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ ndr_push_save(ndr, save);
+ NDR_CHECK(ndr_push_uint32(ndr, 0xFFFFFFFF));
+ save->next = ndr->relative_list;
+ ndr->relative_list = save;
+ }
+ if (ndr_flags & NDR_BUFFERS) {
+ struct ndr_push_save save2;
+ if (!p) {
+ return NT_STATUS_OK;
+ }
+ save = ndr->relative_list;
+ if (!save) {
+ return ndr_push_error(ndr, NDR_ERR_RELATIVE, "Empty relative stack");
+ }
+ ndr->relative_list = save->next;
+ NDR_CHECK(ndr_push_align(ndr, 8));
+ ndr_push_save(ndr, &save2);
+ ndr_push_restore(ndr, save);
+ NDR_CHECK(ndr_push_uint32(ndr, save2.offset));
+ ndr_push_restore(ndr, &save2);
+ NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
+ }
+ return NT_STATUS_OK;
+}