r5603: add "authservice()" property to the interface property list
[samba.git] / source4 / build / pidl / ndr.pm
index da2086e765c6c5f4f499301bd43b4fb1099719d8..c460c92c95a037cf929ab1f41571c913ceed876e 100644 (file)
@@ -89,9 +89,7 @@ sub is_fixed_array($)
 {
        my $e = shift;
        my $len = $e->{"ARRAY_LEN"};
-       if (defined $len && util::is_constant($len)) {
-               return 1;
-       }
+       return 1 if (defined $len && util::is_constant($len));
        return 0;
 }
 
@@ -159,6 +157,7 @@ sub need_wire_pointer($)
        my $n = $e->{POINTERS};
        my $pt = pointer_type($e);
 
+       # Top level "ref" pointers do not have a referrent identifier
        if (    defined($pt) 
                and $pt eq "ref" 
                and $e->{PARENT}->{TYPE} eq "FUNCTION") 
@@ -169,17 +168,16 @@ sub need_wire_pointer($)
        return $n;
 }
 
-# determine if an element is a pure scalar. pure scalars do not
-# have a "buffers" section in NDR
-sub is_pure_scalar($)
+# determine if an element needs a "buffers" section in NDR
+sub need_buffers_section($)
 {
        my $e = shift;
-       if (is_scalar_type($e->{TYPE}) && 
-           need_wire_pointer($e) == 0 && 
+       if ((is_scalar_type($e->{TYPE}) || util::has_property($e, "subcontext")) &&
+           $e->{POINTERS} == 0 && 
            !util::array_size($e)) {
-               return 1;
+               return 0;
        }
-       return 0;
+       return 1;
 }
 
 # see if a variable needs to be allocated by the NDR subsystem on pull
@@ -192,6 +190,7 @@ sub need_alloc($)
        return 0;
 }
 
+# Prefix to get the actual value of a variable
 sub c_ptr_prefix($)
 {
        my $e = shift;
@@ -255,35 +254,16 @@ sub pidl($)
        $res .="\n";
 }
 
-sub indent
+sub indent()
 {
        $tabs .= "\t";
 }
 
-sub deindent
+sub deindent()
 {
        $tabs = substr($tabs, 0, -1);
 }
 
-###################################
-# find a sibling var in a structure
-sub find_sibling($$)
-{
-       my($e) = shift;
-       my($name) = shift;
-       my($fn) = $e->{PARENT};
-
-       if ($name =~ /\*(.*)/) {
-               $name = $1;
-       }
-
-       for my $e2 (@{$fn->{ELEMENTS}}) {
-               return $e2 if ($e2->{NAME} eq $name);
-       }
-
-       die "invalid sibling '$name'";
-}
-
 ####################################################################
 # work out the name of a size_is() variable
 sub ParseExpr($$$)
@@ -309,7 +289,7 @@ sub ParseExpr($$$)
                return $prefix . "r->$size";
        }
 
-       my $e2 = find_sibling($e, $size);
+       my $e2 = util::find_sibling($e, $size);
 
        if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
                return $prefix . "$var_prefix$size";
@@ -354,17 +334,12 @@ sub check_null_pointer_void($)
 sub fn_prefix($)
 {
        my $fn = shift;
-       if ($fn->{TYPE} eq "TYPEDEF") {
-               if (util::has_property($fn, "public")) {
-                       return "";
-               }
-       }
 
-       if ($fn->{TYPE} eq "FUNCTION") {
-               if (util::has_property($fn, "public")) {
-                       return "";
-               }
+       if ($fn->{TYPE} eq "TYPEDEF" or 
+           $fn->{TYPE} eq "FUNCTION") {
+               return "" if (util::has_property($fn, "public"));
        }
+
        return "static ";
 }
 
@@ -449,14 +424,16 @@ sub ParseArrayPushPreceding($$$)
 
 #####################################################################
 # parse the data of an array - push side
-sub ParseArrayPush($$$)
+sub ParseArrayPush($$$$)
 {
        my $e = shift;
+       my $ndr = shift;
        my $var_prefix = shift;
        my $ndr_flags = shift;
 
        my $size = ParseExpr($e, util::array_size($e), $var_prefix);
 
+       # See whether the array size has been pushed yet
        if (!is_surrounding_array($e)) {
                ParseArrayPushPreceding($e, $var_prefix, $ndr_flags);
        }
@@ -464,15 +441,15 @@ sub ParseArrayPush($$$)
        if (is_varying_array($e)) {
                my $length = util::has_property($e, "length_is");
                $length = ParseExpr($e, $length, $var_prefix);
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));";
-               pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $length));";
+               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));";
+               pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));";
                $size = $length;
        }
 
        if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+               pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
        } else {
-               pidl "NDR_CHECK(ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
+               pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));";
        }
 }
 
