From e427f58622e3d88c59953d6c1fb583acfb046213 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 25 May 2005 13:50:27 +0000 Subject: [PATCH] r6973: Merge new version of pidl into the main SAMBA_4_0 branch. The main difference in this new version is the extra data structure generated between the IDL data structure and the NDR parser: IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc } This makes the ndr_parser.pm internals much more sane. Other changes include: - Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags. - Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc.. - Use if() {} rather then if () goto foo; everywhere - NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC - By default, top level pointers are now "ref" (as is the default in most other IDL compilers). This can be overridden using the default_pointer_top() property. - initial work on new ethereal parser generators by Alan DeKok and me - pidl now writes errors in the standard format used by compilers, which is parsable by most editors - ability to warn about the fact that pidl extension(s) have been used, useful for making sure IDL files work with other IDL compilers. oh, and there's probably some other things I can't think of right now.. (This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01) --- source4/build/pidl/README | 4 +- source4/build/pidl/com_header.pm | 4 +- source4/build/pidl/compat.pm | 55 + source4/build/pidl/dcom_proxy.pm | 2 +- source4/build/pidl/eparser.pm | 865 ------------- source4/build/pidl/eth_header.pm | 102 ++ source4/build/pidl/eth_parser.pm | 1410 ++++++++++++++++++++ source4/build/pidl/idl.pm | 159 +-- source4/build/pidl/idl.yp | 49 +- source4/build/pidl/ndr.pm | 286 +++- source4/build/pidl/ndr_client.pm | 8 +- source4/build/pidl/ndr_header.pm | 128 +- source4/build/pidl/ndr_parser.pm | 1873 ++++++++++++++------------- source4/build/pidl/needed.pm | 80 -- source4/build/pidl/odl.pm | 17 + source4/build/pidl/pidl.pl | 62 +- source4/build/pidl/test.pm | 2 +- source4/build/pidl/typelist.pm | 219 +--- source4/build/pidl/validator.pm | 46 +- source4/librpc/idl/atsvc.idl | 3 +- source4/librpc/idl/audiosrv.idl | 1 + source4/librpc/idl/browser.idl | 1 + source4/librpc/idl/dbgidl.idl | 2 +- source4/librpc/idl/dcom.idl | 16 +- source4/librpc/idl/dfs.idl | 1 + source4/librpc/idl/drsblobs.idl | 1 + source4/librpc/idl/drsuapi.idl | 5 +- source4/librpc/idl/dsbackup.idl | 5 +- source4/librpc/idl/dssetup.idl | 1 + source4/librpc/idl/echo.idl | 1 + source4/librpc/idl/efs.idl | 2 +- source4/librpc/idl/epmapper.idl | 3 +- source4/librpc/idl/eventlog.idl | 1 + source4/librpc/idl/exchange.idl | 1 + source4/librpc/idl/initshutdown.idl | 1 + source4/librpc/idl/krb5pac.idl | 1 + source4/librpc/idl/lsa.idl | 1 + source4/librpc/idl/mgmt.idl | 1 + source4/librpc/idl/nbt.idl | 2 +- source4/librpc/idl/netlogon.idl | 1 + source4/librpc/idl/oxidresolver.idl | 1 + source4/librpc/idl/policyagent.idl | 2 +- source4/librpc/idl/remact.idl | 1 + source4/librpc/idl/rot.idl | 3 +- source4/librpc/idl/samr.idl | 3 +- source4/librpc/idl/spoolss.idl | 1 + source4/librpc/idl/srvsvc.idl | 1 + source4/librpc/idl/svcctl.idl | 5 +- source4/librpc/idl/trkwks.idl | 2 +- source4/librpc/idl/winreg.idl | 1 + source4/librpc/idl/winsrepl.idl | 3 +- source4/librpc/idl/wkssvc.idl | 1 + source4/librpc/ndr/libndr.h | 1 - source4/librpc/ndr/ndr.c | 120 +- source4/librpc/ndr/ndr_sec.c | 4 +- source4/librpc/rpc/dcerpc.c | 3 +- source4/rpc_server/dcerpc_server.c | 2 + source4/utils/ndrdump.c | 6 +- 58 files changed, 3164 insertions(+), 2418 deletions(-) create mode 100644 source4/build/pidl/compat.pm delete mode 100644 source4/build/pidl/eparser.pm create mode 100644 source4/build/pidl/eth_header.pm create mode 100644 source4/build/pidl/eth_parser.pm delete mode 100644 source4/build/pidl/needed.pm diff --git a/source4/build/pidl/README b/source4/build/pidl/README index e0878888408..eac0674153d 100644 --- a/source4/build/pidl/README +++ b/source4/build/pidl/README @@ -19,8 +19,8 @@ validator.pm - Validates the parse tree -- DCE/RPC+NDR -- ndr_client.pm - Generates client call functions in C using the NDR parser -eparser.pm - Generates a parser for the ethereal network sniffer by - applying regexes to the output of parser.pm +eth_parser.pm - Generates a parser for the ethereal network sniffer +eth_header.pm - Generates a header for ethereal swig.pm - Generates SWIG interface files (.i) ndr_header.pm - Generates a header file with structures ndr.pm - Generates pull/push functions for parsing NDR diff --git a/source4/build/pidl/com_header.pm b/source4/build/pidl/com_header.pm index 1c7194d85cb..95bbc9c720c 100644 --- a/source4/build/pidl/com_header.pm +++ b/source4/build/pidl/com_header.pm @@ -14,7 +14,7 @@ sub GetArgumentProtoList($) foreach my $a (@{$f->{ELEMENTS}}) { - $res .= ", " . typelist::mapType($a) . " "; + $res .= ", " . typelist::mapType($a->{TYPE}) . " "; my $l = $a->{POINTERS}; $l-- if ($a->{TYPE} eq "string"); @@ -61,7 +61,7 @@ sub HeaderVTable($) my $data = $interface->{DATA}; foreach my $d (@{$data}) { - $res .= "\t" . typelist::mapScalarType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION"); + $res .= "\t" . typelist::mapType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION"); } $res .= "\n"; $res .= "struct $interface->{NAME}_vtable {\n"; diff --git a/source4/build/pidl/compat.pm b/source4/build/pidl/compat.pm new file mode 100644 index 00000000000..3ab94b70f38 --- /dev/null +++ b/source4/build/pidl/compat.pm @@ -0,0 +1,55 @@ +################################################### +# IDL Compatibility checker +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package IDLCompat; + +use strict; + +my($res); + +sub warning($$) +{ + my $l = shift; + my $m = shift; + + print "$l->{FILE}:$l->{LINE}:$m\n"; +} + +sub CheckInterface($) +{ + my $if = shift; + if (util::has_property($if, "pointer_default_top")) { + warning($if, "pointer_default_top() is pidl-specific"); + } + + foreach my $x (@{$if->{DATA}}) { + if ($x->{TYPE} eq "DECLARE") { + warning($if, "the declare keyword is pidl-specific"); + next; + } + + if ($x->{TYPE} eq "TYPEDEF") { + if ($x->{DATA}->{TYPE} eq "UNION") { + if (util::has_property($x, "nodiscriminant")) { + warning($x, "nodiscriminant property is pidl-specific"); + } + } + } + } +} + +sub Check($) +{ + my $pidl = shift; + my $res = ""; + + foreach my $x (@{$pidl}) { + CheckInterface($x) if ($x->{TYPE} eq "INTERFACE"); + } + + return $res; +} + +1; diff --git a/source4/build/pidl/dcom_proxy.pm b/source4/build/pidl/dcom_proxy.pm index 8cc55476802..3d460645484 100644 --- a/source4/build/pidl/dcom_proxy.pm +++ b/source4/build/pidl/dcom_proxy.pm @@ -173,7 +173,7 @@ sub RegistrationFunction($$) next if $interface->{TYPE} ne "INTERFACE"; next if not util::has_property($interface, "object"); - my $data = $interface->{INHERITED_DATA}; + my $data = $interface->{DATA}; my $count = 0; foreach my $d (@{$data}) { if ($d->{TYPE} eq "FUNCTION") { $count++; } diff --git a/source4/build/pidl/eparser.pm b/source4/build/pidl/eparser.pm deleted file mode 100644 index 23ff8e7954f..00000000000 --- a/source4/build/pidl/eparser.pm +++ /dev/null @@ -1,865 +0,0 @@ -################################################### -# Samba4 parser generator for IDL structures -# Copyright tridge@samba.org 2000-2003 -# Copyright tpot@samba.org 2001,2004-2005 -# released under the GNU GPL - -package IdlEParser; - -use ndr_parser; -use strict; - -# the list of needed functions -my %needed; -my %bitmaps; - -my $module; -my $if_uuid; -my $if_version; -my $if_endpoints; - -sub pidl($) -{ - print OUT shift; -} - -##################################################################### -# a list of annotations - -my $nopull_typedefs = { -# "policy_handle" => "1", -}; - -##################################################################### -# work out is a parse function should be declared static or not -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 ""; - } - } - return "static "; -} - - -##################################################################### -# parse a function -sub ParseFunctionPull($) -{ - my($fn) = shift; - my $static = fn_prefix($fn); - - # request function - pidl "int $fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n{\n"; - - pidl "\tstruct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);\n"; - pidl "\tstruct $fn->{NAME} *r = talloc(NULL, struct $fn->{NAME});\n"; - pidl "\tpidl_tree ptree;\n\n"; - - pidl "\tptree.proto_tree = tree;\n"; - pidl "\tptree.subtree_list = NULL;\n\n"; - - pidl "\tndr_pull_$fn->{NAME}(ndr, NDR_IN, &ptree, r);\n"; - - pidl "\n\treturn ndr->offset;\n"; - pidl "}\n\n"; - - # response function - pidl "int $fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n{\n"; - - pidl "\tstruct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);\n"; - pidl "\tstruct $fn->{NAME} *r = talloc(NULL, struct $fn->{NAME});\n"; - pidl "\tpidl_tree ptree;\n\n"; - - pidl "\tptree.proto_tree = tree;\n"; - pidl "\tptree.subtree_list = NULL;\n\n"; - - pidl "\tndr_pull_$fn->{NAME}(ndr, NDR_OUT, &ptree, r);\n"; - - pidl "\n\treturn ndr->offset;\n"; - pidl "}\n\n"; -} - -##################################################################### -# produce a function call table -sub FunctionTable($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - - pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {\n"; - my $num = 0; - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { - # Strip module name from function name, if present - my($n) = $d->{NAME}; - $n = substr($d->{NAME}, length($module) + 1), - if $module eq substr($d->{NAME}, 0, length($module)); - pidl "\t{ $num, \"$n\",\n"; - pidl "\t\t$d->{NAME}_rqst,\n"; - pidl "\t\t$d->{NAME}_resp },\n"; - $num++; - } - } - pidl "};\n\n"; -} - -sub type2ft($) -{ - my($t) = shift; - - return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/; - return "FT_INT$1" if $t =~ /int(8|16|32|64)/; - return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME" - or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper"; - - # Type is an enum - - return "FT_UINT16"; -} - -# Determine the display base for an element - -sub elementbase($) -{ - my($e) = shift; - - if (my $base = util::has_property($e, "display")) { - return "BASE_" . uc($base); - } - - return "BASE_DEC", if $e->{TYPE} eq "ENUM"; - return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/; - return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T"; - - # Probably an enum - - return "BASE_DEC"; -} - -# Convert a IDL structure field name (e.g access_mask) to a prettier -# string like 'Access Mask'. - -sub field2name($) -{ - my($field) = shift; - - $field =~ s/_/ /g; # Replace underscores with spaces - $field =~ s/(\w+)/\u\L$1/g; # Capitalise each word - - return $field; -} - -sub NeededFunction($) -{ - my $fn = shift; - - $needed{"pull_$fn->{NAME}"} = 1; - - # Add entries for function arguments - - foreach my $e (@{$fn->{ELEMENTS}}) { - - $e->{PARENT} = $fn; - $needed{"pull_$e->{TYPE}"} = 1; - - if (NdrParser::is_scalar_type($e->{TYPE})) { - - if (defined($e->{ARRAY_LEN}) or - util::has_property($e, "size_is")) { - - # Array of scalar types - - $needed{"hf_$fn->{NAME}_$e->{NAME}_array"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => "FT_BYTES", - 'base' => elementbase($e) - }; - - } else { - - $needed{"hf_$fn->{NAME}_$e->{NAME}"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => type2ft($e->{TYPE}), - 'base' => elementbase($e) - }; - - } - - $e->{PARENT} = $fn; - - } else { - $needed{"ett_$e->{TYPE}"} = 1; - } - } - - # Add entry for return value - - $needed{"hf_$fn->{NAME}_result"} = { - 'name' => field2name('result'), - 'type' => $fn->{RETURN_TYPE}, - 'ft' => type2ft($fn->{RETURN_TYPE}), - 'base' => elementbase($fn) - }; -} - -sub bitmapbase($) -{ - my $e = shift; - - return "16", if util::has_property($e->{DATA}, "bitmap16bit"); - return "8", if util::has_property($e->{DATA}, "bitmap8bit"); - - return "32"; -} - -sub NeededTypedef($) -{ - my $t = shift; - - if (util::has_property($t, "public")) { - $needed{"pull_$t->{NAME}"} = 1; - } - - if ($t->{DATA}->{TYPE} eq "STRUCT") { - - for my $e (@{$t->{DATA}->{ELEMENTS}}) { - - $e->{PARENT} = $t->{DATA}; - - if ($needed{"pull_$t->{NAME}"}) { - $needed{"pull_$e->{TYPE}"} = 1; - } - - if (NdrParser::is_scalar_type($e->{TYPE})) { - - if (defined($e->{ARRAY_LEN}) or - util::has_property($e, "size_is")) { - - # Arrays of scalar types are FT_BYTES - - $needed{"hf_$t->{NAME}_$e->{NAME}_array"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => "FT_BYTES", - 'base' => elementbase($e) - }; - - } else { - - $needed{"hf_$t->{NAME}_$e->{NAME}"} = { - 'name' => field2name($e->{NAME}), - 'type' => $e->{TYPE}, - 'ft' => type2ft($e->{TYPE}), - 'base' => elementbase($e) - }; - } - - $e->{PARENT} = $t->{DATA}; - - if ($needed{"pull_$t->{NAME}"}) { - $needed{"pull_$e->{TYPE}"} = 1; - } - - } else { - $needed{"ett_$e->{TYPE}"} = 1; - } - } - } - - if ($t->{DATA}->{TYPE} eq "UNION") { - for my $e (@{$t->{DATA}->{ELEMENTS}}) { - - $e->{PARENT} = $t->{DATA}; - - if ($needed{"pull_$t->{NAME}"}) { - $needed{"pull_$e->{TYPE}"} = 1; - } - - $needed{"ett_$e->{TYPE}"} = 1; - } - - $needed{"ett_$t->{NAME}"} = 1; - } - - if ($t->{DATA}->{TYPE} eq "ENUM") { - - $needed{"hf_$t->{NAME}"} = { - 'name' => field2name($t->{NAME}), - 'ft' => 'FT_UINT16', - 'base' => 'BASE_DEC', - 'strings' => "VALS($t->{NAME}_vals)" - }; - } - - if ($t->{DATA}->{TYPE} eq "BITMAP") { - - $bitmaps{$t->{NAME}} = $t; - - foreach my $e (@{$t->{DATA}{ELEMENTS}}) { - $e =~ /^(.*?) \( (.*?) \)$/; - $needed{"hf_$t->{NAME}_$1"} = { - 'name' => "$1", - 'ft' => "FT_BOOLEAN", - 'base' => bitmapbase($t), - 'bitmask' => "$2" - }; - } - - $needed{"ett_$t->{NAME}"} = 1; - } -} - -##################################################################### -# work out what parse functions are needed -sub BuildNeeded($) -{ - my($interface) = shift; - - my($data) = $interface->{DATA}; - - foreach my $d (@{$data}) { - ($d->{TYPE} eq "FUNCTION") && - NeededFunction($d); - } - - foreach my $d (reverse @{$data}) { - ($d->{TYPE} eq "TYPEDEF") && - NeededTypedef($d); - } -} - -##################################################################### -# parse the interface definitions -sub ModuleHeader($) -{ - my($h) = shift; - - $if_uuid = $h->{PROPERTIES}->{uuid}; - $if_version = $h->{PROPERTIES}->{version}; - $if_endpoints = $h->{PROPERTIES}->{endpoints}; -} - -##################################################################### -# Generate a header file that contains function prototypes for -# structs and typedefs. -sub ParseHeader($$) -{ - my($idl) = shift; - my($filename) = shift; - - open(OUT, ">$filename") || die "can't open $filename"; - - pidl "/* parser auto-generated by pidl */\n\n"; - - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - foreach my $d (@{$x->{DATA}}) { - - # Make prototypes for [public] structures and - # unions. - - if ($d->{TYPE} eq "TYPEDEF" and - util::has_property($d, "public")) { - - if ($d->{DATA}{TYPE} eq "STRUCT") { - pidl "void ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree, struct $d->{NAME} *r);\n\n"; - } - - if ($d->{DATA}{TYPE} eq "UNION") { - pidl "void ndr_pull_$d->{NAME}(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree, union $d->{NAME} *r, uint16 level);\n\n"; - } - } - } - } - } - - close(OUT); -} - -##################################################################### -# generate code to parse an enum - -sub ParseEnum($) -{ - my ($e) = shift; - - pidl "static const value_string $e->{PARENT}{NAME}_vals[] =\n"; - pidl "{\n"; - - foreach my $x (@{$e->{ELEMENTS}}) { - $x =~ /([^=]*)=(.*)/; - pidl "\t{ $1, \"$1\" },\n"; - } - - pidl "};\n\n"; -} - -##################################################################### -# rewrite autogenerated header file -sub RewriteHeader($$$) -{ - my($idl) = shift; - my($input) = shift; - my($output) = shift; - - NdrParser::Load($idl); - - %needed = (); - - # Open files - - open(IN, "<$input") || die "can't open $input for reading"; - open(OUT, ">$output") || die "can't open $output for writing"; - - # Read through file - - while() { - - # Not interested in ndr_push or ndr_print routines as they - # define structures we aren't interested in. - - s/^NTSTATUS ndr_push.*?;\n//smg; - s/^void ndr_print.*?;\n//smg; - - # Get rid of async send and receive function. - - s/^NTSTATUS dcerpc_.*?;//smg; - s/^struct rpc_request.*?;//smg; - - # Rewrite librpc includes - - s/^\#include\ \"librpc\/gen_ndr\/ndr_(.*?).h\"$ - /\#include \"packet-dcerpc-$1.h\"/smgx; - - # Rename struct ndr_pull to struct pidl_pull - - s/struct ndr_pull \*ndr/struct pidl_pull \*ndr/smg; - - # Change prototypes for public functions - - s/(struct pidl_pull \*ndr, int ndr_flags)/$1, pidl_tree *tree/smg; - - # Bitmaps - - s/int ndr_flags, (pidl_tree \*tree), (uint32_t \*r\);)/$1, int hf, $2/smg; - - pidl $_; - } - - close(OUT); -} - -##################################################################### -# rewrite autogenerated C file -sub RewriteC($$$) -{ - my($idl) = shift; - my($input) = shift; - my($output) = shift; - - NdrParser::Load($idl); - - # Open files - - open(IN, "<$input") || die "can't open $input for reading"; - open(OUT, ">$output") || die "can't open $output for writing"; - - # Get name of module - - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - ModuleHeader($x); - $module = $x->{NAME}; - BuildNeeded($x); - } - } - - pidl "#include \"eparser.h\"\n\n"; - - pidl "extern const value_string NT_errors[];\n\n"; - - # Declarations for hf variables - - pidl "static int hf_opnum = -1;\n"; - pidl "static int hf_ptr = -1;\n"; - pidl "static int hf_array_size = -1;\n"; - pidl "static int hf_result_NTSTATUS = -1;\n"; - - pidl "\n"; - - foreach my $y (keys(%needed)) { - pidl "static int $y = -1;\n", if $y =~ /^hf_/; - } - - pidl "\n"; - - foreach my $y (keys(%needed)) { - pidl "static gint $y = -1;\n", if $y =~ /^ett_/; - } - - pidl "\n"; - - # Read through file - - my $cur_fn = ""; - - while() { - - # - # Regexps to do a first pass at removing stuff we aren't - # interested in for ethereal parsers. - # - - next, if /^\#include \"includes.h\"/; - - # Rewrite includes to packet-dcerpc-foo.h instead of ndr_foo.h - - s/^\#include \".*?ndr_(.*?).h\"$/\#include \"packet-dcerpc-$1.h\"/smg; - - if (/\.h\"$/) { - pidl $_; - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - foreach my $y (@{$x->{INHERITED_DATA}}) { - if ($y->{TYPE} eq "TYPEDEF") { - ParseEnum($y->{DATA}), if $y->{DATA}{TYPE} eq "ENUM"; - } - } - } - } - next; - } - - # Remove the NDR_CHECK() macro calls. Ethereal take care of - # this for us as part of the tvbuff_t structure. - - s/NDR_CHECK\((.*)\)/$1/g; - - # We're not interested in ndr_{print,push,size} functions so - # just delete them. - - next, if /^(static )?NTSTATUS ndr_push/ .. /^}/; - next, if /^void ndr_print/ .. /^}/; - next, if /^size_t ndr_size/ .. /^}/; - - # get rid of the init functions - next, if /^NTSTATUS dcerpc_ndr_\w+_init/ .. /^}/; - - # Get rid of dcerpc interface structures and functions since - # they are also not very interesting. - - next, if /^static const struct dcerpc_interface_call/ .. /^};/; - next, if /^static const char \* const [a-z]+_endpoint_strings/ ../^};/; - next, if /^static const struct dcerpc_endpoint_list/ .. /^};/; - next, if /^const struct dcerpc_interface_table/ .. /^};/; - next, if /^static NTSTATUS dcerpc_ndr_[a-z]+_init/ .. /^}/; - next, if /^NTSTATUS dcerpc_[a-z]+_init/ .. /^}/; - - # - # Remember which structure or function we are processing. - # - - $cur_fn = $1, if /NTSTATUS ndr_pull_(.*?)\(struct/; - - # Skip functions we have marked as nopull - - my $skip_fn = 0; - - foreach my $f (keys(%{$nopull_typedefs})) { - $skip_fn = 1, if $cur_fn eq $f; - } - - $cur_fn = "", if /^}/; - - next, if $skip_fn; - - # - # OK start wrapping the ndr_pull functions that actually - # implement the NDR decoding routines. This mainly consists - # of adding a couple of parameters to each function call. - # - - # Add proto tree and name argument to ndr_pull_unique_ptr() calls. - - s/(ndr_pull_unique_ptr\(ndr,\ (&_ptr_([^\)]*?))\);) - /ndr_pull_ptr(ndr, tree, "$3", $2);/smgx; - - # Wrap ndr_pull_array_size() and ndr_pull_array_length() - # functions. Add leading space in front of first parameter so - # we won't get caught by later regexps. - - s/(ndr_pull_array_(size|length)\(ndr,\ ([^\)]*?)\);) - /ndr_pull_array_$2( ndr, tree, $3);/smgx; - - # Add tree argument to ndr_pull_array() and - # ndr_pull_array_foo() calls. - - s/(ndr_pull_array\( - ndr,\ - ([^,]*?),\ # NDR_SCALARS etc - (\(void\ \*\*\)r->(in|out|)\.?([^,]*?)),\ # Pointer to array entries - ([^\)].*?)\);) # All other arguments - /ndr_pull_array( ndr, $2, tree, $3, $6);/smgx; - - s/(ndr_pull_array_([^\(]*?)\( - ndr,\ - ([^,]*?),\ # NDR_SCALARS etc - (r->((in|out).)?([^,]*?)),\ # Pointer to array elements - (.*?)\);) # Number of elements - /ndr_pull_array_$2( ndr, $3, tree, hf_${cur_fn}_$7_array, $4, $8);/smgx; - - # Save ndr_pull_relative_ptr{1,2}() calls from being wrapped by the - # proceeding regexp by adding a leading space. - - s/ndr_pull_(relative_ptr1|relative_ptr2)\((.*?)\);/ - ndr_pull_$1( $2);/smgx; - - # Enums - - s/(^static\ NTSTATUS\ ndr_pull_(.+?),\ int\ ndr_flags,\ (enum\ .+?)\)) - /static NTSTATUS ndr_pull_$2, pidl_tree *tree, int hf, $3)/smgx; - s/uint(8|16|32) v;/uint$1_t v;/smg; - s/(ndr_pull_([^\(]+?)\(ndr,\ NDR_[^,]*,\ &_level\);) - /ndr_pull_$2(ndr, tree, hf_${cur_fn}_level, &_level);/smgx; - - # Bitmaps - - s/(^(static\ )?NTSTATUS\ ndr_pull_(.+?),\ int\ ndr_flags,\ uint(8|16|32)_t\ \*r\)) - /NTSTATUS ndr_pull_$3, pidl_tree *tree, int hf, uint$4_t *r)/smgx; - - if (/ndr_pull_([^\)]*?)\(ndr,\ NDR_[^,]*,\ &v\);/) { - - s/(ndr_pull_([^\)]*?)\(ndr,\ (NDR_[^,]*?),\ &v\);) - /ndr_pull_$2(ndr, tree, hf, &v);/smgx; - - pidl $_; - - if (defined($bitmaps{$cur_fn})) { - pidl "\t{\n\t\tproto_tree *subtree = NULL;\n\n"; - pidl "\t\tif (tree->proto_tree)\n\t\t\tsubtree = proto_item_add_subtree(tree->proto_tree->last_child, ett_$cur_fn);\n\n"; - foreach my $e (@{$bitmaps{$cur_fn}->{DATA}{ELEMENTS}}) { - $e =~ /^(.*?) \( (.*?) \)$/; - pidl "\t\tproto_tree_add_boolean(subtree, hf_${cur_fn}_$1, ndr->tvb, ndr->offset - sizeof(v), sizeof(v), v);\n"; - } - pidl "\t}\n"; - } - - next; - } - - # Call ethereal wrappers for pull of scalar values in - # structures and functions, e.g - # - # ndr_pull_uint32(ndr, &r->in.access_mask); - # ndr_pull_uint32(ndr, &r->idx); - - if (/(ndr_pull_([^\)]*?)\(ndr, NDR_[^,]*?, (&?r->((in|out)\.)?([^\)]*?))\);)/ and NdrParser::is_scalar_type($2)) { - - my $pull_type = "${cur_fn}_$6"; - - if (defined($needed{"hf_$2"})) { - $pull_type = "$2"; - } - - s/(ndr_pull_([^\)]*?)\( - ndr,\ - NDR_[^,]*?,\ - (&?r->((in|out)\.)? # Function args contain leading junk - ([^\)]*?)) # Element name - \);) - /ndr_pull_$2(ndr, tree, hf_$pull_type, $3);/smgx; - } - - # Add tree and hf argument to pulls of "internal" scalars like - # array sizes, levels, etc. - - s/(ndr_pull_(uint32|uint16)\( - ndr,\ - NDR_[^,]*?,\ - (&_([^\)]*?)) # Internal arg names have leading underscore - \);) - /ndr_pull_$2(ndr, tree, hf_$4, $3);/smgx; - - # Add subtree argument to calls dissecting structures/unions, e.g - # - # ndr_pull_string(ndr, NDR_SCALARS|NDR_BUFFERS, &r->command); - # ndr_pull_atsvc_enum_ctr(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.ctr); - - # Three argument version is for structures - - if (/ndr_pull_([^\)]*?)\(ndr, (NDR_[^,]*?), ([^,]*?)\);/ and - not NdrParser::is_scalar_type($1)) { - s/(ndr_pull_([^\)]*?)\( - ndr,\ - (NDR_[^,]*?),\ - (&?r->((in|out)\.)?([^\(].*?))\);) - /ndr_pull_$2(ndr, $3, get_subtree(tree, \"$7\", ndr, ett_$2), $4); - /smgx; - } - - # Four argument version if for unions - if (/ndr_pull_([^\)]*?)\(ndr, (NDR_[SB][^,]*?), ([^,]*?), ([^,]*?)\);/ and - not NdrParser::is_scalar_type($1)) { - s/(ndr_pull_([^\)]*?)\( - ndr,\ - (NDR_[^,]*?),\ - (&?r->((in|out)\.)?([^\(].*?))\);) - /ndr_pull_$2(ndr, $3, get_subtree(tree, \"$2\", ndr, ett_$2), $4); - /smgx; - } - - # Add proto_tree parameter to pull function prototypes, e.g - # - # static NTSTATUS ndr_pull_atsvc_JobInfo(struct ndr_pull *ndr, - # int ndr_flags, struct atsvc_JobInfo *r) - - s/^((static\ )?NTSTATUS\ ndr_pull_([^\(]*?)\( - struct\ ndr_pull\ \*ndr,\ - int\ (ndr_)?flags) - /$1, proto_tree \*tree/smgx; - - # Add proto_tree parameter to ndr_pull_subcontext_flags_fn() - - s/(ndr_pull_subcontext_flags_fn\(ndr)(.*?);/$1, tree$2;/smg; - - # Get rid of ndr_pull_error() calls for the moment. Ethereal - # should take care of buffer overruns and inconsistent array - # sizes for us but it would be nice to have some error text in - # the dissection. - - s/(return ndr_pull_error([^;]*?);)/return NT_STATUS_OK; \/\/ $1/smg; - - # Rename proto_tree args to pidl_tree - - s/(int (ndr_)?flags), proto_tree \*tree/$1, pidl_tree \*tree/smg; - - # Rename struct ndr_pull to struct pidl_pull - - s/struct ndr_pull \*ndr/struct pidl_pull \*ndr/smg; - - # Fix some internal variable declarations - - s/(u?)int(8|16|32) _level;/$1int$2_t _level;/smg; - s/ndr_pull_([^\(]*)\(ndr,\ tree,\ hf_level,\ &_level\); - /ndr_pull_$1(ndr, tree, hf_level_$1, &_level);/smgx; - - # Set the end of a structure - - s/(ndr_pull_struct_end.*)/$1\tproto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);\n/smg; - - pidl $_; - } - - # Function call table - - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - foreach my $y (@{$x->{"INHERITED_DATA"}}) { - ($y->{TYPE} eq "FUNCTION") && ParseFunctionPull($y); - } - - FunctionTable($x); - } - } - - # Ethereal protocol registration - - pidl "int proto_dcerpc_pidl_$module = -1;\n\n"; - - pidl "static gint ett_dcerpc_$module = -1;\n\n"; - - if (defined($if_uuid)) { - - pidl "static e_uuid_t uuid_dcerpc_$module = {\n"; - pidl "\t0x" . substr($if_uuid, 1, 8); - pidl ", 0x" . substr($if_uuid, 10, 4); - pidl ", 0x" . substr($if_uuid, 15, 4) . ",\n"; - pidl "\t{ 0x" . substr($if_uuid, 20, 2); - pidl ", 0x" . substr($if_uuid, 22, 2); - pidl ", 0x" . substr($if_uuid, 25, 2); - pidl ", 0x" . substr($if_uuid, 27, 2); - pidl ", 0x" . substr($if_uuid, 29, 2); - pidl ", 0x" . substr($if_uuid, 31, 2); - pidl ", 0x" . substr($if_uuid, 33, 2); - pidl ", 0x" . substr($if_uuid, 35, 2) . " }\n"; - pidl "};\n\n"; - } - - if (defined($if_version)) { - pidl "static guint16 ver_dcerpc_$module = " . $if_version . ";\n\n"; - } - - pidl "void proto_register_dcerpc_pidl_$module(void)\n"; - pidl "{\n"; - - pidl "\tstatic hf_register_info hf[] = {\n"; - pidl "\t{ &hf_opnum, { \"Operation\", \"$module.opnum\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Operation\", HFILL }},\n"; - pidl "\t{ &hf_result_NTSTATUS, { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},\n"; - pidl "\t{ &hf_ptr, { \"Pointer\", \"$module.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},\n"; - - foreach my $x (keys(%needed)) { - next, if !($x =~ /^hf_/); - pidl "\t{ &$x,\n"; - $needed{$x}{strings} = "NULL", if !defined($needed{$x}{strings}); - $needed{$x}{bitmask} = "0", if !defined($needed{$x}{bitmask}); - pidl "\t { \"$needed{$x}{name}\", \"$x\", $needed{$x}{ft}, $needed{$x}{base}, $needed{$x}{strings}, $needed{$x}{bitmask}, \"$x\", HFILL }},\n"; - } - - pidl "\t};\n\n"; - - pidl "\tstatic gint *ett[] = {\n"; - pidl "\t\t&ett_dcerpc_$module,\n"; - foreach my $x (keys(%needed)) { - pidl "\t\t&$x,\n", if $x =~ /^ett_/; - } - pidl "\t};\n\n"; - - if (defined($if_uuid)) { - - # These can be changed to non-pidl names if the old dissectors - # in epan/dissctors are deleted. - - my $name = uc($module) . " (pidl)"; - my $short_name = "pidl_$module"; - my $filter_name = "pidl_$module"; - - pidl "\tproto_dcerpc_pidl_$module = proto_register_protocol(\"$name\", \"$short_name\", \"$filter_name\");\n\n"; - - pidl "\tproto_register_field_array(proto_dcerpc_pidl_$module, hf, array_length (hf));\n"; - pidl "\tproto_register_subtree_array(ett, array_length(ett));\n"; - - pidl "}\n\n"; - - pidl "void proto_reg_handoff_dcerpc_pidl_$module(void)\n"; - pidl "{\n"; - pidl "\tdcerpc_init_uuid(proto_dcerpc_pidl_$module, ett_dcerpc_$module, \n"; - pidl "\t\t&uuid_dcerpc_$module, ver_dcerpc_$module, \n"; - pidl "\t\tdcerpc_dissectors, hf_opnum);\n"; - pidl "}\n"; - - } else { - - pidl "\tint proto_dcerpc;\n\n"; - pidl "\tproto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");\n"; - pidl "\tproto_register_field_array(proto_dcerpc, hf, array_length(hf));\n"; - pidl "\tproto_register_subtree_array(ett, array_length(ett));\n"; - - pidl "}\n"; - - } - - close(OUT); -} - -1; diff --git a/source4/build/pidl/eth_header.pm b/source4/build/pidl/eth_header.pm new file mode 100644 index 00000000000..f0a57788544 --- /dev/null +++ b/source4/build/pidl/eth_header.pm @@ -0,0 +1,102 @@ +################################################### +# create C header files for an IDL structure +# Copyright tridge@samba.org 2000 +# Copyright jelmer@samba.org 2005 +# released under the GNU GPL + +package EthHeader; + +use strict; +use typelist; + +my($res); +my($tab_depth); + +sub pidl ($) +{ + $res .= shift; +} + +sub tabs() +{ + for (my($i)=0; $i < $tab_depth; $i++) { + pidl "\t"; + } +} + +##################################################################### +# prototype a typedef +sub HeaderTypedefProto($) +{ + my($d) = shift; + + my $tf = EthParser::get_typefamily($d->{DATA}{TYPE}); + + return unless util::has_property($d, "public"); + + unless (util::has_property($d, "nopull")) { + pidl "dcerpc_dissect_fnct_t $d->{NAME};\n"; + } +} + +##################################################################### +# parse a const +sub HeaderConst($) +{ + my($const) = shift; + if (!defined($const->{ARRAY_LEN})) { + pidl "#define $const->{NAME}\t( $const->{VALUE} )\n"; + } else { + pidl "#define $const->{NAME}\t $const->{VALUE}\n"; + } +} + +my %headerstructs = (); + +##################################################################### +# parse the interface definitions +sub HeaderInterface($) +{ + my($interface) = shift; + + my $count = 0; + + pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n"; + pidl "#define _HEADER_NDR_$interface->{NAME}\n\n"; + + if (defined $interface->{PROPERTIES}->{depends}) { + my @d = split / /, $interface->{PROPERTIES}->{depends}; + foreach my $i (@d) { + pidl "#include \"packet-dcerpc-$i\.h\"\n"; + } + } + + foreach my $d (@{$interface->{CONSTS}}) { + HeaderConst($d); + } + + foreach my $d (@{$interface->{TYPEDEFS}}) { + HeaderTypedefProto($d); + } + + pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; +} + +##################################################################### +# parse a parsed IDL into a C header +sub Parse($) +{ + my($idl) = shift; + $tab_depth = 0; + + $res = ""; + pidl "/* header auto-generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + if ($x->{TYPE} eq "INTERFACE") { + HeaderInterface($x); + } + } + return $res; +} + +1; diff --git a/source4/build/pidl/eth_parser.pm b/source4/build/pidl/eth_parser.pm new file mode 100644 index 00000000000..a2e1bf051ce --- /dev/null +++ b/source4/build/pidl/eth_parser.pm @@ -0,0 +1,1410 @@ +################################################## +# Samba4 NDR parser generator for IDL structures +# Copyright tridge@samba.org 2000-2003 +# Copyright tpot@samba.org 2001 +# Copyright jelmer@samba.org 2004-2005 +# released under the GNU GPL + +package EthParser; + +use strict; +use typelist; +use ndr; + +# the list of needed functions + +# list of known types +my %typefamily; + + +sub NeededFunction($$) +{ + my $fn = shift; + my $needed = shift; + $needed->{"pull_$fn->{NAME}"} = 1; + foreach my $e (@{$fn->{ELEMENTS}}) { + $e->{PARENT} = $fn; + unless(defined($needed->{"pull_$e->{TYPE}"})) { + $needed->{"pull_$e->{TYPE}"} = 1; + } + + # for Ethereal + if (Ndr::is_scalar_type($e->{TYPE})) { + + if (defined($e->{ARRAY_LEN}) or + util::has_property($e, "size_is")) { + + # Array of scalar types + + $needed->{"hf_$fn->{NAME}_$e->{NAME}_array"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => "FT_BYTES", + 'base' => elementbase($e) + }; + + } else { + $needed->{"hf_$fn->{NAME}_$e->{NAME}"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => elementbase($e) + }; + } + } else { + $needed->{"hf_$fn->{NAME}_$e->{NAME}"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => elementbase($e) + }; + $needed->{"hf_$e->{TYPE}"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => elementbase($e) + }; + $needed->{"ett_$e->{TYPE}"} = 1; + } + } + + # Add entry for return value + if (defined($fn->{RETURN_TYPE})) { + $needed->{"hf_$fn->{NAME}_result"} = { + 'name' => field2name('result'), + 'type' => $fn->{RETURN_TYPE}, + 'ft' => type2ft($fn->{RETURN_TYPE}), + 'base' => elementbase($fn) + }; + } +} + +sub NeededTypedef($$) +{ + my $t = shift; + my $needed = shift; + + if (util::has_property($t, "public")) { + $needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull"); + } + + if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") { + + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + $e->{PARENT} = $t->{DATA}; + if ($needed->{"pull_$t->{NAME}"} and + not defined($needed->{"pull_$e->{TYPE}"})) { + $needed->{"pull_$e->{TYPE}"} = 1; + } + + if (Ndr::is_scalar_type($e->{TYPE})) { + if (defined($e->{ARRAY_LEN}) or + util::has_property($e, "size_is")) { + + # Arrays of scalar types are FT_BYTES + + $needed->{"hf_$t->{NAME}_$e->{NAME}_array"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => "FT_BYTES", + 'base' => elementbase($e) + }; + + } else { + $needed->{"hf_$t->{NAME}_$e->{NAME}"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => elementbase($e) + }; + } + + $e->{PARENT} = $t->{DATA}; + + if ($needed->{"pull_$t->{NAME}"}) { + $needed->{"pull_$e->{TYPE}"} = 1; + } + + } else { + $needed->{"hf_$t->{NAME}_$e->{NAME}"} = { + 'name' => field2name($e->{NAME}), + 'type' => $e->{TYPE}, + 'ft' => type2ft($e->{TYPE}), + 'base' => elementbase($e) + }; + $needed->{"ett_$e->{TYPE}"} = 1; + } + } + } + + if ($t->{DATA}->{TYPE} eq "ENUM") { + + $needed->{"hf_$t->{NAME}"} = { + 'name' => field2name($t->{NAME}), + 'ft' => 'FT_UINT16', + 'base' => 'BASE_DEC', + 'strings' => "VALS($t->{NAME}_vals)" + }; + $needed->{"ett_$t->{NAME}"} = 1; + } + + if ($t->{DATA}->{TYPE} eq "BITMAP") { + $needed->{BITMAPS}->{$t->{NAME}} = $t; + + foreach my $e (@{$t->{DATA}{ELEMENTS}}) { + $e =~ /^(.*?) \( (.*?) \)$/; + $needed->{"hf_$t->{NAME}_$1"} = { + 'name' => "$1", + 'ft' => "FT_BOOLEAN", + 'base' => bitmapbase($t), + 'bitmask' => "$2" + }; + } + $needed->{"ett_$t->{NAME}"} = 1; + } +} + +##################################################################### +# work out what parse functions are needed +sub NeededInterface($) +{ + my($interface) = shift; + my %needed = (); + + $needed{"hf_$interface->{NAME}_opnum"} = { + 'name' => "Operation", + 'ft' => "FT_UINT16", + 'base' => "BASE_DEC" + }; + + $needed{"ett_dcerpc_$interface->{NAME}"} = 1; + + foreach my $d (@{$interface->{FUNCTIONS}}) { + NeededFunction($d, \%needed); + } + foreach my $d (reverse @{$interface->{TYPEDEFS}}) { + NeededTypedef($d, \%needed); + } + + return \%needed; +} + +sub type2ft($) +{ + my($t) = shift; + + return "FT_UINT$1" if $t =~ /uint(8|16|32|64)/; + return "FT_INT$1" if $t =~ /int(8|16|32|64)/; + return "FT_UINT64", if $t eq "HYPER_T" or $t eq "NTTIME" + or $t eq "NTTIME_1sec" or $t eq "NTTIME_hyper" or $t eq "hyper"; + + # Type is an enum + + return "FT_UINT16"; +} + +# Determine the display base for an element + +sub elementbase($) +{ + my($e) = shift; + + if (my $base = util::has_property($e, "display")) { + return "BASE_" . uc($base); + } + + return "BASE_DEC", if $e->{TYPE} eq "ENUM"; + return "BASE_DEC", if $e->{TYPE} =~ /u?int(8|16|32|64)/; + return "BASE_DEC", if $e->{TYPE} eq "NTTIME" or $e->{TYPE} eq "HYPER_T"; + + # Probably an enum + + return "BASE_DEC"; +} + +# Convert a IDL structure field name (e.g access_mask) to a prettier +# string like 'Access Mask'. + +sub field2name($) +{ + my($field) = shift; + + $field =~ s/_/ /g; # Replace underscores with spaces + $field =~ s/(\w+)/\u\L$1/g; # Capitalise each word + + return $field; +} + +sub bitmapbase($) +{ + my $e = shift; + + return "16", if util::has_property($e->{DATA}, "bitmap16bit"); + return "8", if util::has_property($e->{DATA}, "bitmap8bit"); + + return "32"; +} + +sub get_typefamily($) +{ + my $n = shift; + return $typefamily{$n}; +} + +sub append_prefix($$) +{ + my $e = shift; + my $var_name = shift; + my $pointers = 0; + + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER") { + $pointers++; + } elsif ($l->{TYPE} eq "ARRAY") { + if (($pointers == 0) and + (not $l->{IS_FIXED}) and + (not $l->{IS_INLINE})) { + return get_value_of($var_name) + } + } elsif ($l->{TYPE} eq "DATA") { + if ($l->{DATA_TYPE} eq "string" or + $l->{DATA_TYPE} eq "nbt_string") { + return get_value_of($var_name) unless ($pointers); + } + } + } + + return $var_name; +} + +# see if a variable needs to be allocated by the NDR subsystem on pull +sub need_alloc($) +{ + my $e = shift; + + return 0; +} + +sub get_pointer_to($) +{ + my $var_name = shift; + + if ($var_name =~ /^\*(.*)$/) { + return $1; + } elsif ($var_name =~ /^\&(.*)$/) { + return $var_name; +# return "&($var_name)"; + } else { + return "&$var_name"; + } +} + +sub get_value_of($) +{ + my $var_name = shift; + + if ($var_name =~ /^\&(.*)$/) { + return $1; + } else { + return "*$var_name"; + } +} + +my $res; +my $tabs = ""; +sub pidl($) +{ + my $d = shift; + if ($d) { + $res .= $tabs; + $res .= $d; + } + $res .="\n"; +} + +sub indent() +{ + $tabs .= "\t"; +} + +sub deindent() +{ + $tabs = substr($tabs, 0, -1); +} + +#################################################################### +# work out the name of a size_is() variable +sub ParseExpr($$) +{ + my($orig_expr) = shift; + my $varlist = shift; + + die("Undefined value in ParseExpr") if not defined($orig_expr); + + my $expr = $orig_expr; + + return $expr if (util::is_constant($expr)); + + my $prefix = ""; + my $postfix = ""; + + if ($expr =~ /\*(.*)/) { + $expr = $1; + $prefix = "*"; + } + + if ($expr =~ /^(.*)([\&\|\/+])(.*)$/) { + $postfix = $2.$3; + $expr = $1; + } + + if (defined($varlist->{$expr})) { + return $prefix.$varlist->{$expr}.$postfix; + } + + return $prefix.$expr.$postfix; +} + +##################################################################### +# check that a variable we get from ParseExpr isn't a null pointer +sub check_null_pointer($) +{ + my $size = shift; + if ($size =~ /^\*/) { + my $size2 = substr($size, 1); + pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;"; + } +} + +##################################################################### +# check that a variable we get from ParseExpr isn't a null pointer +# void return varient +sub check_null_pointer_void($) +{ + my $size = shift; + if ($size =~ /^\*/) { + my $size2 = substr($size, 1); + pidl "if ($size2 == NULL) return;"; + } +} + +##################################################################### +# work out is a parse function should be declared static or not +sub fn_prefix($) +{ + my $fn = shift; + + return "" if (util::has_property($fn, "public")); + return "static "; +} + +################################################################### +# setup any special flags for an element or structure +sub start_flags($) +{ + my $e = shift; + my $flags = util::has_property($e, "flag"); + if (defined $flags) { + pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;"; + pidl "ndr_set_flags(&ndr->flags, $flags);"; + indent; + } +} + +################################################################### +# end any special flags for an element or structure +sub end_flags($) +{ + my $e = shift; + my $flags = util::has_property($e, "flag"); + if (defined $flags) { + pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}"; + deindent; + } +} + +sub GenerateStructEnv($) +{ + my $x = shift; + my %env; + + foreach my $e (@{$x->{ELEMENTS}}) { + $env{$e->{NAME}} = "r->$e->{NAME}"; + } + + $env{"this"} = "r"; + + return \%env; +} + +sub GenerateFunctionEnv($) +{ + my $fn = shift; + my %env; + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep (/out/, @{$e->{DIRECTION}})) { + $env{$e->{NAME}} = "r->out.$e->{NAME}"; + } + if (grep (/in/, @{$e->{DIRECTION}})) { + $env{$e->{NAME}} = "r->in.$e->{NAME}"; + } + } + + return \%env; +} + +##################################################################### +sub ParseArrayPreceding($$$) +{ + my $e = shift; + my $l = shift; + my $var_name = shift; + + return if ($l->{NO_METADATA}); + + # non fixed arrays encode the size just before the array + pidl "ndr_pull_array_size(ndr, tree, " . get_pointer_to($var_name) . ");"; +} + +sub compression_alg($$) +{ + my $e = shift; + my $l = shift; + my $compression = $l->{COMPRESSION}; + my ($alg, $clen, $dlen) = split(/ /, $compression); + + return $alg; +} + +sub compression_clen($$$) +{ + my $e = shift; + my $l = shift; + my $env = shift; + my $compression = $l->{COMPRESSION}; + my ($alg, $clen, $dlen) = split(/ /, $compression); + + return ParseExpr($clen, $env); +} + +sub compression_dlen($$$) +{ + my $e = shift; + my $l = shift; + my $env = shift; + my $compression = $l->{COMPRESSION}; + my ($alg, $clen, $dlen) = split(/ /, $compression); + + return ParseExpr($dlen, $env); +} + +sub ParseCompressionStart($$$$) +{ + my $e = shift; + my $l = shift; + my $subndr = shift; + my $env = shift; + my $comndr = $subndr."_compressed"; + my $alg = compression_alg($e, $l); + my $dlen = compression_dlen($e, $l, $env); + + pidl "{"; + indent; + pidl "struct pidl_pull *$comndr;"; + pidl "NDR_ALLOC($subndr, $comndr);"; + pidl "ndr_pull_compression($subndr, $comndr, $alg, $dlen);"; + + return $comndr; +} + +sub ParseCompressionEnd($$$) +{ + my $e = shift; + my $l = shift; + my $subndr = shift; + my $comndr = $subndr."_compressed"; + + deindent; + pidl "}"; +} + +sub ParseObfuscationStart($$) +{ + my $e = shift; + my $ndr = shift; + my $obfuscation = util::has_property($e, "obfuscation"); + + pidl "ndr_pull_obfuscation($ndr, $obfuscation);"; + + return $ndr; +} + +sub ParseObfuscationEnd($$) +{ + my $e = shift; + my $ndr = shift; + + # nothing to do here +} + +sub ParseSubcontextStart($$$$$$) +{ + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $ndr_flags = shift; + my $env = shift; + my $retndr = "_ndr_$e->{NAME}"; + + pidl "/* NDR_FLAGS $ndr_flags */"; + pidl "if ((ndr_flags) & NDR_SCALARS) {"; + indent; + pidl "struct pidl_pull *$retndr;"; + pidl "NDR_ALLOC(ndr, $retndr);"; + pidl "ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr);"; + + if (defined $l->{COMPRESSION}) { + $retndr = ParseCompressionStart($e, $l, $retndr, $env); + } + + if (defined $l->{OBFUSCATION}) { + $retndr = ParseObfuscationStart($e, $retndr); + } + + return ($retndr,$var_name); +} + +sub ParseSubcontextEnd($$) +{ + my $e = shift; + my $l = shift; + my $ndr = "_ndr_$e->{NAME}"; + + if (defined $l->{COMPRESSION}) { + ParseCompressionEnd($e, $l, $ndr); + } + + if (defined $l->{OBFUSCATION}) { + ParseObfuscationEnd($e, $ndr); + } + + my $advance; + if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) { + $advance = $l->{SUBCONTEXT_SIZE}; + } elsif ($l->{HEADER_SIZE}) { + $advance = "$ndr->data_size"; + } else { + $advance = "$ndr->offset"; + } + pidl "ndr_pull_advance(ndr, $advance);"; + deindent; + pidl "}"; +} + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseSwitch($$$$$$) +{ + my($e) = shift; + my $l = shift; + my $ndr = shift; + my($var_name) = shift; + my($ndr_flags) = shift; + my $env = shift; + my $switch_var = ParseExpr($l->{SWITCH_IS}, $env); + + check_null_pointer($switch_var); + + $var_name = get_pointer_to($var_name); + pidl "ndr_pull_set_switch_value($ndr, $var_name, $switch_var);"; + +} + +sub ParseData($$$$$) +{ + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $ndr_flags = shift; + + $var_name = get_pointer_to($var_name); + + # + # ALAND! for packet-dcerpc-lsa.c, uncommenting this code + # produces constructs like &(&r->string), to pass to another + # function, which gives compiler errors. + # + if ($l->{DATA_TYPE} eq "string" or + $l->{DATA_TYPE} eq "nbt_string") { + $var_name = get_pointer_to($var_name); + } + + pidl "offset += dissect_$l->{DATA_TYPE}(tvb, offset, pinfo, tree, drep, hf_FIXME, NULL);"; + + if (my $range = util::has_property($e, "range")) { + $var_name = get_value_of($var_name); + my ($low, $high) = split(/ /, $range, 2); + if (($l->{DATA_TYPE} =~ /^uint/) and ($low eq "0")) { + pidl "if ($var_name > $high) {"; + } else { + pidl "if ($var_name < $low || $var_name > $high) {"; + } + pidl "\treturn NT_STATUS_OK;"; + pidl "}"; + } +} + +sub CalcNdrFlags($$$) +{ + my $l = shift; + my $primitives = shift; + my $deferred = shift; + + my $scalars = 0; + my $buffers = 0; + + # Add NDR_SCALARS if this one is deferred + # and deferreds may be pushed + $scalars = 1 if ($l->{IS_DEFERRED} and $deferred); + + # Add NDR_SCALARS if this one is not deferred and + # primitives may be pushed + $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives); + + # Add NDR_BUFFERS if this one contains deferred stuff + # and deferreds may be pushed + $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred); + + return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers); + return "NDR_SCALARS" if ($scalars); + return "NDR_BUFFERS" if ($buffers); + return undef; +} + + +sub ParseElementLevel +{ + my($e) = shift; + my $l = shift; + my $ndr = shift; + my($var_name) = shift; + my $env = shift; + my $primitives = shift; + my $deferred = shift; + + my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); + + # Only pull something if there's actually something to be pulled + if (defined($ndr_flags)) { + if ($l->{TYPE} eq "SUBCONTEXT") { + ($ndr,$var_name) = ParseSubcontextStart($e, $l, $ndr, $var_name, $ndr_flags, $env); + ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + ParseSubcontextEnd($e, $l); + } elsif ($l->{TYPE} eq "ARRAY") { + my $length = ParseArrayHeader($e, $l, $ndr, $var_name, $env); + } elsif ($l->{TYPE} eq "POINTER") { + ParsePtr($e, $l, $ndr, $var_name); + } elsif ($l->{TYPE} eq "SWITCH") { + ParseSwitch($e, $l, $ndr, $var_name, $ndr_flags, $env); + } elsif ($l->{TYPE} eq "DATA") { + ParseData($e, $l, $ndr, $var_name, $ndr_flags); + } + } + + # add additional constructions + if ($l->{TYPE} eq "POINTER" and $deferred) { + if ($l->{POINTER_TYPE} ne "ref") { + pidl "if ($var_name) {"; + indent; + + if ($l->{POINTER_TYPE} eq "relative") { + pidl "struct ndr_pull_save _relative_save;"; + pidl "ndr_pull_save(ndr, &_relative_save);"; + pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));"; + } + } + + $var_name = get_value_of($var_name); + ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + + if ($l->{POINTER_TYPE} ne "ref") { + if ($l->{POINTER_TYPE} eq "relative") { + pidl "ndr_pull_restore(ndr, &_relative_save);"; + } + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "ARRAY") { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; + + $var_name = $var_name . "[$counter]"; + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } + + if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0); + deindent; + pidl "}"; + } + + if ($deferred and Ndr::ContainsDeferred($e, $l)) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "SWITCH") { + ParseElementLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + } +} + +##################################################################### +# parse scalars in a structure element - pull size +sub ParseElement($$$$$$) +{ + my($e) = shift; + my $ndr = shift; + my($var_prefix) = shift; + my $env = shift; + my $primitives = shift; + my $deferred = shift; + + my $var_name = $var_prefix.$e->{NAME}; + + $var_name = append_prefix($e, $var_name); + + return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0])); + + start_flags($e); + + ParseElementLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); + + end_flags($e); +} + +##################################################################### +# parse a pointer in a struct element or function +sub ParsePtr($$$$) +{ + my($e) = shift; + my $l = shift; + my $ndr = shift; + my($var_name) = shift; + + my $nl = Ndr::GetNextLevel($e, $l); + my $next_is_array = ($nl->{TYPE} eq "ARRAY"); + + if ($l->{LEVEL} eq "EMBEDDED") { + pidl "dissect_ndr_embedded_pointer(FIXME);"; + } elsif ($l->{POINTER_TYPE} ne "ref") { + pidl "dissect_ndr_toplevel_pointer(FIXME);"; + } + + #pidl "memset($var_name, 0, sizeof($var_name));"; + if ($l->{POINTER_TYPE} eq "relative") { + pidl "ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME});"; + } +} + +$typefamily{ENUM} = { + DECL => \&DeclEnum, +}; + +##################################################################### +# generate a pull function for an bitmap +sub ParseBitmap($$) +{ + my($bitmap) = shift; + my $name = shift; + my $type_fn = $bitmap->{BASE_TYPE}; + my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE}); + + pidl "$type_decl v_bitmap;"; + start_flags($bitmap); + pidl "dissect_$type_fn(ndr, tree, hf, &v_bitmap);"; + + pidl "{\n\tproto_tree *subtree = NULL;"; + pidl ""; + pidl "\tif (tree->proto_tree)\n\t\tsubtree = proto_item_add_subtree(tree->proto_tree->last_child, ett_$name);"; + pidl ""; + foreach my $e (@{$bitmap->{DATA}{ELEMENTS}}) { + $e =~ /^(.*?) \( (.*?) \)$/; + pidl "\tproto_tree_add_boolean(subtree, hf_${name}_$1, ndr->tvb, ndr->offset - sizeof(v_bitmap), sizeof(v_bitmap), v_bitmap);"; + } + pidl "}"; + + pidl "*r = v_bitmap;"; + + end_flags($bitmap); +} + +$typefamily{BITMAP} = { + FN_BODY => \&ParseBitmap, +}; + +##################################################################### +# parse a struct - pull side +sub ParseStruct($$) +{ + my($struct) = shift; + my $name = shift; + my $conform_e; + + return unless defined $struct->{ELEMENTS}; + + my $env = GenerateStructEnv($struct); + + # see if the structure contains a conformant array. If it + # does, then it must be the last element of the structure, and + # we need to pull the conformant length early, as it fits on + # the wire before the structure (and even before the structure + # alignment) + $conform_e = $struct->{SURROUNDING_ELEMENT}; + + # declare any internal pointers we need + foreach my $e (@{$struct->{ELEMENTS}}) { + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { + pidl "uint32_t _ptr_$e->{NAME};"; + last; + } + } + } + + start_flags($struct); + + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; + + if (defined $conform_e) { + ParseArrayPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}"); + } + + pidl "ndr_pull_align(ndr, $struct->{ALIGN});"; + + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElement($e, "ndr", "r->", $env, 1, 0); + } + deindent; + pidl "}"; + + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; + foreach my $e (@{$struct->{ELEMENTS}}) { + ParseElement($e, "ndr", "r->", $env, 0, 0); + } + + pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);"; + deindent; + pidl "}"; + + end_flags($struct); +} + +$typefamily{STRUCT} = { + FN_BODY => \&ParseStruct, +}; + +##################################################################### +# parse a union - pull side +sub ParseUnion($$$) +{ + my $e = shift; + my $name = shift; + my $have_default = 0; + my $switch_type = $e->{SWITCH_TYPE}; + + pidl "int level;"; + if (defined($switch_type)) { + if (typelist::typeIs($switch_type, "ENUM")) { + $switch_type = typelist::enum_type_fn(typelist::getType($switch_type)); + } + pidl typelist::mapType($switch_type) . " _level;"; + } + + start_flags($e); + + pidl "level = ndr_pull_get_switch_value(ndr, r);"; + + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; + + if (defined($switch_type)) { + pidl "ndr_pull_$switch_type(ndr, tree, hf_${name}, &_level);"; + pidl "if (_level != level) {"; + pidl "\treturn NT_STATUS_OK;"; + pidl "}"; + } + +# my $align = union_alignment($e); +# pidl "\tndr_pull_align(ndr, $align);\n"; + + pidl "switch (level) {"; + indent; + foreach my $el (@{$e->{ELEMENTS}}) { + if ($el->{CASE} eq "default") { + $have_default = 1; + } + pidl "$el->{CASE}: {"; + + if ($el->{TYPE} ne "EMPTY") { + indent; + foreach my $l (@{$el->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { + pidl "uint32_t _ptr_$el->{NAME};"; + last; + } + } + ParseElement($el, "ndr", "r->", {}, 1, 0); + deindent; + } + pidl "break; }"; + pidl ""; + } + if (! $have_default) { + pidl "default:"; + pidl "\treturn NT_STATUS_OK;"; + } + deindent; + pidl "}"; + deindent; + pidl "}"; + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; + pidl "switch (level) {"; + indent; + foreach my $el (@{$e->{ELEMENTS}}) { + pidl "$el->{CASE}:"; + if ($el->{TYPE} ne "EMPTY") { + indent; + ParseElement($el, "ndr", "r->", {}, 0, 1); + deindent; + } + pidl "break;"; + pidl ""; + } + if (! $have_default) { + pidl "default:"; + pidl "\treturn NT_STATUS_OK;"; + } + deindent; + pidl "}"; + pidl "proto_item_set_end(tree->proto_tree, ndr->tvb, ndr->offset);"; + deindent; + pidl "}"; + end_flags($e); +} + +$typefamily{UNION} = { + FN_BODY => \&ParseUnion, +}; + +##################################################################### +# parse an array +sub ParseArrayHeader($$$$$) +{ + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $env = shift; + + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } + + # $var_name contains the name of the first argument here + + my $length = ParseExpr($l->{SIZE_IS}, $env); + my $size = $length; + + if ($l->{IS_CONFORMANT}) { + $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")"; + } + + # if this is a conformant array then we use that size to allocate, and make sure + # we allocate enough to pull the elements + if (!$l->{IS_SURROUNDING}) { + ParseArrayPreceding($e, $l, $var_name); + } + + + if ($l->{IS_VARYING}) { + pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));"; + $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; + } + + check_null_pointer($length); + + if ($length ne $size) { + pidl "if ($length > $size) {"; + indent; + pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);"; + deindent; + pidl "}"; + } + + if ($l->{IS_CONFORMANT}) { + my $size = ParseExpr($l->{SIZE_IS}, $env); + check_null_pointer($size); + pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));"; + } + + if ($l->{IS_VARYING}) { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + check_null_pointer($length); + pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));"; + } + + return $length; +} + +##################################################################### +# parse a typedef - pull side +sub ParseTypedef($) +{ + my($e) = shift; + + return unless (defined ($typefamily{$e->{DATA}->{TYPE}})); + + pidl fn_prefix($e) . "int dissect_$e->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int hf_index, guint32 param)"; + + pidl "{"; + indent; + $typefamily{$e->{DATA}->{TYPE}}->{FN_BODY}->($e->{DATA}, $e->{NAME}); + pidl "return NT_STATUS_OK;"; + deindent; + pidl "}"; + pidl ""; +} + +##################################################################### +# parse a function +sub ParseFunctionRqst($) +{ + my($fn) = shift; + + my $env = GenerateFunctionEnv($fn); + + # request function + pidl "static int dissect_$fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)"; + pidl "{"; + indent; + + pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);"; + + # declare any internal pointers we need + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep (/in/, @{$e->{DIRECTIONS}})); + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER" and + not ($l->{POINTER_TYPE} eq "ref" and + $l->{LEVEL} eq "TOP")) { + pidl "uint32_t _ptr_$e->{NAME};"; + last; + } + } + } + + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/in/, @{$e->{DIRECTION}})); + ParseElement($e, "ndr", "r->in.", $env, 1, 1); + } + + pidl "return offset;"; + deindent; + pidl "}"; + pidl ""; +} + +sub ParseFunctionResp($) +{ + my($fn) = shift; + + my $env = GenerateFunctionEnv($fn); + + # response function + pidl "static int dissect_$fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)"; + pidl "{"; + indent; + + pidl "struct pidl_pull *ndr = pidl_pull_init(tvb, offset, pinfo, drep);"; + + # declare any internal pointers we need + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep (/out/, @{$e->{DIRECTIONS}})); + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER" and + not ($l->{POINTER_TYPE} eq "ref" and + $l->{LEVEL} eq "TOP")) { + pidl "uint32_t _ptr_$e->{NAME};"; + last; + } + } + } + + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless grep(/out/, @{$e->{DIRECTION}}); + ParseElement($e, "ndr", "r->out.", $env, 1, 1); + } + + if ($fn->{RETURN_TYPE}) { + pidl "dissect_$fn->{RETURN_TYPE}(ndr, tree, hf_$fn->{NAME}_result, drep);"; + } + + pidl "return offset;"; + deindent; + pidl "}"; + pidl ""; +} + +##################################################################### +# produce a function call table +sub FunctionTable($) +{ + my($interface) = shift; + + pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {"; + my $num = 0; + foreach my $d (@{$interface->{FUNCTIONS}}) { + # Strip interface name from function name, if present + my($n) = $d->{NAME}; + $n = substr($d->{NAME}, length($interface->{NAME}) + 1), + if $interface->{NAME} eq substr($d->{NAME}, 0, length($interface->{NAME})); + pidl "\t{ $num, \"$n\","; + pidl "\t\tdissect_$d->{NAME}_rqst,"; + pidl "\t\tdissect_$d->{NAME}_resp },"; + $num++; + } + pidl "};\n"; +} + +##################################################################### +# parse the interface definitions +sub ParseInterface($$) +{ + my($interface) = shift; + my $needed = shift; + + # Typedefs + foreach my $d (@{$interface->{TYPEDEFS}}) { + ($needed->{"pull_$d->{NAME}"}) && ParseTypedef($d); + # Make sure we don't generate a function twice... + $needed->{"pull_$d->{NAME}"} = 0; + } + + # Functions + foreach my $d (@{$interface->{FUNCTIONS}}) { + if ($needed->{"pull_$d->{NAME}"}) { + ParseFunctionRqst($d); + ParseFunctionResp($d); + } + + # Make sure we don't generate a function twice... + $needed->{"pull_$d->{NAME}"} = 0; + } +} + +##################################################################### +# generate code to parse an enum +sub DeclEnum($$) +{ + my ($e) = shift; + my $n = shift; + + pidl "static const value_string $n\_vals[] ="; + pidl "{"; + + foreach my $x (@{$e->{ELEMENTS}}) { + $x =~ /([^=]*)=(.*)/; + pidl "\t{ $1, \"$1\" },"; + } + + pidl "};\n"; +} + +sub DeclInterface($$) +{ + my($interface) = shift; + my $needed = shift; + + # Typedefs + foreach my $d (@{$interface->{TYPEDEFS}}) { + ($needed->{"pull_$d->{NAME}"}) && DeclTypedef($d); + + # Make sure we don't generate a function twice... + $needed->{"pull_$d->{NAME}"} = 0; + } +} + +sub DeclTypedef($) +{ + my $e = shift; + + if (defined($typefamily{$e->{DATA}->{TYPE}}->{DECL})) { + $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $e->{NAME}); + } +} + +sub RegisterInterface($$) +{ + my $x = shift; + my $needed = shift; + + pidl "void proto_register_dcerpc_pidl_$x->{NAME}(void)"; + pidl "{"; + indent; + + pidl "static hf_register_info hf[] = {"; + pidl "{ &hf_ptr, { \"Pointer\", \"$x->{NAME}.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},"; + + foreach my $x (sort keys(%{$needed})) { + next, if !($x =~ /^hf_/); + pidl "{ &$x,"; + $needed->{$x}->{strings} = "NULL", if !defined($needed->{$x}->{strings}); + $needed->{$x}->{bitmask} = "0", if !defined($needed->{$x}->{bitmask}); + pidl " { \"$needed->{$x}->{name}\", \"$x\", $needed->{$x}->{ft}, $needed->{$x}->{base}, $needed->{$x}->{strings}, $needed->{$x}->{bitmask}, \"$x\", HFILL }},"; + } + + pidl "};\n"; + + pidl "static gint *ett[] = {"; + indent; + foreach my $x (sort keys(%{$needed})) { + pidl "&$x,", if $x =~ /^ett_/; + } + deindent; + + pidl "};\n"; + + if (defined($x->{UUID})) { + # These can be changed to non-pidl names if the old dissectors + # in epan/dissctors are deleted. + + my $name = "\"" . uc($x->{NAME}) . " (pidl)\""; + if (util::has_property($x, "helpstring")) { + $name = $x->{PROPERTIES}->{helpstring}; + } + my $short_name = "pidl_$x->{NAME}"; + my $filter_name = "pidl_$x->{NAME}"; + + pidl "proto_dcerpc_pidl_$x->{NAME} = proto_register_protocol($name, \"$short_name\", \"$filter_name\");"; + + pidl "proto_register_field_array(proto_dcerpc_pidl_$x->{NAME}, hf, array_length (hf));"; + pidl "proto_register_subtree_array(ett, array_length(ett));"; + } else { + pidl "int proto_dcerpc;"; + pidl "proto_dcerpc = proto_get_id_by_filter_name(\"dcerpc\");"; + pidl "proto_register_field_array(proto_dcerpc, hf, array_length(hf));"; + pidl "proto_register_subtree_array(ett, array_length(ett));"; + } + + deindent; + pidl "}\n"; +} + +sub RegisterInterfaceHandoff($) +{ + my $x = shift; + pidl "void proto_reg_handoff_dcerpc_pidl_$x->{NAME}(void)"; + pidl "{"; + indent; + pidl "dcerpc_init_uuid(proto_dcerpc_pidl_$x->{NAME}, ett_dcerpc_$x->{NAME},"; + pidl "\t&uuid_dcerpc_$x->{NAME}, ver_dcerpc_$x->{NAME},"; + pidl "\tdcerpc_dissectors, hf_opnum);"; + deindent; + pidl "}"; +} + +sub ProcessInterface($) +{ + my $x = shift; + my $needed = NeededInterface($x); + + # Required global declarations + DeclInterface($x, $needed); + + foreach my $y (sort keys(%{$needed})) { + pidl "static int $y = -1;", if $y =~ /^hf_/; + } + pidl ""; + + foreach my $y (sort keys(%{$needed})) { + pidl "static gint $y = -1;", if $y =~ /^ett_/; + } + pidl ""; + + pidl "int proto_dcerpc_pidl_$x->{NAME} = -1;\n"; + + if (defined($x->{UUID})) { + my $if_uuid = $x->{UUID}; + + pidl "static e_uuid_t uuid_dcerpc_$x->{NAME} = {"; + pidl "\t0x" . substr($if_uuid, 1, 8) + . ", 0x" . substr($if_uuid, 10, 4) + . ", 0x" . substr($if_uuid, 15, 4) . ","; + pidl "\t{ 0x" . substr($if_uuid, 20, 2) + . ", 0x" . substr($if_uuid, 22, 2) + . ", 0x" . substr($if_uuid, 25, 2) + . ", 0x" . substr($if_uuid, 27, 2) + . ", 0x" . substr($if_uuid, 29, 2) + . ", 0x" . substr($if_uuid, 31, 2) + . ", 0x" . substr($if_uuid, 33, 2) + . ", 0x" . substr($if_uuid, 35, 2) . " }"; + pidl "};\n"; + + pidl "static guint16 ver_dcerpc_$x->{NAME} = $x->{VERSION};"; + } + + # dissect_* functions + ParseInterface($x, $needed); + + # Function call tables + FunctionTable($x); + + RegisterInterface($x, $needed); + RegisterInterfaceHandoff($x); +} + +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($$$) +{ + my($ndr) = shift; + my $module = shift; + my($filename) = shift; + + $tabs = ""; + my $h_filename = $filename; + $res = ""; + + if ($h_filename =~ /(.*)\.c/) { + $h_filename = "$1.h"; + } + + pidl "/* parser auto-generated by pidl */"; + pidl "#include \"packet-dcerpc.h\""; + pidl "#include \"$h_filename\""; + pidl ""; + pidl "static int hf_ptr = -1;"; + pidl "static int hf_array_size = -1;"; + pidl ""; + +# print keys %{$needed->{hf_atsvc_JobGetInfo_result}}, "\n"; + + # Ethereal protocol registration + + ProcessInterface($_) foreach (@$ndr); + + return $res; +} + +1; diff --git a/source4/build/pidl/idl.pm b/source4/build/pidl/idl.pm index 53c06f22d8d..d5100812ed6 100644 --- a/source4/build/pidl/idl.pm +++ b/source4/build/pidl/idl.pm @@ -1808,6 +1808,8 @@ sub "PROPERTIES" => $_[1], "NAME" => $_[3], "DATA" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 5 @@ -1816,19 +1818,21 @@ sub [#Rule 6 'interface_names', 4, sub -#line 34 "build/pidl/idl.yp" +#line 36 "build/pidl/idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 7 'interface', 8, sub -#line 38 "build/pidl/idl.yp" +#line 40 "build/pidl/idl.yp" {$_[3] => { "TYPE" => "INTERFACE", "PROPERTIES" => $_[1], "NAME" => $_[3], "BASE" => $_[4], "DATA" => $_[6], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 8 @@ -1837,19 +1841,19 @@ sub [#Rule 9 'base_interface', 2, sub -#line 49 "build/pidl/idl.yp" +#line 53 "build/pidl/idl.yp" { $_[2] } ], [#Rule 10 'definitions', 1, sub -#line 53 "build/pidl/idl.yp" +#line 57 "build/pidl/idl.yp" { [ $_[1] ] } ], [#Rule 11 'definitions', 2, sub -#line 54 "build/pidl/idl.yp" +#line 58 "build/pidl/idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 12 @@ -1867,47 +1871,55 @@ sub [#Rule 16 'const', 6, sub -#line 62 "build/pidl/idl.yp" +#line 66 "build/pidl/idl.yp" {{ "TYPE" => "CONST", "DTYPE" => $_[2], "NAME" => $_[3], - "VALUE" => $_[5] + "VALUE" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 17 'const', 7, sub -#line 69 "build/pidl/idl.yp" +#line 75 "build/pidl/idl.yp" {{ "TYPE" => "CONST", "DTYPE" => $_[2], "NAME" => $_[3], "ARRAY_LEN" => $_[4], "VALUE" => $_[6], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 18 'function', 7, sub -#line 80 "build/pidl/idl.yp" +#line 88 "build/pidl/idl.yp" {{ "TYPE" => "FUNCTION", "NAME" => $_[3], "RETURN_TYPE" => $_[2], "PROPERTIES" => $_[1], - "ELEMENTS" => $_[5] - }} + "ELEMENTS" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, + }} ], [#Rule 19 'declare', 5, sub -#line 90 "build/pidl/idl.yp" +#line 100 "build/pidl/idl.yp" {{ "TYPE" => "DECLARE", "PROPERTIES" => $_[2], "NAME" => $_[4], "DATA" => $_[3], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 20 @@ -1919,7 +1931,7 @@ sub [#Rule 22 'decl_enum', 1, sub -#line 102 "build/pidl/idl.yp" +#line 114 "build/pidl/idl.yp" {{ "TYPE" => "ENUM" }} @@ -1927,7 +1939,7 @@ sub [#Rule 23 'decl_bitmap', 1, sub -#line 108 "build/pidl/idl.yp" +#line 120 "build/pidl/idl.yp" {{ "TYPE" => "BITMAP" }} @@ -1935,13 +1947,15 @@ sub [#Rule 24 'typedef', 6, sub -#line 114 "build/pidl/idl.yp" +#line 126 "build/pidl/idl.yp" {{ "TYPE" => "TYPEDEF", "PROPERTIES" => $_[2], "NAME" => $_[4], "DATA" => $_[3], - "ARRAY_LEN" => $_[5] + "ARRAY_LEN" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 25 @@ -1962,28 +1976,28 @@ sub [#Rule 30 'type', 1, sub -#line 124 "build/pidl/idl.yp" +#line 138 "build/pidl/idl.yp" { "void" } ], [#Rule 31 'enum', 4, sub -#line 129 "build/pidl/idl.yp" +#line 143 "build/pidl/idl.yp" {{ - "TYPE" => "ENUM", + "TYPE" => "ENUM", "ELEMENTS" => $_[3] }} ], [#Rule 32 'enum_elements', 1, sub -#line 136 "build/pidl/idl.yp" +#line 150 "build/pidl/idl.yp" { [ $_[1] ] } ], [#Rule 33 'enum_elements', 3, sub -#line 137 "build/pidl/idl.yp" +#line 151 "build/pidl/idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 34 @@ -1992,13 +2006,13 @@ sub [#Rule 35 'enum_element', 3, sub -#line 141 "build/pidl/idl.yp" +#line 155 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 36 'bitmap', 4, sub -#line 145 "build/pidl/idl.yp" +#line 159 "build/pidl/idl.yp" {{ "TYPE" => "BITMAP", "ELEMENTS" => $_[3] @@ -2007,25 +2021,25 @@ sub [#Rule 37 'bitmap_elements', 1, sub -#line 152 "build/pidl/idl.yp" +#line 166 "build/pidl/idl.yp" { [ $_[1] ] } ], [#Rule 38 'bitmap_elements', 3, sub -#line 153 "build/pidl/idl.yp" +#line 167 "build/pidl/idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 39 'bitmap_element', 3, sub -#line 156 "build/pidl/idl.yp" +#line 170 "build/pidl/idl.yp" { "$_[1] ( $_[3] )" } ], [#Rule 40 'struct', 4, sub -#line 160 "build/pidl/idl.yp" +#line 174 "build/pidl/idl.yp" {{ "TYPE" => "STRUCT", "ELEMENTS" => $_[3] @@ -2034,12 +2048,14 @@ sub [#Rule 41 'empty_element', 2, sub -#line 167 "build/pidl/idl.yp" +#line 181 "build/pidl/idl.yp" {{ "NAME" => "", "TYPE" => "EMPTY", "PROPERTIES" => $_[1], - "POINTERS" => 0 + "POINTERS" => 0, + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 42 @@ -2051,7 +2067,7 @@ sub [#Rule 44 'optional_base_element', 2, sub -#line 178 "build/pidl/idl.yp" +#line 194 "build/pidl/idl.yp" { $_[2]->{PROPERTIES} = util::FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] } ], [#Rule 45 @@ -2060,13 +2076,13 @@ sub [#Rule 46 'union_elements', 2, sub -#line 183 "build/pidl/idl.yp" +#line 199 "build/pidl/idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 47 'union', 4, sub -#line 187 "build/pidl/idl.yp" +#line 203 "build/pidl/idl.yp" {{ "TYPE" => "UNION", "ELEMENTS" => $_[3] @@ -2075,25 +2091,27 @@ sub [#Rule 48 'base_element', 5, sub -#line 194 "build/pidl/idl.yp" +#line 210 "build/pidl/idl.yp" {{ "NAME" => $_[4], "TYPE" => $_[2], "PROPERTIES" => $_[1], "POINTERS" => $_[3], - "ARRAY_LEN" => $_[5] + "ARRAY_LEN" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ], [#Rule 49 'pointers', 0, sub -#line 206 "build/pidl/idl.yp" +#line 224 "build/pidl/idl.yp" { 0 } ], [#Rule 50 'pointers', 2, sub -#line 207 "build/pidl/idl.yp" +#line 225 "build/pidl/idl.yp" { $_[1]+1 } ], [#Rule 51 @@ -2102,7 +2120,7 @@ sub [#Rule 52 'element_list1', 3, sub -#line 212 "build/pidl/idl.yp" +#line 230 "build/pidl/idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 53 @@ -2114,13 +2132,13 @@ sub [#Rule 55 'element_list2', 1, sub -#line 218 "build/pidl/idl.yp" +#line 236 "build/pidl/idl.yp" { [ $_[1] ] } ], [#Rule 56 'element_list2', 3, sub -#line 219 "build/pidl/idl.yp" +#line 237 "build/pidl/idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 57 @@ -2129,13 +2147,13 @@ sub [#Rule 58 'array_len', 2, sub -#line 224 "build/pidl/idl.yp" +#line 242 "build/pidl/idl.yp" { "*" } ], [#Rule 59 'array_len', 3, sub -#line 225 "build/pidl/idl.yp" +#line 243 "build/pidl/idl.yp" { "$_[2]" } ], [#Rule 60 @@ -2144,31 +2162,31 @@ sub [#Rule 61 'property_list', 4, sub -#line 231 "build/pidl/idl.yp" +#line 249 "build/pidl/idl.yp" { util::FlattenHash([$_[1],$_[3]]); } ], [#Rule 62 'properties', 1, sub -#line 234 "build/pidl/idl.yp" +#line 252 "build/pidl/idl.yp" { $_[1] } ], [#Rule 63 'properties', 3, sub -#line 235 "build/pidl/idl.yp" +#line 253 "build/pidl/idl.yp" { util::FlattenHash([$_[1], $_[3]]); } ], [#Rule 64 'property', 1, sub -#line 238 "build/pidl/idl.yp" +#line 256 "build/pidl/idl.yp" {{ "$_[1]" => "1" }} ], [#Rule 65 'property', 4, sub -#line 239 "build/pidl/idl.yp" +#line 257 "build/pidl/idl.yp" {{ "$_[1]" => "$_[3]" }} ], [#Rule 66 @@ -2177,7 +2195,7 @@ sub [#Rule 67 'listtext', 3, sub -#line 244 "build/pidl/idl.yp" +#line 262 "build/pidl/idl.yp" { "$_[1] $_[3]" } ], [#Rule 68 @@ -2186,13 +2204,13 @@ sub [#Rule 69 'commalisttext', 3, sub -#line 249 "build/pidl/idl.yp" +#line 267 "build/pidl/idl.yp" { "$_[1],$_[3]" } ], [#Rule 70 'anytext', 0, sub -#line 253 "build/pidl/idl.yp" +#line 271 "build/pidl/idl.yp" { "" } ], [#Rule 71 @@ -2207,67 +2225,67 @@ sub [#Rule 74 'anytext', 3, sub -#line 255 "build/pidl/idl.yp" +#line 273 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 75 'anytext', 3, sub -#line 256 "build/pidl/idl.yp" +#line 274 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 76 'anytext', 3, sub -#line 257 "build/pidl/idl.yp" +#line 275 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 77 'anytext', 3, sub -#line 258 "build/pidl/idl.yp" +#line 276 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 78 'anytext', 3, sub -#line 259 "build/pidl/idl.yp" +#line 277 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 79 'anytext', 3, sub -#line 260 "build/pidl/idl.yp" +#line 278 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 80 'anytext', 3, sub -#line 261 "build/pidl/idl.yp" +#line 279 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 81 'anytext', 3, sub -#line 262 "build/pidl/idl.yp" +#line 280 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 82 'anytext', 3, sub -#line 263 "build/pidl/idl.yp" +#line 281 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 83 'anytext', 5, sub -#line 264 "build/pidl/idl.yp" +#line 282 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 84 'anytext', 5, sub -#line 265 "build/pidl/idl.yp" +#line 283 "build/pidl/idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 85 @@ -2279,7 +2297,7 @@ sub [#Rule 87 'text', 1, sub -#line 274 "build/pidl/idl.yp" +#line 292 "build/pidl/idl.yp" { "\"$_[1]\"" } ], [#Rule 88 @@ -2293,13 +2311,13 @@ sub bless($self,$class); } -#line 285 "build/pidl/idl.yp" +#line 303 "build/pidl/idl.yp" use util; sub _Error { - if (exists $_[0]->YYData->{ERRMSG}) { + if (exists $_[0]->YYData->{ERRMSG}) { print $_[0]->YYData->{ERRMSG}; delete $_[0]->YYData->{ERRMSG}; return; @@ -2385,21 +2403,6 @@ sub parse_idl($$) my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); - foreach my $x (@{$idl}) { - # Do the inheritance - if (defined($x->{BASE}) and $x->{BASE} ne "") { - my $parent = util::get_interface($idl, $x->{BASE}); - - if(not defined($parent)) { - die("No such parent interface " . $x->{BASE}); - } - - @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}}); - } else { - $x->{INHERITED_DATA} = $x->{DATA}; - } - } - return util::CleanData($idl); } diff --git a/source4/build/pidl/idl.yp b/source4/build/pidl/idl.yp index 186f0033962..d58dc9d0233 100644 --- a/source4/build/pidl/idl.yp +++ b/source4/build/pidl/idl.yp @@ -26,6 +26,8 @@ coclass: property_list 'coclass' identifier '{' interface_names '}' optional_sem "PROPERTIES" => $_[1], "NAME" => $_[3], "DATA" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -41,6 +43,8 @@ interface: property_list 'interface' identifier base_interface '{' definitions ' "NAME" => $_[3], "BASE" => $_[4], "DATA" => $_[6], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -63,7 +67,9 @@ const: 'const' identifier identifier '=' anytext ';' "TYPE" => "CONST", "DTYPE" => $_[2], "NAME" => $_[3], - "VALUE" => $_[5] + "VALUE" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} | 'const' identifier identifier array_len '=' anytext ';' {{ @@ -72,6 +78,8 @@ const: 'const' identifier identifier '=' anytext ';' "NAME" => $_[3], "ARRAY_LEN" => $_[4], "VALUE" => $_[6], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -82,8 +90,10 @@ function: property_list type identifier '(' element_list2 ')' ';' "NAME" => $_[3], "RETURN_TYPE" => $_[2], "PROPERTIES" => $_[1], - "ELEMENTS" => $_[5] - }} + "ELEMENTS" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, + }} ; declare: 'declare' property_list decl_type identifier';' @@ -92,6 +102,8 @@ declare: 'declare' property_list decl_type identifier';' "PROPERTIES" => $_[2], "NAME" => $_[4], "DATA" => $_[3], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -116,7 +128,9 @@ typedef: 'typedef' property_list type identifier array_len ';' "PROPERTIES" => $_[2], "NAME" => $_[4], "DATA" => $_[3], - "ARRAY_LEN" => $_[5] + "ARRAY_LEN" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -127,7 +141,7 @@ type: struct | union | enum | bitmap | identifier enum: 'enum' '{' enum_elements '}' {{ - "TYPE" => "ENUM", + "TYPE" => "ENUM", "ELEMENTS" => $_[3] }} ; @@ -168,7 +182,9 @@ empty_element: property_list ';' "NAME" => "", "TYPE" => "EMPTY", "PROPERTIES" => $_[1], - "POINTERS" => 0 + "POINTERS" => 0, + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -196,7 +212,9 @@ base_element: property_list type pointers identifier array_len "TYPE" => $_[2], "PROPERTIES" => $_[1], "POINTERS" => $_[3], - "ARRAY_LEN" => $_[5] + "ARRAY_LEN" => $_[5], + "FILE" => $_[0]->YYData->{INPUT_FILENAME}, + "LINE" => $_[0]->YYData->{LINE}, }} ; @@ -287,7 +305,7 @@ optional_semicolon: use util; sub _Error { - if (exists $_[0]->YYData->{ERRMSG}) { + if (exists $_[0]->YYData->{ERRMSG}) { print $_[0]->YYData->{ERRMSG}; delete $_[0]->YYData->{ERRMSG}; return; @@ -373,20 +391,5 @@ sub parse_idl($$) my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error ); - foreach my $x (@{$idl}) { - # Do the inheritance - if (defined($x->{BASE}) and $x->{BASE} ne "") { - my $parent = util::get_interface($idl, $x->{BASE}); - - if(not defined($parent)) { - die("No such parent interface " . $x->{BASE}); - } - - @{$x->{INHERITED_DATA}} = (@{$parent->{INHERITED_DATA}}, @{$x->{DATA}}); - } else { - $x->{INHERITED_DATA} = $x->{DATA}; - } - } - return util::CleanData($idl); } diff --git a/source4/build/pidl/ndr.pm b/source4/build/pidl/ndr.pm index 3c75b29227e..5c39578f404 100644 --- a/source4/build/pidl/ndr.pm +++ b/source4/build/pidl/ndr.pm @@ -23,40 +23,73 @@ sub GetElementLevelTable($) { my $e = shift; - return ($e->{NDR_ORDER_TABLE}) if (defined $e->{NDR_ORDER_TABLE}); - my $order = []; my $is_deferred = 0; - # FIXME: Process {ARRAY_SIZE} kinds of arrays + # FIXME: Process {ARRAY_LEN} kinds of arrays # First, all the pointers - foreach my $i (1..need_wire_pointer($e)) { + foreach my $i (1..$e->{POINTERS}) { + my $pt = pointer_type($e); + + my $level = "EMBEDDED"; + # Top level "ref" pointers do not have a referrent identifier + $level = "TOP" if ( defined($pt) + and $i == 1 + and $e->{PARENT}->{TYPE} eq "FUNCTION"); + push (@$order, { TYPE => "POINTER", # for now, there can only be one pointer type per element POINTER_TYPE => pointer_type($e), - IS_DEFERRED => "$is_deferred" + IS_DEFERRED => "$is_deferred", + LEVEL => $level }); # everything that follows will be deferred - $is_deferred = 1; + $is_deferred = 1 if ($e->{PARENT}->{TYPE} ne "FUNCTION"); # FIXME: Process array here possibly (in case of multi-dimensional arrays, etc) } - if (defined($e->{ARRAY_LEN})) { + if (defined($e->{ARRAY_LEN}) or util::has_property($e, "size_is")) { + my $length = util::has_property($e, "length_is"); + my $size = util::has_property($e, "size_is"); + + if (not defined($size) and defined($e->{ARRAY_LEN})) { + $size = $e->{ARRAY_LEN}; + } + + if (not defined($length)) { + $length = $size; + } + push (@$order, { TYPE => "ARRAY", - ARRAY_TYPE => array_type($e), - SIZE_IS => util::has_property($e, "size_is"), - LENGTH_IS => util::has_property($e, "length_is"), - IS_DEFERRED => "$is_deferred" + SIZE_IS => $size, + LENGTH_IS => $length, + IS_DEFERRED => "$is_deferred", + # Inline arrays (which are a pidl extension) are never encoded + # as surrounding the struct they're part of + IS_SURROUNDING => (is_surrounding_array($e) and not is_inline_array($e)), + IS_VARYING => is_varying_array($e), + IS_CONFORMANT => is_conformant_array($e), + IS_FIXED => is_fixed_array($e), + NO_METADATA => (is_inline_array($e) or is_fixed_array($e)), + IS_INLINE => is_inline_array($e) }); + + $is_deferred = 0; } - if (my $sub_size = util::has_property($e, "subcontext")) { + if (my $hdr_size = util::has_property($e, "subcontext")) { + my $subsize = util::has_property($e, "subcontext_size"); + if (not defined($subsize)) { + $subsize = -1; + } + push (@$order, { TYPE => "SUBCONTEXT", - SUBCONTEXT_SIZE => $sub_size, + HEADER_SIZE => $hdr_size, + SUBCONTEXT_SIZE => $subsize, IS_DEFERRED => $is_deferred, COMPRESSION => util::has_property($e, "compression") }); @@ -73,12 +106,13 @@ sub GetElementLevelTable($) push (@$order, { TYPE => "DATA", DATA_TYPE => $e->{TYPE}, - NAME => $e->{NAME}, IS_DEFERRED => $is_deferred, - CONTAINS_DEFERRED => can_contain_deferred($e) + CONTAINS_DEFERRED => can_contain_deferred($e), + IS_SURROUNDING => is_surrounding_string($e) }); - $e->{NDR_ORDER_TABLE} = $order; + my $i = 0; + foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; } return $order; } @@ -107,7 +141,7 @@ sub is_scalar_type($) { my $type = shift; - return 0 unless typelist::hasType($type); + return 0 unless(typelist::hasType($type)); if (my $dt = typelist::getType($type)->{DATA}->{TYPE}) { return 1 if ($dt eq "SCALAR" or $dt eq "ENUM" or $dt eq "BITMAP"); @@ -152,9 +186,8 @@ sub is_conformant_array($) sub is_inline_array($) { my $e = shift; - my $len = $e->{"ARRAY_LEN"}; - if (is_fixed_array($e) || - defined $len && $len ne "*") { + my $len = $e->{ARRAY_LEN}; + if (defined $len && $len ne "*" && !is_fixed_array($e)) { return 1; } return 0; @@ -181,17 +214,15 @@ sub is_surrounding_array($) and $e->{PARENT}->{TYPE} ne "FUNCTION"); } -sub array_type($) +sub is_surrounding_string($) { my $e = shift; - return "conformant-varying" if (is_varying_array($e) and is_conformant_array($e)); - return "conformant" if (is_varying_array($e)); - return "varying" if (is_varying_array($e)); - return "inline" if (is_inline_array($e)); - return "fixed" if (is_fixed_array($e)); + return 0; #FIXME - return undef; + return ($e->{TYPE} eq "string") and ($e->{POINTERS} == 0) + and util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*") + and $e->{PARENT}->{TYPE} ne "FUNCTION"; } ##################################################################### @@ -216,6 +247,35 @@ sub find_largest_alignment($) return $align; } +my %scalar_alignments = +( + "char" => 1, + "int8" => 1, + "uint8" => 1, + "short" => 2, + "wchar_t" => 2, + "int16" => 2, + "uint16" => 2, + "long" => 4, + "int32" => 4, + "uint32" => 4, + "dlong" => 4, + "udlong" => 4, + "udlongr" => 4, + "NTTIME" => 4, + "NTTIME_1sec" => 4, + "time_t" => 4, + "DATA_BLOB" => 4, + "error_status_t" => 4, + "WERROR" => 4, + "NTSTATUS" => 4, + "boolean32" => 4, + "unsigned32" => 4, + "ipv4address" => 4, + "hyper" => 8, + "NTTIME_hyper" => 8 +); + ##################################################################### # align a type sub align_type @@ -237,10 +297,10 @@ sub align_type } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) { return find_largest_alignment($dt); } elsif ($dt->{TYPE} eq "SCALAR") { - return typelist::getScalarAlignment($dt->{NAME}); + return $scalar_alignments{$dt->{NAME}}; + } else { + die("Unknown data type type $dt->{TYPE}"); } - - die("Unknown data type type $dt->{TYPE}"); } # determine if an element needs a reference pointer on the wire @@ -269,6 +329,7 @@ sub ParseElement($) return { NAME => $e->{NAME}, + TYPE => $e->{TYPE}, PROPERTIES => $e->{PROPERTIES}, LEVELS => GetElementLevelTable($e) }; @@ -276,18 +337,31 @@ sub ParseElement($) sub ParseStruct($) { - my $e = shift; + my $struct = shift; my @elements = (); + my $surrounding = undef; - foreach my $x (@{$e->{ELEMENTS}}) + foreach my $x (@{$struct->{ELEMENTS}}) { push @elements, ParseElement($x); } + my $e = $elements[-1]; + if (defined($e) and defined($e->{LEVELS}[0]->{IS_SURROUNDING}) and + $e->{LEVELS}[0]->{IS_SURROUNDING}) { + $surrounding = $e; + } + + if (defined $e->{TYPE} && $e->{TYPE} eq "string" + && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { + $surrounding = $struct->{ELEMENTS}[-1]; + } + return { TYPE => "STRUCT", + SURROUNDING_ELEMENT => $surrounding, ELEMENTS => \@elements, - PROPERTIES => $e->{PROPERTIES} + PROPERTIES => $struct->{PROPERTIES} }; } @@ -295,6 +369,10 @@ sub ParseUnion($) { my $e = shift; my @elements = (); + my $switch_type = util::has_property($e, "switch_type"); + unless (defined($switch_type)) { $switch_type = "uint32"; } + + if (util::has_property($e, "nodiscriminant")) { $switch_type = undef; } foreach my $x (@{$e->{ELEMENTS}}) { @@ -303,17 +381,20 @@ sub ParseUnion($) $t = { TYPE => "EMPTY" }; } else { $t = ParseElement($x); - if (util::has_property($t, "default")) { - $t->{DEFAULT} = "default"; - } else { - $t->{CASE} = $t->{PROPERTIES}->{CASE}; - } + } + if (util::has_property($x, "default")) { + $t->{CASE} = "default"; + } elsif (defined($x->{PROPERTIES}->{case})) { + $t->{CASE} = "case $x->{PROPERTIES}->{case}"; + } else { + die("Union element $x->{NAME} has neither default nor case property"); } push @elements, $t; } return { TYPE => "UNION", + SWITCH_TYPE => $switch_type, ELEMENTS => \@elements, PROPERTIES => $e->{PROPERTIES} }; @@ -325,6 +406,7 @@ sub ParseEnum($) return { TYPE => "ENUM", + BASE_TYPE => typelist::enum_type_fn($e), ELEMENTS => $e->{ELEMENTS}, PROPERTIES => $e->{PROPERTIES} }; @@ -336,11 +418,19 @@ sub ParseBitmap($) return { TYPE => "BITMAP", + BASE_TYPE => typelist::bitmap_type_fn($e), ELEMENTS => $e->{ELEMENTS}, PROPERTIES => $e->{PROPERTIES} }; } +sub ParseDeclare($$) +{ + my $ndr = shift; + my $d = shift; + +} + sub ParseTypedef($$) { my $ndr = shift; @@ -371,41 +461,56 @@ sub ParseTypedef($$) return { NAME => $d->{NAME}, - TYPE => "TYPEDEF", + TYPE => $d->{TYPE}, PROPERTIES => $d->{PROPERTIES}, DATA => $data }; } -sub ParseFunction($$) +sub ParseConst($$) { my $ndr = shift; my $d = shift; - my @in = (); - my @out = (); + + return $d; +} + +sub ParseFunction($$$) +{ + my $ndr = shift; + my $d = shift; + my $opnum = shift; + my @elements = (); + my $rettype = undef; CheckPointerTypes($d, - $ndr->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref" + $ndr->{PROPERTIES}->{pointer_default_top} ); foreach my $x (@{$d->{ELEMENTS}}) { + my $e = ParseElement($x); if (util::has_property($x, "in")) { - push (@in, ParseElement($x)); + push (@{$e->{DIRECTION}}, "in"); } + if (util::has_property($x, "out")) { - push (@out, ParseElement($x)); + push (@{$e->{DIRECTION}}, "out"); } + + push (@elements, $e); + } + + if ($d->{RETURN_TYPE} ne "void") { + $rettype = $d->{RETURN_TYPE}; } return { NAME => $d->{NAME}, TYPE => "FUNCTION", - RETURN_TYPE => $d->{RETURN_TYPE}, + OPNUM => $opnum, + RETURN_TYPE => $rettype, PROPERTIES => $d->{PROPERTIES}, - ELEMENTS => { - IN => \@in, - OUT => \@out - } + ELEMENTS => \@elements }; } @@ -430,8 +535,12 @@ sub CheckPointerTypes($$) sub ParseInterface($) { my $idl = shift; - my @functions = (); my @typedefs = (); + my @consts = (); + my @functions = (); + my @endpoints; + my @declares = (); + my $opnum = 0; my $version; if (not util::has_property($idl, "pointer_default")) { @@ -440,22 +549,41 @@ sub ParseInterface($) $idl->{PROPERTIES}->{pointer_default} = "unique"; } + if (not util::has_property($idl, "pointer_default_top")) { + $idl->{PROPERTIES}->{pointer_default_top} = "ref"; + } + foreach my $d (@{$idl->{DATA}}) { - if ($d->{TYPE} eq "DECLARE" or $d->{TYPE} eq "TYPEDEF") { + if ($d->{TYPE} eq "TYPEDEF") { push (@typedefs, ParseTypedef($idl, $d)); } + if ($d->{TYPE} eq "DECLARE") { + push (@declares, ParseDeclare($idl, $d)); + } + if ($d->{TYPE} eq "FUNCTION") { - push (@functions, ParseFunction($idl, $d)); + push (@functions, ParseFunction($idl, $d, $opnum)); + $opnum+=1; + } + + if ($d->{TYPE} eq "CONST") { + push (@consts, ParseConst($idl, $d)); } } - + $version = "0.0"; if(defined $idl->{PROPERTIES}->{version}) { $version = $idl->{PROPERTIES}->{version}; } - + + # If no endpoint is set, default to the interface name as a named pipe + if (!defined $idl->{PROPERTIES}->{endpoint}) { + push @endpoints, "\"ncacn_np:[\\\\pipe\\\\" . $idl->{NAME} . "]\""; + } else { + @endpoints = split / /, $idl->{PROPERTIES}->{endpoint}; + } return { NAME => $idl->{NAME}, @@ -464,7 +592,10 @@ sub ParseInterface($) TYPE => "INTERFACE", PROPERTIES => $idl->{PROPERTIES}, FUNCTIONS => \@functions, - TYPEDEFS => \@typedefs + CONSTS => \@consts, + TYPEDEFS => \@typedefs, + DECLARES => \@declares, + ENDPOINTS => \@endpoints }; } @@ -503,4 +634,47 @@ sub Parse($) return \@ndr; } +sub GetNextLevel($$) +{ + my $e = shift; + my $fl = shift; + + my $seen = 0; + + foreach my $l (@{$e->{LEVELS}}) { + return $l if ($seen); + ($seen = 1) if ($l == $fl); + } + + return undef; +} + +sub GetPrevLevel($$) +{ + my $e = shift; + my $fl = shift; + my $prev = undef; + + foreach my $l (@{$e->{LEVELS}}) { + (return $prev) if ($l == $fl); + $prev = $l; + } + + return undef; +} + +sub ContainsDeferred($$) +{ + my $e = shift; + my $l = shift; + + do { + return 1 if ($l->{IS_DEFERRED}); + return 1 if ($l->{CONTAINS_DEFERRED}); + } while ($l = Ndr::GetNextLevel($e,$l)); + + return 0; +} + + 1; diff --git a/source4/build/pidl/ndr_client.pm b/source4/build/pidl/ndr_client.pm index e5d4cc15696..ca6fc224659 100644 --- a/source4/build/pidl/ndr_client.pm +++ b/source4/build/pidl/ndr_client.pm @@ -52,6 +52,7 @@ NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name * "; } +my %done; ##################################################################### # parse the interface definitions @@ -60,9 +61,12 @@ sub ParseInterface($) my($interface) = shift; my($data) = $interface->{DATA}; $res = "/* Client functions generated by pidl */\n\n"; + foreach my $d (@{$data}) { - ($d->{TYPE} eq "FUNCTION") && - ParseFunction($interface, $d); + if (($d->{TYPE} eq "FUNCTION") and not $done{$d->{NAME}}) { + ParseFunction($interface, $d); + } + $done{$d->{NAME}} = 1; } return $res; } diff --git a/source4/build/pidl/ndr_header.pm b/source4/build/pidl/ndr_header.pm index 0c6291fca75..bebf6937ae4 100644 --- a/source4/build/pidl/ndr_header.pm +++ b/source4/build/pidl/ndr_header.pm @@ -1,12 +1,12 @@ ################################################### # create C header files for an IDL structure # Copyright tridge@samba.org 2000 +# Copyright jelmer@samba.org 2005 # released under the GNU GPL package NdrHeader; use strict; -use needed; use typelist; my($res); @@ -60,17 +60,23 @@ sub HeaderElement($) pidl tabs(); HeaderType($element, $element->{TYPE}, ""); pidl " "; - if ($element->{POINTERS} && not $element->{TYPE} =~ "string") { - for (my($i)=$element->{POINTERS}; $i > 0; $i--) { + my $pointers = 0; + foreach my $l (@{$element->{LEVELS}}) + { + if (($l->{TYPE} eq "POINTER")) { + next if ($element->{TYPE} eq "string"); pidl "*"; - } - } elsif (Ndr::is_surrounding_array($element) || - defined $element->{ARRAY_LEN} && !util::is_constant($element->{ARRAY_LEN})) { - # surrounding arrays are ugly! I choose to implement them with - # pointers instead of the [1] method - pidl "*"; - } - pidl "$element->{NAME}"; + $pointers+=1; + } elsif ($l->{TYPE} eq "ARRAY") { + if (!$pointers and !$l->{IS_FIXED}) { pidl "*"; } + pidl "$element->{NAME}"; + if ($l->{IS_FIXED}) { pidl "[$l->{SIZE_IS}]"; } + last; #FIXME + } elsif ($l->{TYPE} eq "DATA") { + pidl "$element->{NAME}"; + } + } + if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) { pidl "[$element->{ARRAY_LEN}]"; } @@ -106,24 +112,17 @@ sub HeaderEnum($$) { my($enum) = shift; my($name) = shift; + my $first = 1; pidl "\nenum $name {\n"; $tab_depth++; - my $els = \@{$enum->{ELEMENTS}}; - foreach my $i (0 .. $#{$els}-1) { - my $e = ${$els}[$i]; + foreach my $e (@{$enum->{ELEMENTS}}) { + unless ($first) { pidl ",\n"; } + $first = 0; tabs(); - chomp $e; - pidl "$e,\n"; - } - - my $e = ${$els}[$#{$els}]; - tabs(); - chomp $e; - if ($e !~ /^(.*?)\s*$/) { - die "Bad enum $name\n"; + pidl $e; } - pidl "$1\n"; + pidl "\n"; $tab_depth--; pidl "}"; } @@ -137,10 +136,8 @@ sub HeaderBitmap($$) pidl "\n/* bitmap $name */\n"; - my $els = \@{$bitmap->{ELEMENTS}}; - foreach my $i (0 .. $#{$els}) { - my $e = ${$els}[$i]; - chomp $e; + foreach my $e (@{$bitmap->{ELEMENTS}}) + { pidl "#define $e\n"; } @@ -180,18 +177,14 @@ sub HeaderType($$$) my($data) = shift; my($name) = shift; if (ref($data) eq "HASH") { - ($data->{TYPE} eq "ENUM") && - HeaderEnum($data, $name); - ($data->{TYPE} eq "BITMAP") && - HeaderBitmap($data, $name); - ($data->{TYPE} eq "STRUCT") && - HeaderStruct($data, $name); - ($data->{TYPE} eq "UNION") && - HeaderUnion($data, $name); + ($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name); + ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name); + ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name); + ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name); return; } - pidl typelist::mapType($e); + pidl typelist::mapType($e->{TYPE}); } ##################################################################### @@ -211,7 +204,7 @@ sub HeaderTypedefProto($) my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE}); - if (needed::is_needed("ndr_size_$d->{NAME}")) { + if (util::has_property($d, "gensize")) { my $size_args = $tf->{SIZE_FN_ARGS}->($d); pidl "size_t ndr_size_$d->{NAME}($size_args);\n"; } @@ -265,7 +258,7 @@ sub HeaderFunctionInOut_needed($$) my($fn) = shift; my($prop) = shift; - if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + if ($prop eq "out" && $fn->{RETURN_TYPE}) { return 1; } @@ -278,12 +271,18 @@ sub HeaderFunctionInOut_needed($$) return undef; } +my %headerstructs = (); + ##################################################################### # parse a function sub HeaderFunction($) { my($fn) = shift; + return if ($headerstructs{$fn->{NAME}}); + + $headerstructs{$fn->{NAME}} = 1; + pidl "\nstruct $fn->{NAME} {\n"; $tab_depth++; my $needed = 0; @@ -304,9 +303,9 @@ sub HeaderFunction($) pidl "struct {\n"; $tab_depth++; HeaderFunctionInOut($fn, "out"); - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + if ($fn->{RETURN_TYPE}) { tabs(); - pidl typelist::mapScalarType($fn->{RETURN_TYPE}) . " result;\n"; + pidl typelist::mapType($fn->{RETURN_TYPE}) . " result;\n"; } $tab_depth--; tabs(); @@ -350,7 +349,6 @@ sub HeaderFnProto($$) sub HeaderInterface($) { my($interface) = shift; - my($data) = $interface->{DATA}; my $count = 0; @@ -364,11 +362,6 @@ sub HeaderInterface($) } } - # Object interfaces use ORPC - if (util::has_property($interface, "object")) { - pidl "#include \"librpc/gen_ndr/ndr_orpc.h\"\n"; - } - if (defined $interface->{PROPERTIES}->{uuid}) { my $name = uc $interface->{NAME}; pidl "#define DCERPC_$name\_UUID " . @@ -386,18 +379,16 @@ sub HeaderInterface($) pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n"; } - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { - my $u_name = uc $d->{NAME}; - pidl "#define DCERPC_$u_name ("; + foreach my $d (@{$interface->{FUNCTIONS}}) { + my $u_name = uc $d->{NAME}; + pidl "#define DCERPC_$u_name ("; + + if (defined($interface->{BASE})) { + pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; + } - if (defined($interface->{BASE})) { - pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; - } - - pidl sprintf("0x%02x", $count) . ")\n"; - $count++; - } + pidl sprintf("0x%02x", $count) . ")\n"; + $count++; } pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT ("; @@ -408,19 +399,21 @@ sub HeaderInterface($) pidl "$count)\n\n"; - foreach my $d (@{$data}) { - ($d->{TYPE} eq "CONST") && + foreach my $d (@{$interface->{CONSTS}}) { HeaderConst($d); - ($d->{TYPE} eq "TYPEDEF") && + } + + foreach my $d (@{$interface->{TYPEDEFS}}) { HeaderTypedef($d); - ($d->{TYPE} eq "TYPEDEF") && HeaderTypedefProto($d); - ($d->{TYPE} eq "FUNCTION") && + } + + foreach my $d (@{$interface->{FUNCTIONS}}) { HeaderFunction($d); - ($d->{TYPE} eq "FUNCTION") && HeaderFnProto($interface, $d); - } - + } + + pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; } @@ -431,13 +424,10 @@ sub Parse($) my($idl) = shift; $tab_depth = 0; - NdrParser::Load($idl); - $res = ""; pidl "/* header auto-generated by pidl */\n\n"; foreach my $x (@{$idl}) { if ($x->{TYPE} eq "INTERFACE") { - needed::BuildNeeded($x); HeaderInterface($x); } } diff --git a/source4/build/pidl/ndr_parser.pm b/source4/build/pidl/ndr_parser.pm index d0eba81beff..1abf8f7006e 100644 --- a/source4/build/pidl/ndr_parser.pm +++ b/source4/build/pidl/ndr_parser.pm @@ -8,7 +8,6 @@ package NdrParser; use strict; -use needed; use typelist; use ndr; @@ -21,15 +20,30 @@ sub get_typefamily($) return $typefamily{$n}; } -# determine if an element needs a "buffers" section in NDR -sub need_buffers_section($) +sub append_prefix($$) { my $e = shift; - if (!Ndr::can_contain_deferred($e) && - !util::array_size($e)) { - return 0; + my $var_name = shift; + my $pointers = 0; + + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER") { + $pointers++; + } elsif ($l->{TYPE} eq "ARRAY") { + if (($pointers == 0) and + (not $l->{IS_FIXED}) and + (not $l->{IS_INLINE})) { + return get_value_of($var_name) + } + } elsif ($l->{TYPE} eq "DATA") { + if ($l->{DATA_TYPE} eq "string" or + $l->{DATA_TYPE} eq "nbt_string") { + return get_value_of($var_name) unless ($pointers); + } + } } - return 1; + + return $var_name; } # see if a variable needs to be allocated by the NDR subsystem on pull @@ -37,63 +51,45 @@ sub need_alloc($) { my $e = shift; - return 0 if (util::has_property($e, "ref") && $e->{PARENT}->{TYPE} eq "FUNCTION"); - return 1 if ($e->{POINTERS} || util::array_size($e)); return 0; } -# Prefix to get the actual value of a variable -sub c_ptr_prefix($) -{ - my $e = shift; - my $pointers = ""; - foreach my $i (Ndr::need_wire_pointer($e)..$e->{POINTERS}-1) { $pointers.="*"; } - return $pointers; -} - -# determine the C prefix used to refer to a variable when passing to a push -# function. This will be '*' for pointers to scalar types, '' for scalar -# types and normal pointers and '&' for pass-by-reference structures -sub c_push_prefix($) +sub is_scalar_array($$) { my $e = shift; + my $l = shift; - my $ret = ""; + return 0 if ($l->{TYPE} ne "ARRAY"); - if ($e->{TYPE} =~ "string") { - $ret = ""; - } elsif (Ndr::is_scalar_type($e->{TYPE}) and $e->{POINTERS} and - !util::array_size($e)) { - $ret .="*"; - } elsif (!Ndr::is_scalar_type($e->{TYPE}) && - !$e->{POINTERS} && - !util::array_size($e)) { - return "&"; - } + my $nl = Ndr::GetNextLevel($e,$l); + return (($nl->{TYPE} eq "DATA") and + (Ndr::is_scalar_type($nl->{DATA_TYPE}))); +} - foreach my $i (2..$e->{POINTERS}) { $ret.="*"; } +sub get_pointer_to($) +{ + my $var_name = shift; - return $ret; + if ($var_name =~ /^\*(.*)$/) { + return $1; + } elsif ($var_name =~ /^\&(.*)$/) { + return "&($var_name)"; + } else { + return "&$var_name"; + } } -# determine the C prefix used to refer to a variable when passing to a pull -# return '&' or '' -sub c_pull_prefix($) +sub get_value_of($) { - my $e = shift; + my $var_name = shift; - if (!$e->{POINTERS} && !util::array_size($e)) { - return "&"; - } - - if ($e->{TYPE} =~ "string") { - return "&"; + if ($var_name =~ /^\&(.*)$/) { + return $1; + } else { + return "*$var_name"; } - - my $ret = ""; - foreach my $i (2..$e->{POINTERS}) { $ret.="*"; } - return $ret; } + my $res = ""; my $tabs = ""; sub pidl($) @@ -118,46 +114,35 @@ sub deindent() #################################################################### # work out the name of a size_is() variable -sub ParseExpr($$$) +sub ParseExpr($$) { - my($e) = shift; - my($size) = shift; - my($var_prefix) = shift; + my($orig_expr) = shift; + my $varlist = shift; - my($fn) = $e->{PARENT}; + die("Undefined value in ParseExpr") if not defined($orig_expr); - return $size if (util::is_constant($size)); + my $expr = $orig_expr; - return $size if ($size =~ /ndr->|\(/); + return $expr if (util::is_constant($expr)); my $prefix = ""; + my $postfix = ""; - if ($size =~ /\*(.*)/) { - $size = $1; + if ($expr =~ /\*(.*)/) { + $expr = $1; $prefix = "*"; } - if ($fn->{TYPE} ne "FUNCTION") { - return $prefix . "r->$size"; + if ($expr =~ /^(.*)([\&\|\/+])(.*)$/) { + $postfix = $2.$3; + $expr = $1; } - my $e2 = util::find_sibling($e, $size); - - die("Invalid sibling '$size'") unless defined($e2); - - if (util::has_property($e2, "in") && util::has_property($e2, "out")) { - return $prefix . "$var_prefix$size"; - } - - if (util::has_property($e2, "in")) { - return $prefix . "r->in.$size"; - } - - if (util::has_property($e2, "out")) { - return $prefix . "r->out.$size"; + if (defined($varlist->{$expr})) { + return $prefix.$varlist->{$expr}.$postfix; } - die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n"; + return $prefix.$expr.$postfix; } ##################################################################### @@ -189,11 +174,7 @@ sub fn_prefix($) { my $fn = shift; - if ($fn->{TYPE} eq "TYPEDEF" or - $fn->{TYPE} eq "FUNCTION") { - return "" if (util::has_property($fn, "public")); - } - + return "" if (util::has_property($fn, "public")); return "static "; } @@ -204,7 +185,9 @@ sub start_flags($) my $e = shift; my $flags = util::has_property($e, "flag"); if (defined $flags) { - pidl "{ uint32_t _flags_save_$e->{TYPE} = ndr->flags;"; + pidl "{"; + indent; + pidl "uint32_t _flags_save_$e->{TYPE} = ndr->flags;"; pidl "ndr_set_flags(&ndr->flags, $flags);"; } } @@ -216,150 +199,135 @@ sub end_flags($) my $e = shift; my $flags = util::has_property($e, "flag"); if (defined $flags) { - pidl "ndr->flags = _flags_save_$e->{TYPE};\n\t}"; + pidl "ndr->flags = _flags_save_$e->{TYPE};"; + deindent; + pidl "}"; } } -##################################################################### -# parse array preceding data - push side -sub ParseArrayPushPreceding($$$) +sub GenerateStructEnv($) { - my $e = shift; - my $var_prefix = shift; - my $ndr_flags = shift; - - my $size = ParseExpr($e, util::array_size($e), $var_prefix); + my $x = shift; + my %env; - if (!Ndr::is_inline_array($e)) { - # we need to emit the array size - pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));"; + foreach my $e (@{$x->{ELEMENTS}}) { + $env{$e->{NAME}} = "r->$e->{NAME}"; } + + $env{"this"} = "r"; + + return \%env; } -##################################################################### -# parse the data of an array - push side -sub ParseArrayPush($$$$) +sub GenerateFunctionEnv($) { - my $e = shift; - my $ndr = shift; - my $var_prefix = shift; - my $ndr_flags = shift; - my $cprefix = c_push_prefix($e); - - my $size = ParseExpr($e, util::array_size($e), $var_prefix); + my $fn = shift; + my %env; - # See whether the array size has been pushed yet - if (!Ndr::is_surrounding_array($e)) { - ParseArrayPushPreceding($e, $var_prefix, $ndr_flags); - } - - if (Ndr::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));"; - $size = $length; + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep (/out/, @{$e->{DIRECTION}})) { + $env{$e->{NAME}} = "r->out.$e->{NAME}"; + } + if (grep (/in/, @{$e->{DIRECTION}})) { + $env{$e->{NAME}} = "r->in.$e->{NAME}"; + } } - if (Ndr::is_scalar_type($e->{TYPE})) { - pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $size));"; - } else { - pidl "NDR_CHECK(ndr_push_array($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE}));"; - } + return \%env; } ##################################################################### -# print an array -sub ParseArrayPrint($$) +# parse array preceding data - push side +sub ParseArrayPushPreceding($$$$) { my $e = shift; - my $var_prefix = shift; - my $size = ParseExpr($e, util::array_size($e), $var_prefix); - my $cprefix = c_push_prefix($e); + my $l = shift; + my $var_name = shift; + my $env = shift; - if (Ndr::is_varying_array($e)) { - $size = ParseExpr($e, util::has_property($e, "length_is"), $var_prefix); - } + return if ($l->{NO_METADATA}); - if (Ndr::is_scalar_type($e->{TYPE})) { - pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, $size);"; - } else { - pidl "ndr_print_array(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $size, (ndr_print_fn_t)ndr_print_$e->{TYPE});"; - } + my $size = ParseExpr($l->{SIZE_IS}, $env); + + # we need to emit the array size + pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, $size));"; } ##################################################################### -# check the size_is and length_is constraints -sub CheckArraySizes($$) +# parse the data of an array - push side +sub ParseArrayPushHeader($$$$$) { my $e = shift; - my $var_prefix = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $env = shift; - if (Ndr::is_conformant_array($e)) { - my $size = ParseExpr($e, util::array_size($e), $var_prefix); - pidl "if ($var_prefix$e->{NAME}) {"; - indent; - check_null_pointer($size); - pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)&$var_prefix$e->{NAME}, $size));"; - deindent; - pidl "}"; + if (!$l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); } - if (Ndr::is_varying_array($e)) { - my $length = util::has_property($e, "length_is"); - $length = ParseExpr($e, $length, $var_prefix); - pidl "if ($var_prefix$e->{NAME}) {"; - indent; - check_null_pointer($length); - pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)&$var_prefix$e->{NAME}, $length));"; - deindent; - pidl "}" + my $size = ParseExpr($l->{SIZE_IS}, $env); + my $length = ParseExpr($l->{LENGTH_IS}, $env); + + # See whether the array size has been pushed yet + if (!$l->{IS_SURROUNDING}) { + ParseArrayPushPreceding($e, $l, $var_name, $env); } + + if ($l->{IS_VARYING}) { + pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, 0));"; + pidl "NDR_CHECK(ndr_push_uint32($ndr, NDR_SCALARS, $length));"; + } + + return $length; } sub ParseArrayPullPreceding($$$) { my $e = shift; - my $var_prefix = shift; - my $ndr_flags = shift; + my $l = shift; + my $var_name = shift; - if (!Ndr::is_inline_array($e)) { - # non fixed arrays encode the size just before the array - pidl "NDR_CHECK(ndr_pull_array_size(ndr, &$var_prefix$e->{NAME}));"; - } + return if ($l->{NO_METADATA}); + + # non fixed arrays encode the size just before the array + pidl "NDR_CHECK(ndr_pull_array_size(ndr, " . get_pointer_to($var_name) . "));"; } ##################################################################### # parse an array - pull side -sub ParseArrayPull($$$$) +sub ParseArrayPullHeader($$$$$) { my $e = shift; + my $l = shift; my $ndr = shift; - my $var_prefix = shift; - my $ndr_flags = shift; + my $var_name = shift; + my $env = shift; + + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } - my $cprefix = c_pull_prefix($e); - my $length = ParseExpr($e, util::array_size($e), $var_prefix); + # $var_name contains the name of the first argument here + + my $length = ParseExpr($l->{SIZE_IS}, $env); my $size = $length; - if (Ndr::is_conformant_array($e)) { - $length = $size = "ndr_get_array_size($ndr, &$var_prefix$e->{NAME})"; + if ($l->{IS_CONFORMANT}) { + $length = $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")"; } # if this is a conformant array then we use that size to allocate, and make sure # we allocate enough to pull the elements - if (!Ndr::is_inline_array($e) and not Ndr::is_surrounding_array($e)) { - if ($var_prefix =~ /^r->out/ && $length =~ /^\*r->in/) { - my $length2 = substr($length, 1); - pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC($ndr, $length2); }"; - } - - ParseArrayPullPreceding($e, $var_prefix, $ndr_flags); + if (!$l->{IS_SURROUNDING}) { + ParseArrayPullPreceding($e, $l, $var_name); } - if (Ndr::is_varying_array($e)) { - pidl "NDR_CHECK(ndr_pull_array_length($ndr, &$var_prefix$e->{NAME}));"; - $length = "ndr_get_array_length($ndr, &$var_prefix$e->{NAME})"; + + if ($l->{IS_VARYING}) { + pidl "NDR_CHECK(ndr_pull_array_length($ndr, " . get_pointer_to($var_name) . "));"; + $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; } check_null_pointer($length); @@ -367,63 +335,66 @@ sub ParseArrayPull($$$$) if ($length ne $size) { pidl "if ($length > $size) {"; indent; - pidl "return ndr_pull_error($ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $size, $length);"; + pidl "return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $size, $length);"; deindent; pidl "}"; } - if ((need_alloc($e) && !Ndr::is_fixed_array($e)) || - ($var_prefix eq "r->in." && util::has_property($e, "ref"))) { - if (!Ndr::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { - pidl "NDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);"; - } + if ($l->{IS_CONFORMANT}) { + my $size = ParseExpr($l->{SIZE_IS}, $env); + check_null_pointer($size); + pidl "NDR_CHECK(ndr_check_array_size(ndr, (void*)" . get_pointer_to($var_name) . ", $size));"; } - if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) { - if (!Ndr::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") { - pidl "if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; - pidl "\tNDR_ALLOC_N($ndr, $var_prefix$e->{NAME}, $size);"; - pidl "}"; - } + if ($l->{IS_VARYING}) { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + check_null_pointer($length); + pidl "NDR_CHECK(ndr_check_array_length(ndr, (void*)" . get_pointer_to($var_name) . ", $length));"; } - if (Ndr::is_scalar_type($e->{TYPE})) { - pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}, $length));"; - } else { - pidl "NDR_CHECK(ndr_pull_array($ndr, $ndr_flags, (void **)$cprefix$var_prefix$e->{NAME}, sizeof($cprefix$var_prefix$e->{NAME}\[0]), $length, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE}));"; + if (!$l->{IS_FIXED}) { + AllocateArrayLevel($e,$l,$ndr,$env,$size); } + + return $length; } -sub compression_alg($) +sub compression_alg($$) { my $e = shift; - my $compression = util::has_property($e, "compression"); + my $l = shift; + my $compression = $l->{COMPRESSION}; my ($alg, $clen, $dlen) = split(/ /, $compression); return $alg; } -sub compression_clen($) +sub compression_clen($$$) { my $e = shift; - my $compression = util::has_property($e, "compression"); + my $l = shift; + my $env = shift; + my $compression = $l->{COMPRESSION}; my ($alg, $clen, $dlen) = split(/ /, $compression); - return ParseExpr($e, $clen, "r->"); + return ParseExpr($clen, $env); } -sub compression_dlen($) +sub compression_dlen($$$) { my $e = shift; - my $compression = util::has_property($e, "compression"); + my $l = shift; + my $env = shift; + my $compression = $l->{COMPRESSION}; my ($alg, $clen, $dlen) = split(/ /, $compression); - return ParseExpr($e, $dlen, "r->"); + return ParseExpr($dlen, $env); } -sub ParseCompressionPushStart($$) +sub ParseCompressionPushStart($$$) { my $e = shift; + my $l = shift; my $subndr = shift; my $comndr = $subndr."_compressed"; @@ -439,25 +410,28 @@ sub ParseCompressionPushStart($$) return $comndr; } -sub ParseCompressionPushEnd($$) +sub ParseCompressionPushEnd($$$) { my $e = shift; + my $l = shift; my $subndr = shift; my $comndr = $subndr."_compressed"; - my $alg = compression_alg($e); + my $alg = compression_alg($e, $l); pidl "NDR_CHECK(ndr_push_compression($subndr, $comndr, $alg));"; deindent; pidl "}"; } -sub ParseCompressionPullStart($$) +sub ParseCompressionPullStart($$$$) { my $e = shift; + my $l = shift; my $subndr = shift; + my $env = shift; my $comndr = $subndr."_compressed"; - my $alg = compression_alg($e); - my $dlen = compression_dlen($e); + my $alg = compression_alg($e, $l); + my $dlen = compression_dlen($e, $l, $env); pidl "{"; indent; @@ -468,9 +442,10 @@ sub ParseCompressionPullStart($$) return $comndr; } -sub ParseCompressionPullEnd($$) +sub ParseCompressionPullEnd($$$) { my $e = shift; + my $l = shift; my $subndr = shift; my $comndr = $subndr."_compressed"; @@ -516,113 +491,105 @@ sub ParseObfuscationPullEnd($$) # nothing to do here } -sub ParseSubcontextPushStart($$) +sub ParseSubcontextPushStart($$$$$) { my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; my $ndr_flags = shift; - my $compression = util::has_property($e, "compression"); - my $obfuscation = util::has_property($e, "obfuscation"); my $retndr = "_ndr_$e->{NAME}"; - pidl "if (($ndr_flags) & NDR_SCALARS) {"; + return unless ($ndr_flags =~ /NDR_SCALARS/); + + pidl "{"; indent; pidl "struct ndr_push *$retndr;"; pidl ""; - pidl "$retndr = ndr_push_init_ctx(ndr);"; + pidl "$retndr = ndr_push_init_ctx($ndr);"; pidl "if (!$retndr) return NT_STATUS_NO_MEMORY;"; - pidl "$retndr->flags = ndr->flags;"; + pidl "$retndr->flags = $ndr->flags;"; pidl ""; - if (defined $compression) { - $retndr = ParseCompressionPushStart($e, $retndr); + if (defined $l->{COMPRESSION}) { + $retndr = ParseCompressionPushStart($e, $l, $retndr); } - if (defined $obfuscation) { + if (defined $l->{OBFUSCATION}) { $retndr = ParseObfuscationPushStart($e, $retndr); } - return $retndr + return $retndr; } -sub ParseSubcontextPushEnd($) +sub ParseSubcontextPushEnd($$$) { my $e = shift; - my $header_size = util::has_property($e, "subcontext"); - my $size_is = util::has_property($e, "subcontext_size"); - my $compression = util::has_property($e, "compression"); - my $obfuscation = util::has_property($e, "obfuscation"); + my $l = shift; + my $ndr_flags = shift; my $ndr = "_ndr_$e->{NAME}"; - if (defined $obfuscation) { - ParseObfuscationPushEnd($e, $ndr); - } + return unless ($ndr_flags =~ /NDR_SCALARS/); - if (defined $compression) { - ParseCompressionPushEnd($e, $ndr); + if (defined $l->{COMPRESSION}) { + ParseCompressionPushEnd($e, $l, $ndr); } - if (not defined($size_is)) { - $size_is = "-1"; + if (defined $l->{OBFUSCATION}) { + ParseObfuscationPushEnd($e, $ndr); } - pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $header_size, $size_is, $ndr));"; + pidl "NDR_CHECK(ndr_push_subcontext_header(ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $ndr));"; pidl "NDR_CHECK(ndr_push_bytes(ndr, $ndr->data, $ndr->offset));"; deindent; pidl "}"; } -sub ParseSubcontextPullStart($$) +sub ParseSubcontextPullStart($$$$$$) { my $e = shift; - my $ndr_flags = shift; - my $header_size = util::has_property($e, "subcontext"); - my $size_is = util::has_property($e, "subcontext_size"); - my $compression = util::has_property($e, "compression"); - my $obfuscation = util::has_property($e, "obfuscation"); + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $ndr_flags = shift; + my $env = shift; my $retndr = "_ndr_$e->{NAME}"; - if (not defined($size_is)) { - $size_is = "-1"; - } - pidl "if (($ndr_flags) & NDR_SCALARS) {"; indent; pidl "struct ndr_pull *$retndr;"; pidl "NDR_ALLOC(ndr, $retndr);"; - pidl "NDR_CHECK(ndr_pull_subcontext_header(ndr, $header_size, $size_is, $retndr));"; + pidl "NDR_CHECK(ndr_pull_subcontext_header($ndr, $l->{HEADER_SIZE}, $l->{SUBCONTEXT_SIZE}, $retndr));"; - if (defined $compression) { - $retndr = ParseCompressionPullStart($e, $retndr); + if (defined $l->{COMPRESSION}) { + $retndr = ParseCompressionPullStart($e, $l, $retndr, $env); } - if (defined $obfuscation) { + if (defined $l->{OBFUSCATION}) { $retndr = ParseObfuscationPullStart($e, $retndr); } - return $retndr; + return ($retndr,$var_name); } -sub ParseSubcontextPullEnd($) +sub ParseSubcontextPullEnd($$) { my $e = shift; - my $header_size = util::has_property($e, "subcontext"); - my $size_is = util::has_property($e, "subcontext_size"); - my $compression = util::has_property($e, "compression"); - my $obfuscation = util::has_property($e, "obfuscation"); + my $l = shift; my $ndr = "_ndr_$e->{NAME}"; - if (defined $obfuscation) { - ParseObfuscationPullEnd($e, $ndr); + if (defined $l->{COMPRESSION}) { + ParseCompressionPullEnd($e, $l, $ndr); } - if (defined $compression) { - ParseCompressionPullEnd($e, $ndr); + if (defined $l->{OBFUSCATION}) { + ParseObfuscationPullEnd($e, $ndr); } my $advance; - if (defined ($size_is)) { - $advance = "$size_is"; - } elsif ($header_size) { + if (defined($l->{SUBCONTEXT_SIZE}) and ($l->{SUBCONTEXT_SIZE} ne "-1")) { + $advance = $l->{SUBCONTEXT_SIZE}; + } elsif ($l->{HEADER_SIZE}) { $advance = "$ndr->data_size"; } else { $advance = "$ndr->offset"; @@ -632,369 +599,506 @@ sub ParseSubcontextPullEnd($) pidl "}"; } +sub ParseElementPushLevel +{ + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $env = shift; + my $primitives = shift; + my $deferred = shift; + + my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); + + if (defined($ndr_flags)) { + if ($l->{TYPE} eq "SUBCONTEXT") { + $ndr = ParseSubcontextPushStart($e, $l, $ndr, $var_name, $ndr_flags); + ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred); + ParseSubcontextPushEnd($e, $l, $ndr_flags); + } elsif ($l->{TYPE} eq "POINTER") { + ParsePtrPush($e, $l, $var_name); + } elsif ($l->{TYPE} eq "ARRAY") { + my $length = ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); + # Allow speedups for arrays of scalar types + if (is_scalar_array($e,$l)) { + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } + + pidl "NDR_CHECK(ndr_push_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));"; + return; + } + } elsif ($l->{TYPE} eq "SWITCH") { + ParseSwitchPush($e, $l, $ndr, $var_name, $ndr_flags, $env); + } elsif ($l->{TYPE} eq "DATA") { + ParseDataPush($e, $l, $ndr, $var_name, $ndr_flags); + } + } + + if ($l->{TYPE} eq "POINTER" and $deferred) { + if ($l->{POINTER_TYPE} ne "ref") { + pidl "if ($var_name) {"; + indent; + if ($l->{POINTER_TYPE} eq "relative") { + pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_name));"; + } + } + $var_name = get_value_of($var_name); + ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred); + + if ($l->{POINTER_TYPE} ne "ref") { + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; + + $var_name = $var_name . "[$counter]"; + + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } + + if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 0); + deindent; + pidl "}"; + } + + if ($deferred and Ndr::ContainsDeferred($e, $l)) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, 0, 1); + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "SWITCH") { + ParseElementPushLevel($e, Ndr::GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred); + } +} + ##################################################################### # parse scalars in a structure element -sub ParseElementPushScalar($$$) +sub ParseElementPush($$$$$$) { - my($e) = shift; - my($var_prefix) = shift; - my($ndr_flags) = shift; - my $cprefix = c_push_prefix($e); - my $ptr_prefix = c_ptr_prefix($e); - my $sub_size = util::has_property($e, "subcontext"); - my $ndr = "ndr"; + my $e = shift; + my $ndr = shift; + my $var_prefix = shift; + my $env = shift; + my $primitives = shift; + my $deferred = shift; my $subndr = undef; - start_flags($e); + my $var_name = $var_prefix.$e->{NAME}; - if (my $value = util::has_property($e, "value")) { - pidl "$cprefix$var_prefix$e->{NAME} = $value;"; - } + $var_name = append_prefix($e, $var_name); - if (defined $sub_size and $e->{POINTERS} == 0) { - $subndr = ParseSubcontextPushStart($e, "NDR_SCALARS"); - $ndr = $subndr; - } + return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0])); - if (Ndr::need_wire_pointer($e)) { - ParsePtrPush($e, $ptr_prefix.$var_prefix); - } elsif (Ndr::is_inline_array($e)) { - ParseArrayPush($e, $ndr, "r->", "NDR_SCALARS"); - } elsif (need_alloc($e)) { - # no scalar component - } else { - if (my $switch = util::has_property($e, "switch_is")) { - ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch); - } + start_flags($e); - pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));"; + if (my $value = util::has_property($e, "value")) { + pidl "$var_name = $value;"; } - if (defined $sub_size and $e->{POINTERS} == 0) { - ParseSubcontextPushEnd($e); - } + ParseElementPushLevel($e, $e->{LEVELS}[0], $ndr, $var_name, $env, $primitives, $deferred); end_flags($e); } ##################################################################### # parse a pointer in a struct element or function -sub ParsePtrPush($$) +sub ParsePtrPush($$$) { my $e = shift; - my $var_prefix = shift; + my $l = shift; + my $var_name = shift; - if (util::has_property($e, "ref")) { - pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_prefix$e->{NAME}));"; - } elsif (util::has_property($e, "relative")) { - pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_prefix$e->{NAME}));"; + if ($l->{POINTER_TYPE} eq "ref") { + if ($l->{LEVEL} eq "EMBEDDED") { + pidl "NDR_CHECK(ndr_push_ref_ptr(ndr, $var_name));"; + } else { + check_null_pointer(get_value_of($var_name)); + } + } elsif ($l->{POINTER_TYPE} eq "relative") { + pidl "NDR_CHECK(ndr_push_relative_ptr1(ndr, $var_name));"; + } elsif ($l->{POINTER_TYPE} eq "unique") { + pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_name));"; } else { - pidl "NDR_CHECK(ndr_push_unique_ptr(ndr, $var_prefix$e->{NAME}));"; + die("Unhandled pointer type $l->{POINTER_TYPE}"); } } ##################################################################### # print scalars in a structure element -sub ParseElementPrint($$) +sub ParseElementPrint($$$) { my($e) = shift; - my($var_prefix) = shift; - my $cprefix = c_push_prefix($e); - my $ptr_prefix = c_ptr_prefix($e); + my($var_name) = shift; + my $env = shift; + $var_name = append_prefix($e, $var_name); return if (util::has_property($e, "noprint")); if (my $value = util::has_property($e, "value")) { pidl "if (ndr->flags & LIBNDR_PRINT_SET_VALUES) {"; - pidl "\t$cprefix$var_prefix$e->{NAME} = $value;"; + pidl "\t$var_name = $value;"; pidl "}"; } - my $l = $e->{POINTERS}; - $l++ if (util::array_size($e) and $l == 0 and !Ndr::is_fixed_array($e)); + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER") { + pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_name);"; + pidl "ndr->depth++;"; + if ($l->{POINTER_TYPE} ne "ref") { + pidl "if ($var_name) {"; + indent; + } + $var_name = get_value_of($var_name); + } elsif ($l->{TYPE} eq "ARRAY") { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + + if (is_scalar_array($e, $l)) { + unless ($l->{NO_METADATA}){ + $var_name = get_pointer_to($var_name); + } + pidl "ndr_print_array_$e->{TYPE}(ndr, \"$e->{NAME}\", $var_name, $length);"; + last; + } - foreach my $i (1..$l) { - pidl "ndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});"; - pidl "ndr->depth++;"; - if ($i > $l-Ndr::need_wire_pointer($e)) { - pidl "if ($ptr_prefix$var_prefix$e->{NAME}) {"; + my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; + + pidl "ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);"; + pidl 'ndr->depth++;'; + pidl "for ($counter=0;$counter<$length;$counter++) {"; + indent; + pidl "char *idx_$l->{LEVEL_INDEX}=NULL;"; + pidl "asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter);"; + pidl "if (idx_$l->{LEVEL_INDEX}) {"; indent; - } - } - if (util::array_size($e)) { - ParseArrayPrint($e, $var_prefix) - } else { - if (my $switch = util::has_property($e, "switch_is")) { - my $switch_var = ParseExpr($e, $switch, $var_prefix); - check_null_pointer_void($switch_var); + $var_name = $var_name . "[$counter]"; - pidl "ndr_print_set_switch_value(ndr, $cprefix$var_prefix$e->{NAME}, $switch_var);"; - } + unless ($l->{NO_METADATA}){ $var_name = get_pointer_to($var_name); } - pidl "ndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});"; + } elsif ($l->{TYPE} eq "DATA") { + if (not Ndr::is_scalar_type($l->{DATA_TYPE})) { + $var_name = get_pointer_to($var_name); + } + pidl "ndr_print_$l->{DATA_TYPE}(ndr, \"$e->{NAME}\", $var_name);"; + } elsif ($l->{TYPE} eq "SWITCH") { + my $switch_var = ParseExpr($l->{SWITCH_IS}, $env); + check_null_pointer_void($switch_var); + pidl "ndr_print_set_switch_value(ndr, " . get_pointer_to($var_name) . ", $switch_var);"; + } } - foreach my $i (1..$l) { - if ($i > $l-Ndr::need_wire_pointer($e)) { + foreach my $l (reverse @{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER") { + if ($l->{POINTER_TYPE} ne "ref") { + deindent; + pidl "}"; + } + pidl "ndr->depth--;"; + } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e, $l)) { + pidl "free(idx_$l->{LEVEL_INDEX});"; deindent; pidl "}"; + deindent; + pidl "}"; + pidl "ndr->depth--;"; } - pidl "ndr->depth--;"; } } ##################################################################### # parse scalars in a structure element - pull size -sub ParseSwitchPull($$$$$) +sub ParseSwitchPull($$$$$$) { my($e) = shift; + my $l = shift; my $ndr = shift; - my($var_prefix) = shift; + my($var_name) = shift; my($ndr_flags) = shift; - my $switch = shift; - my $switch_var = ParseExpr($e, $switch, $var_prefix); - - my $cprefix = c_pull_prefix($e); - - my $utype = typelist::getType($e->{TYPE}); + my $env = shift; + my $switch_var = ParseExpr($l->{SWITCH_IS}, $env); check_null_pointer($switch_var); - pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));"; + $var_name = get_pointer_to($var_name); + pidl "NDR_CHECK(ndr_pull_set_switch_value($ndr, $var_name, $switch_var));"; } ##################################################################### # push switch element -sub ParseSwitchPush($$$$$) +sub ParseSwitchPush($$$$$$) { my($e) = shift; + my $l = shift; my $ndr = shift; - my($var_prefix) = shift; + my($var_name) = shift; my($ndr_flags) = shift; - my $switch = shift; - my $switch_var = ParseExpr($e, $switch, $var_prefix); - my $cprefix = c_push_prefix($e); + my $env = shift; + my $switch_var = ParseExpr($l->{SWITCH_IS}, $env); check_null_pointer($switch_var); - - pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $cprefix$var_prefix$e->{NAME}, $switch_var));"; - + $var_name = get_pointer_to($var_name); + pidl "NDR_CHECK(ndr_push_set_switch_value($ndr, $var_name, $switch_var));"; } -##################################################################### -# parse scalars in a structure element - pull size -sub ParseElementPullScalar($$$) +sub ParseDataPull($$$$$) { - my($e) = shift; - my($var_prefix) = shift; - my($ndr_flags) = shift; - my $cprefix = c_pull_prefix($e); - my $ptr_prefix = c_ptr_prefix($e); - my $sub_size = util::has_property($e, "subcontext"); - my $ndr = "ndr"; - my $subndr = undef; + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $ndr_flags = shift; - start_flags($e); + $var_name = get_pointer_to($var_name); - if (defined $sub_size && $e->{POINTERS} == 0) { - $subndr = ParseSubcontextPullStart($e, $ndr_flags); - $ndr = $subndr; - $ndr_flags = "NDR_SCALARS|NDR_BUFFERS"; + if ($l->{DATA_TYPE} eq "string" or + $l->{DATA_TYPE} eq "nbt_string") { + $var_name = get_pointer_to($var_name); } - if (Ndr::is_inline_array($e)) { - ParseArrayPull($e, $ndr, "r->", "NDR_SCALARS"); - } elsif (Ndr::need_wire_pointer($e)) { - ParsePtrPull($e, $ptr_prefix.$var_prefix); - } elsif (Ndr::is_surrounding_array($e)) { - } else { - if (my $switch = util::has_property($e, "switch_is")) { - ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch); - } - - pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));"; - } + pidl "NDR_CHECK(ndr_pull_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));"; if (my $range = util::has_property($e, "range")) { + $var_name = get_value_of($var_name); my ($low, $high) = split(/ /, $range, 2); - pidl "if ($var_prefix$e->{NAME} < $low || $var_prefix$e->{NAME} > $high) {"; + pidl "if ($var_name < $low || $var_name > $high) {"; 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 ParsePtrPull($$) +sub ParseDataPush($$$$$) { - my($e) = shift; - my($var_prefix) = shift; + my $e = shift; + my $l = shift; + my $ndr = shift; + my $var_name = shift; + my $ndr_flags = shift; - if (util::has_property($e, "ref")) { - pidl "NDR_CHECK(ndr_pull_ref_ptr(ndr, &_ptr_$e->{NAME}));"; - } else { - pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));"; + # strings are passed by value rather then reference + if (not Ndr::is_scalar_type($l->{DATA_TYPE})) { + $var_name = get_pointer_to($var_name); } - pidl "if (_ptr_$e->{NAME}) {"; - indent; - pidl "NDR_ALLOC(ndr, $var_prefix$e->{NAME});"; - if (util::has_property($e, "relative")) { - pidl "NDR_CHECK(ndr_pull_relative_ptr1(ndr, $var_prefix$e->{NAME}, _ptr_$e->{NAME}));"; - } - deindent; - pidl "} else {"; - pidl "\t$var_prefix$e->{NAME} = NULL;"; - pidl "}"; + + pidl "NDR_CHECK(ndr_push_$l->{DATA_TYPE}($ndr, $ndr_flags, $var_name));"; } -##################################################################### -# parse buffers in a structure element -sub ParseElementPushBuffer($$) +sub CalcNdrFlags($$$) { - my($e) = shift; - my($var_prefix) = shift; - my $cprefix = c_push_prefix($e); - my $sub_size = util::has_property($e, "subcontext"); - my $ndr = "ndr"; - my $subndr = undef; + my $l = shift; + my $primitives = shift; + my $deferred = shift; - return unless (need_buffers_section($e)); + my $scalars = 0; + my $buffers = 0; - start_flags($e); + # Add NDR_SCALARS if this one is deferred + # and deferreds may be pushed + $scalars = 1 if ($l->{IS_DEFERRED} and $deferred); - my $pointers = c_ptr_prefix($e); - for my $i (1..Ndr::need_wire_pointer($e)) { - if ($i > 1) { - ParsePtrPush($e,$pointers.$var_prefix); - } - pidl "if ($pointers$var_prefix$e->{NAME}) {"; - indent; - $pointers.="*"; - } + # Add NDR_SCALARS if this one is not deferred and + # primitives may be pushed + $scalars = 1 if (!$l->{IS_DEFERRED} and $primitives); - if (util::has_property($e, "relative")) { - pidl "NDR_CHECK(ndr_push_relative_ptr2(ndr, $var_prefix$e->{NAME}));"; - } + # Add NDR_BUFFERS if this one contains deferred stuff + # and deferreds may be pushed + $buffers = 1 if ($l->{CONTAINS_DEFERRED} and $deferred); - my $ndr_flags = "NDR_BUFFERS"; - if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e))) - { - $ndr_flags="NDR_SCALARS|$ndr_flags" - } + return "NDR_SCALARS|NDR_BUFFERS" if ($scalars and $buffers); + return "NDR_SCALARS" if ($scalars); + return "NDR_BUFFERS" if ($buffers); + return undef; +} - if (defined $sub_size) { - $subndr = ParseSubcontextPushStart($e, $ndr_flags); - $ndr = $subndr; - $ndr_flags = "NDR_SCALARS|NDR_BUFFERS"; +sub ParseElementPullLevel +{ + my($e) = shift; + my $l = shift; + my $ndr = shift; + my($var_name) = shift; + my $env = shift; + my $primitives = shift; + my $deferred = shift; + + my $ndr_flags = CalcNdrFlags($l, $primitives, $deferred); + + # Only pull something if there's actually something to be pulled + if (defined($ndr_flags)) { + if ($l->{TYPE} eq "SUBCONTEXT") { + ($ndr,$var_name) = ParseSubcontextPullStart($e, $l, $ndr, $var_name, $ndr_flags, $env); + ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + ParseSubcontextPullEnd($e, $l); + } elsif ($l->{TYPE} eq "ARRAY") { + my $length = ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); + + # Speed things up a little - special array pull functions + # for scalars + if (is_scalar_array($e, $l)) { + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } + + pidl "NDR_CHECK(ndr_pull_array_$e->{TYPE}($ndr, $ndr_flags, $var_name, $length));"; + return; + } + } elsif ($l->{TYPE} eq "POINTER") { + ParsePtrPull($e, $l, $ndr, $var_name); + } elsif ($l->{TYPE} eq "SWITCH") { + ParseSwitchPull($e, $l, $ndr, $var_name, $ndr_flags, $env); + } elsif ($l->{TYPE} eq "DATA") { + ParseDataPull($e, $l, $ndr, $var_name, $ndr_flags); + } } - if (util::array_size($e)) { - ParseArrayPush($e, $ndr, "r->", $ndr_flags); - } else { - if (my $switch = util::has_property($e, "switch_is")) { - ParseSwitchPush($e, $ndr, $var_prefix, $ndr_flags, $switch); + # add additional constructions + if ($l->{TYPE} eq "POINTER" and $deferred) { + if ($l->{POINTER_TYPE} ne "ref") { + pidl "if ($var_name) {"; + indent; + + if ($l->{POINTER_TYPE} eq "relative") { + pidl "struct ndr_pull_save _relative_save;"; + pidl "ndr_pull_save(ndr, &_relative_save);"; + pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_name));"; + } } - pidl "NDR_CHECK(ndr_push_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));"; - } + $var_name = get_value_of($var_name); + ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); - if (defined $sub_size) { - ParseSubcontextPushEnd($e); - } + if ($l->{POINTER_TYPE} ne "ref") { + if ($l->{POINTER_TYPE} eq "relative") { + pidl "ndr_pull_restore(ndr, &_relative_save);"; + } + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "ARRAY" and not is_scalar_array($e,$l)) { + my $length = ParseExpr($l->{LENGTH_IS}, $env); + my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - for my $i (1..Ndr::need_wire_pointer($e)) { - deindent; - pidl "}"; - } + $var_name = $var_name . "[$counter]"; + unless ($l->{NO_METADATA}) { + $var_name = get_pointer_to($var_name); + } - end_flags($e); + if (($primitives and not $l->{IS_DEFERRED}) or ($deferred and $l->{IS_DEFERRED})) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 1, 0); + deindent; + pidl "}"; + } + + if ($deferred and Ndr::ContainsDeferred($e, $l)) { + pidl "for ($counter = 0; $counter < $length; $counter++) {"; + indent; + ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); + deindent; + pidl "}"; + } + } elsif ($l->{TYPE} eq "SWITCH") { + ParseElementPullLevel($e,Ndr::GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + } } ##################################################################### -# parse buffers in a structure element - pull side -sub ParseElementPullBuffer($$) +# parse scalars in a structure element - pull size +sub ParseElementPull($$$$$$) { my($e) = shift; + my $ndr = shift; my($var_prefix) = shift; - my $cprefix = c_pull_prefix($e); - my $sub_size = util::has_property($e, "subcontext"); - my $ndr = "ndr"; - my $subndr = undef; + my $env = shift; + my $primitives = shift; + my $deferred = shift; + + my $var_name = $var_prefix.$e->{NAME}; - return unless (need_buffers_section($e)); + $var_name = append_prefix($e, $var_name); + + return unless $primitives or ($deferred and Ndr::ContainsDeferred($e, $e->{LEVELS}[0])); start_flags($e); - my $pointers = c_ptr_prefix($e); - for my $i (1..Ndr::need_wire_pointer($e)) { - if ($i > 1) { - ParsePtrPull($e,$pointers.$var_prefix); - } - pidl "if ($pointers$var_prefix$e->{NAME}) {"; - indent; - $pointers.="*"; - } - - if (util::has_property($e, "relative")) { - pidl "struct ndr_pull_save _relative_save;"; - pidl "ndr_pull_save(ndr, &_relative_save);"; - pidl "NDR_CHECK(ndr_pull_relative_ptr2(ndr, $var_prefix$e->{NAME}));"; - } - - my $ndr_flags = "NDR_BUFFERS"; - if ($e->{POINTERS} || (util::array_size($e) && !Ndr::is_inline_array($e))) - { - $ndr_flags="NDR_SCALARS|$ndr_flags" - } - - if (defined $sub_size) { - $subndr = ParseSubcontextPullStart($e, $ndr_flags); - $ndr = $subndr; - $ndr_flags = "NDR_SCALARS|NDR_BUFFERS"; - } - - if (util::array_size($e)) { - ParseArrayPull($e, $ndr, "r->", $ndr_flags); - } else { - if (my $switch = util::has_property($e, "switch_is")) { - ParseSwitchPull($e, $ndr, $var_prefix, $ndr_flags, $switch); - } + ParseElementPullLevel($e,$e->{LEVELS}[0],$ndr,$var_name,$env,$primitives,$deferred); - pidl "NDR_CHECK(ndr_pull_$e->{TYPE}($ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME}));"; - } + end_flags($e); +} - if (defined $sub_size) { - ParseSubcontextPullEnd($e); - } +##################################################################### +# parse a pointer in a struct element or function +sub ParsePtrPull($$$$) +{ + my($e) = shift; + my $l = shift; + my $ndr = shift; + my($var_name) = shift; + + my $nl = Ndr::GetNextLevel($e, $l); + my $next_is_array = ($nl->{TYPE} eq "ARRAY"); - if (util::has_property($e, "relative")) { - pidl "ndr_pull_restore(ndr, &_relative_save);"; + if ($l->{POINTER_TYPE} eq "ref") { + unless ($l->{LEVEL} eq "TOP") { + pidl "NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));"; + } + + unless ($next_is_array) { + pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; + pidl "\tNDR_ALLOC($ndr, $var_name);"; + pidl "}"; + } + + return; + } else { + pidl "NDR_CHECK(ndr_pull_unique_ptr($ndr, &_ptr_$e->{NAME}));"; + pidl "if (_ptr_$e->{NAME}) {"; + indent; } - for my $i (1..Ndr::need_wire_pointer($e)) { - deindent; - pidl "}"; + # Don't do this for arrays, they're allocated at the actual level + # of the array + unless ($next_is_array) { + pidl "NDR_ALLOC($ndr, $var_name);"; + } else { + pidl "NDR_ALLOC_SIZE($ndr, $var_name, 1);"; # FIXME: Yes, this is nasty. We allocate an array twice - once just to indicate that it's there, then the real allocation... } - end_flags($e); + #pidl "memset($var_name, 0, sizeof($var_name));"; + if ($l->{POINTER_TYPE} eq "relative") { + pidl "NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));"; + } + deindent; + pidl "} else {"; + pidl "\t$var_name = NULL;"; + pidl "}"; } ##################################################################### # parse a struct -sub ParseStructPush($) +sub ParseStructPush($$) { my($struct) = shift; + my $name = shift; return unless defined($struct->{ELEMENTS}); + my $env = GenerateStructEnv($struct); + + foreach my $e (@{$struct->{ELEMENTS}}) { + DeclareArrayVariables($e); + } + start_flags($struct); # see if the structure contains a conformant array. If it @@ -1003,60 +1107,66 @@ sub ParseStructPush($) # the wire before the structure (and even before the structure # alignment) my $e = $struct->{ELEMENTS}[-1]; - if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) { - ParseArrayPushPreceding($e, "r->", "NDR_SCALARS"); - } + if (defined($struct->{SURROUNDING_ELEMENT})) { + my $e = $struct->{SURROUNDING_ELEMENT}; - if (defined $e->{TYPE} && $e->{TYPE} eq "string" - && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { - pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));"; + if (defined($e->{LEVELS}[0]) and + $e->{LEVELS}[0]->{TYPE} eq "ARRAY") { + ParseArrayPushPreceding($e, $e->{LEVELS}[0], "r->$e->{NAME}", $env); + } else { + pidl "NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, ndr_string_array_size(ndr, r->$e->{NAME})));"; + } } - pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;"; + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; pidl "NDR_CHECK(ndr_push_struct_start(ndr));"; - my $align = Ndr::find_largest_alignment($struct); - pidl "NDR_CHECK(ndr_push_align(ndr, $align));"; + pidl "NDR_CHECK(ndr_push_align(ndr, $struct->{ALIGN}));"; foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElementPushScalar($e, "r->", "NDR_SCALARS"); + ParseElementPush($e, "ndr", "r->", $env, 1, 0); } - pidl "buffers:"; - pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;"; + deindent; + pidl "}"; + + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElementPushBuffer($e, "r->"); + ParseElementPush($e, "ndr", "r->", $env, 0, 1); } pidl "ndr_push_struct_end(ndr);"; - pidl "done:"; + deindent; + pidl "}"; end_flags($struct); } ##################################################################### # generate a push function for an enum -sub ParseEnumPush($) +sub ParseEnumPush($$) { my($enum) = shift; - my($type_fn) = typelist::enum_type_fn($enum); + my $name = shift; + my($type_fn) = $enum->{BASE_TYPE}; start_flags($enum); - pidl "NDR_CHECK(ndr_push_$type_fn(ndr, NDR_SCALARS, r));"; - end_flags($enum); } ##################################################################### # generate a pull function for an enum -sub ParseEnumPull($) +sub ParseEnumPull($$) { my($enum) = shift; - my($type_fn) = typelist::enum_type_fn($enum); - my($type_v_decl) = typelist::mapScalarType(typelist::enum_type_fn($enum)); + my $name = shift; + my($type_fn) = $enum->{BASE_TYPE}; + my($type_v_decl) = typelist::mapType($type_fn); pidl "$type_v_decl v;"; start_flags($enum); @@ -1068,9 +1178,10 @@ sub ParseEnumPull($) ##################################################################### # generate a print function for an enum -sub ParseEnumPrint($) +sub ParseEnumPrint($$) { my($enum) = shift; + my $name = shift; pidl "const char *val = NULL;"; pidl ""; @@ -1126,10 +1237,11 @@ $typefamily{ENUM} = { ##################################################################### # generate a push function for a bitmap -sub ParseBitmapPush($) +sub ParseBitmapPush($$) { my($bitmap) = shift; - my($type_fn) = typelist::bitmap_type_fn($bitmap); + my $name = shift; + my($type_fn) = $bitmap->{BASE_TYPE}; start_flags($bitmap); @@ -1140,11 +1252,12 @@ sub ParseBitmapPush($) ##################################################################### # generate a pull function for an bitmap -sub ParseBitmapPull($) +sub ParseBitmapPull($$) { my($bitmap) = shift; - my($type_fn) = typelist::bitmap_type_fn($bitmap); - my($type_decl) = typelist::mapType($bitmap); + my $name = shift; + my $type_fn = $bitmap->{BASE_TYPE}; + my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE}); pidl "$type_decl v;"; start_flags($bitmap); @@ -1156,13 +1269,13 @@ sub ParseBitmapPull($) ##################################################################### # generate a print function for an bitmap -sub ParseBitmapPrintElement($$) +sub ParseBitmapPrintElement($$$) { my($e) = shift; my($bitmap) = shift; - my($type_decl) = typelist::mapType($bitmap); - my($type_fn) = typelist::bitmap_type_fn($bitmap); - my($name) = $bitmap->{PARENT}->{NAME}; + my($name) = shift; + my($type_decl) = typelist::mapType($bitmap->{BASE_TYPE}); + my($type_fn) = $bitmap->{BASE_TYPE}; my($flag); if ($e =~ /^(\w+) .*$/) { @@ -1176,11 +1289,12 @@ sub ParseBitmapPrintElement($$) ##################################################################### # generate a print function for an bitmap -sub ParseBitmapPrint($) +sub ParseBitmapPrint($$) { my($bitmap) = shift; - my($type_decl) = typelist::mapType($bitmap); - my($type_fn) = typelist::bitmap_type_fn($bitmap); + my $name = shift; + my($type_decl) = typelist::mapType($bitmap->{TYPE}); + my($type_fn) = $bitmap->{BASE_TYPE}; start_flags($bitmap); @@ -1188,7 +1302,7 @@ sub ParseBitmapPrint($) pidl "ndr->depth++;"; foreach my $e (@{$bitmap->{ELEMENTS}}) { - ParseBitmapPrintElement($e, $bitmap); + ParseBitmapPrintElement($e, $bitmap, $name); } pidl "ndr->depth--;"; @@ -1198,21 +1312,21 @@ sub ParseBitmapPrint($) sub ArgsBitmapPush($) { my $e = shift; - my $type_decl = typelist::mapType($e->{DATA}); + my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE}); return "struct ndr_push *ndr, int ndr_flags, $type_decl r"; } sub ArgsBitmapPrint($) { my $e = shift; - my $type_decl = typelist::mapType($e->{DATA}); + my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE}); return "struct ndr_print *ndr, const char *name, $type_decl r"; } sub ArgsBitmapPull($) { my $e = shift; - my $type_decl = typelist::mapType($e->{DATA}); + my $type_decl = typelist::mapType($e->{DATA}->{BASE_TYPE}); return "struct ndr_pull *ndr, int ndr_flags, $type_decl *r"; } @@ -1227,87 +1341,110 @@ $typefamily{BITMAP} = { ##################################################################### # generate a struct print function -sub ParseStructPrint($) +sub ParseStructPrint($$) { my($struct) = shift; - my($name) = $struct->{PARENT}->{NAME}; + my($name) = shift; return unless defined $struct->{ELEMENTS}; + my $env = GenerateStructEnv($struct); + + foreach my $e (@{$struct->{ELEMENTS}}) { + DeclareArrayVariables($e); + } + pidl "ndr_print_struct(ndr, name, \"$name\");"; start_flags($struct); pidl "ndr->depth++;"; foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElementPrint($e, "r->"); + ParseElementPrint($e, "r->$e->{NAME}", $env); } pidl "ndr->depth--;"; end_flags($struct); } +sub DeclarePtrVariables($) +{ + my $e = shift; + foreach my $l (@{$e->{LEVELS}}) { + if ($l->{TYPE} eq "POINTER" and + not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { + pidl "uint32_t _ptr_$e->{NAME};"; + last; + } + } +} + +sub DeclareArrayVariables($) +{ + my $e = shift; + + foreach my $l (@{$e->{LEVELS}}) { + next if (is_scalar_array($e,$l)); + if ($l->{TYPE} eq "ARRAY") { + pidl "uint32_t cntr_$e->{NAME}_$l->{LEVEL_INDEX};"; + } + } +} + ##################################################################### # parse a struct - pull side -sub ParseStructPull($) +sub ParseStructPull($$) { my($struct) = shift; + my $name = shift; my $conform_e; return unless defined $struct->{ELEMENTS}; + my $env = GenerateStructEnv($struct); + # see if the structure contains a conformant array. If it # does, then it must be the last element of the structure, and # we need to pull the conformant length early, as it fits on # the wire before the structure (and even before the structure # alignment) - my $e = $struct->{ELEMENTS}[-1]; - if (Ndr::is_conformant_array($e) and Ndr::is_surrounding_array($e)) { - $conform_e = $e; - } - - if (defined $e->{TYPE} && $e->{TYPE} eq "string" - && util::property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { - $conform_e = $e; - } + $conform_e = $struct->{SURROUNDING_ELEMENT}; # declare any internal pointers we need foreach my $e (@{$struct->{ELEMENTS}}) { - if (Ndr::need_wire_pointer($e)) { - pidl "uint32_t _ptr_$e->{NAME};"; - } + DeclarePtrVariables($e); + DeclareArrayVariables($e); } start_flags($struct); - pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;"; + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; pidl "NDR_CHECK(ndr_pull_struct_start(ndr));"; if (defined $conform_e) { - ParseArrayPullPreceding($conform_e, "r->", "NDR_SCALARS"); + ParseArrayPullPreceding($conform_e, $conform_e->{LEVELS}[0], "r->$conform_e->{NAME}"); } - my $align = Ndr::find_largest_alignment($struct); - pidl "NDR_CHECK(ndr_pull_align(ndr, $align));"; + pidl "NDR_CHECK(ndr_pull_align(ndr, $struct->{ALIGN}));"; foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElementPullScalar($e, "r->", "NDR_SCALARS"); + ParseElementPull($e, "ndr", "r->", $env, 1, 0); } - pidl "buffers:\n"; - pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;"; - foreach my $e (@{$struct->{ELEMENTS}}) { - ParseElementPullBuffer($e, "r->"); - } - + deindent; + pidl "}"; + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; foreach my $e (@{$struct->{ELEMENTS}}) { - CheckArraySizes($e, "r->"); + ParseElementPull($e, "ndr", "r->", $env, 0, 1); } pidl "ndr_pull_struct_end(ndr);"; - pidl "done:"; + deindent; + pidl "}"; end_flags($struct); } @@ -1317,7 +1454,6 @@ sub ParseStructPull($) sub ParseStructNdrSize($) { my $t = shift; - my $static = fn_prefix($t); my $sizevar; if (my $flags = util::has_property($t, "flag")) { @@ -1366,7 +1502,6 @@ $typefamily{STRUCT} = { sub ParseUnionNdrSize($) { my $t = shift; - my $static = fn_prefix($t); my $sizevar; if (my $flags = util::has_property($t, "flag")) { @@ -1378,23 +1513,24 @@ sub ParseUnionNdrSize($) ##################################################################### # parse a union - push side -sub ParseUnionPush($) +sub ParseUnionPush($$) { my $e = shift; + my $name = shift; my $have_default = 0; pidl "int level;"; + start_flags($e); pidl "level = ndr_push_get_switch_value(ndr, r);"; - pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;"; + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; - if (!util::has_property($e, "nodiscriminant")) { - my $switch_type = util::has_property($e, "switch_type"); - $switch_type = "uint32" unless (defined ($switch_type)); - pidl "NDR_CHECK(ndr_push_$switch_type(ndr, NDR_SCALARS, level));"; + if (defined($e->{SWITCH_TYPE})) { + pidl "NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}(ndr, NDR_SCALARS, level));"; } pidl "NDR_CHECK(ndr_push_struct_start(ndr));"; @@ -1405,16 +1541,15 @@ sub ParseUnionPush($) pidl "switch (level) {"; indent; foreach my $el (@{$e->{ELEMENTS}}) { - if (util::has_property($el, "default")) { - pidl "default:"; + if ($el->{CASE} eq "default") { $have_default = 1; - } else { - pidl "case $el->{PROPERTIES}->{case}:"; - } + pidl "$el->{CASE}:"; + if ($el->{TYPE} ne "EMPTY") { indent; - ParseElementPushScalar($el, "r->", "NDR_SCALARS"); + DeclareArrayVariables($el); + ParseElementPush($el, "ndr", "r->", {}, 1, 0); deindent; } pidl "break;"; @@ -1426,19 +1561,17 @@ sub ParseUnionPush($) } deindent; pidl "}"; - pidl "buffers:"; - pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;"; + deindent; + pidl "}"; + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; pidl "switch (level) {"; indent; foreach my $el (@{$e->{ELEMENTS}}) { - if (util::has_property($el, "default")) { - pidl "default:"; - } else { - pidl "case $el->{PROPERTIES}->{case}:"; - } + pidl "$el->{CASE}:"; if ($el->{TYPE} ne "EMPTY") { indent; - ParseElementPushBuffer($el, "r->"); + ParseElementPush($el, "ndr", "r->", {}, 0, 1); deindent; } pidl "break;"; @@ -1451,35 +1584,38 @@ sub ParseUnionPush($) deindent; pidl "}"; pidl "ndr_push_struct_end(ndr);"; - pidl "done:"; + deindent; + pidl "}"; end_flags($e); } ##################################################################### # print a union -sub ParseUnionPrint($) +sub ParseUnionPrint($$) { my $e = shift; my $have_default = 0; - my($name) = $e->{PARENT}->{NAME}; + my $name = shift; pidl "int level = ndr_print_get_switch_value(ndr, r);"; + foreach my $el (@{$e->{ELEMENTS}}) { + DeclareArrayVariables($el); + } + pidl "ndr_print_union(ndr, name, level, \"$name\");"; start_flags($e); pidl "switch (level) {"; indent; foreach my $el (@{$e->{ELEMENTS}}) { - if (util::has_property($el, "default")) { + if ($el->{CASE} eq "default") { $have_default = 1; - pidl "default:"; - } else { - pidl "case $el->{PROPERTIES}->{case}:"; } + pidl "$el->{CASE}:"; if ($el->{TYPE} ne "EMPTY") { indent; - ParseElementPrint($el, "r->"); + ParseElementPrint($el, "r->$el->{NAME}", {}); deindent; } pidl "break;"; @@ -1497,31 +1633,32 @@ sub ParseUnionPrint($) ##################################################################### # parse a union - pull side -sub ParseUnionPull($) +sub ParseUnionPull($$) { my $e = shift; + my $name = shift; my $have_default = 0; - my $switch_type = util::has_property($e, "switch_type"); - $switch_type = "uint32" unless defined($switch_type); + my $switch_type = $e->{SWITCH_TYPE}; pidl "int level;"; - if (!util::has_property($e, "nodiscriminant")) { + if (defined($switch_type)) { if (typelist::typeIs($switch_type, "ENUM")) { $switch_type = typelist::enum_type_fn(typelist::getType($switch_type)); } - pidl typelist::mapScalarType($switch_type) . " _level;"; + pidl typelist::mapType($switch_type) . " _level;"; } start_flags($e); pidl "level = ndr_pull_get_switch_value(ndr, r);"; - pidl "if (!(ndr_flags & NDR_SCALARS)) goto buffers;"; + pidl "if (ndr_flags & NDR_SCALARS) {"; + indent; - if (!util::has_property($e, "nodiscriminant")) { + if (defined($switch_type)) { pidl "NDR_CHECK(ndr_pull_$switch_type(ndr, NDR_SCALARS, &_level));"; pidl "if (_level != level) {"; - pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $e->{PARENT}->{NAME}\", _level);"; + pidl "\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $name\", _level);"; pidl "}"; } @@ -1533,18 +1670,16 @@ sub ParseUnionPull($) pidl "switch (level) {"; indent; foreach my $el (@{$e->{ELEMENTS}}) { - if (util::has_property($el, "default")) { - pidl "default: {"; + if ($el->{CASE} eq "default") { $have_default = 1; - } else { - pidl "case $el->{PROPERTIES}->{case}: {"; - } + } + pidl "$el->{CASE}: {"; + if ($el->{TYPE} ne "EMPTY") { indent; - if ($el->{POINTERS}) { - pidl "uint32_t _ptr_$el->{NAME};"; - } - ParseElementPullScalar($el, "r->", "NDR_SCALARS"); + DeclarePtrVariables($el); + DeclareArrayVariables($el); + ParseElementPull($el, "ndr", "r->", {}, 1, 0); deindent; } pidl "break; }"; @@ -1556,19 +1691,17 @@ sub ParseUnionPull($) } deindent; pidl "}"; - pidl "buffers:"; - pidl "if (!(ndr_flags & NDR_BUFFERS)) goto done;"; + deindent; + pidl "}"; + pidl "if (ndr_flags & NDR_BUFFERS) {"; + indent; pidl "switch (level) {"; indent; foreach my $el (@{$e->{ELEMENTS}}) { - if (util::has_property($el, "default")) { - pidl "default:"; - } else { - pidl "case $el->{PROPERTIES}->{case}:"; - } + pidl "$el->{CASE}:"; if ($el->{TYPE} ne "EMPTY") { indent; - ParseElementPullBuffer($el, "r->"); + ParseElementPull($el, "ndr", "r->", {}, 0, 1); deindent; } pidl "break;"; @@ -1581,7 +1714,8 @@ sub ParseUnionPull($) deindent; pidl "}"; pidl "ndr_pull_struct_end(ndr);"; - pidl "done:"; + deindent; + pidl "}"; end_flags($e); } @@ -1625,39 +1759,32 @@ $typefamily{UNION} = { sub ParseTypedefPush($) { my($e) = shift; - my $static = fn_prefix($e); - - return unless needed::is_needed("push_$e->{NAME}"); my $args = $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_ARGS}->($e); - pidl $static . "NTSTATUS ndr_push_$e->{NAME}($args)"; + pidl fn_prefix($e) . "NTSTATUS ndr_push_$e->{NAME}($args)"; pidl "{"; indent; - $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA}); + $typefamily{$e->{DATA}->{TYPE}}->{PUSH_FN_BODY}->($e->{DATA}, $e->{NAME}); pidl "return NT_STATUS_OK;"; deindent; pidl "}"; pidl "";; } - ##################################################################### # parse a typedef - pull side sub ParseTypedefPull($) { my($e) = shift; - my $static = fn_prefix($e); - - return unless needed::is_needed("pull_$e->{NAME}"); my $args = $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_ARGS}->($e); - pidl $static . "NTSTATUS ndr_pull_$e->{NAME}($args)"; + pidl fn_prefix($e) . "NTSTATUS ndr_pull_$e->{NAME}($args)"; pidl "{"; indent; - $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA}); + $typefamily{$e->{DATA}->{TYPE}}->{PULL_FN_BODY}->($e->{DATA}, $e->{NAME}); pidl "return NT_STATUS_OK;"; deindent; pidl "}"; @@ -1672,12 +1799,10 @@ 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; - $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}); + $typefamily{$e->{DATA}->{TYPE}}->{PRINT_FN_BODY}->($e->{DATA}, $e->{NAME}); deindent; pidl "}"; pidl ""; @@ -1689,8 +1814,6 @@ sub ParseTypedefNdrSize($) { my($t) = shift; - return unless needed::is_needed("ndr_size_$t->{NAME}"); - my $tf = $typefamily{$t->{DATA}->{TYPE}}; my $args = $tf->{SIZE_FN_ARGS}->($t); @@ -1709,11 +1832,18 @@ sub ParseFunctionPrint($) { my($fn) = shift; - return unless !util::has_property($fn, "noprint"); + return if util::has_property($fn, "noprint"); + + my $env = GenerateFunctionEnv($fn); pidl "void ndr_print_$fn->{NAME}(struct ndr_print *ndr, const char *name, int flags, struct $fn->{NAME} *r)"; pidl "{"; indent; + + foreach my $e (@{$fn->{ELEMENTS}}) { + DeclareArrayVariables($e); + } + pidl "ndr_print_struct(ndr, name, \"$fn->{NAME}\");"; pidl "ndr->depth++;"; @@ -1727,8 +1857,8 @@ sub ParseFunctionPrint($) pidl "ndr->depth++;"; foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "in")) { - ParseElementPrint($e, "r->in."); + if (grep(/in/,@{$e->{DIRECTION}})) { + ParseElementPrint($e, "r->in.$e->{NAME}", $env); } } pidl "ndr->depth--;"; @@ -1740,14 +1870,12 @@ sub ParseFunctionPrint($) pidl "ndr_print_struct(ndr, \"out\", \"$fn->{NAME}\");"; pidl "ndr->depth++;"; foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "out")) { - ParseElementPrint($e, "r->out."); + if (grep(/out/,@{$e->{DIRECTION}})) { + ParseElementPrint($e, "r->out.$e->{NAME}", $env); } } - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { - my $cprefix = "&"; - $cprefix = "" if (Ndr::is_scalar_type($fn->{RETURN_TYPE})) ; # FIXME: Should really use util::c_push_prefix here - pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", $cprefix"."r->out.result);"; + if ($fn->{RETURN_TYPE}) { + pidl "ndr_print_$fn->{RETURN_TYPE}(ndr, \"result\", r->out.result);"; } pidl "ndr->depth--;"; deindent; @@ -1759,153 +1887,82 @@ sub ParseFunctionPrint($) pidl ""; } -##################################################################### -# parse a function element -sub ParseFunctionElementPush($$) -{ - my $e = shift; - my $inout = shift; - - if (util::array_size($e)) { - if (Ndr::need_wire_pointer($e)) { - ParsePtrPush($e, "r->$inout."); - pidl "if (r->$inout.$e->{NAME}) {"; - indent; - ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); - deindent; - pidl "}"; - } else { - ParseArrayPush($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); - } - } else { - ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); - if (Ndr::need_wire_pointer($e)) { - ParseElementPushBuffer($e, "r->$inout."); - } - } -} - ##################################################################### # parse a function sub ParseFunctionPush($) { my($fn) = shift; - my $static = fn_prefix($fn); - return unless !util::has_property($fn, "nopush"); + return if util::has_property($fn, "nopush"); + + my $env = GenerateFunctionEnv($fn); - pidl $static . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)"; + pidl fn_prefix($fn) . "NTSTATUS ndr_push_$fn->{NAME}(struct ndr_push *ndr, int flags, struct $fn->{NAME} *r)"; pidl "{"; indent; - pidl "if (!(flags & NDR_IN)) goto ndr_out;"; - pidl ""; + foreach my $e (@{$fn->{ELEMENTS}}) { + DeclareArrayVariables($e); + } + + pidl "if (flags & NDR_IN) {"; + indent; foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "in")) { - if (util::has_property($e, "ref")) { - check_null_pointer("*r->in.$e->{NAME}"); - } - ParseFunctionElementPush($e, "in"); - } + if (grep(/in/,@{$e->{DIRECTION}})) { + ParseElementPush($e, "ndr", "r->in.", $env, 1, 1); + } } - pidl "ndr_out:"; - pidl "if (!(flags & NDR_OUT)) goto done;"; - pidl ""; + deindent; + pidl "}"; + + pidl "if (flags & NDR_OUT) {"; + indent; foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "out")) { - if (util::has_property($e, "ref")) { - check_null_pointer("*r->out.$e->{NAME}"); - } - ParseFunctionElementPush($e, "out"); - } + if (grep(/out/,@{$e->{DIRECTION}})) { + ParseElementPush($e, "ndr", "r->out.", $env, 1, 1); + } } - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + if ($fn->{RETURN_TYPE}) { pidl "NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, r->out.result));"; } - pidl "done:"; + deindent; + pidl "}"; pidl "return NT_STATUS_OK;"; deindent; pidl "}"; pidl ""; } -##################################################################### -# parse a function element -sub ParseFunctionElementPull($$) -{ - my $e = shift; - my $inout = shift; - - if (util::array_size($e)) { - if (Ndr::need_wire_pointer($e)) { - pidl "NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_$e->{NAME}));"; - pidl "r->$inout.$e->{NAME} = NULL;"; - pidl "if (_ptr_$e->{NAME}) {"; - indent; - } elsif ($inout eq "out" && util::has_property($e, "ref")) { - pidl "if (r->$inout.$e->{NAME}) {"; - indent; - } - - ParseArrayPull($e, "ndr", "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); - - if (Ndr::need_wire_pointer($e) or ($inout eq "out" and util::has_property($e, "ref"))) { - deindent; - pidl "}"; - } - } else { - if ($inout eq "out" && util::has_property($e, "ref")) { - pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; - pidl "\tNDR_ALLOC(ndr, r->out.$e->{NAME});"; - pidl "}"; - } - - if ($inout eq "in" && util::has_property($e, "ref")) { - pidl "NDR_ALLOC(ndr, r->in.$e->{NAME});"; - } - - ParseElementPullScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS"); - if (Ndr::need_wire_pointer($e)) { - ParseElementPullBuffer($e, "r->$inout."); - } - } -} - -############################################################ -# allocate ref variables -sub AllocateRefVars($) +sub AllocateArrayLevel($$$$$) { my $e = shift; - my $asize = util::array_size($e); - - # note that if the variable is also an "in" - # variable then we copy the initial value from - # the in side + my $l = shift; + my $ndr = shift; + my $env = shift; + my $size = shift; - if (!defined $asize) { - # its a simple variable - pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});"; - if (util::has_property($e, "in")) { - pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};"; - } else { - pidl "ZERO_STRUCTP(r->out.$e->{NAME});"; - } - return; - } + my $var = ParseExpr($e->{NAME}, $env); - # its an array - my $size = ParseExpr($e, $asize, "r->out."); check_null_pointer($size); - pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);"; - if (util::has_property($e, "in")) { - pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));"; + my $pl = Ndr::GetPrevLevel($e, $l); + if (defined($pl) and + $pl->{TYPE} eq "POINTER" and + $pl->{POINTER_TYPE} eq "ref") { + pidl "if (ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"; + pidl "\tNDR_ALLOC_N($ndr, $var, $size);"; + pidl "}"; } else { - pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));"; + pidl "NDR_ALLOC_N($ndr, $var, $size);"; + } + #pidl "memset($var, 0, $size * sizeof(" . $var . "[0]));"; + if (grep(/in/,@{$e->{DIRECTION}}) and + grep(/out/,@{$e->{DIRECTION}})) { + pidl "memcpy(r->out.$e->{NAME},r->in.$e->{NAME},$size * sizeof(*r->in.$e->{NAME}));"; } } @@ -1914,76 +1971,89 @@ sub AllocateRefVars($) sub ParseFunctionPull($) { my($fn) = shift; - my $static = fn_prefix($fn); - return unless !util::has_property($fn, "nopull"); + return if util::has_property($fn, "nopull"); + + my $env = GenerateFunctionEnv($fn); # pull function args - pidl $static . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)"; + pidl fn_prefix($fn) . "NTSTATUS ndr_pull_$fn->{NAME}(struct ndr_pull *ndr, int flags, struct $fn->{NAME} *r)"; pidl "{"; indent; # declare any internal pointers we need - foreach my $e (@{$fn->{ELEMENTS}}) { - if (Ndr::need_wire_pointer($e)) { - pidl "uint32_t _ptr_$e->{NAME};"; - } + foreach my $e (@{$fn->{ELEMENTS}}) { + DeclarePtrVariables($e); + DeclareArrayVariables($e); } - pidl "if (!(flags & NDR_IN)) goto ndr_out;"; - pidl ""; + pidl "if (flags & NDR_IN) {"; + indent; # auto-init the out section of a structure. I originally argued that # this was a bad idea as it hides bugs, but coping correctly # with initialisation and not wiping ref vars is turning # out to be too tricky (tridge) foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "out")) { - pidl "ZERO_STRUCT(r->out);"; - pidl ""; - last; - } + next unless grep(/out/, @{$e->{DIRECTION}}); + pidl "ZERO_STRUCT(r->out);"; + pidl ""; + last; } foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "in")) { - ParseFunctionElementPull($e, "in"); - } - # we need to allocate any reference output variables, so that - # a dcerpc backend can be sure they are non-null - if (util::has_property($e, "out") && util::has_property($e, "ref")) { - AllocateRefVars($e); - } + next unless (grep(/in/, @{$e->{DIRECTION}})); + ParseElementPull($e, "ndr", "r->in.", $env, 1, 1); } + # allocate the "simple" out ref variables. FIXME: Shouldn't this have it's + # own flag rather then be in NDR_IN ? + foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "in")) { - CheckArraySizes($e, "r->in."); - } - } + next unless (grep(/out/, @{$e->{DIRECTION}})); + next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and + $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref"); - pidl "ndr_out:"; - pidl "if (!(flags & NDR_OUT)) goto done;"; - pidl ""; - foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "out")) { - ParseFunctionElementPull($e, "out"); + if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { + my $size = ParseExpr($e->{LEVELS}[1]->{SIZE_IS}, $env); + check_null_pointer($size); + + pidl "NDR_ALLOC_N(ndr, r->out.$e->{NAME}, $size);"; + + if (grep(/in/, @{$e->{DIRECTION}})) { + pidl "memcpy(r->out.$e->{NAME}, r->in.$e->{NAME}, $size * sizeof(*r->in.$e->{NAME}));"; + } else { + pidl "memset(r->out.$e->{NAME}, 0, $size * sizeof(*r->out.$e->{NAME}));"; + } + } else { + pidl "NDR_ALLOC(ndr, r->out.$e->{NAME});"; + + if (grep(/in/, @{$e->{DIRECTION}})) { + pidl "*r->out.$e->{NAME} = *r->in.$e->{NAME};"; + } else { + pidl "ZERO_STRUCTP(r->out.$e->{NAME});"; + } } } + deindent; + pidl "}"; + + pidl "if (flags & NDR_OUT) {"; + indent; + foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, "out")) { - CheckArraySizes($e, "r->out."); - } + next unless grep(/out/, @{$e->{DIRECTION}}); + ParseElementPull($e, "ndr", "r->out.", $env, 1, 1); } - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + if ($fn->{RETURN_TYPE}) { pidl "NDR_CHECK(ndr_pull_$fn->{RETURN_TYPE}(ndr, NDR_SCALARS, &r->out.result));"; } - pidl "done:"; - pidl ""; + deindent; + pidl "}"; pidl "return NT_STATUS_OK;"; deindent; pidl "}"; @@ -1995,44 +2065,33 @@ sub ParseFunctionPull($) sub FunctionTable($) { my($interface) = shift; - my($data) = $interface->{INHERITED_DATA}; my $count = 0; my $uname = uc $interface->{NAME}; - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { $count++; } - } + $count = $#{$interface->{FUNCTIONS}}+1; return if ($count == 0); pidl "static const struct dcerpc_interface_call $interface->{NAME}\_calls[] = {"; - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { - pidl "\t{"; - pidl "\t\t\"$d->{NAME}\","; - pidl "\t\tsizeof(struct $d->{NAME}),"; - pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},"; - pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"; - pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}"; - pidl "\t},"; - } + foreach my $d (@{$interface->{FUNCTIONS}}) { + pidl "\t{"; + pidl "\t\t\"$d->{NAME}\","; + pidl "\t\tsizeof(struct $d->{NAME}),"; + pidl "\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},"; + pidl "\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"; + pidl "\t\t(ndr_print_function_t) ndr_print_$d->{NAME}"; + pidl "\t},"; } pidl "\t{ NULL, 0, NULL, NULL, NULL }"; pidl "};"; pidl ""; - # If no endpoint is set, default to the interface name as a named pipe - if (! defined $interface->{PROPERTIES}->{endpoint}) { - $interface->{PROPERTIES}->{endpoint} = "\"ncacn_np:[\\\\pipe\\\\" . $interface->{NAME} . "]\""; - } - - my @e = split / /, $interface->{PROPERTIES}->{endpoint}; - my $endpoint_count = $#e + 1; - pidl "static const char * const $interface->{NAME}\_endpoint_strings[] = {"; - foreach my $ep (@e) { + foreach my $ep (@{$interface->{ENDPOINTS}}) { pidl "\t$ep, "; } + my $endpoint_count = $#{$interface->{ENDPOINTS}}+1; + pidl "};"; pidl ""; @@ -2083,27 +2142,33 @@ sub FunctionTable($) ##################################################################### # parse the interface definitions -sub ParseInterface($) +sub ParseInterface($$) { my($interface) = shift; - my($data) = $interface->{DATA}; - - # Push functions - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "TYPEDEF") { - ParseTypedefPush($d); - ParseTypedefPull($d); - ParseTypedefPrint($d); - ParseTypedefNdrSize($d); - } + my $needed = shift; + + # Typedefs + foreach my $d (@{$interface->{TYPEDEFS}}) { + ($needed->{"push_$d->{NAME}"}) && ParseTypedefPush($d); + ($needed->{"pull_$d->{NAME}"}) && ParseTypedefPull($d); + ($needed->{"print_$d->{NAME}"}) && ParseTypedefPrint($d); + + # Make sure we don't generate a function twice... + $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} = + $needed->{"print_$d->{NAME}"} = 0; + + ($needed->{"ndr_size_$d->{NAME}"}) && ParseTypedefNdrSize($d); } - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { - ParseFunctionPush($d); - ParseFunctionPull($d); - ParseFunctionPrint($d); - } + # Functions + foreach my $d (@{$interface->{FUNCTIONS}}) { + ($needed->{"push_$d->{NAME}"}) && ParseFunctionPush($d); + ($needed->{"pull_$d->{NAME}"}) && ParseFunctionPull($d); + ($needed->{"print_$d->{NAME}"}) && ParseFunctionPrint($d); + + # Make sure we don't generate a function twice... + $needed->{"push_$d->{NAME}"} = $needed->{"pull_$d->{NAME}"} = + $needed->{"print_$d->{NAME}"} = 0; } FunctionTable($interface); @@ -2123,11 +2188,7 @@ sub RegistrationFunction($$) foreach my $interface (@{$idl}) { next if $interface->{TYPE} ne "INTERFACE"; - my $data = $interface->{INHERITED_DATA}; - my $count = 0; - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { $count++; } - } + my $count = ($#{$interface->{FUNCTIONS}}+1); next if ($count == 0); @@ -2143,92 +2204,108 @@ sub RegistrationFunction($$) pidl ""; } -sub CheckPointerTypes($$) +##################################################################### +# parse a parsed IDL structure back into an IDL file +sub Parse($$) { - my $s = shift; - my $default = shift; + my($ndr) = shift; + my($filename) = shift; - foreach my $e (@{$s->{ELEMENTS}}) { - if ($e->{POINTERS}) { - if (not defined(Ndr::pointer_type($e))) { - $e->{PROPERTIES}->{$default} = 1; - } + $tabs = ""; + my $h_filename = $filename; + $res = ""; - if (Ndr::pointer_type($e) eq "ptr") { - print "Warning: ptr is not supported by pidl yet\n"; - } - } + if ($h_filename =~ /(.*)\.c/) { + $h_filename = "$1.h"; } -} -sub LoadInterface($) -{ - my $x = shift; + pidl "/* parser auto-generated by pidl */"; + pidl ""; + pidl "#include \"includes.h\""; + pidl "#include \"$h_filename\""; + pidl ""; + + my %needed = (); - if (not util::has_property($x, "pointer_default")) { - # MIDL defaults to "ptr" in DCE compatible mode (/osf) - # and "unique" in Microsoft Extensions mode (default) - $x->{PROPERTIES}->{pointer_default} = "unique"; + foreach my $x (@{$ndr}) { + ($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed); } - foreach my $d (@{$x->{DATA}}) { - if (($d->{TYPE} eq "DECLARE") or ($d->{TYPE} eq "TYPEDEF")) { - if ($d->{DATA}->{TYPE} eq "STRUCT" or $d->{DATA}->{TYPE} eq "UNION") { - CheckPointerTypes($d->{DATA}, $x->{PROPERTIES}->{pointer_default}); - } + foreach my $x (@{$ndr}) { + ($x->{TYPE} eq "INTERFACE") && ParseInterface($x, \%needed); + } - if (defined($d->{PROPERTIES}) && !defined($d->{DATA}->{PROPERTIES})) { - $d->{DATA}->{PROPERTIES} = $d->{PROPERTIES}; - } + RegistrationFunction($ndr, $filename); + + return $res; +} + +sub NeededFunction($$) +{ + my $fn = shift; + my $needed = shift; + $needed->{"pull_$fn->{NAME}"} = 1; + $needed->{"push_$fn->{NAME}"} = 1; + $needed->{"print_$fn->{NAME}"} = 1; + foreach my $e (@{$fn->{ELEMENTS}}) { + $e->{PARENT} = $fn; + unless(defined($needed->{"pull_$e->{TYPE}"})) { + $needed->{"pull_$e->{TYPE}"} = 1; } - if ($d->{TYPE} eq "FUNCTION") { - CheckPointerTypes($d, - $x->{PROPERTIES}->{pointer_default} # MIDL defaults to "ref" - ); + unless(defined($needed->{"push_$e->{TYPE}"})) { + $needed->{"push_$e->{TYPE}"} = 1; + } + unless(defined($needed->{"print_$e->{TYPE}"})) { + $needed->{"print_$e->{TYPE}"} = 1; } } } -sub Load($) +sub NeededTypedef($$) { - my $idl = shift; + my $t = shift; + my $needed = shift; + if (util::has_property($t, "public")) { + $needed->{"pull_$t->{NAME}"} = not util::has_property($t, "nopull"); + $needed->{"push_$t->{NAME}"} = not util::has_property($t, "nopush"); + $needed->{"print_$t->{NAME}"} = not util::has_property($t, "noprint"); + } + + if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") { + if (util::has_property($t, "gensize")) { + $needed->{"ndr_size_$t->{NAME}"} = 1; + } - foreach my $x (@{$idl}) { - LoadInterface($x); + for my $e (@{$t->{DATA}->{ELEMENTS}}) { + $e->{PARENT} = $t->{DATA}; + if ($needed->{"pull_$t->{NAME}"} and + not defined($needed->{"pull_$e->{TYPE}"})) { + $needed->{"pull_$e->{TYPE}"} = 1; + } + if ($needed->{"push_$t->{NAME}"} and + not defined($needed->{"push_$e->{TYPE}"})) { + $needed->{"push_$e->{TYPE}"} = 1; + } + if ($needed->{"print_$t->{NAME}"} and + not defined($needed->{"print_$e->{TYPE}"})) { + $needed->{"print_$e->{TYPE}"} = 1; + } + } } } ##################################################################### -# parse a parsed IDL structure back into an IDL file -sub Parse($$) +# work out what parse functions are needed +sub NeededInterface($$) { - my($idl) = shift; - my($filename) = shift; - my $h_filename = $filename; - $res = ""; - - Load($idl); - - if ($h_filename =~ /(.*)\.c/) { - $h_filename = "$1.h"; + my ($interface) = shift; + my $needed = shift; + foreach my $d (@{$interface->{FUNCTIONS}}) { + NeededFunction($d, $needed); } - - pidl "/* parser auto-generated by pidl */"; - pidl ""; - pidl "#include \"includes.h\""; - pidl "#include \"$h_filename\""; - pidl ""; - - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - needed::BuildNeeded($x); - ParseInterface($x); - } + foreach my $d (reverse @{$interface->{TYPEDEFS}}) { + NeededTypedef($d, $needed); } - - RegistrationFunction($idl, $filename); - - return $res; } 1; diff --git a/source4/build/pidl/needed.pm b/source4/build/pidl/needed.pm deleted file mode 100644 index ae8bf7f078f..00000000000 --- a/source4/build/pidl/needed.pm +++ /dev/null @@ -1,80 +0,0 @@ -################################################### -# Samba4 parser generator for IDL structures -# Copyright tridge@samba.org 2000-2004 -# Copyright jelmer@samba.org 2004 -# released under the GNU GPL - -package needed; - -use strict; - -# the list of needed functions -my %needed; - -sub NeededFunction($) -{ - my $fn = shift; - $needed{"pull_$fn->{NAME}"} = 1; - $needed{"push_$fn->{NAME}"} = 1; - foreach my $e (@{$fn->{ELEMENTS}}) { - $e->{PARENT} = $fn; - $needed{"pull_$e->{TYPE}"} = 1; - $needed{"push_$e->{TYPE}"} = 1; - } -} - -sub NeededTypedef($) -{ - my $t = shift; - if (util::has_property($t, "public")) { - $needed{"pull_$t->{NAME}"} = 1; - $needed{"push_$t->{NAME}"} = 1; - } - - if (util::has_property($t, "nopull")) { - $needed{"pull_$t->{NAME}"} = 0; - } - if (util::has_property($t, "nopush")) { - $needed{"push_$t->{NAME}"} = 0; - } - - if ($t->{DATA}->{TYPE} eq "STRUCT" or $t->{DATA}->{TYPE} eq "UNION") { - if (util::has_property($t, "gensize")) { - $needed{"ndr_size_$t->{NAME}"} = 1; - } - - for my $e (@{$t->{DATA}->{ELEMENTS}}) { - $e->{PARENT} = $t->{DATA}; - if ($needed{"pull_$t->{NAME}"}) { - $needed{"pull_$e->{TYPE}"} = 1; - } - if ($needed{"push_$t->{NAME}"}) { - $needed{"push_$e->{TYPE}"} = 1; - } - } - } -} - -##################################################################### -# work out what parse functions are needed -sub BuildNeeded($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - foreach my $d (@{$data}) { - ($d->{TYPE} eq "FUNCTION") && - NeededFunction($d); - } - foreach my $d (reverse @{$data}) { - ($d->{TYPE} eq "TYPEDEF") && - NeededTypedef($d); - } -} - -sub is_needed($) -{ - my $name = shift; - return $needed{$name}; -} - -1; diff --git a/source4/build/pidl/odl.pm b/source4/build/pidl/odl.pm index 95e81c07ce0..5ed508dc939 100644 --- a/source4/build/pidl/odl.pm +++ b/source4/build/pidl/odl.pm @@ -43,12 +43,29 @@ sub ODL2IDL($) foreach my $x (@{$odl}) { # Add [in] ORPCTHIS *this, [out] ORPCTHAT *that + # and replace interfacepointers with MInterfacePointer # for 'object' interfaces if (util::has_property($x, "object")) { foreach my $e (@{$x->{DATA}}) { ($e->{TYPE} eq "FUNCTION") && FunctionAddObjArgs($e); ReplaceInterfacePointers($e); } + # Object interfaces use ORPC + my @depends = (); + if(util::has_property($x, "depends")) { + @depends = split /,/, $x->{PROPERTIES}->{depends}; + } + push @depends, "orpc"; + $x->{PROPERTIES}->{depends} = join(',',@depends); + } + + if ($x->{BASE}) { + my $base = util::get_interface($odl, $x->{BASE}); + + foreach my $fn (reverse @{$base->{DATA}}) { + next unless ($fn->{TYPE} eq "FUNCTION"); + unshift (@{$x->{DATA}}, $fn); + } } } diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index 2305d9243b2..c7b98a0d34e 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -14,9 +14,9 @@ use lib "$RealBin"; use lib "$RealBin/lib"; use Getopt::Long; use File::Basename; +use idl; use dump; use ndr_client; -use idl; use ndr_header; use ndr_parser; use server; @@ -24,12 +24,14 @@ use dcom_proxy; use dcom_stub; use com_header; use odl; -use eparser; +use eth_parser; +use eth_header; use validator; use typelist; use util; use template; use swig; +use compat; my($opt_help) = 0; my($opt_parse) = 0; @@ -40,7 +42,8 @@ my($opt_template) = 0; my($opt_client) = 0; my($opt_server) = 0; my($opt_parser); -my($opt_eparser) = 0; +my($opt_eth_parser); +my($opt_eth_header); my($opt_keep) = 0; my($opt_swig) = 0; my($opt_dcom_proxy) = 0; @@ -48,6 +51,7 @@ my($opt_com_header) = 0; my($opt_odl) = 0; my($opt_quiet) = 0; my($opt_output); +my($opt_warn_compat) = 0; my $idl_parser = new idl; @@ -71,13 +75,15 @@ sub ShowHelp() --client create a C NDR client --server create server boilerplate --template print a template for a pipe - --eparser create an ethereal parser + --eth-parser create an ethereal parser + --eth-header create an ethereal header file --swig create swig wrapper file --diff run diff on the idl and dumped output --keep keep the .pidl file --odl accept ODL input --dcom-proxy create DCOM proxy (implies --odl) --com-header create header for COM interfaces (implies --odl) + --warn-compat warn about incompatibility with other compilers --quiet be quiet \n"; exit(0); @@ -94,14 +100,16 @@ GetOptions ( 'template' => \$opt_template, 'parser:s' => \$opt_parser, 'client' => \$opt_client, - 'eparser' => \$opt_eparser, + 'eth-parser:s' => \$opt_eth_parser, + 'eth-header:s' => \$opt_eth_header, 'diff' => \$opt_diff, 'odl' => \$opt_odl, 'keep' => \$opt_keep, 'swig' => \$opt_swig, 'dcom-proxy' => \$opt_dcom_proxy, 'com-header' => \$opt_com_header, - 'quiet' => \$opt_quiet + 'quiet' => \$opt_quiet, + 'warn-compat' => \$opt_warn_compat ); if ($opt_help) { @@ -114,6 +122,7 @@ sub process_file($) my $idl_file = shift; my $output; my $pidl; + my $ndr; my $basename = basename($idl_file, ".idl"); @@ -175,21 +184,25 @@ sub process_file($) $opt_odl = 1; } + if ($opt_warn_compat) { + IDLCompat::Check($pidl); + } + if ($opt_odl) { $pidl = ODL::ODL2IDL($pidl); } + if (defined($opt_header) or defined($opt_eth_parser) or defined($opt_eth_header) or $opt_client or $opt_server or defined($opt_parser)) { + $ndr = Ndr::Parse($pidl); +# print util::MyDumper($ndr); + } + if (defined($opt_header)) { my $header = $opt_header; if ($header eq "") { $header = util::ChangeExtension($output, ".h"); } - - util::FileSave($header, NdrHeader::Parse($pidl)); - if ($opt_eparser) { - my($eparserhdr) = dirname($output) . "/packet-dcerpc-$basename.h"; - IdlEParser::RewriteHeader($pidl, $header, $eparserhdr); - } + util::FileSave($header, NdrHeader::Parse($ndr)); if ($opt_swig) { my($filename) = $output; $filename =~ s/\/ndr_/\//; @@ -198,6 +211,15 @@ sub process_file($) } } + if (defined($opt_eth_header)) { + my($eparserhdr) = $opt_eth_header; + if ($eparserhdr eq "") { + $eparserhdr = dirname($output) . "/packet-dcerpc-$basename.h"; + } + + util::FileSave($eparserhdr, EthHeader::Parse($ndr)); + } + if ($opt_client) { my ($client) = util::ChangeExtension($output, "_c.c"); my $res = ""; @@ -250,13 +272,19 @@ $dcom if ($parser eq "") { $parser = util::ChangeExtension($output, ".c"); } - util::FileSave($parser, NdrParser::Parse($pidl, $parser)); - if($opt_eparser) { - my($eparser) = dirname($output) . "/packet-dcerpc-$basename.c"; - IdlEParser::RewriteC($pidl, $parser, $eparser); - } + + util::FileSave($parser, NdrParser::Parse($ndr, $parser)); } + if (defined($opt_eth_parser)) { + my($eparser) = $opt_eth_parser; + if ($eparser eq "") { + $eparser = dirname($output) . "/packet-dcerpc-$basename.c"; + } + util::FileSave($eparser, EthParser::Parse($ndr, $basename, $eparser)); + } + + if ($opt_template) { print IdlTemplate::Parse($pidl); } diff --git a/source4/build/pidl/test.pm b/source4/build/pidl/test.pm index 920db52aa58..5f25d4195c1 100644 --- a/source4/build/pidl/test.pm +++ b/source4/build/pidl/test.pm @@ -87,7 +87,7 @@ sub link_files($$) { my ($exe_name,$objs) = @_; - return system($cc, @ldflags, '-Lbin', '-o', $exe_name, @$objs, '-lrpc', '-ldl', '-lldap'); + return system($cc, @ldflags, '-Lbin', '-lrpc', '-o', $exe_name, @$objs); } sub test_idl($$$$) diff --git a/source4/build/pidl/typelist.pm b/source4/build/pidl/typelist.pm index 8559878a694..f5a06500061 100644 --- a/source4/build/pidl/typelist.pm +++ b/source4/build/pidl/typelist.pm @@ -9,147 +9,6 @@ use strict; my %typedefs = (); -# a list of known scalar types -my $scalars = { - # 0 byte types - "void" => { - C_TYPE => "void", - NDR_ALIGN => 0 - }, - - # 1 byte types - "char" => { - C_TYPE => "char", - NDR_ALIGN => 1 - }, - "int8" => { - C_TYPE => "int8_t", - NDR_ALIGN => 1 - }, - "uint8" => { - C_TYPE => "uint8_t", - NDR_ALIGN => 1 - }, - - # 2 byte types - "int16" => { - C_TYPE => "int16_t", - NDR_ALIGN => 2 - }, - "uint16" => { C_TYPE => "uint16_t", - NDR_ALIGN => 2 - }, - - # 4 byte types - "int32" => { - C_TYPE => "int32_t", - NDR_ALIGN => 4 - }, - "uint32" => { C_TYPE => "uint32_t", - NDR_ALIGN => 4 - }, - - # 8 byte types - "int64" => { - C_TYPE => "int64_t", - NDR_ALIGN => 8 - }, - "hyper" => { - C_TYPE => "uint64_t", - NDR_ALIGN => 8 - }, - "dlong" => { - C_TYPE => "int64_t", - NDR_ALIGN => 4 - }, - "udlong" => { - C_TYPE => "uint64_t", - NDR_ALIGN => 4 - }, - "udlongr" => { - C_TYPE => "uint64_t", - NDR_ALIGN => 4 - }, - - # DATA_BLOB types - "DATA_BLOB" => { - C_TYPE => "DATA_BLOB", - NDR_ALIGN => 4 - }, - - # string types - "string" => { - C_TYPE => "const char *", - NDR_ALIGN => 4 #??? - }, - "string_array" => { - C_TYPE => "const char **", - NDR_ALIGN => 4 #??? - }, - - # time types - "time_t" => { - C_TYPE => "time_t", - NDR_ALIGN => 4 - }, - "NTTIME" => { - C_TYPE => "NTTIME", - NDR_ALIGN => 4 - }, - "NTTIME_1sec" => { - C_TYPE => "NTTIME", - NDR_ALIGN => 4 - }, - "NTTIME_hyper" => { - C_TYPE => "NTTIME", - NDR_ALIGN => 8 - }, - - - # error code types - "WERROR" => { - C_TYPE => "WERROR", - NDR_ALIGN => 4 - }, - "NTSTATUS" => { - C_TYPE => "NTSTATUS", - NDR_ALIGN => 4 - }, - - # special types - "nbt_string" => { - C_TYPE => "const char *", - NDR_ALIGN => 4 #??? - }, - "ipv4address" => { - C_TYPE => "const char *", - NDR_ALIGN => 4 - } -}; - -# map from a IDL type to a C header type -sub mapScalarType($) -{ - my $name = shift; - - # it's a bug when a type is not in the list - # of known scalars or has no mapping - return $scalars->{$name}{C_TYPE} if defined($scalars->{$name}) and defined($scalars->{$name}{C_TYPE}); - - die("Unknown scalar type $name"); -} - -sub getScalarAlignment($) -{ - my $name = shift; - - # it's a bug when a type is not in the list - # of known scalars or has no mapping - return $scalars->{$name}{NDR_ALIGN} if defined($scalars->{$name}) and defined($scalars->{$name}{NDR_ALIGN}); - - die("Unknown scalar type $name"); -} - sub addType($) { my $t = shift; @@ -159,7 +18,7 @@ sub addType($) sub getType($) { my $t = shift; - return undef unless(defined($typedefs{$t})); + return undef if not hasType($t); return $typedefs{$t}; } @@ -179,9 +38,17 @@ sub hasType($) return 0; } -sub RegisterScalars() +sub RegisterPrimitives() { - foreach my $k (keys %{$scalars}) { + my @primitives = ( + "char", "int8", "uint8", "short", "wchar_t", + "int16", "uint16", "long", "int32", "uint32", + "dlong", "udlong", "udlongr", "NTTIME", "NTTIME_1sec", + "time_t", "DATA_BLOB", "error_status_t", "WERROR", + "NTSTATUS", "boolean32", "unsigned32", "ipv4address", + "hyper", "NTTIME_hyper"); + + foreach my $k (@primitives) { $typedefs{$k} = { NAME => $k, TYPE => "TYPEDEF", @@ -218,25 +85,66 @@ sub bitmap_type_fn($) return "uint32"; } +# provide mappings between IDL base types and types in our headers +my %scalar_type_mappings = + ( + "int8" => "int8_t", + "uint8" => "uint8_t", + "short" => "int16_t", + "wchar_t" => "uint16_t", + "int16" => "int16_t", + "uint16" => "uint16_t", + "int32" => "int32_t", + "uint32" => "uint32_t", + "int64" => "int64_t", + "dlong" => "int64_t", + "udlong" => "uint64_t", + "udlongr" => "uint64_t", + "hyper" => "uint64_t", + "NTTIME" => "NTTIME", + "NTTIME_1sec" => "NTTIME", + "time_t" => "time_t", + "NTTIME_hyper" => "NTTIME", + "NTSTATUS" => "NTSTATUS", + "WERROR" => "WERROR", + "DATA_BLOB" => "DATA_BLOB", + "ipv4address" => "const char *", + "nbt_string" => "const char *" + ); + +# map from a IDL type to a C header type +sub mapScalarType($) +{ + my $name = shift; + die("Undef passed to mapScalarType") unless defined($name); + if (defined($scalar_type_mappings{$name})) { + return $scalar_type_mappings{$name}; + } + die("Tried to map non-scalar type $name"); +} + sub mapType($) { - my $e = shift; + my $t = shift; + die("Undef passed to mapType") unless defined($t); my $dt; - if ($e->{TYPE} eq "ENUM" or $e->{TYPE} eq "BITMAP") { - $dt = getType($e->{PARENT}->{NAME}); - } - - unless ($dt or $dt = getType($e->{TYPE})) { + return "void" if ($t eq "void"); + return "const char *" if ($t =~ "string"); + + unless ($dt or ($dt = getType($t))) { # Best guess - return "struct $e->{TYPE}"; + return "struct $t"; } - return mapScalarType($e->{TYPE}) if ($dt->{DATA}->{TYPE} eq "SCALAR"); + return mapScalarType($t) if ($dt->{DATA}->{TYPE} eq "SCALAR"); return "enum $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "ENUM"); return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "STRUCT"); return "struct $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "INTERFACE"); return "union $dt->{NAME}" if ($dt->{DATA}->{TYPE} eq "UNION"); - return mapScalarType(bitmap_type_fn($dt->{DATA})) if ($dt->{DATA}->{TYPE} eq "BITMAP"); + + if ($dt->{DATA}->{TYPE} eq "BITMAP") { + return mapScalarType(bitmap_type_fn($dt->{DATA})); + } die("Unknown type $dt->{DATA}->{TYPE}"); } @@ -258,11 +166,12 @@ sub LoadIdl($) foreach my $y (@{$x->{DATA}}) { addType($y) if ( $y->{TYPE} eq "TYPEDEF" - or $y->{TYPE} eq "DECLARE"); + or $y->{TYPE} eq "DECLARE"); } } } -RegisterScalars(); +RegisterPrimitives(); + 1; diff --git a/source4/build/pidl/validator.pm b/source4/build/pidl/validator.pm index 42e9f699dc3..bb86fcca50a 100644 --- a/source4/build/pidl/validator.pm +++ b/source4/build/pidl/validator.pm @@ -10,11 +10,11 @@ use strict; ##################################################################### # signal a fatal validation error -sub fatal($) +sub fatal($$) { + my $pos = shift; my $s = shift; - print "$s\n"; - die "IDL is not valid\n"; + die("$pos->{FILE}:$pos->{LINE}:$s\n"); } sub el_name($) @@ -42,6 +42,7 @@ my %property_list = ( "uuid" => {}, "endpoint" => {}, "pointer_default" => {}, + "pointer_default_top" => {}, "depends" => {}, "authservice" => {}, @@ -103,7 +104,6 @@ my %property_list = ( "range" => {}, "size_is" => {}, "length_is" => {}, - "length_of" => {}, # what is that? --metze ); ##################################################################### @@ -116,7 +116,7 @@ sub ValidProperties($) foreach my $key (keys %{$e->{PROPERTIES}}) { if (not defined $property_list{$key}) { - fatal(el_name($e) . ": unknown property '$key'\n"); + fatal($e, el_name($e) . ": unknown property '$key'\n"); } } } @@ -130,7 +130,7 @@ sub ValidElement($) ValidProperties($e); if (util::has_property($e, "ptr")) { - fatal(el_name($e) . " : pidl does not support full NDR pointers yet\n"); + fatal($e, el_name($e) . " : pidl does not support full NDR pointers yet\n"); } # Check whether switches are used correctly. @@ -139,7 +139,7 @@ sub ValidElement($) my $type = typelist::getType($e->{TYPE}); if (defined($type) and $type->{DATA}->{TYPE} ne "UNION") { - fatal(el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}"); + fatal($e, el_name($e) . ": switch_is() used on non-union type $e->{TYPE} which is a $type->{DATA}->{TYPE}"); } if (!util::has_property($type, "nodiscriminant") and defined($e2)) { @@ -152,24 +152,16 @@ sub ValidElement($) } } - if (util::has_property($e, "size_is") and not defined ($e->{ARRAY_LEN})) { - fatal(el_name($e) . " : size_is() on non-array element"); - } - - if (util::has_property($e, "length_is") and not defined ($e->{ARRAY_LEN})) { - fatal(el_name($e) . " : length_is() on non-array element"); - } - if (defined (util::has_property($e, "subcontext_size")) and not defined(util::has_property($e, "subcontext"))) { - fatal(el_name($e) . " : subcontext_size() on non-subcontext element"); + fatal($e, el_name($e) . " : subcontext_size() on non-subcontext element"); } if (defined (util::has_property($e, "compression")) and not defined(util::has_property($e, "subcontext"))) { - fatal(el_name($e) . " : compression() on non-subcontext element"); + fatal($e, el_name($e) . " : compression() on non-subcontext element"); } if (defined (util::has_property($e, "obfuscation")) and not defined(util::has_property($e, "subcontext"))) { - fatal(el_name($e) . " : obfuscation() on non-subcontext element"); + fatal($e, el_name($e) . " : obfuscation() on non-subcontext element"); } if (!$e->{POINTERS} && ( @@ -177,7 +169,7 @@ sub ValidElement($) util::has_property($e, "unique") or util::has_property($e, "relative") or util::has_property($e, "ref"))) { - fatal(el_name($e) . " : pointer properties on non-pointer element\n"); + fatal($e, el_name($e) . " : pointer properties on non-pointer element\n"); } } @@ -204,7 +196,7 @@ sub ValidUnion($) ValidProperties($union); if (util::has_property($union->{PARENT}, "nodiscriminant") and util::has_property($union->{PARENT}, "switch_type")) { - fatal($union->{PARENT}->{NAME} . ": switch_type() on union without discriminant"); + fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type() on union without discriminant"); } foreach my $e (@{$union->{ELEMENTS}}) { @@ -212,16 +204,16 @@ sub ValidUnion($) if (defined($e->{PROPERTIES}->{default}) and defined($e->{PROPERTIES}->{case})) { - fatal "Union member $e->{NAME} can not have both default and case properties!\n"; + fatal $e, "Union member $e->{NAME} can not have both default and case properties!\n"; } unless (defined ($e->{PROPERTIES}->{default}) or defined ($e->{PROPERTIES}->{case})) { - fatal "Union member $e->{NAME} must have default or case property\n"; + fatal $e, "Union member $e->{NAME} must have default or case property\n"; } if (util::has_property($e, "ref")) { - fatal(el_name($e) . " : embedded ref pointers are not supported yet\n"); + fatal($e, el_name($e) . " : embedded ref pointers are not supported yet\n"); } @@ -262,7 +254,7 @@ sub ValidFunction($) foreach my $e (@{$fn->{ELEMENTS}}) { $e->{PARENT} = $fn; if (util::has_property($e, "ref") && !$e->{POINTERS}) { - fatal "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n"; + fatal $e, "[ref] variables must be pointers ($fn->{NAME}/$e->{NAME})\n"; } ValidElement($e); } @@ -279,18 +271,18 @@ sub ValidInterface($) if (util::has_property($interface, "pointer_default") && $interface->{PROPERTIES}->{pointer_default} eq "ptr") { - fatal "Full pointers are not supported yet\n"; + fatal $interface, "Full pointers are not supported yet\n"; } if (util::has_property($interface, "object")) { if (util::has_property($interface, "version") && $interface->{PROPERTIES}->{version} != 0) { - fatal "Object interfaces must have version 0.0 ($interface->{NAME})\n"; + fatal $interface, "Object interfaces must have version 0.0 ($interface->{NAME})\n"; } if (!defined($interface->{BASE}) && not ($interface->{NAME} eq "IUnknown")) { - fatal "Object interfaces must all derive from IUnknown ($interface->{NAME})\n"; + fatal $interface, "Object interfaces must all derive from IUnknown ($interface->{NAME})\n"; } } diff --git a/source4/librpc/idl/atsvc.idl b/source4/librpc/idl/atsvc.idl index bf7743a37ca..a11a2cf7464 100644 --- a/source4/librpc/idl/atsvc.idl +++ b/source4/librpc/idl/atsvc.idl @@ -7,6 +7,7 @@ [ uuid("1ff70682-0a51-30e8-076d-740be8cee98b"), version(1.0), pointer_default(unique), + pointer_default_top(unique), helpstring("Queue/List/Remove jobs for later execution"), endpoint("ncacn_np:[\\pipe\\atsvc]", "ncalrpc:") ] interface atsvc @@ -46,7 +47,7 @@ typedef struct { uint32 entries_read; - [size_is(entries_read)] atsvc_JobEnumInfo *first_entry[]; + [size_is(entries_read)] atsvc_JobEnumInfo *first_entry; } atsvc_enum_ctr; /******************/ diff --git a/source4/librpc/idl/audiosrv.idl b/source4/librpc/idl/audiosrv.idl index 9b9399ffee2..2b27b757dd3 100644 --- a/source4/librpc/idl/audiosrv.idl +++ b/source4/librpc/idl/audiosrv.idl @@ -2,6 +2,7 @@ uuid("0a74ef1c-41a4-4e06-83ae-dc74fb1cdd53"), version(1.0), pointer_default(unique), + pointer_default_top(unique), helpstring("Audio Server") ] interface audiosrv { diff --git a/source4/librpc/idl/browser.idl b/source4/librpc/idl/browser.idl index 5cc2475119f..b2008c7321c 100644 --- a/source4/librpc/idl/browser.idl +++ b/source4/librpc/idl/browser.idl @@ -3,6 +3,7 @@ version(0.0), helpstring("Browsing"), pointer_default(unique), + pointer_default_top(unique), endpoint("ncacn_np:[\\pipe\\browser]", "ncacn_ip_tcp:", "ncalrpc:") ] interface browser diff --git a/source4/librpc/idl/dbgidl.idl b/source4/librpc/idl/dbgidl.idl index 8d2133d81f2..1c21637b74e 100644 --- a/source4/librpc/idl/dbgidl.idl +++ b/source4/librpc/idl/dbgidl.idl @@ -1,7 +1,7 @@ [ uuid("1d55b526-c137-46c5-ab79-638f2a68e869"), version(1.0), - pointer_default(unique), + pointer_default(unique), helpstring("Remote IDL debugger") ] interface dbgidl { diff --git a/source4/librpc/idl/dcom.idl b/source4/librpc/idl/dcom.idl index 3e4d9d0c2cc..f8db720817b 100644 --- a/source4/librpc/idl/dcom.idl +++ b/source4/librpc/idl/dcom.idl @@ -10,6 +10,7 @@ [ uuid("18f70770-8e64-11cf-9af1-0020af6e72f4"), pointer_default(unique), + pointer_default_top(unique), version(0.0) ] interface dcom_Unknown { @@ -22,6 +23,7 @@ object, uuid("00000000-0000-0000-C000-000000000046"), pointer_default(unique), + pointer_default_top(unique), helpstring("Base interface for all COM interfaces") ] interface IUnknown @@ -46,6 +48,7 @@ interface IUnknown [ object, uuid("00000001-0000-0000-C000-000000000046"), + pointer_default_top(unique), pointer_default(unique) ] interface IClassFactory : IUnknown { @@ -72,6 +75,7 @@ interface IUnknown [ uuid("00000131-0000-0000-C000-000000000046"), object, + pointer_default_top(unique), pointer_default(unique), helpstring("Remote version of IUnknown") ] @@ -113,6 +117,7 @@ interface IRemUnknown : IUnknown [ uuid("00000140-0000-0000-c000-000000000046"), + pointer_default_top(unique), pointer_default(unique), object ] interface IClassActivator : IUnknown @@ -126,6 +131,7 @@ interface IRemUnknown : IUnknown [ uuid("00000136-0000-0000-c000-000000000046"), + pointer_default_top(unique), pointer_default(unique), object ] interface ISCMLocalActivator : IClassActivator @@ -135,6 +141,7 @@ interface IRemUnknown : IUnknown [ pointer_default(unique), + pointer_default_top(unique), uuid("c6f3ee72-ce7e-11d1-b71e-00c04fc3111a") ] interface IMachineLocalActivator { @@ -143,6 +150,7 @@ interface IRemUnknown : IUnknown [ pointer_default(unique), + pointer_default_top(unique), uuid("e60c73e6-88f9-11cf-9af1-0020af6e72f4") ] interface ILocalObjectExporter { @@ -154,6 +162,7 @@ interface IRemUnknown : IUnknown [ uuid("000001a0-0000-0000-c000-000000000046"), pointer_default(unique), + pointer_default_top(unique), object ] interface ISystemActivator : IClassActivator @@ -173,6 +182,7 @@ interface IRemUnknown : IUnknown [ object, pointer_default(unique), + pointer_default_top(unique), uuid("00000143-0000-0000-C000-000000000046") ] @@ -188,8 +198,9 @@ interface IRemUnknown2 : IRemUnknown } [ -object, + object, pointer_default(unique), + pointer_default_top(unique), uuid("00000136-0000-0000-C000-000000000046") ] interface ISCMActivator : IClassActivator { @@ -199,6 +210,7 @@ object, [ object, pointer_default(unique), + pointer_default_top(unique), uuid("00020400-0000-0000-C000-000000000046") ] interface IDispatch : IUnknown { @@ -267,6 +279,7 @@ object, uuid(DA23F6DB-6F45-466C-9EED-0B65286F2D78), helpstring("ICoffeeMachine Interface"), pointer_default(unique), + pointer_default_top(unique), object ] interface ICoffeeMachine : IUnknown { @@ -284,6 +297,7 @@ object, [ object, pointer_default(unique), + pointer_default_top(unique), uuid("0000000C-0000-0000-C000-000000000046"), helpstring("Stream") ] diff --git a/source4/librpc/idl/dfs.idl b/source4/librpc/idl/dfs.idl index d418b8b5468..8bbb3e02ff1 100644 --- a/source4/librpc/idl/dfs.idl +++ b/source4/librpc/idl/dfs.idl @@ -7,6 +7,7 @@ [ uuid("4fc742e0-4a10-11cf-8273-00aa004ae673"), version(3.0), pointer_default(unique), + pointer_default_top(unique), helpstring("Settings for Microsoft Distributed File System") ] interface netdfs { diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index e682de452f9..c7d1a5fb48a 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -4,6 +4,7 @@ uuid("38578646-4566-4564-2244-275796345667"), version(0.0), pointer_default(unique), + pointer_default_top(unique), helpstring("Active Directory Replication LDAP Blobs"), depends(drsuapi) ] diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 16b8da82b89..737cd3b131f 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -7,6 +7,7 @@ authservice("ldap"), helpstring("Active Directory Replication"), pointer_default(unique), + pointer_default_top(unique), depends(security) ] interface drsuapi @@ -554,7 +555,7 @@ interface drsuapi [size_is(count)] drsuapi_DsReplicaMetaData meta_data[]; } drsuapi_DsReplicaMetaDataCtr; - typedef [noprint] struct { + typedef [public,noprint] struct { drsuapi_DsReplicaObjectListItemEx *next_object; drsuapi_DsReplicaObject object; uint32 unknown1; @@ -908,7 +909,7 @@ interface drsuapi /*****************/ /* Function 0x11 */ - typedef [noprint] struct { + typedef [public,noprint] struct { drsuapi_DsReplicaObjectListItem *next_object; drsuapi_DsReplicaObject object; } drsuapi_DsReplicaObjectListItem; diff --git a/source4/librpc/idl/dsbackup.idl b/source4/librpc/idl/dsbackup.idl index c4f3d3cded5..5ba5ffe9592 100644 --- a/source4/librpc/idl/dsbackup.idl +++ b/source4/librpc/idl/dsbackup.idl @@ -1,7 +1,8 @@ [ uuid("ecec0d70-a603-11d0-96b1-00a0c91ece30"), version(1.0), - pointer_default(unique), + pointer_default(unique), + pointer_default_top(unique), helpstring("Backup support for Active Directory") ] interface ad_backup { @@ -19,7 +20,7 @@ [ uuid("16e0cf3a-a604-11d0-96b1-00a0c91ece30"), version(1.0), - pointer_default(unique), + pointer_default(unique), helpstring("Restoring Active Directory backups") ] interface ad_restore { diff --git a/source4/librpc/idl/dssetup.idl b/source4/librpc/idl/dssetup.idl index 098a1489049..f10027466b7 100644 --- a/source4/librpc/idl/dssetup.idl +++ b/source4/librpc/idl/dssetup.idl @@ -9,6 +9,7 @@ version(0.0), endpoint("ncacn_np:[\\pipe\\lsarpc]", "ncacn_np:[\\pipe\\lsass]", "ncacn_ip_tcp:", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), helpstring("Active Directory Setup") ] interface dssetup { diff --git a/source4/librpc/idl/echo.idl b/source4/librpc/idl/echo.idl index d3d0305cb6d..deb7c95bac5 100644 --- a/source4/librpc/idl/echo.idl +++ b/source4/librpc/idl/echo.idl @@ -5,6 +5,7 @@ uuid("60a15ec5-4de8-11d7-a637-005056a20182"), endpoint("ncacn_np:[\\pipe\\rpcecho]", "ncacn_ip_tcp:", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), version(1.0), helpstring("Simple echo pipe") ] diff --git a/source4/librpc/idl/efs.idl b/source4/librpc/idl/efs.idl index 9a97223e6ad..8ff34c92b96 100644 --- a/source4/librpc/idl/efs.idl +++ b/source4/librpc/idl/efs.idl @@ -1,7 +1,7 @@ [ uuid("c681d488-d850-11d0-8c52-00c04fd90f7e"), version(1.0), - pointer_default(unique), + pointer_default(unique), helpstring("Encrypted File System") ] interface efs { diff --git a/source4/librpc/idl/epmapper.idl b/source4/librpc/idl/epmapper.idl index 7881e47fe67..766b867a356 100644 --- a/source4/librpc/idl/epmapper.idl +++ b/source4/librpc/idl/epmapper.idl @@ -14,6 +14,7 @@ http://www.opengroup.org/onlinepubs/9629399/chap6.htm#tagcjh_11_02_03_01: bindin endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", "ncalrpc:[EPMAPPER]"), helpstring("EndPoint Mapper"), + pointer_default_top(unique), pointer_default(unique) ] interface epmapper @@ -202,7 +203,7 @@ interface epmapper typedef struct { [subcontext(2)] epm_lhs lhs; - [subcontext(2),switch_is(lhs.protocol)] epm_rhs rhs; + [subcontext(2),switch_is(r->lhs.protocol)] epm_rhs rhs; } epm_floor; /* note that the NDR_NOALIGN flag is inherited by all nested diff --git a/source4/librpc/idl/eventlog.idl b/source4/librpc/idl/eventlog.idl index 14923e390fe..8b4963c1e1f 100644 --- a/source4/librpc/idl/eventlog.idl +++ b/source4/librpc/idl/eventlog.idl @@ -7,6 +7,7 @@ version(0.0), depends(security), pointer_default(unique), + pointer_default_top(unique), helpstring("Event Logger") ] interface eventlog { diff --git a/source4/librpc/idl/exchange.idl b/source4/librpc/idl/exchange.idl index 15b31794fae..f8af3c77c62 100644 --- a/source4/librpc/idl/exchange.idl +++ b/source4/librpc/idl/exchange.idl @@ -192,6 +192,7 @@ System Attendant Private Interface [ uuid("a4f1db00-ca47-1067-b31f-00dd010662da"), pointer_default(unique), + pointer_default_top(unique), version(0.81), helpstring("Exchange 5.5 EMSMDB") ] interface exchange_emsmdb diff --git a/source4/librpc/idl/initshutdown.idl b/source4/librpc/idl/initshutdown.idl index e84edb47b89..f4f1f93f5ed 100644 --- a/source4/librpc/idl/initshutdown.idl +++ b/source4/librpc/idl/initshutdown.idl @@ -9,6 +9,7 @@ version(1.0), endpoint("ncacn_np:[\\pipe\\InitShutdown]"), pointer_default(unique), + pointer_default_top(unique), helpstring("Init shutdown service") ] interface initshutdown { diff --git a/source4/librpc/idl/krb5pac.idl b/source4/librpc/idl/krb5pac.idl index a8a0ca06974..16524197c57 100644 --- a/source4/librpc/idl/krb5pac.idl +++ b/source4/librpc/idl/krb5pac.idl @@ -8,6 +8,7 @@ uuid("46746756-7567-7567-5677-756756756756"), version(0.0), pointer_default(unique), + pointer_default_top(unique), depends(security,netlogon) ] interface krb5pac diff --git a/source4/librpc/idl/lsa.idl b/source4/librpc/idl/lsa.idl index 68adcf1d9dc..3737d4c0eac 100644 --- a/source4/librpc/idl/lsa.idl +++ b/source4/librpc/idl/lsa.idl @@ -8,6 +8,7 @@ version(0.0), endpoint("ncacn_np:[\\pipe\\lsarpc]","ncacn_np:[\\pipe\\lsass]", "ncacn_ip_tcp:", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), helpstring("Local Security Authority"), depends(security) ] interface lsarpc diff --git a/source4/librpc/idl/mgmt.idl b/source4/librpc/idl/mgmt.idl index b649e0db29a..2c4910e677e 100644 --- a/source4/librpc/idl/mgmt.idl +++ b/source4/librpc/idl/mgmt.idl @@ -8,6 +8,7 @@ uuid("afa8bd80-7d8a-11c9-bef4-08002b102989"), version(1.0), pointer_default(unique), + pointer_default_top(unique), endpoint("ncalrpc:[EPMAPPER]", "ncacn_ip_tcp:[135]", "ncacn_np:[\\pipe\\epmapper]"), helpstring("DCE/RPC Remote Management") ] diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index 371084bc652..95e4abd9747 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -66,7 +66,7 @@ /* the ndr parser for nbt_name is separately defined in nbtname.c (along with the parsers for nbt_string) */ - typedef [nopull,nopush] struct { + typedef [public,nopull,nopush] struct { string name; string scope; nbt_name_type type; diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index 68a5078aae5..9d9d2dd98f6 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -11,6 +11,7 @@ version(1.0), endpoint("ncacn_np:[\\pipe\\netlogon]","ncacn_ip_tcp:","ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), depends(lsa,samr) ] diff --git a/source4/librpc/idl/oxidresolver.idl b/source4/librpc/idl/oxidresolver.idl index 3b6d4efd283..ad38fce9a54 100644 --- a/source4/librpc/idl/oxidresolver.idl +++ b/source4/librpc/idl/oxidresolver.idl @@ -17,6 +17,7 @@ helpstring("Object Exporter ID Resolver"), endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), depends(dcom) ] interface IOXIDResolver diff --git a/source4/librpc/idl/policyagent.idl b/source4/librpc/idl/policyagent.idl index 6da5cbb8f46..295b70a2a1d 100644 --- a/source4/librpc/idl/policyagent.idl +++ b/source4/librpc/idl/policyagent.idl @@ -3,7 +3,7 @@ [ uuid("d335b8f6-cb31-11d0-b0f9-006097ba4e54"), version(1.5), - pointer_default(unique), + pointer_default(unique), helpstring("IPSec Policy Agent") ] interface policyagent { diff --git a/source4/librpc/idl/remact.idl b/source4/librpc/idl/remact.idl index 7a879e717fe..232ae9fffcb 100644 --- a/source4/librpc/idl/remact.idl +++ b/source4/librpc/idl/remact.idl @@ -8,6 +8,7 @@ [ uuid("4d9f4ab8-7d1c-11cf-861e-0020af6e7c57"), pointer_default(unique), + pointer_default_top(unique), endpoint("ncalrpc:", "ncacn_ip_tcp:[135]", "ncacn_np:[\\pipe\\epmapper]"), depends(dcom) ] diff --git a/source4/librpc/idl/rot.idl b/source4/librpc/idl/rot.idl index fd9fd424676..8ae5502bdc1 100644 --- a/source4/librpc/idl/rot.idl +++ b/source4/librpc/idl/rot.idl @@ -3,7 +3,8 @@ [ uuid("b9e79e60-3d52-11ce-aaa1-00006901293f"), version(0.2), - pointer_default(unique), + pointer_default(unique), + pointer_default_top(unique), depends(orpc), endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", "ncalrpc:[EPMAPPER]") diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl index 3cf2aeaf7eb..59de0d1b4a3 100644 --- a/source4/librpc/idl/samr.idl +++ b/source4/librpc/idl/samr.idl @@ -12,6 +12,7 @@ version(1.0), endpoint("ncacn_np:[\\pipe\\samr]","ncacn_ip_tcp:", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), depends(lsa,security) ] interface samr { @@ -336,7 +337,7 @@ typedef struct { uint32 count; - [size_is(count)] samr_String *names[]; + [size_is(count)] samr_String *names; } samr_Strings; NTSTATUS samr_LookupRids( diff --git a/source4/librpc/idl/spoolss.idl b/source4/librpc/idl/spoolss.idl index 5d4e957f071..0693d3c3c48 100644 --- a/source4/librpc/idl/spoolss.idl +++ b/source4/librpc/idl/spoolss.idl @@ -8,6 +8,7 @@ version(1.0), endpoint("ncacn_np:[\\pipe\\spoolss]"), pointer_default(unique), + pointer_default_top(unique), helpstring("Spooler SubSystem"), depends(security) ] interface spoolss diff --git a/source4/librpc/idl/srvsvc.idl b/source4/librpc/idl/srvsvc.idl index e986ea16ede..3661bfb9cc2 100644 --- a/source4/librpc/idl/srvsvc.idl +++ b/source4/librpc/idl/srvsvc.idl @@ -8,6 +8,7 @@ version(3.0), endpoint("ncacn_np:[\\pipe\\srvsvc]", "ncacn_ip_tcp:", "ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), helpstring("Server Service"), depends(security,svcctl) ] interface srvsvc diff --git a/source4/librpc/idl/svcctl.idl b/source4/librpc/idl/svcctl.idl index 544d5d83f32..3ffe41c109b 100644 --- a/source4/librpc/idl/svcctl.idl +++ b/source4/librpc/idl/svcctl.idl @@ -7,6 +7,7 @@ [ uuid("367abb81-9844-35f1-ad32-98f038001003"), version(2.0), pointer_default(unique), + pointer_default_top(unique), endpoint("ncacn_np:[\\pipe\\svcctl]", "ncalrpc:"), helpstring("Service Control") ] interface svcctl @@ -233,7 +234,7 @@ WERROR svcctl_StartServiceW( [in,ref] policy_handle *handle, [in] uint32 NumArgs, - [in,length_of(NumArgs)] unistr *Arguments); + [in,length_is(NumArgs)] unistr *Arguments); /*****************/ /* Function 0x14 */ @@ -343,7 +344,7 @@ WERROR svcctl_StartServiceA( [in,ref] policy_handle *handle, [in] uint32 NumArgs, - [in,length_of(NumArgs)] unistr *Arguments); + [in,length_is(NumArgs)] unistr *Arguments); /*****************/ /* Function 0x20 */ diff --git a/source4/librpc/idl/trkwks.idl b/source4/librpc/idl/trkwks.idl index 8f8c759d177..7f11af189ba 100644 --- a/source4/librpc/idl/trkwks.idl +++ b/source4/librpc/idl/trkwks.idl @@ -5,7 +5,7 @@ [ uuid("300f3532-38cc-11d0-a3f0-0020af6b0add"), version(1.2), - pointer_default(unique), + pointer_default(unique), helpstring("Distributed Key Tracking Service") ] interface trkwks diff --git a/source4/librpc/idl/winreg.idl b/source4/librpc/idl/winreg.idl index 47531d47102..31f293267a1 100644 --- a/source4/librpc/idl/winreg.idl +++ b/source4/librpc/idl/winreg.idl @@ -9,6 +9,7 @@ version(1.0), endpoint("ncacn_np:[\\pipe\\winreg]","ncacn_ip_tcp:","ncalrpc:"), pointer_default(unique), + pointer_default_top(unique), helpstring("Remote Registry Service"), depends(lsa,initshutdown) ] interface winreg diff --git a/source4/librpc/idl/winsrepl.idl b/source4/librpc/idl/winsrepl.idl index cec82a51066..8bcea421aae 100644 --- a/source4/librpc/idl/winsrepl.idl +++ b/source4/librpc/idl/winsrepl.idl @@ -12,7 +12,8 @@ [ uuid("0-1-2-3-4"), version(0.0), - pointer_default(unique) + pointer_default(unique), + pointer_default_top(unique) ] interface wrepl { diff --git a/source4/librpc/idl/wkssvc.idl b/source4/librpc/idl/wkssvc.idl index 0d018db4b93..a948f53dbf2 100644 --- a/source4/librpc/idl/wkssvc.idl +++ b/source4/librpc/idl/wkssvc.idl @@ -7,6 +7,7 @@ [ uuid("6bffd098-a112-3610-9833-46c3f87e345a"), version(1.0), pointer_default(unique), + pointer_default_top(unique), helpstring("Workstation Service"), depends(srvsvc) ] interface wkssvc diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index ddf9664b9b5..892f3c27ca1 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -147,7 +147,6 @@ struct ndr_print { #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN) enum ndr_err_code { - NDR_ERR_CONFORMANT_SIZE, NDR_ERR_ARRAY_SIZE, NDR_ERR_BAD_SWITCH, NDR_ERR_OFFSET, diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c index 82967268665..dfd21018d2e 100644 --- a/source4/librpc/ndr/ndr.c +++ b/source4/librpc/ndr/ndr.c @@ -182,120 +182,6 @@ NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size) return NT_STATUS_OK; } -/* This function does not appear to be used */ - -#if 0 - -/* - set the push offset to 'ofs' -*/ -static NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32_t ofs) -{ - NDR_CHECK(ndr_push_expand(ndr, ofs)); - ndr->offset = ofs; - return NT_STATUS_OK; -} - -#endif - -/* - push a generic array -*/ -NTSTATUS ndr_push_array(struct ndr_push *ndr, int ndr_flags, void *base, - size_t elsize, uint32_t count, - NTSTATUS (*push_fn)(struct ndr_push *, int, void *)) -{ - int i; - char *p = base; - if (!(ndr_flags & NDR_SCALARS)) goto buffers; - for (i=0;idata += ndr->offset; - ndr->offset = 0; - NDR_CHECK(pull_fn(ndr, NDR_SCALARS|NDR_BUFFERS, &base[count * elsize])); - } - - return NT_STATUS_OK; -} - -/* - print a generic array -*/ -void ndr_print_array(struct ndr_print *ndr, const char *name, void *base, - size_t elsize, uint32_t count, - void (*print_fn)(struct ndr_print *, const char *, void *)) -{ - int i; - char *p = base; - ndr->print(ndr, "%s: ARRAY(%d)", name, count); - ndr->depth++; - for (i=0;idepth--; -} - - - void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) { va_list ap; @@ -390,7 +276,7 @@ static NTSTATUS ndr_map_error(enum ndr_err_code err) break; } - /* we should all error codes to different status codes */ + /* we should map all error codes to different status codes */ return NT_STATUS_INVALID_PARAMETER; } @@ -623,7 +509,7 @@ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p) NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size) { uint32_t stored; - NDR_CHECK(ndr_token_retrieve(&ndr->array_size_list, p, &stored)); + stored = ndr_token_peek(&ndr->array_size_list, p); if (stored != size) { return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array size - got %u expected %u\n", @@ -661,7 +547,7 @@ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p) NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length) { uint32_t stored; - NDR_CHECK(ndr_token_retrieve(&ndr->array_length_list, p, &stored)); + stored = ndr_token_peek(&ndr->array_length_list, p); if (stored != length) { return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "Bad array length - got %u expected %u\n", diff --git a/source4/librpc/ndr/ndr_sec.c b/source4/librpc/ndr/ndr_sec.c index 9e4bc526dcf..2e9bf86aac1 100644 --- a/source4/librpc/ndr/ndr_sec.c +++ b/source4/librpc/ndr/ndr_sec.c @@ -37,8 +37,8 @@ NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid * NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &num_auths)); NDR_CHECK(ndr_pull_dom_sid(ndr, ndr_flags, sid)); if (sid->num_auths != num_auths) { - return ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, - "Bad conformant size %u should be %u", + return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, + "Bad array size %u should exceed %u", num_auths, sid->num_auths); } return NT_STATUS_OK; diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 2a7ca8eb176..0194decb4a3 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -1025,6 +1025,7 @@ static NTSTATUS dcerpc_ndr_validate_in(struct dcerpc_connection *c, if (!pull) { return NT_STATUS_NO_MEMORY; } + pull->flags |= LIBNDR_FLAG_REF_ALLOC; status = ndr_pull(pull, NDR_IN, st); if (!NT_STATUS_IS_OK(status)) { @@ -1277,7 +1278,7 @@ NTSTATUS dcerpc_ndr_request_recv(struct rpc_request *req) if (pull->offset != pull->data_size) { DEBUG(0,("Warning! ignoring %d unread bytes in rpc packet!\n", pull->data_size - pull->offset)); - /* we used return NT_STATUS_INFO_LENGTH_MISMATCH here, + /* we used to return NT_STATUS_INFO_LENGTH_MISMATCH here, but it turns out that early versions of NT (specifically NT3.1) add junk onto the end of rpc packets, so if we want to interoperate at all with diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index 52da43a35e4..241986a4b1b 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -756,6 +756,8 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call) pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call); NT_STATUS_HAVE_NO_MEMORY(pull); + pull->flags |= LIBNDR_FLAG_REF_ALLOC; + call->context = context; call->event_ctx = context->conn->srv_conn->event.ctx; call->ndr_pull = pull; diff --git a/source4/utils/ndrdump.c b/source4/utils/ndrdump.c index bcfbb45e60b..eabeaad5374 100644 --- a/source4/utils/ndrdump.c +++ b/source4/utils/ndrdump.c @@ -200,6 +200,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size) blob.length = size; ndr = ndr_pull_init_blob(&blob, mem_ctx); + ndr->flags |= LIBNDR_FLAG_REF_ALLOC; status = f->ndr_pull(ndr, NDR_IN, st); @@ -230,10 +231,7 @@ static char *stdin_load(TALLOC_CTX *mem_ctx, size_t *size) blob.length = size; ndr = ndr_pull_init_blob(&blob, mem_ctx); - - if (flags == NDR_OUT) { - ndr->flags |= LIBNDR_FLAG_REF_ALLOC; - } + ndr->flags |= LIBNDR_FLAG_REF_ALLOC; status = f->ndr_pull(ndr, flags, st); -- 2.34.1