librpc/ndr: provide infrastructure for NDR_SPOOLSS_{PUSH|PULL}_ENUM macros
authorGünther Deschner <gd@samba.org>
Tue, 7 Jan 2020 13:58:15 +0000 (14:58 +0100)
committerJeremy Allison <jra@samba.org>
Wed, 8 Jan 2020 23:51:31 +0000 (23:51 +0000)
The new macros allow the same macro convenience for enum functions without
level discriminator.

Guenther

Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
librpc/ndr/ndr_spoolss_buf.c

index 8b7e1d3bffb056a08975b6c031bd32832704cd15..1efbdf1ea4c33a67f0ba93a8ee073ce648908ae9 100644 (file)
@@ -26,7 +26,7 @@
 #include "librpc/gen_ndr/ndr_spoolss.h"
 #include "librpc/gen_ndr/ndr_security.h"
 
-#define NDR_SPOOLSS_PUSH_ENUM_IN_LEVEL(fn) do { \
+#define NDR_SPOOLSS_PUSH_ENUM_IN(fn) do { \
        if (!r->in.buffer && r->in.offered != 0) {\
                return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
                        "SPOOLSS Buffer: r->in.offered[%u] but there's no buffer",\
                        "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of r->in.buffer[%u]",\
                        (unsigned)r->in.offered, (unsigned)r->in.buffer->length);\
        }\
-       _r.in.level     = r->in.level;\
        _r.in.buffer    = r->in.buffer;\
        _r.in.offered   = r->in.offered;\
        NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
 } while(0)
 
+#define NDR_SPOOLSS_PUSH_ENUM_IN_LEVEL(fn) do { \
+       _r.in.level     = r->in.level;\
+       NDR_SPOOLSS_PUSH_ENUM_IN(fn);\
+} while(0)
+
 #define NDR_SPOOLSS_PUSH_ENUM_OUT_LEVEL(fn) do { \
        DATA_BLOB _data_blob_info = data_blob_null;\
        struct ndr_push *_ndr_info = NULL;\
        NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
 } while(0)
 
+#define NDR_SPOOLSS_PUSH_ENUM_OUT(fn) do { \
+       DATA_BLOB _data_blob_info = data_blob_null;\
+       struct ndr_push *_ndr_info = NULL;\
+       _r.in.buffer    = r->in.buffer;\
+       _r.in.offered   = r->in.offered;\
+       _r.out.info     = NULL;\
+       _r.out.needed   = r->out.needed;\
+       _r.out.count    = r->out.count;\
+       _r.out.result   = r->out.result;\
+       if (r->out.info && *r->out.info && !r->in.buffer) {\
+               return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+                       "SPOOLSS Buffer: *r->out.info but there's no r->in.buffer");\
+       }\
+       if (r->in.buffer) {\
+               _ndr_info = ndr_push_init_ctx(ndr);\
+               NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+               _ndr_info->flags= ndr->flags;\
+               if (r->out.info) {\
+                       struct ndr_push *_subndr_info;\
+                       struct __##fn __r;\
+                       __r.in.count    = *r->out.count;\
+                       __r.out.info    = *r->out.info;\
+                       NDR_CHECK(ndr_push_subcontext_start(_ndr_info, &_subndr_info, 0, r->in.offered));\
+                       NDR_CHECK(ndr_push___##fn(_subndr_info, flags, &__r)); \
+                       NDR_CHECK(ndr_push_subcontext_end(_ndr_info, _subndr_info, 0, r->in.offered));\
+               }\
+               if (r->in.offered > _ndr_info->offset) {\
+                       uint32_t _padding_len = r->in.offered - _ndr_info->offset;\
+                       NDR_CHECK(ndr_push_zero(_ndr_info, _padding_len));\
+               } else if (r->in.offered < _ndr_info->offset) {\
+                       return ndr_push_error(ndr, NDR_ERR_BUFSIZE,\
+                               "SPOOLSS Buffer: r->in.offered[%u] doesn't match length of out buffer[%u]!",\
+                               (unsigned)r->in.offered, (unsigned)_ndr_info->offset);\
+               }\
+               _data_blob_info = ndr_push_blob(_ndr_info);\
+               _r.out.info     = &_data_blob_info;\
+       }\
+       NDR_CHECK(ndr_push__##fn(ndr, flags, &_r));\
+} while(0)
+
 #define NDR_SPOOLSS_PUSH_ENUM_LEVEL(fn,in,out) do { \
        struct _##fn _r;\
        if (flags & NDR_IN) {\
        }\
 } while(0)
 