@@ -538,9 +515,10 @@ sub ParseArrayPullPreceding($$$)
 
 #####################################################################
 # parse an array - pull side
-sub ParseArrayPull($$$)
+sub ParseArrayPull($$$$)
 {
        my $e = shift;
+       my $ndr = shift;
        my $var_prefix = shift;
        my $ndr_flags = shift;
 
@@ -550,55 +528,110 @@ sub ParseArrayPull($$$)
        # if this is a conformant array then we use that size to allocate, and make sure
        # we allocate enough to pull the elements
        if (is_conformant_array($e) and is_surrounding_array($e)) {
-               $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
+               $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
                check_null_pointer($size);
                pidl "if ($size > $alloc_size) {";
                indent;
-               pidl "return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
+               pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);";
                deindent;
                pidl "}";
        } elsif (!is_inline_array($e)) {
                if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
                        my $size2 = substr($size, 1);
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }";
+                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $size2); }";
                }
 
                ParseArrayPullPreceding($e, $var_prefix, $ndr_flags);
 
-               $alloc_size = "ndr_get_array_size(ndr, &$var_prefix$e->{NAME})";
+               $alloc_size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})";
        }
 
        if ((need_alloc($e) && !is_fixed_array($e)) ||
            ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
                if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
+                       pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
                }
        }
 
        if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
                if (!is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
-                       pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
-                       indent;
-                       pidl "NDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, $alloc_size);";
-                       deindent;
+                       pidl "if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {";
+                       pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $alloc_size);";
                        pidl "}";
                }
        }
 
        if (is_varying_array($e)) {
-               pidl "NDR_CHECK(ndr_pull_array_length(ndr, &$var_prefix$e->{NAME}));";
-               $size = "ndr_get_array_length(ndr, &$var_prefix$e->{NAME})";
+               pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));";
+               $size = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})";
        }
 
        check_null_pointer($size);
 
        if (is_scalar_type($e->{TYPE})) {
-               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
+               pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_prefix$e->{NAME}, $size));";
        } else {
-               pidl "NDR_CHECK(ndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
+               pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));";
        }
 }
 
+sub ParseSubcontextPushStart($)
+{
+       my $e = shift;
+       my $sub_size = util::has_property($e, "subcontext");
+
+       pidl "{";
+       indent;
+       pidl "struct ndr_push *_ndr_$e->{NAME};";
+       pidl "";
+       pidl "_ndr_$e->{NAME} = ndr_push_init_ctx(ndr);";
+       pidl "if (!_ndr_$e->{NAME}) return NT_STATUS_NO_MEMORY;";
+       pidl "_ndr_$e->{NAME}->flags = ndr->flags;";
+       pidl "";
+       
+       return "_ndr_$e->{NAME}";
+}
+
+sub ParseSubcontextPushEnd($)
+{
+       my $e = shift;
+       my $sub_size = util::has_property($e, "subcontext");
+       pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $sub_size, _ndr_$e->{NAME}));";
+       pidl "NDR_CHECK(ndr_push_bytes(ndr, _ndr_$e->{NAME}->data, _ndr_$e->{NAME}->offset));";
+       deindent;
+       pidl "}";
+}
+
+sub ParseSubcontextPullStart($)
+{
+       my $e = shift;
+       my $sub_size = util::has_property($e, "subcontext");
+
+       pidl "{";
+       indent;
+       pidl "struct ndr_pull *_ndr_$e->{NAME};";
+       pidl "NDR_ALLOC(ndr, _ndr_$e->{NAME});";
+       pidl "NDR_CHECK(ndr_pull_subcontext_header(ndr, $sub_size, _ndr_$e->{NAME}));"; 
+
+       return "_ndr_$e->{NAME}";
+}
+
+sub ParseSubcontextPullEnd($)
+{
+       my $e = shift;
+       my $sub_size = util::has_property($e, "subcontext");
+
+       my $advance;
+       if ($sub_size) {
+               $advance = "_ndr_$e->{NAME}->data_size";
+       } else {
+               $advance = "_ndr_$e->{NAME}->offset";
+       }
+       pidl "NDR_CHECK(ndr_pull_advance(ndr, $advance));";
+       deindent;
+       pidl "}";
+}
+
 #####################################################################
 # parse scalars in a structure element
 sub ParseElementPushScalar($$$)
@@ -609,6 +642,7 @@ sub ParseElementPushScalar($$$)
        my $cprefix = c_push_prefix($e);
        my $ptr_prefix = c_ptr_prefix($e);
        my $sub_size = util::has_property($e, "subcontext");
+       my $ndr = "ndr";
 
        start_flags($e);
 
@@ -616,20 +650,24 @@ sub ParseElementPushScalar($$$)
                pidl "$cprefix$var_prefix$e->{NAME} = $value;";
        }
 
-       if (util::has_property($e, "relative")) {
-               pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $ptr_prefix$var_prefix$e->{NAME}));";
-       } elsif (need_wire_pointer($e)) {
-               ParseElementPushPtr($e, $ptr_prefix.$var_prefix, "NDR_SCALARS");
+       if (defined $sub_size and $e->{POINTERS} == 0) {
+               $ndr = ParseSubcontextPushStart($e);
+       }
+
+       if (need_wire_pointer($e)) {
+               ParsePtrPush($e, $ptr_prefix.$var_prefix);
        } elsif (is_inline_array($e)) {
-               ParseArrayPush($e, "r->", "NDR_SCALARS");
+               ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS");
        } elsif (need_alloc($e)) {
                # no scalar component
        } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
-       } elsif (defined $sub_size) {
-               pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
+               ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+               pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+       }
+
+       if (defined $sub_size and $e->{POINTERS} == 0) {
+               ParseSubcontextPushEnd($e);
        }
 
        end_flags($e);
@@ -637,13 +675,16 @@ sub ParseElementPushScalar($$$)
 
 #####################################################################
 # parse a pointer in a struct element or function
-sub ParseElementPushPtr($$$)
+sub ParsePtrPush($$)
 {
        my $e = shift;
        my $var_prefix = shift;
-       my $ndr_flags = shift;
 
-       pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
+       if (util::has_property($e, "relative")) {
+               pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));";
+       } else {
+               pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));";
+       }
 }
 
 #####################################################################
@@ -659,9 +700,7 @@ sub ParseElementPrint($$)
 
        if (my $value = util::has_property($e, "value")) {
                pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {";
-               indent;
-               pidl "$cprefix$var_prefix$e->{NAME} = $value;";
-               deindent;
+               pidl "\t$cprefix$var_prefix$e->{NAME} = $value;";
                pidl "}";
        }
 
@@ -699,9 +738,10 @@ sub ParseElementPrint($$)
 
 #####################################################################
 # parse scalars in a structure element - pull size
-sub ParseElementPullSwitch($$$$)
+sub ParseSwitchPull($$$$$)
 {
        my($e) = shift;
+       my $ndr = shift;
        my($var_prefix) = shift;
        my($ndr_flags) = shift;
        my $switch = shift;
@@ -715,25 +755,20 @@ sub ParseElementPullSwitch($$$$)
 
        if (!defined $utype ||
            !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = find_sibling($e, $switch);
+               my $e2 = util::find_sibling($e, $switch);
                my $type_decl = typelist::mapType($e2);
                pidl "if (($ndr_flags) & NDR_SCALARS) {";
                indent;
-               if (typelist::getType($e2->{TYPE})->{DATA}->{TYPE} eq "ENUM") {
-                       $type_decl = typelist::mapType($e2);
-               } elsif (typelist::getType($e2->{TYPE})->{DATA}->{TYPE} eq "BITMAP") {
-                       $type_decl = typelist::mapType($e2);
-               }
                pidl "$type_decl _level;";
-               pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}(ndr, NDR_SCALARS, &_level));";
+               pidl "NDR_CHECK(ndr_pull_$e2->{TYPE}($ndr, NDR_SCALARS, &_level));";
                if ($switch_var =~ /r->in/) {
-                       pidl "if (!(ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
+                       pidl "if (!($ndr->flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {";
                        indent;
                } else {
                        pidl "if (_level != $switch_var) {"; 
                        indent;
                }
-               pidl "return ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
+               pidl "return ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\", _level);";
                deindent;
                if ($switch_var =~ /r->/) {
                        pidl "} else { $switch_var = _level; }";
@@ -744,25 +779,15 @@ sub ParseElementPullSwitch($$$$)
                pidl "}";
        }
 
-       my $sub_size = util::has_property($e, "subcontext");
-       if (defined $sub_size) {
-               pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE}));";
-               deindent;
-               pidl "}";
-       } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
-       }
-
-
+       pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
 }
 
 #####################################################################
 # push switch element