-#define NDR_SPOOLSS_PULL_ENUM_IN_LEVEL(fn) do { \
+#define NDR_SPOOLSS_PUSH_ENUM(fn,in,out) do { \
+       struct _##fn _r;\
+       if (flags & NDR_IN) {\
+               in;\
+               NDR_SPOOLSS_PUSH_ENUM_IN(fn);\
+       }\
+       if (flags & NDR_OUT) {\
+               out;\
+               NDR_SPOOLSS_PUSH_ENUM_OUT(fn);\
+       }\
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn) do { \
        ZERO_STRUCT(r->out);\
-       NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
-       r->in.level     = _r.in.level;\
        r->in.buffer    = _r.in.buffer;\
        r->in.offered   = _r.in.offered;\
        r->out.needed   = _r.out.needed;\
        ZERO_STRUCTP(r->out.info);\
 } while(0)
 
+#define NDR_SPOOLSS_PULL_ENUM_IN(fn) do { \
+       NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+       NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn); \
+} while(0)
+
+#define NDR_SPOOLSS_PULL_ENUM_IN_LEVEL(fn) do { \
+       NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+       r->in.level     = _r.in.level;\
+       NDR_SPOOLSS_PULL_ENUM_IN_COMMON(fn); \
+} while(0)
+
 #define NDR_SPOOLSS_PULL_ENUM_OUT_LEVEL(fn) do { \
        _r.in.level     = r->in.level;\
        _r.in.buffer    = r->in.buffer;\
        }\
 } while(0)
 
+#define NDR_SPOOLSS_PULL_ENUM_OUT(fn) do { \
+       _r.in.buffer    = r->in.buffer;\
+       _r.in.offered   = r->in.offered;\
+       _r.out.needed   = r->out.needed;\
+       _r.out.count    = r->out.count;\
+       NDR_CHECK(ndr_pull__##fn(ndr, flags, &_r));\
+       if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {\
+               NDR_PULL_ALLOC(ndr, r->out.info);\
+       }\
+       *r->out.info = NULL;\
+       r->out.needed   = _r.out.needed;\
+       r->out.count    = _r.out.count;\
+       r->out.result   = _r.out.result;\
+       if (_r.out.info) {\
+               struct ndr_pull *_ndr_info;\
+               NDR_PULL_ALLOC(ndr, *r->out.info);\
+               _ndr_info = ndr_pull_init_blob(_r.out.info, *r->out.info);\
+               NDR_ERR_HAVE_NO_MEMORY(_ndr_info);\
+               _ndr_info->flags= ndr->flags;\
+               if (r->in.offered != _ndr_info->data_size) {\
+                       return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,\
+                               "SPOOLSS Buffer: offered[%u] doesn't match length of buffer[%u]",\
+                               (unsigned)r->in.offered, (unsigned)_ndr_info->data_size);\
+               }\
+               if (*r->out.needed <= _ndr_info->data_size) {\
+                       struct __##fn __r;\
+                       __r.in.count    = *r->out.count;\
+                       __r.out.info    = NULL;\
+                       NDR_CHECK(ndr_pull___##fn(_ndr_info, flags, &__r));\
+                       *r->out.info    = __r.out.info;\
+               }\
+       }\
+} while(0)
+
 #define NDR_SPOOLSS_PULL_ENUM_LEVEL(fn,in,out) do { \
        struct _##fn _r;\
        if (flags & NDR_IN) {\
        }\
 } while(0)
 
+#define NDR_SPOOLSS_PULL_ENUM(fn,in,out) do { \
+       struct _##fn _r;\
+       if (flags & NDR_IN) {\
+               out;\
+               NDR_SPOOLSS_PULL_ENUM_IN(fn);\
+               in;\
+       }\
+       if (flags & NDR_OUT) {\
+               out;\
+               NDR_SPOOLSS_PULL_ENUM_OUT(fn);\
+       }\
+} while(0)
+
 #define _NDR_CHECK_UINT32(call) do {\
        enum ndr_err_code _ndr_err; \
         _ndr_err = call; \