-sub ParseElementPushSwitch($$$$)
+sub ParseSwitchPush($$$$$)
 {
        my($e) = shift;
+       my $ndr = shift;
        my($var_prefix) = shift;
        my($ndr_flags) = shift;
        my $switch = shift;
@@ -774,24 +799,13 @@ sub ParseElementPushSwitch($$$$)
        my $utype = typelist::getType($e->{TYPE});
        if (!defined $utype ||
            !util::has_property($utype, "nodiscriminant")) {
-               my $e2 = find_sibling($e, $switch);
+               my $e2 = util::find_sibling($e, $switch);
                pidl "if (($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_push_$e2->{TYPE}(ndr, NDR_SCALARS, $switch_var));";
-               deindent;
+               pidl "\tNDR_CHECK(ndr_push_$e2->{TYPE}($ndr, NDR_SCALARS, $switch_var));";
                pidl "}";
        }
 
-       my $sub_size = util::has_property($e, "subcontext");
-       if (defined $sub_size) {
-               pidl "if(($ndr_flags) & NDR_SCALARS) {";
-               indent;
-               pidl "NDR_CHECK(ndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE}));";
-               deindent;
-               pidl "}";
-       } else {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
-       }
+       pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME}));";
 }
 
 #####################################################################
@@ -804,39 +818,46 @@ sub ParseElementPullScalar($$$)
        my $cprefix = c_pull_prefix($e);
        my $ptr_prefix = c_ptr_prefix($e);
        my $sub_size = util::has_property($e, "subcontext");
+       my $ndr = "ndr";
 
        start_flags($e);
 
+       if (defined $sub_size && $e->{POINTERS} == 0) {
+               $ndr = ParseSubcontextPullStart($e);
+               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
+       }
+
        if (is_inline_array($e)) {
-               ParseArrayPull($e, "r->", "NDR_SCALARS");
+               ParseArrayPull($e, $ndr, "r->", "NDR_SCALARS");
        } elsif (need_wire_pointer($e)) {
-               ParseElementPullPtr($e, $ptr_prefix.$var_prefix, "NDR_SCALARS");
+               ParsePtrPull($e, $ptr_prefix.$var_prefix);
        } elsif (is_surrounding_array($e)) {
        } elsif (my $switch = util::has_property($e, "switch_is")) {
-               ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
-       } elsif (defined $sub_size) {
-               pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
+               ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
        if (my $range = util::has_property($e, "range")) {
                my ($low, $high) = split(/ /, $range, 2);
                pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {";
-               pidl "\treturn ndr_pull_error(ndr, NDR_ERR_RANGE, \"value out of range\");";
+               pidl "\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");";
                pidl "}";
        }
 
+       if (defined $sub_size && $e->{POINTERS} == 0) {
+               ParseSubcontextPullEnd($e);
+       }
+
        end_flags($e);
 }
 
 #####################################################################
 # parse a pointer in a struct element or function
-sub ParseElementPullPtr($$$)
+sub ParsePtrPull($$)
 {
        my($e) = shift;
        my($var_prefix) = shift;
-       my($ndr_flags) = shift;
 
        pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));";
        pidl "if (_ptr_$e->{NAME}) {";
@@ -853,52 +874,55 @@ sub ParseElementPullPtr($$$)
 
 #####################################################################
 # parse buffers in a structure element
-sub ParseElementPushBuffer($$$)
+sub ParseElementPushBuffer($$)
 {
        my($e) = shift;
        my($var_prefix) = shift;
-       my($ndr_flags) = shift;
        my $cprefix = c_push_prefix($e);
        my $sub_size = util::has_property($e, "subcontext");
+       my $ndr = "ndr";
 
-       return if (is_pure_scalar($e));
+       return unless (need_buffers_section($e));
 
        start_flags($e);
 
        my $pointers = c_ptr_prefix($e);
        for my $i (1..need_wire_pointer($e)) {
                if ($i > 1) {
-                       ParseElementPushPtr($e,$pointers.$var_prefix,$ndr_flags);
+                       ParsePtrPush($e,$pointers.$var_prefix);
                }
                pidl "if ($pointers$var_prefix$e->{NAME}) {";
                indent;
                $pointers.="*";
        }
-               
+       
        if (util::has_property($e, "relative")) {
                pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
        }
+
+       my $ndr_flags = "NDR_BUFFERS";
+       if ($e->{POINTERS} || (util::array_size($e) && !is_inline_array($e)))
+       {
+               $ndr_flags="NDR_SCALARS|$ndr_flags" 
+       }
+
+       if (defined $sub_size) {
+               $ndr = ParseSubcontextPushStart($e);
+               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
+       }
            
-       if (is_inline_array($e)) {
-               ParseArrayPush($e, "r->", "NDR_BUFFERS");
-       } elsif (util::array_size($e)) {
-               ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
+       if (util::array_size($e)) {
+               ParseArrayPush($e, $ndr, "r->", $ndr_flags);
        } elsif (my $switch = util::has_property($e, "switch_is")) {
-               if ($e->{POINTERS}) {
-                       ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
-               } else {
-                       ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
-               }
-       } elsif (defined $sub_size) {
-               if ($e->{POINTERS}) {
-                       pidl "NDR_CHECK(ndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE}));";
-               }
-       } elsif ($e->{POINTERS}) {
-               pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
+               ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
                pidl "NDR_CHECK(ndr_push_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
        }
 
+       if (defined $sub_size) {
+               ParseSubcontextPushEnd($e);
+       }
+
        for my $i (1..need_wire_pointer($e)) {
                deindent;
                pidl "}";
@@ -909,22 +933,22 @@ sub ParseElementPushBuffer($$$)
 
 #####################################################################
 # parse buffers in a structure element - pull side
-sub ParseElementPullBuffer($$$)
+sub ParseElementPullBuffer($$)
 {
        my($e) = shift;
        my($var_prefix) = shift;
-       my($ndr_flags) = shift;
        my $cprefix = c_pull_prefix($e);
        my $sub_size = util::has_property($e, "subcontext");
+       my $ndr = "ndr";
 
-       return if (is_pure_scalar($e));
+       return unless (need_buffers_section($e));
 
        start_flags($e);
 
        my $pointers = c_ptr_prefix($e);
        for my $i (1..need_wire_pointer($e)) {
                if ($i > 1) {
-                       ParseElementPullPtr($e,$pointers.$var_prefix,"NDR_SCALARS");
+                       ParsePtrPull($e,$pointers.$var_prefix);
                }
                pidl "if ($pointers$var_prefix$e->{NAME}) {";
                indent;
@@ -936,30 +960,34 @@ sub ParseElementPullBuffer($$$)
                pidl "ndr_pull_save(ndr, &_relative_save);";
                pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));";
        }
-           
-       if (is_inline_array($e)) {
-               ParseArrayPull($e, "r->", "NDR_BUFFERS");
-       } elsif (util::array_size($e)) {
-               ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
+
+       my $ndr_flags = "NDR_BUFFERS";
+       if ($e->{POINTERS} || (util::array_size($e) && !is_inline_array($e)))
+       {
+               $ndr_flags="NDR_SCALARS|$ndr_flags" 
+       }
+
+       if (defined $sub_size) {
+               $ndr = ParseSubcontextPullStart($e);
+               $ndr_flags = "NDR_SCALARS|NDR_BUFFERS";
+       }
+
+       if (util::array_size($e)) {
+               ParseArrayPull($e, $ndr, "r->", $ndr_flags);
        } elsif (my $switch = util::has_property($e, "switch_is")) {
-               if ($e->{POINTERS}) {
-                       ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
-               } else {
-                       ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
-               }
-       } elsif (defined $sub_size) {
-               if ($e->{POINTERS}) {
-                       pidl "NDR_CHECK(ndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE}));";
-               }
-       } elsif ($e->{POINTERS}) {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}));";
+               ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch);
        } else {
-               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+               pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));";
+       }
+
+       if (defined $sub_size) {
+               ParseSubcontextPullEnd($e);
        }
 
        if (util::has_property($e, "relative")) {
                pidl "ndr_pull_restore(ndr, &_relative_save);";
        }
+
        for my $i (1..need_wire_pointer($e)) {
                deindent;
                pidl "}";
@@ -1007,7 +1035,7 @@ sub ParseStructPush($)
        pidl "buffers:";
        pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
+               ParseElementPushBuffer($e, "r->");
        }
 
        pidl "ndr_push_struct_end(ndr);";
@@ -1281,7 +1309,7 @@ sub ParseStructPull($)
        pidl "buffers:\n";
        pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;";
        foreach my $e (@{$struct->{ELEMENTS}}) {
-               ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
+               ParseElementPullBuffer($e, "r->");
        }
 
        foreach my $e (@{$struct->{ELEMENTS}}) {
@@ -1303,16 +1331,10 @@ sub ParseStructNdrSize($)
        my $static = fn_prefix($t);
        my $sizevar;
 
-       pidl "size_t ndr_size_$t->{NAME}(const struct $t->{NAME} *r, int flags)";
-       pidl "{";
-       indent;
        if (my $flags = util::has_property($t, "flag")) {
                pidl "flags |= $flags;";
        }
        pidl "return ndr_size_struct(r, flags, (ndr_push_flags_fn_t)ndr_push_$t->{NAME});";
-       deindent;
-       pidl "}";
-       pidl "";
 }
 
 sub ArgsStructPush($)
@@ -1333,6 +1355,12 @@ sub ArgsStructPull($)
        return "struct ndr_pull *ndr, int ndr_flags, struct $e->{NAME} *r";
 }
 
+sub ArgsStructNdrSize($)
+{
+       my $d = shift;
+       return "const struct $d->{NAME} *r, int flags";
+}
+
 $typefamily{STRUCT} = {
        PUSH_FN_BODY => \&ParseStructPush,
        PUSH_FN_ARGS => \&ArgsStructPush,
@@ -1340,7 +1368,8 @@ $typefamily{STRUCT} = {
        PULL_FN_ARGS => \&ArgsStructPull,
        PRINT_FN_BODY => \&ParseStructPrint,
        PRINT_FN_ARGS => \&ArgsStructPrint,
-       SIZE_FN => \&ParseStructNdrSize,
+       SIZE_FN_BODY => \&ParseStructNdrSize,
+       SIZE_FN_ARGS => \&ArgsStructNdrSize,
        ALIGN => \&find_largest_alignment
 };
 
@@ -1352,16 +1381,10 @@ sub ParseUnionNdrSize($)
        my $static = fn_prefix($t);
        my $sizevar;
 
-       pidl "size_t ndr_size_$t->{NAME}(const union $t->{NAME} *r, int level, int flags)";
-       pidl "{";
-       indent;
        if (my $flags = util::has_property($t, "flag")) {
                pidl "flags |= $flags;";
        }
        pidl "return ndr_size_union(r, flags, level, (ndr_push_union_fn_t)ndr_push_$t->{NAME});";
-       deindent;
-       pidl "}";
-       pidl "";;
 }
 
 #####################################################################
@@ -1416,7 +1439,7 @@ sub ParseUnionPush($)
                }
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPushBuffer($el, "r->", "NDR_BUFFERS");
+                       ParseElementPushBuffer($el, "r->");
                        deindent;
                }
                pidl "break;";
@@ -1525,7 +1548,7 @@ sub ParseUnionPull($)
                }
                if ($el->{TYPE} ne "EMPTY") {
                        indent;
-                       ParseElementPullBuffer($el, "r->", "NDR_BUFFERS");
+                       ParseElementPullBuffer($el, "r->");
                        deindent;
                }
                pidl "break;";
@@ -1560,6 +1583,12 @@ sub ArgsUnionPull($)
        return "struct ndr_pull *ndr, int ndr_flags, int level, union $e->{NAME} *r";
 }
 
+sub ArgsUnionNdrSize($)
+{
+       my $d = shift;
+       return "const union $d->{NAME} *r, uint32_t level, int flags";
+}
+
 $typefamily{UNION} = {
        PUSH_FN_BODY => \&ParseUnionPush,
        PUSH_FN_ARGS => \&ArgsUnionPush,
@@ -1567,7 +1596,8 @@ $typefamily{UNION} = {
        PULL_FN_ARGS => \&ArgsUnionPull,
        PRINT_FN_BODY => \&ParseUnionPrint,
        PRINT_FN_ARGS => \&ArgsUnionPrint,
-       SIZE_FN => \&ParseUnionNdrSize,
+       SIZE_FN_ARGS => \&ArgsUnionNdrSize,
+       SIZE_FN_BODY => \&ParseUnionNdrSize,
        ALIGN => \&find_largest_alignment
 };
        
@@ -1623,6 +1653,8 @@ sub ParseTypedefPrint($)
 
        my $args = $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_ARGS}->($e);
 
+       return unless !util::has_property($e, "noprint");
+
        pidl "void ndr_print_$e->{NAME}($args)";
        pidl "{";
        indent;
@@ -1639,7 +1671,16 @@ sub ParseTypedefNdrSize($)
 
        return unless needed::is_needed("ndr_size_$t->{NAME}");
 
-       $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN}->($t);
+       my $tf = $typefamily{$t->{DATA}->{TYPE}};
+       my $args = $tf->{SIZE_FN_ARGS}->($t);
+
+       pidl "size_t ndr_size_$t->{NAME}($args)";
+       pidl "{";
+       indent;
+       $typefamily{$t->{DATA}->{TYPE}}->{SIZE_FN_BODY}->($t);
+       deindent;
+       pidl "}";
+       pidl "";
 }
 
 #####################################################################
@@ -1648,6 +1689,8 @@ sub ParseFunctionPrint($)
 {
        my($fn) = shift;
 
+       return unless !util::has_property($fn, "noprint");
+
        pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
@@ -1708,17 +1751,16 @@ sub ParseFunctionElementPush($$)
                        pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, r->$inout.$e->{NAME}));";
                        pidl "if (r->$inout.$e->{NAME}) {";
                        indent;
-                       ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
+                       ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
                        deindent;
                        pidl "}";
                } else {
-                       ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
+                       ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
                }
        } else {
                ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
-
                if (need_wire_pointer($e)) {
-                       ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
+                       ParseElementPushBuffer($e, "r->$inout.");
                }
        }
 }      
@@ -1730,6 +1772,8 @@ sub ParseFunctionPush($)
        my($fn) = shift;
        my $static = fn_prefix($fn);
 
+       return unless !util::has_property($fn, "nopush");
+
        pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
        indent;
@@ -1782,7 +1826,7 @@ sub ParseFunctionElementPull($$)
                        pidl "{";
                }
                indent;
-               ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
+               ParseArrayPull($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
                deindent;
                pidl "}";
        } else {
@@ -1798,7 +1842,7 @@ sub ParseFunctionElementPull($$)
 
                ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
                if (need_wire_pointer($e)) {
-                       ParseElementPullBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
+                       ParseElementPullBuffer($e, "r->$inout.");
                }
        }
 }
@@ -1843,6 +1887,8 @@ sub ParseFunctionPull($)
        my($fn) = shift;
        my $static = fn_prefix($fn);
 
+       return unless !util::has_property($fn, "nopull");
+
        # pull function args
        pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)";
        pidl "{";
@@ -1962,18 +2008,40 @@ sub FunctionTable($)
        pidl "";
 
        pidl "static const struct dcerpc_endpoint_list $interface->{NAME}\_endpoints = {";
-       pidl "\t$endpoint_count, $interface->{NAME}\_endpoint_strings";
+       pidl "\t.count\t= $endpoint_count,";
+       pidl "\t.names\t= $interface->{NAME}\_endpoint_strings";
+       pidl "};";
+       pidl "";
+
+       if (! defined $interface->{PROPERTIES}->{authservice}) {
+               $interface->{PROPERTIES}->{authservice} = "\"host\"";
+       }
+
+       my @a = split / /, $interface->{PROPERTIES}->{authservice};
+       my $authservice_count = $#a + 1;
+
+       pidl "static const char * const $interface->{NAME}\_authservice_strings[] = {";
+       foreach my $ap (@a) {
+               pidl "\t$ap, ";
+       }
+       pidl "};";
+       pidl "";
+
+       pidl "static const struct dcerpc_authservice_list $interface->{NAME}\_authservices = {";
+       pidl "\t.count\t= $endpoint_count,";
+       pidl "\t.names\t= $interface->{NAME}\_authservice_strings";
        pidl "};";
        pidl "";
 
        pidl "\nconst struct dcerpc_interface_table dcerpc_table_$interface->{NAME} = {";
-       pidl "\t\"$interface->{NAME}\",";
-       pidl "\tDCERPC_$uname\_UUID,";
-       pidl "\tDCERPC_$uname\_VERSION,";
-       pidl "\tDCERPC_$uname\_HELPSTRING,";
-       pidl "\t$count,";
-       pidl "\t$interface->{NAME}\_calls,";
-       pidl "\t&$interface->{NAME}\_endpoints";
+       pidl "\t.name\t\t= \"$interface->{NAME}\",";
+       pidl "\t.uuid\t\t= DCERPC_$uname\_UUID,";
+       pidl "\t.if_version\t= DCERPC_$uname\_VERSION,";
+       pidl "\t.helpstring\t= DCERPC_$uname\_HELPSTRING,";
+       pidl "\t.num_calls\t= $count,";
+       pidl "\t.calls\t\t= $interface->{NAME}\_calls,";
+       pidl "\t.endpoints\t= &$interface->{NAME}\_endpoints,";
+       pidl "\t.authservices\t= &$interface->{NAME}\_authservices";
        pidl "};";
        pidl "";
 
@@ -2009,14 +2077,10 @@ sub ParseInterface($)
        
        # Print functions
        foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "TYPEDEF" &&
-                   !util::has_property($d, "noprint")) {
+               ($d->{TYPE} eq "TYPEDEF") &&
                        ParseTypedefPrint($d);
-               }
-               if ($d->{TYPE} eq "FUNCTION" &&
-                   !util::has_property($d, "noprint")) {
+               ($d->{TYPE} eq "FUNCTION") &&
                        ParseFunctionPrint($d);
-               }
        }
 
        # Size functions
@@ -2108,33 +2172,6 @@ sub LoadInterface($)
        }
 }
 
-# Add ORPC specific bits to an interface.
-sub InterfaceORPC($)
-{
-       my $x = shift;  
-       # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
-       # for 'object' interfaces
-       if (util::has_property($x, "object")) {
-               foreach my $e (@{$x->{DATA}}) {
-                       if($e->{TYPE} eq "FUNCTION") {
-                               $e->{PROPERTIES}->{object} = 1;
-                               unshift(@{$e->{ELEMENTS}}, 
-                       { 'NAME' => 'ORPCthis',
-                         'POINTERS' => 0,
-                         'PROPERTIES' => { 'in' => '1' },
-                         'TYPE' => 'ORPCTHIS'
-                       });
-                               unshift(@{$e->{ELEMENTS}},
-                       { 'NAME' => 'ORPCthat',
-                         'POINTERS' => 0,
-                         'PROPERTIES' => { 'out' => '1' },
-                                         'TYPE' => 'ORPCTHAT'
-                       });
-                       }
-               }
-       }
-}
-
 sub Load($)
 {
        my $idl = shift;