diff options
Diffstat (limited to '')
51 files changed, 1735 insertions, 1163 deletions
diff --git a/tools/pidl/idl.yp b/tools/pidl/idl.yp index 08f982a9..8889632b 100644 --- a/tools/pidl/idl.yp +++ b/tools/pidl/idl.yp @@ -680,12 +680,29 @@ sub parse_file($$) undef $/; my $cpp = $ENV{CPP}; my $options = ""; - if (! defined $cpp) { - if (defined $ENV{CC}) { - $cpp = "$ENV{CC}"; - $options = "-E"; - } else { - $cpp = "cpp"; + if ($^O eq "MSWin32") { + $cpp = "cpp"; + }else{ + if (! defined $cpp) { + if (defined $ENV{CC}) { + $cpp = "$ENV{CC}"; + $options = "-E"; + } else { + # + # If cc is Clang-based don't use cpp, as + # at least some versions of Clang, cpp + # doesn't strip // comments, but cc -E + # does. + # + + my $cc_version = `cc --version`; + if ($cc_version =~ /clang/) { + $cpp = "cc"; + $options = "-E" + } else { + $cpp = "cpp"; + } + } } } my $includes = join('',map { " -I$_" } @$incdirs); diff --git a/tools/pidl/lib/Parse/Pidl.pm b/tools/pidl/lib/Parse/Pidl.pm index 40e36739..e4c39b3d 100644 --- a/tools/pidl/lib/Parse/Pidl.pm +++ b/tools/pidl/lib/Parse/Pidl.pm @@ -12,7 +12,7 @@ require Exporter; @EXPORT_OK = qw(warning error fatal $VERSION); use strict; - +use warnings; use vars qw ( $VERSION ); $VERSION = '0.02'; diff --git a/tools/pidl/lib/Parse/Pidl/CUtil.pm b/tools/pidl/lib/Parse/Pidl/CUtil.pm index 9deb6ee1..ccd8fcc3 100644 --- a/tools/pidl/lib/Parse/Pidl/CUtil.pm +++ b/tools/pidl/lib/Parse/Pidl/CUtil.pm @@ -11,6 +11,7 @@ use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; sub get_pointer_to($) { diff --git a/tools/pidl/lib/Parse/Pidl/Compat.pm b/tools/pidl/lib/Parse/Pidl/Compat.pm index b8abcb88..062a53b8 100644 --- a/tools/pidl/lib/Parse/Pidl/Compat.pm +++ b/tools/pidl/lib/Parse/Pidl/Compat.pm @@ -8,6 +8,7 @@ package Parse::Pidl::Compat; use Parse::Pidl qw(warning); use Parse::Pidl::Util qw(has_property); use strict; +use warnings; use vars qw($VERSION); $VERSION = '0.01'; diff --git a/tools/pidl/lib/Parse/Pidl/Dump.pm b/tools/pidl/lib/Parse/Pidl/Dump.pm index 4e623db6..5d241b81 100644 --- a/tools/pidl/lib/Parse/Pidl/Dump.pm +++ b/tools/pidl/lib/Parse/Pidl/Dump.pm @@ -27,6 +27,7 @@ $VERSION = '0.01'; @EXPORT_OK = qw(DumpType DumpTypedef DumpStruct DumpEnum DumpBitmap DumpUnion DumpFunction); use strict; +use warnings; use Parse::Pidl::Util qw(has_property); my($res); diff --git a/tools/pidl/lib/Parse/Pidl/Expr.pm b/tools/pidl/lib/Parse/Pidl/Expr.pm index 24581d29..967d6876 100644 --- a/tools/pidl/lib/Parse/Pidl/Expr.pm +++ b/tools/pidl/lib/Parse/Pidl/Expr.pm @@ -10,6 +10,7 @@ package Parse::Pidl::Expr; use vars qw ( @ISA ); use strict; +use warnings; @ISA= qw ( Parse::Yapp::Driver ); use Parse::Yapp::Driver; diff --git a/tools/pidl/lib/Parse/Pidl/IDL.pm b/tools/pidl/lib/Parse/Pidl/IDL.pm index 6927c892..46f9813c 100644 --- a/tools/pidl/lib/Parse/Pidl/IDL.pm +++ b/tools/pidl/lib/Parse/Pidl/IDL.pm @@ -10,6 +10,7 @@ package Parse::Pidl::IDL; use vars qw ( @ISA ); use strict; +use warnings; @ISA= qw ( Parse::Yapp::Driver ); use Parse::Yapp::Driver; @@ -2646,12 +2647,29 @@ sub parse_file($$) undef $/; my $cpp = $ENV{CPP}; my $options = ""; - if (! defined $cpp) { - if (defined $ENV{CC}) { - $cpp = "$ENV{CC}"; - $options = "-E"; - } else { - $cpp = "cpp"; + if ($^O eq "MSWin32") { + $cpp = "cpp"; + }else{ + if (! defined $cpp) { + if (defined $ENV{CC}) { + $cpp = "$ENV{CC}"; + $options = "-E"; + } else { + # + # If cc is Clang-based don't use cpp, as + # at least some versions of Clang, cpp + # doesn't strip // comments, but cc -E + # does. + # + + my $cc_version = `cc --version`; + if ($cc_version =~ /clang/) { + $cpp = "cc"; + $options = "-E" + } else { + $cpp = "cpp"; + } + } } } my $includes = join('',map { " -I$_" } @$incdirs); diff --git a/tools/pidl/lib/Parse/Pidl/NDR.pm b/tools/pidl/lib/Parse/Pidl/NDR.pm index 003156e3..18db6cfe 100644 --- a/tools/pidl/lib/Parse/Pidl/NDR.pm +++ b/tools/pidl/lib/Parse/Pidl/NDR.pm @@ -38,6 +38,7 @@ $VERSION = '0.01'; @EXPORT_OK = qw(GetElementLevelTable ParseElement ReturnTypeElement ValidElement align_type mapToScalar ParseType can_contain_deferred is_charset_array); use strict; +use warnings; use Parse::Pidl qw(warning fatal); use Parse::Pidl::Typelist qw(hasType getType typeIs expandAlias mapScalarType is_fixed_size_scalar); use Parse::Pidl::Util qw(has_property property_matches); @@ -57,6 +58,7 @@ my $scalar_alignment = { 'int3264' => 5, 'uint3264' => 5, 'hyper' => 8, + 'int64' => 8, 'double' => 8, 'pointer' => 8, 'dlong' => 4, @@ -64,6 +66,7 @@ my $scalar_alignment = { 'udlongr' => 4, 'DATA_BLOB' => 4, 'string' => 4, + 'u16string' => 4, 'string_array' => 4, #??? 'time_t' => 4, 'uid_t' => 8, @@ -80,7 +83,10 @@ my $scalar_alignment = { 'ipv4address' => 4, 'ipv6address' => 4, #16? 'dnsp_name' => 1, - 'dnsp_string' => 1 + 'dnsp_string' => 1, + 'HRESULT' => 4, + 'libndr_flags' => 8, + 'ndr_flags_type' => 4, }; sub GetElementLevelTable($$$) @@ -115,7 +121,7 @@ sub GetElementLevelTable($$$) warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS}); } - my $allow_pipe = ($e->{PARENT}->{TYPE} eq "FUNCTION"); + my $allow_pipe = (($e->{PARENT}->{TYPE} // '') eq "FUNCTION"); my $is_pipe = typeIs($e->{TYPE}, "PIPE"); if ($is_pipe) { @@ -193,7 +199,7 @@ sub GetElementLevelTable($$$) $length = $size; } - if ($e == $e->{PARENT}->{ELEMENTS}[-1] + if ($e == $e->{PARENT}->{ELEMENTS}[-1] and $e->{PARENT}->{TYPE} ne "FUNCTION") { $is_surrounding = 1; } @@ -252,7 +258,7 @@ sub GetElementLevelTable($$$) $pt = $pointer_default; } - push (@$order, { + push (@$order, { TYPE => "POINTER", POINTER_TYPE => $pt, POINTER_INDEX => $pointer_idx, @@ -260,13 +266,13 @@ sub GetElementLevelTable($$$) LEVEL => $level }); - warning($e, "top-level \[out\] pointer `$e->{NAME}' is not a \[ref\] pointer") + warning($e, "top-level \[out\] pointer `$e->{NAME}' is not a \[ref\] pointer") if ($i == 1 and $pt ne "ref" and - $e->{PARENT}->{TYPE} eq "FUNCTION" and + $e->{PARENT}->{TYPE} eq "FUNCTION" and not has_property($e, "in")); $pointer_idx++; - + # everything that follows will be deferred $is_deferred = 1 if ($level ne "TOP"); @@ -283,9 +289,9 @@ sub GetElementLevelTable($$$) $array_length = $array_size; $is_varying =0; } - } - - if (scalar(@size_is) == 0 and has_property($e, "string") and + } + + if (scalar(@size_is) == 0 and has_property($e, "string") and $i == $e->{POINTERS}) { $is_string = 1; $is_varying = $is_conformant = has_property($e, "noheader")?0:1; @@ -307,7 +313,7 @@ sub GetElementLevelTable($$$) }); $is_deferred = 0; - } + } } if ($is_pipe) { @@ -326,10 +332,10 @@ sub GetElementLevelTable($$$) if (defined(has_property($e, "subcontext"))) { my $hdr_size = has_property($e, "subcontext"); my $subsize = has_property($e, "subcontext_size"); - if (not defined($subsize)) { - $subsize = -1; + if (not defined($subsize)) { + $subsize = -1; } - + push (@$order, { TYPE => "SUBCONTEXT", HEADER_SIZE => $hdr_size, @@ -341,7 +347,7 @@ sub GetElementLevelTable($$$) if (my $switch = has_property($e, "switch_is")) { push (@$order, { - TYPE => "SWITCH", + TYPE => "SWITCH", SWITCH_IS => $switch, IS_DEFERRED => $is_deferred }); @@ -390,11 +396,11 @@ sub GetTypedefLevelTable($$$$) } ##################################################################### -# see if a type contains any deferred data -sub can_contain_deferred($) +# see if a type contains any deferred data +sub can_contain_deferred { - sub can_contain_deferred($); - my ($type) = @_; + sub can_contain_deferred; + my ($type, @types_visited) = @_; return 1 unless (hasType($type)); # assume the worst @@ -402,15 +408,29 @@ sub can_contain_deferred($) return 0 if (Parse::Pidl::Typelist::is_scalar($type)); - return can_contain_deferred($type->{DATA}) if ($type->{TYPE} eq "TYPEDEF"); + foreach (@types_visited) { + if ($_ == $type) { + # we have already encountered this + # type, avoid recursion loop here + # and return + return 0; + } + } + + return can_contain_deferred($type->{DATA}, + @types_visited) if ($type->{TYPE} eq "TYPEDEF"); return 0 unless defined($type->{ELEMENTS}); foreach (@{$type->{ELEMENTS}}) { return 1 if ($_->{POINTERS}); - return 1 if (can_contain_deferred ($_->{TYPE})); + push(@types_visited,$type); + if (can_contain_deferred ($_->{TYPE},@types_visited)) { + pop(@types_visited); + return 1; + } + pop(@types_visited); } - return 0; } @@ -419,7 +439,7 @@ sub pointer_type($) my $e = shift; return undef unless $e->{POINTERS}; - + return "ref" if (has_property($e, "ref")); return "full" if (has_property($e, "ptr")); return "sptr" if (has_property($e, "sptr")); @@ -433,25 +453,25 @@ sub pointer_type($) ##################################################################### # work out the correct alignment for a structure or union -sub find_largest_alignment($) +sub find_largest_alignment { - my $s = shift; + my ($s, @types_visited) = @_; my $align = 1; for my $e (@{$s->{ELEMENTS}}) { my $a = 1; - if ($e->{POINTERS}) { # this is a hack for NDR64 # the NDR layer translates this into # an alignment of 4 for NDR and 8 for NDR64 $a = 5; - } elsif (has_property($e, "subcontext")) { + } elsif (has_property($e, "subcontext")) { $a = 1; } elsif (has_property($e, "transmit_as")) { - $a = align_type($e->{PROPERTIES}->{transmit_as}); + $a = align_type($e->{PROPERTIES}->{transmit_as}, + @types_visited); } else { - $a = align_type($e->{TYPE}); + $a = align_type($e->{TYPE}, @types_visited); } $align = $a if ($align < $a); @@ -462,37 +482,71 @@ sub find_largest_alignment($) ##################################################################### # align a type -sub align_type($) +sub align_type { - sub align_type($); - my ($e) = @_; - + sub align_type; + my ($e, @types_visited) = @_; if (ref($e) eq "HASH" and $e->{TYPE} eq "SCALAR") { - return $scalar_alignment->{$e->{NAME}}; + my $ret = $scalar_alignment->{$e->{NAME}}; + if (not defined $ret) { + warning($e, "no scalar alignment for $e->{NAME}!"); + return 0; + } + return $ret; } return 0 if ($e eq "EMPTY"); unless (hasType($e)) { - # it must be an external type - all we can do is guess + # it must be an external type - all we can do is guess # warning($e, "assuming alignment of unknown type '$e' is 4"); return 4; } - my $dt = getType($e); + foreach (@types_visited) { + if ($_ == $dt) { + # Chapt 14 of the DCE 1.1: Remote Procedure Call + # specification (available from pubs.opengroup.org) + # states: + # "The alignment of a structure in the octet stream is + # the largest of the alignments of the fields it + # contains. These fields may also be constructed types. + # The same alignment rules apply recursively to + # nested constructed types. " + # + # in the worst case scenario + # struct c1 { + # membertypea mema; + # membertypeb memb; + # struct c1 memc; + # } + # the nested struct c1 memc when encountered + # returns 0 ensuring the alignment will be calculated + # based on the other fields + return 0; + } + } + + if ($dt->{TYPE} eq "TYPEDEF") { - return align_type($dt->{DATA}); + return align_type($dt->{DATA}, @types_visited); } elsif ($dt->{TYPE} eq "CONFORMANCE") { return $dt->{DATA}->{ALIGN}; } elsif ($dt->{TYPE} eq "ENUM") { - return align_type(Parse::Pidl::Typelist::enum_type_fn($dt)); + return align_type(Parse::Pidl::Typelist::enum_type_fn($dt), + @types_visited); } elsif ($dt->{TYPE} eq "BITMAP") { - return align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt)); + return align_type(Parse::Pidl::Typelist::bitmap_type_fn($dt), + @types_visited); } elsif (($dt->{TYPE} eq "STRUCT") or ($dt->{TYPE} eq "UNION")) { # Struct/union without body: assume 4 return 4 unless (defined($dt->{ELEMENTS})); - return find_largest_alignment($dt); + my $res; + push(@types_visited, $dt); + $res = find_largest_alignment($dt, @types_visited); + pop(@types_visited); + return $res } elsif (($dt->{TYPE} eq "PIPE")) { return 5; } @@ -539,10 +593,10 @@ sub ParseStruct($$$) CheckPointerTypes($struct, $pointer_default); - foreach my $x (@{$struct->{ELEMENTS}}) + foreach my $x (@{$struct->{ELEMENTS}}) { my $e = ParseElement($x, $pointer_default, $ms_union); - if ($x != $struct->{ELEMENTS}[-1] and + if ($x != $struct->{ELEMENTS}[-1] and $e->{LEVELS}[0]->{IS_SURROUNDING}) { fatal($x, "conformant member not at end of struct"); } @@ -555,7 +609,7 @@ sub ParseStruct($$$) $surrounding = $e; } - if (defined $e->{TYPE} && $e->{TYPE} eq "string" + if (defined $e->{TYPE} && Parse::Pidl::Typelist::is_string_type($e->{TYPE}) && property_matches($e, "flag", ".*LIBNDR_FLAG_STR_CONFORMANT.*")) { $surrounding = $struct->{ELEMENTS}[-1]; } @@ -564,7 +618,7 @@ sub ParseStruct($$$) if ($struct->{NAME}) { $align = align_type($struct->{NAME}); } - + return { TYPE => "STRUCT", NAME => $struct->{NAME}, @@ -601,7 +655,7 @@ sub ParseUnion($$) CheckPointerTypes($e, $pointer_default); - foreach my $x (@{$e->{ELEMENTS}}) + foreach my $x (@{$e->{ELEMENTS}}) { my $t; if ($x->{TYPE} eq "EMPTY") { @@ -793,7 +847,7 @@ sub ParseFunction($$$$) if ($d->{RETURN_TYPE} ne "void") { $rettype = expandAlias($d->{RETURN_TYPE}); } - + return { NAME => $d->{NAME}, TYPE => "FUNCTION", @@ -885,7 +939,7 @@ sub ParseInterface($) $version = "0.0"; - if(defined $idl->{PROPERTIES}->{version}) { + if(defined $idl->{PROPERTIES}->{version}) { my @if_version = split(/\./, $idl->{PROPERTIES}->{version}); if ($if_version[0] == $idl->{PROPERTIES}->{version}) { $version = $idl->{PROPERTIES}->{version}; @@ -901,9 +955,9 @@ sub ParseInterface($) @endpoints = split /,/, $idl->{PROPERTIES}->{endpoint}; } - return { + return { NAME => $idl->{NAME}, - UUID => lc(has_property($idl, "uuid")), + UUID => lc(has_property($idl, "uuid") // ''), VERSION => $version, TYPE => "INTERFACE", PROPERTIES => $idl->{PROPERTIES}, @@ -925,7 +979,7 @@ sub Parse($) return undef unless (defined($idl)); Parse::Pidl::NDR::Validate($idl); - + my @ndr = (); foreach (@{$idl}) { @@ -997,10 +1051,10 @@ sub ContainsDeferred($$) while ($l = GetNextLevel($e,$l)) { - return 1 if ($l->{IS_DEFERRED}); + return 1 if ($l->{IS_DEFERRED}); return 1 if ($l->{CONTAINS_DEFERRED}); - } - + } + return 0; } @@ -1094,6 +1148,7 @@ my %property_list = ( "gensize" => ["TYPEDEF", "STRUCT", "UNION"], "value" => ["ELEMENT"], "flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], + "max_recursion" => ["ELEMENT"], # generic "public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], @@ -1252,7 +1307,7 @@ sub ValidElement($) has_property($e, "relative") or has_property($e, "relative_short") or has_property($e, "ref"))) { - fatal($e, el_name($e) . " : pointer properties on non-pointer element\n"); + fatal($e, el_name($e) . " : pointer properties on non-pointer element\n"); } } @@ -1298,7 +1353,7 @@ sub ValidUnion($) ValidProperties($union,"UNION"); - if (has_property($union->{PARENT}, "nodiscriminant") and + if (has_property($union->{PARENT}, "nodiscriminant") and has_property($union->{PARENT}, "switch_type")) { fatal($union->{PARENT}, $union->{PARENT}->{NAME} . ": switch_type(" . $union->{PARENT}->{PROPERTIES}->{switch_type} . ") on union without discriminant"); } @@ -1308,12 +1363,12 @@ sub ValidUnion($) foreach my $e (@{$union->{ELEMENTS}}) { $e->{PARENT} = $union; - if (defined($e->{PROPERTIES}->{default}) and + if (defined($e->{PROPERTIES}->{default}) and defined($e->{PROPERTIES}->{case})) { fatal($e, "Union member $e->{NAME} can not have both default and case properties!"); } - - unless (defined ($e->{PROPERTIES}->{default}) or + + unless (defined ($e->{PROPERTIES}->{default}) or defined ($e->{PROPERTIES}->{case})) { fatal($e, "Union member $e->{NAME} must have default or case property"); } @@ -1386,7 +1441,7 @@ sub ValidType($) { my ($t) = @_; - { + { TYPEDEF => \&ValidTypedef, STRUCT => \&ValidStruct, UNION => \&ValidUnion, @@ -1410,29 +1465,29 @@ sub ValidInterface($) ValidProperties($interface,"INTERFACE"); if (has_property($interface, "pointer_default")) { - if (not grep (/$interface->{PROPERTIES}->{pointer_default}/, + if (not grep (/$interface->{PROPERTIES}->{pointer_default}/, ("ref", "unique", "ptr"))) { fatal($interface, "Unknown default pointer type `$interface->{PROPERTIES}->{pointer_default}'"); } } if (has_property($interface, "object")) { - if (has_property($interface, "version") && + if (has_property($interface, "version") && $interface->{PROPERTIES}->{version} != 0) { fatal($interface, "Object interfaces must have version 0.0 ($interface->{NAME})"); } - if (!defined($interface->{BASE}) && + if (!defined($interface->{BASE}) && not ($interface->{NAME} eq "IUnknown")) { fatal($interface, "Object interfaces must all derive from IUnknown ($interface->{NAME})"); } } - + foreach my $d (@{$data}) { ($d->{TYPE} eq "FUNCTION") && ValidFunction($d); - ($d->{TYPE} eq "TYPEDEF" or + ($d->{TYPE} eq "TYPEDEF" or $d->{TYPE} eq "STRUCT" or - $d->{TYPE} eq "UNION" or + $d->{TYPE} eq "UNION" or $d->{TYPE} eq "ENUM" or $d->{TYPE} eq "BITMAP" or $d->{TYPE} eq "PIPE") && ValidType($d); @@ -1447,7 +1502,7 @@ sub Validate($) my($idl) = shift; foreach my $x (@{$idl}) { - ($x->{TYPE} eq "INTERFACE") && + ($x->{TYPE} eq "INTERFACE") && ValidInterface($x); ($x->{TYPE} eq "IMPORTLIB") && fatal($x, "importlib() not supported"); diff --git a/tools/pidl/lib/Parse/Pidl/ODL.pm b/tools/pidl/lib/Parse/Pidl/ODL.pm index 14e77fa9..0943f3a8 100644 --- a/tools/pidl/lib/Parse/Pidl/ODL.pm +++ b/tools/pidl/lib/Parse/Pidl/ODL.pm @@ -1,5 +1,5 @@ ########################################## -# Converts ODL stuctures to IDL structures +# Converts ODL structures to IDL structures # (C) 2004-2005, 2008 Jelmer Vernooij <jelmer@samba.org> package Parse::Pidl::ODL; @@ -10,6 +10,7 @@ use Parse::Pidl::Util qw(has_property unmake_str); use Parse::Pidl::Typelist qw(hasType getType); use File::Basename; use strict; +use warnings; use vars qw($VERSION); $VERSION = '0.01'; diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 6acf1c5a..816440ef 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -6,12 +6,10 @@ # released under the GNU GPL package Parse::Pidl::Samba3::ClientNDR; - -use Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(ParseFunction $res $res_hdr); +use base Parse::Pidl::Base; use strict; +use warnings; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property ParseExpr genpad); use Parse::Pidl::NDR qw(ContainsPipe); @@ -19,13 +17,10 @@ use Parse::Pidl::Typelist qw(mapTypeName); use Parse::Pidl::Samba4 qw(DeclLong); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); + use vars qw($VERSION); $VERSION = '0.01'; -sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; } -sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); } -sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; } -sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; } sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); } sub new($) diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm b/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm index c87d17a5..2dcc35e7 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm @@ -11,6 +11,7 @@ use Exporter; @EXPORT_OK = qw(DeclLevel); use strict; +use warnings; use Parse::Pidl qw(warning error fatal); use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference); use Parse::Pidl::Util qw(ParseExpr has_property is_constant); @@ -62,11 +63,11 @@ sub AllocOutVar($$$$$$$) $l = $nl if ($nl->{TYPE} eq "ARRAY"); } elsif - # we don't support multi-dimentional arrays yet + # we don't support multi-dimensional arrays yet ($l->{TYPE} eq "ARRAY") { my $nl = GetNextLevel($e, $l); if ($nl->{TYPE} eq "ARRAY") { - fatal($e->{ORIGINAL},"multi-dimentional [out] arrays are not supported!"); + fatal($e->{ORIGINAL},"multi-dimensional [out] arrays are not supported!"); } } else { # neither pointer nor array, no need to alloc something. @@ -103,7 +104,7 @@ sub CallWithStruct($$$$$$) if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; } } - pidl "ZERO_STRUCT(r->out);" if ($hasout); + pidl "NDR_ZERO_STRUCT(r->out);" if ($hasout); foreach (@{$fn->{ELEMENTS}}) { my @dir = @{$_->{DIRECTION}}; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4.pm b/tools/pidl/lib/Parse/Pidl/Samba4.pm index b720ab90..6b3f2218 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4.pm @@ -14,6 +14,7 @@ use Parse::Pidl::NDR qw(GetNextLevel); use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference); use Parse::Pidl qw(fatal error); use strict; +use warnings; use vars qw($VERSION); $VERSION = '0.01'; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm index de7d4547..159f4172 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm @@ -10,6 +10,7 @@ use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; sub GetArgumentProtoList($) { diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm index 35e6e3f0..1630cf23 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm @@ -14,6 +14,7 @@ use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; my($res); @@ -101,7 +102,7 @@ static $tn dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TAL return status; } - ZERO_STRUCT(r.in.ORPCthis); + NDR_ZERO_STRUCT(r.in.ORPCthis); r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; "; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm index 239f5baa..71980383 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm @@ -9,6 +9,7 @@ package Parse::Pidl::Samba4::COM::Stub; use Parse::Pidl::Util qw(has_property); use strict; +use warnings; use vars qw($VERSION); $VERSION = '0.01'; @@ -125,8 +126,6 @@ static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_C /* unravel the NDR for the packet */ status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); if (!NT_STATUS_IS_OK(status)) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); dce_call->fault_code = DCERPC_FAULT_NDR; return NT_STATUS_NET_WRITE_FAULT; } @@ -152,8 +151,6 @@ pidl " } if (dce_call->fault_code != 0) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); return NT_STATUS_NET_WRITE_FAULT; } @@ -175,8 +172,6 @@ pidl " } if (dce_call->fault_code != 0) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); return NT_STATUS_NET_WRITE_FAULT; } diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm index e9b7bee0..a0b002f6 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm @@ -11,6 +11,7 @@ require Exporter; @EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); use strict; +use warnings; use Parse::Pidl qw(fatal); use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference); use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr); @@ -142,7 +143,7 @@ sub HeaderEnum($$;$) my $count = 0; my $with_val = 0; my $without_val = 0; - pidl " { __do_not_use_enum_$name=0x7FFFFFFF}\n"; + pidl " { __do_not_use_enum_$name=INT_MAX}\n"; foreach my $e (@{$enum->{ELEMENTS}}) { my $t = "$e"; my $name; @@ -493,7 +494,7 @@ sub EnvSubstituteValue($$) # Substitute the value() values in the env foreach my $e (@{$s->{ELEMENTS}}) { next unless (defined(my $v = has_property($e, "value"))); - + $env->{$e->{NAME}} = ParseExpr($v, $env, $e); } diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm index 040cd5a4..84e2bebb 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm @@ -5,10 +5,7 @@ # released under the GNU GPL package Parse::Pidl::Samba4::NDR::Client; - -use Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(Parse); +use parent Parse::Pidl::Base; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property ParseExpr genpad); @@ -17,18 +14,14 @@ use Parse::Pidl::Typelist qw(mapTypeName); use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); + use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; -sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; } -sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); } -sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; } -sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; } -sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; } sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); } - sub new($) { my ($class) = shift; @@ -496,7 +489,7 @@ sub ParseFunction_Send($$$$) if (defined($fn->{RETURN_TYPE})) { $self->pidl("/* Result */"); - $self->pidl("ZERO_STRUCT(state->orig.out.result);"); + $self->pidl("NDR_ZERO_STRUCT(state->orig.out.result);"); $self->pidl(""); } @@ -585,7 +578,7 @@ sub ParseFunction_Done($$$$) } $self->pidl("/* Reset temporary structure */"); - $self->pidl("ZERO_STRUCT(state->tmp);"); + $self->pidl("NDR_ZERO_STRUCT(state->tmp);"); $self->pidl(""); $self->pidl("tevent_req_done(req);"); @@ -698,7 +691,7 @@ sub ParseFunction_Sync($$$$) if (defined($fn->{RETURN_TYPE})) { $self->pidl("/* Result */"); - $self->pidl("ZERO_STRUCT(r.out.result);"); + $self->pidl("NDR_ZERO_STRUCT(r.out.result);"); $self->pidl(""); } @@ -770,8 +763,8 @@ sub ParseFunction($$$) # TODO: make this fatal at NDR level if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { if ($e->{LEVELS}[1]->{TYPE} eq "DATA" and - $e->{LEVELS}[1]->{DATA_TYPE} eq "string") { - $reason = "is a pointer to type 'string'"; + Parse::Pidl::Typelist::is_string_type($e->{LEVELS}[1]->{DATA_TYPE})) { + $reason = "is a pointer to a string type"; } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) { next; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index cfcd29e2..d7386d5b 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -6,14 +6,22 @@ # released under the GNU GPL package Parse::Pidl::Samba4::NDR::Parser; +use parent Parse::Pidl::Base; require Exporter; -@ISA = qw(Exporter); +push @ISA, qw(Exporter); @EXPORT_OK = qw(check_null_pointer NeededFunction NeededElement NeededType $res NeededInterface TypeFunctionName ParseElementPrint); use strict; -use Parse::Pidl::Typelist qw(hasType getType mapTypeName typeHasBody); -use Parse::Pidl::Util qw(has_property ParseExpr ParseExprExt print_uuid unmake_str); +use warnings; +use Parse::Pidl::Typelist qw(hasType getType mapTypeName mapTypeSpecifier typeHasBody); +use Parse::Pidl::Util qw(has_property + ParseExpr + ParseExprExt + print_uuid + unmake_str + parse_int + parse_range); use Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element); use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated); @@ -49,7 +57,7 @@ sub append_prefix($$) $pointers++; } elsif ($l->{TYPE} eq "ARRAY") { $arrays++; - if (($pointers == 0) and + if (($pointers == 0) and (not $l->{IS_FIXED}) and (not $l->{IS_INLINE})) { return get_value_of($var_name); @@ -60,7 +68,7 @@ sub append_prefix($$) } } } - + return $var_name; } @@ -76,28 +84,26 @@ sub has_fast_array($$) my $t = getType($nl->{DATA_TYPE}); - # Only uint8 and string have fast array functions at the moment - return ($t->{NAME} eq "uint8") or ($t->{NAME} eq "string"); + # Only uint8 has a fast array function at the moment + return ($t->{NAME} eq "uint8"); } - -#################################### -# pidl() is our basic output routine -sub pidl($$) +sub is_public_struct { - my ($self, $d) = @_; - if ($d) { - $self->{res} .= $self->{tabs}; - $self->{res} .= $d; + my ($d) = @_; + if (!has_property($d, "public")) { + return 0; + } + my $t = $d; + if ($d->{TYPE} eq "TYPEDEF") { + $t = $d->{DATA}; } - $self->{res} .="\n"; + return $t->{TYPE} eq "STRUCT"; } -sub pidl_hdr($$) { my ($self, $d) = @_; $self->{res_hdr} .= "$d\n"; } - #################################### -# defer() is like pidl(), but adds to -# a deferred buffer which is then added to the +# defer() is like pidl(), but adds to +# a deferred buffer which is then added to the # output buffer at the end of the structure/union/function # This is needed to cope with code that must be pushed back # to the end of a block of elements @@ -123,18 +129,6 @@ sub add_deferred($) $self->{defer_tabs} = ""; } -sub indent($) -{ - my ($self) = @_; - $self->{tabs} .= "\t"; -} - -sub deindent($) -{ - my ($self) = @_; - $self->{tabs} = substr($self->{tabs}, 0, -1); -} - ##################################################################### # declare a function public or static, depending on its attributes sub fn_declare($$$$) @@ -165,7 +159,7 @@ sub start_flags($$$) if (defined $flags) { $self->pidl("{"); $self->indent; - $self->pidl("uint32_t _flags_save_$e->{TYPE} = $ndr->flags;"); + $self->pidl("libndr_flags _flags_save_$e->{TYPE} = $ndr->flags;"); $self->pidl("ndr_set_flags(&$ndr->flags, $flags);"); } } @@ -241,7 +235,7 @@ sub check_fully_dereferenced($$) last; } } - + return($origvar) unless (defined($var)); my $e; foreach (@{$element->{PARENT}->{ELEMENTS}}) { @@ -264,7 +258,7 @@ sub check_fully_dereferenced($$) warning($element->{ORIGINAL}, "Got pointer for `$e->{NAME}', expected fully dereferenced variable") if ($nump > length($ptr)); return ($origvar); } -} +} sub check_null_pointer($$$$) { @@ -285,7 +279,7 @@ sub check_null_pointer($$$$) last; } } - + if (defined($var)) { my $e; # lookup ptr in $e @@ -301,7 +295,7 @@ sub check_null_pointer($$$$) # See if pointer at pointer level $level # needs to be checked. foreach my $l (@{$e->{LEVELS}}) { - if ($l->{TYPE} eq "POINTER" and + if ($l->{TYPE} eq "POINTER" and $l->{POINTER_INDEX} == length($ptr)) { # No need to check ref pointers $check = ($l->{POINTER_TYPE} ne "ref"); @@ -316,7 +310,7 @@ sub check_null_pointer($$$$) warning($element, "unknown dereferenced expression `$expandedvar'"); $check = 1; } - + $print_fn->("if ($ptr$expandedvar == NULL) $return") if $check; } } @@ -346,22 +340,29 @@ sub ParseArrayPullGetSize($$$$$$) my $size; - if ($l->{IS_CONFORMANT}) { - $size = "ndr_get_array_size($ndr, " . get_pointer_to($var_name) . ")"; + my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}"; + + if ($l->{IS_CONFORMANT} and (defined($l->{SIZE_IS}) or not $l->{IS_ZERO_TERMINATED})) { + $self->pidl("NDR_CHECK(ndr_get_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_size));"); + + } elsif ($l->{IS_CONFORMANT}) { + # This will be the last use of the array_size token + $self->pidl("NDR_CHECK(ndr_steal_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_size));"); + } elsif ($l->{IS_ZERO_TERMINATED} and $l->{SIZE_IS} == 0 and $l->{LENGTH_IS} == 0) { # Noheader arrays $size = "ndr_get_string_size($ndr, sizeof(*$var_name))"; + $self->pidl("$array_size = $size;"); + } else { $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); + $self->pidl("$array_size = $size;"); } - $self->pidl("size_$e->{NAME}_$l->{LEVEL_INDEX} = $size;"); - my $array_size = "size_$e->{NAME}_$l->{LEVEL_INDEX}"; - if (my $range = has_property($e, "range")) { - my ($low, $high) = split(/,/, $range, 2); + my ($low, $high) = parse_range($range); if ($low < 0) { warning(0, "$low is invalid for the range of an array size"); } @@ -370,7 +371,8 @@ sub ParseArrayPullGetSize($$$$$$) } else { $self->pidl("if ($array_size < $low || $array_size > $high) {"); } - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value (%\"PRIu32\") out of range (%\"PRIu32\" - %\"PRIu32\")\", $array_size, (uint32_t)($low), (uint32_t)($high));"); + $self->pidl("}"); } @@ -391,12 +393,16 @@ sub ParseArrayPullGetLength($$$$$$;$) return $array_size; } - my $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; - $self->pidl("length_$e->{NAME}_$l->{LEVEL_INDEX} = $length;"); my $array_length = "length_$e->{NAME}_$l->{LEVEL_INDEX}"; + if ($l->{IS_VARYING} and (defined($l->{LENGTH_IS}) or not $l->{IS_ZERO_TERMINATED})) { + $self->pidl("NDR_CHECK(ndr_get_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_length));"); + } else { + # This will be the last use of the array_length token + $self->pidl("NDR_CHECK(ndr_steal_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", &$array_length));"); + } if (my $range = has_property($e, "range")) { - my ($low, $high) = split(/,/, $range, 2); + my ($low, $high) = parse_range($range); if ($low < 0) { warning(0, "$low is invalid for the range of an array size"); } @@ -405,7 +411,7 @@ sub ParseArrayPullGetLength($$$$$$;$) } else { $self->pidl("if ($array_length < $low || $array_length > $high) {"); } - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value (%\"PRIu32\") out of range (%\"PRIu32\" - %\"PRIu32\")\", $array_length, (uint32_t)($low), (uint32_t)($high));"); $self->pidl("}"); } @@ -432,7 +438,7 @@ sub ParseArrayPullHeader($$$$$$) if ($array_length ne $array_size) { $self->pidl("if ($array_length > $array_size) {"); $self->indent; - $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should exceed array length %u\", $array_size, $array_length);"); + $self->pidl("return ndr_pull_error($ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %\"PRIu32\": should exceed array length %\"PRIu32\"\", $array_size, $array_length);"); $self->deindent; $self->pidl("}"); } @@ -444,7 +450,14 @@ sub ParseArrayPullHeader($$$$$$) check_null_pointer($e, $env, sub { $self->defer(shift); }, "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for size_is()\");"), check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + if (ContainsDeferred($e, $l)) { + # We will be needing the array_size token in + # the NDR_BUFFERS call, so don't steal it now + $self->defer("NDR_CHECK(ndr_check_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + } else { + # This will be deferred until after the last ndr_get_array_size() + $self->defer("NDR_CHECK(ndr_check_steal_array_size($ndr, (void*)" . get_pointer_to($var_name) . ", $size));"); + } $self->defer_deindent; $self->defer("}"); } @@ -452,11 +465,12 @@ sub ParseArrayPullHeader($$$$$$) if ($l->{IS_VARYING} and (defined($l->{LENGTH_IS}) or not $l->{IS_ZERO_TERMINATED})) { $self->defer("if ($var_name) {"); $self->defer_indent; - my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, + my $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->defer(shift); }, "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for length_is()\");"), check_fully_dereferenced($e, $env)); - $self->defer("NDR_CHECK(ndr_check_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", $length));"); + # This will be deferred until after the last ndr_get_array_length() + $self->defer("NDR_CHECK(ndr_check_steal_array_length($ndr, (void*)" . get_pointer_to($var_name) . ", $length));"); $self->defer_deindent; $self->defer("}"); } @@ -468,12 +482,12 @@ sub ParseArrayPullHeader($$$$$$) return $array_length; } -sub compression_alg($$) +sub compression_alg($$$) { - my ($e, $l) = @_; + my ($e, $l, $env) = @_; my ($alg, $clen, $dlen) = split(/,/, $l->{COMPRESSION}); - return $alg; + return ParseExpr($alg, $env, $e->{ORIGINAL}); } sub compression_clen($$$) @@ -496,13 +510,13 @@ sub ParseCompressionPushStart($$$$$) { my ($self,$e,$l,$ndr,$env) = @_; my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); + my $alg = compression_alg($e, $l, $env); $self->pidl("{"); $self->indent; $self->pidl("struct ndr_push *$comndr;"); - $self->pidl("NDR_CHECK(ndr_push_compression_start($ndr, &$comndr, $alg, $dlen));"); + $self->pidl("NDR_CHECK(ndr_push_compression_state_init($ndr, $alg));"); + $self->pidl("NDR_CHECK(ndr_push_compression_start($ndr, &$comndr));"); return $comndr; } @@ -511,10 +525,10 @@ sub ParseCompressionPushEnd($$$$$) { my ($self,$e,$l,$ndr,$env) = @_; my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); - my $dlen = compression_dlen($e, $l, $env); + my $alg = compression_alg($e, $l, $env); - $self->pidl("NDR_CHECK(ndr_push_compression_end($ndr, $comndr, $alg, $dlen));"); + $self->pidl("NDR_CHECK(ndr_push_compression_end($ndr, $comndr));"); + $self->pidl("TALLOC_FREE($ndr->cstate);"); $self->deindent; $self->pidl("}"); } @@ -523,7 +537,7 @@ sub ParseCompressionPullStart($$$$$) { my ($self,$e,$l,$ndr,$env) = @_; my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); + my $alg = compression_alg($e, $l, $env); my $dlen = compression_dlen($e, $l, $env); my $clen = compression_clen($e, $l, $env); @@ -539,7 +553,7 @@ sub ParseCompressionPullEnd($$$$$) { my ($self,$e,$l,$ndr,$env) = @_; my $comndr = "$ndr\_compressed"; - my $alg = compression_alg($e, $l); + my $alg = compression_alg($e, $l, $env); my $dlen = compression_dlen($e, $l, $env); $self->pidl("NDR_CHECK(ndr_pull_compression_end($ndr, $comndr, $alg, $dlen));"); @@ -589,7 +603,8 @@ sub ParseSubcontextPullStart($$$$$) $self->pidl("{"); $self->indent; $self->pidl("struct ndr_pull *$subndr;"); - $self->pidl("NDR_CHECK(ndr_pull_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, $subcontext_size));"); + $self->pidl("ssize_t sub_size = $subcontext_size;"); + $self->pidl("NDR_CHECK(ndr_pull_subcontext_start($ndr, &$subndr, $l->{HEADER_SIZE}, sub_size));"); if (defined $l->{COMPRESSION}) { $subndr = $self->ParseCompressionPullStart($e, $l, $subndr, $env); @@ -608,7 +623,7 @@ sub ParseSubcontextPullEnd($$$$$) $self->ParseCompressionPullEnd($e, $l, $subndr, $env); } - $self->pidl("NDR_CHECK(ndr_pull_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, $subcontext_size));"); + $self->pidl("NDR_CHECK(ndr_pull_subcontext_end($ndr, $subndr, $l->{HEADER_SIZE}, sub_size));"); $self->deindent; $self->pidl("}"); } @@ -631,7 +646,7 @@ sub ParseElementPushLevel } elsif ($l->{TYPE} eq "POINTER") { $self->ParsePtrPush($e, $l, $ndr, $var_name); } elsif ($l->{TYPE} eq "ARRAY") { - my $length = $self->ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); + my $length = $self->ParseArrayPushHeader($e, $l, $ndr, $var_name, $env); my $nl = GetNextLevel($e, $l); @@ -646,9 +661,7 @@ sub ParseElementPushLevel } elsif (has_fast_array($e,$l)) { $self->pidl("NDR_CHECK(ndr_push_array_$nl->{DATA_TYPE}($ndr, $ndr_flags, $var_name, $length));"); return; - } - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseSwitchPush($e, $l, $ndr, $var_name, $env); + } } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPush($e, $l, $ndr, $var_name, $primitives, $deferred); } elsif ($l->{TYPE} eq "TYPEDEF") { @@ -709,6 +722,14 @@ sub ParseElementPushLevel $self->pidl("}"); } } elsif ($l->{TYPE} eq "SWITCH") { + my $nl = GetNextLevel($e,$l); + my $needs_deferred_switch = is_deferred_switch_non_empty($nl); + + # Avoid setting a switch value if it will not be + # consumed again in the NDR_BUFFERS pull + if ($needs_deferred_switch or !$deferred) { + $self->ParseSwitchPush($e, $l, $ndr, $var_name, $env); + } $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, $primitives, $deferred); } } @@ -886,13 +907,13 @@ sub ParseElementPrint($$$$$) my $length; if ($l->{IS_CONFORMANT} or $l->{IS_VARYING}) { - $var_name = get_pointer_to($var_name); + $var_name = get_pointer_to($var_name); } - + if ($l->{IS_ZERO_TERMINATED} and not defined($l->{LENGTH_IS})) { $length = "ndr_string_length($var_name, sizeof(*$var_name))"; } else { - $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, + $length = ParseExprExt($l->{LENGTH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env)); } @@ -906,7 +927,7 @@ sub ParseElementPrint($$$$$) } else { my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - $self->pidl("$ndr->print($ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);"); + $self->pidl("$ndr->print($ndr, \"%s: ARRAY(%\"PRIu32\")\", \"$e->{NAME}\", (uint32_t)($length));"); $self->pidl("$ndr->depth++;"); $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {"); $self->indent; @@ -916,10 +937,10 @@ sub ParseElementPrint($$$$$) } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPrint($e, $l, $ndr, $var_name); } elsif ($l->{TYPE} eq "SWITCH") { - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, + my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return;"), check_fully_dereferenced($e, $env)); $self->pidl("ndr_print_set_switch_value($ndr, " . get_pointer_to($var_name) . ", $switch_var);"); - } + } } foreach my $l (reverse @{$e->{LEVELS}}) { @@ -956,7 +977,7 @@ sub ParseElementPrint($$$$$) sub ParseSwitchPull($$$$$$) { my($self,$e,$l,$ndr,$var_name,$env) = @_; - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, + my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return ndr_pull_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), check_fully_dereferenced($e, $env)); @@ -970,7 +991,7 @@ sub ParseSwitchPull($$$$$$) sub ParseSwitchPush($$$$$$) { my($self,$e,$l,$ndr,$var_name,$env) = @_; - my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, + my $switch_var = ParseExprExt($l->{SWITCH_IS}, $env, $e->{ORIGINAL}, check_null_pointer($e, $env, sub { $self->pidl(shift); }, "return ndr_push_error($ndr, NDR_ERR_INVALID_POINTER, \"NULL Pointer for switch_is()\");"), check_fully_dereferenced($e, $env)); @@ -993,15 +1014,22 @@ sub ParseDataPull($$$$$$$) $var_name = get_pointer_to($var_name); + if (my $depth = has_property($e, "max_recursion")) { + my $d = parse_int($depth); + $self->pidl("NDR_RECURSION_CHECK($ndr, $d);"); + } $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));"); + if (has_property($e, "max_recursion")) { + $self->pidl("NDR_RECURSION_UNWIND($ndr);"); + } my $pl = GetPrevLevel($e, $l); my $range = has_property($e, "range"); - if ($range and $pl->{TYPE} ne "ARRAY") { + if ($range and (not $pl or $pl->{TYPE} ne "ARRAY")) { $var_name = get_value_of($var_name); my $signed = Parse::Pidl::Typelist::is_signed($l->{DATA_TYPE}); - my ($low, $high) = split(/,/, $range, 2); + my ($low, $high) = parse_range($range); if ($low < 0 and not $signed) { warning(0, "$low is invalid for the range of an unsigned type"); } @@ -1010,7 +1038,20 @@ sub ParseDataPull($$$$$$$) } else { $self->pidl("if ($var_name < $low || $var_name > $high) {"); } - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); + + my $data_type = mapTypeName($l->{DATA_TYPE}); + my $fmt = mapTypeSpecifier($data_type); + + if (!defined($fmt)) { + if (getType($l->{DATA_TYPE})->{DATA}->{TYPE} eq "ENUM") { + $data_type = "int"; + $fmt = "d"; + } else { + die("Format ($data_type) not supported"); + } + } + + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value (%$fmt) out of range (%$fmt - %$fmt)\", ($data_type)($var_name), ($data_type)($low), ($data_type)($high));"); $self->pidl("}"); } } else { @@ -1044,14 +1085,14 @@ sub CalcNdrFlags($$$) my $scalars = 0; my $buffers = 0; - # Add NDR_SCALARS if this one is deferred + # 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 + # 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); @@ -1079,7 +1120,7 @@ sub ParseMemCtxPullFlags($$$$) my $nl = GetNextLevel($e, $l); return undef if ($nl->{TYPE} eq "PIPE"); return undef if ($nl->{TYPE} eq "ARRAY"); - return undef if (($nl->{TYPE} eq "DATA") and ($nl->{DATA_TYPE} eq "string")); + return undef if (($nl->{TYPE} eq "DATA") and (Parse::Pidl::Typelist::is_string_type($nl->{DATA_TYPE}))); if ($l->{LEVEL} eq "TOP") { $mem_flags = "LIBNDR_FLAG_REF_ALLOC"; @@ -1134,7 +1175,7 @@ sub ParseElementPullLevel if (has_property($e, "skip") or has_property($e, "skip_noinit")) { $self->pidl("/* [skip] '$var_name' */"); if (not has_property($e, "skip_noinit")) { - $self->pidl("ZERO_STRUCT($var_name);"); + $self->pidl("NDR_ZERO_STRUCT($var_name);"); } return; } @@ -1174,8 +1215,6 @@ sub ParseElementPullLevel } } elsif ($l->{TYPE} eq "POINTER") { $self->ParsePtrPull($e, $l, $ndr, $var_name); - } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseSwitchPull($e, $l, $ndr, $var_name, $env); } elsif ($l->{TYPE} eq "DATA") { $self->ParseDataPull($e, $l, $ndr, $var_name, $primitives, $deferred); } elsif ($l->{TYPE} eq "TYPEDEF") { @@ -1217,7 +1256,7 @@ sub ParseElementPullLevel $self->deindent; $self->pidl("}"); } - } elsif ($l->{TYPE} eq "ARRAY" and + } elsif ($l->{TYPE} eq "ARRAY" and not has_fast_array($e,$l) and not is_charset_array($e, $l)) { my $length = $array_length; my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; @@ -1247,16 +1286,28 @@ sub ParseElementPullLevel if ($deferred and ContainsDeferred($e, $l)) { $self->pidl("for ($counter = 0; $counter < ($length); $counter++) {"); + $self->defer("for ($counter = 0; $counter < ($length); $counter++) {"); + $self->defer_indent; $self->indent; $self->ParseElementPullLevel($e,GetNextLevel($e,$l), $ndr, $var_name, $env, 0, 1); $self->deindent; + $self->defer_deindent; $self->pidl("}"); + $self->defer("}"); } $self->ParseMemCtxPullEnd($e, $l, $ndr); } elsif ($l->{TYPE} eq "SWITCH") { - $self->ParseElementPullLevel($e, GetNextLevel($e,$l), $ndr, $var_name, $env, $primitives, $deferred); + my $nl = GetNextLevel($e,$l); + my $needs_deferred_switch = is_deferred_switch_non_empty($nl); + + # Avoid setting a switch value if it will not be + # consumed again in the NDR_BUFFERS pull + if ($needs_deferred_switch or !$deferred) { + $self->ParseSwitchPull($e, $l, $ndr, $var_name, $env); + } + $self->ParseElementPullLevel($e, $nl, $ndr, $var_name, $env, $primitives, $deferred); } } @@ -1307,21 +1358,21 @@ sub ParsePtrPull($$$$$) my $nl = GetNextLevel($e, $l); my $next_is_array = ($nl->{TYPE} eq "ARRAY"); - my $next_is_string = (($nl->{TYPE} eq "DATA") and - ($nl->{DATA_TYPE} eq "string")); + my $next_is_string = (($nl->{TYPE} eq "DATA") and + (Parse::Pidl::Typelist::is_string_type($nl->{DATA_TYPE}))); if ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP") { if (!$next_is_array and !$next_is_string) { $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); - $self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);"); + $self->pidl("\tNDR_PULL_ALLOC($ndr, $var_name);"); $self->pidl("}"); } return; } elsif ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "EMBEDDED") { $self->pidl("NDR_CHECK(ndr_pull_ref_ptr($ndr, &_ptr_$e->{NAME}));"); - } elsif (($l->{POINTER_TYPE} eq "unique") or + } elsif (($l->{POINTER_TYPE} eq "unique") or ($l->{POINTER_TYPE} eq "relative") or ($l->{POINTER_TYPE} eq "full")) { $self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));"); @@ -1343,10 +1394,10 @@ sub ParsePtrPull($$$$$) # allocation, as we forced it to NULL just above, and # we may not know the declared type anyway. } else { - # Don't do this for arrays, they're allocated at the actual level + # Don't do this for arrays, they're allocated at the actual level # of the array - unless ($next_is_array or $next_is_string) { - $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); + unless ($next_is_array or $next_is_string) { + $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); } else { # FIXME: Yes, this is nasty. # We allocate an array twice @@ -1398,10 +1449,10 @@ sub ParseStructPushPrimitives($$$$$) if (defined($struct->{SURROUNDING_ELEMENT})) { my $e = $struct->{SURROUNDING_ELEMENT}; - if (defined($e->{LEVELS}[0]) and + if (defined($e->{LEVELS}[0]) and $e->{LEVELS}[0]->{TYPE} eq "ARRAY") { my $size; - + if ($e->{LEVELS}[0]->{IS_ZERO_TERMINATED}) { if (has_property($e, "charset")) { $size = "ndr_charset_length($varname->$e->{NAME}, CH_$e->{PROPERTIES}->{charset})"; @@ -1450,7 +1501,7 @@ sub ParseStructPushDeferred($$$$) sub ParseStructPush($$$$) { my ($self, $struct, $ndr, $varname) = @_; - + return unless defined($struct->{ELEMENTS}); my $env = GenerateStructEnv($struct, $varname); @@ -1530,7 +1581,7 @@ sub ParseEnumPrint($$$$$) $self->deindent; $self->pidl("}"); - + $self->pidl("ndr_print_enum($ndr, name, \"$enum->{TYPE}\", val, $varname);"); $self->end_flags($enum, $ndr); @@ -1539,7 +1590,7 @@ sub ParseEnumPrint($$$$$) sub DeclEnum($$$$) { my ($e,$t,$name,$varname) = @_; - return "enum $name " . + return "enum $name " . ($t eq "pull"?"*":"") . $varname; } @@ -1622,7 +1673,7 @@ sub ParseBitmapPrint($$$$$) sub DeclBitmap($$$$) { my ($e,$t,$name,$varname) = @_; - return mapTypeName(Parse::Pidl::Typelist::bitmap_type_fn($e)) . + return mapTypeName(Parse::Pidl::Typelist::bitmap_type_fn($e)) . ($t eq "pull"?" *":" ") . $varname; } @@ -1651,7 +1702,7 @@ sub ParseStructPrint($$$$$) $self->start_flags($struct, $ndr); $self->pidl("$ndr->depth++;"); - + $self->ParseElementPrint($_, $ndr, $env->{$_->{NAME}}, $env) foreach (@{$struct->{ELEMENTS}}); $self->pidl("$ndr->depth--;"); @@ -1669,7 +1720,7 @@ sub DeclarePtrVariables($$) foreach my $l (@{$e->{LEVELS}}) { my $size = 32; - if ($l->{TYPE} eq "POINTER" and + if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { if ($l->{POINTER_TYPE} eq "relative_short") { $size = 16; @@ -1833,13 +1884,16 @@ sub ParseStructNdrSize($$$$) sub DeclStruct($$$$) { my ($e,$t,$name,$varname) = @_; + if ($t eq "base") { + return "struct $name $varname"; + } return ($t ne "pull"?"const ":"") . "struct $name *$varname"; } sub ArgsStructNdrSize($$$) { my ($d, $name, $varname) = @_; - return "const struct $name *$varname, int flags"; + return "const struct $name *$varname, libndr_flags flags"; } $typefamily{STRUCT} = { @@ -1871,8 +1925,6 @@ sub ParseUnionPushPrimitives($$$$) my $have_default = 0; - $self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);"); - if (defined($e->{SWITCH_TYPE})) { if (defined($e->{ALIGN})) { $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));"); @@ -1917,7 +1969,7 @@ sub ParseUnionPushPrimitives($$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);"); + $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %\"PRIu32, level);"); } $self->deindent; $self->pidl("}"); @@ -1929,7 +1981,6 @@ sub ParseUnionPushDeferred($$$$) my $have_default = 0; - $self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);"); if (defined($e->{PROPERTIES}{relative_base})) { # retrieve the current offset as base for relative pointers # based on the toplevel struct/union @@ -1953,7 +2004,7 @@ sub ParseUnionPushDeferred($$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);"); + $self->pidl("\treturn ndr_push_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %\"PRIu32, level);"); } $self->deindent; $self->pidl("}"); @@ -1966,17 +2017,28 @@ sub ParseUnionPush($$$$) my ($self,$e,$ndr,$varname) = @_; my $have_default = 0; + $self->pidl("uint32_t level;"); $self->start_flags($e, $ndr); $self->pidl("NDR_PUSH_CHECK_FLAGS(ndr, ndr_flags);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; + $self->pidl("/* This token is not used again (except perhaps below in the NDR_BUFFERS case) */"); + $self->pidl("NDR_CHECK(ndr_push_steal_switch_value($ndr, $varname, &level));"); + $self->ParseUnionPushPrimitives($e, $ndr, $varname); $self->deindent; $self->pidl("}"); if (is_deferred_switch_non_empty($e)) { $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; + # In case we had ndr_flags of NDR_SCALERS|NDR_BUFFERS + $self->pidl("if (!(ndr_flags & NDR_SCALARS)) {"); + $self->indent; + $self->pidl("/* We didn't get it above, and the token is not needed after this. */"); + $self->pidl("NDR_CHECK(ndr_push_steal_switch_value($ndr, $varname, &level));"); + $self->deindent; + $self->pidl("}"); $self->ParseUnionPushDeferred($e, $ndr, $varname); $self->deindent; $self->pidl("}"); @@ -1998,7 +2060,7 @@ sub ParseUnionPrint($$$$$) $self->start_flags($e, $ndr); - $self->pidl("level = ndr_print_get_switch_value($ndr, $varname);"); + $self->pidl("level = ndr_print_steal_switch_value($ndr, $varname);"); $self->pidl("ndr_print_union($ndr, name, level, \"$name\");"); @@ -2038,9 +2100,17 @@ sub ParseUnionPullPrimitives($$$$$) $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));"); } + my $data_type = mapTypeName($switch_type); + my $fmt = mapTypeSpecifier($data_type); + + if (!defined($fmt)) { + $data_type = "int"; + $fmt = "%d"; + } + $self->pidl("NDR_CHECK(ndr_pull_$switch_type($ndr, NDR_SCALARS, &_level));"); - $self->pidl("if (_level != level) {"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u for $varname at \%s\", _level, __location__);"); + $self->pidl("if (_level != level) {"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %$fmt for $varname at \%s\", ($data_type)_level, __location__);"); $self->pidl("}"); } @@ -2058,7 +2128,7 @@ sub ParseUnionPullPrimitives($$$$$) foreach my $el (@{$e->{ELEMENTS}}) { if ($el->{CASE} eq "default") { $have_default = 1; - } + } $self->pidl("$el->{CASE}: {"); if ($el->{TYPE} ne "EMPTY") { @@ -2077,7 +2147,7 @@ sub ParseUnionPullPrimitives($$$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %\"PRIu32\" at %s\", level, __location__);"); } $self->deindent; $self->pidl("}"); @@ -2088,21 +2158,21 @@ sub ParseUnionPullDeferred($$$$) my ($self,$e,$ndr,$varname) = @_; my $have_default = 0; - if (defined($e->{PROPERTIES}{relative_base})) { - # retrieve the current offset as base for relative pointers - # based on the toplevel struct/union - $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); - } $self->pidl("switch (level) {"); $self->indent; foreach my $el (@{$e->{ELEMENTS}}) { if ($el->{CASE} eq "default") { $have_default = 1; - } + } $self->pidl("$el->{CASE}:"); if ($el->{TYPE} ne "EMPTY") { $self->indent; + if (defined($e->{PROPERTIES}{relative_base})) { + # retrieve the current offset as base for relative pointers + # based on the toplevel struct/union + $self->pidl("NDR_CHECK(ndr_pull_setup_relative_base_offset2($ndr, $varname));"); + } $self->ParseElementPull($el, $ndr, {$el->{NAME} => "$varname->$el->{NAME}"}, 0, 1); $self->deindent; } @@ -2111,7 +2181,7 @@ sub ParseUnionPullDeferred($$$$) } if (! $have_default) { $self->pidl("default:"); - $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u at \%s\", level, __location__);"); + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %\"PRIu32\" at %s\", level, __location__);"); } $self->deindent; $self->pidl("}"); @@ -2149,20 +2219,21 @@ sub ParseUnionPull($$$$) $self->pidl("NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);"); $self->pidl("if (ndr_flags & NDR_SCALARS) {"); $self->indent; - if (! $needs_deferred_switch) { - $self->pidl("/* This token is not used again */"); - $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);"); - } else { - $self->pidl("level = ndr_pull_get_switch_value($ndr, $varname);"); - } + $self->pidl("/* This token is not used again (except perhaps below in the NDR_BUFFERS case) */"); + $self->pidl("NDR_CHECK(ndr_pull_steal_switch_value($ndr, $varname, &level));"); $self->ParseUnionPullPrimitives($e,$ndr,$varname,$switch_type); $self->deindent; $self->pidl("}"); if ($needs_deferred_switch) { $self->pidl("if (ndr_flags & NDR_BUFFERS) {"); $self->indent; - $self->pidl("/* The token is not needed after this. */"); - $self->pidl("level = ndr_pull_steal_switch_value($ndr, $varname);"); + # In case we had ndr_flags of NDR_SCALERS|NDR_BUFFERS + $self->pidl("if (!(ndr_flags & NDR_SCALARS)) {"); + $self->indent; + $self->pidl("/* We didn't get it above, and the token is not needed after this. */"); + $self->pidl("NDR_CHECK(ndr_pull_steal_switch_value($ndr, $varname, &level));"); + $self->deindent; + $self->pidl("}"); $self->ParseUnionPullDeferred($e,$ndr,$varname); $self->deindent; $self->pidl("}"); @@ -2175,13 +2246,16 @@ sub ParseUnionPull($$$$) sub DeclUnion($$$$) { my ($e,$t,$name,$varname) = @_; + if ($t eq "base") { + return "union $name $varname"; + } return ($t ne "pull"?"const ":"") . "union $name *$varname"; } sub ArgsUnionNdrSize($$) { my ($d,$name) = @_; - return "const union $name *r, uint32_t level, int flags"; + return "const union $name *r, uint32_t level, libndr_flags flags"; } $typefamily{UNION} = { @@ -2192,7 +2266,7 @@ $typefamily{UNION} = { SIZE_FN_ARGS => \&ArgsUnionNdrSize, SIZE_FN_BODY => \&ParseUnionNdrSize, }; - + ##################################################################### # parse a typedef - push side sub ParseTypedefPush($$$$) @@ -2240,7 +2314,7 @@ sub ParseTypedefNdrSize($$$$) sub DeclTypedef($$$$) { my ($e, $t, $name, $varname) = @_; - + return $typefamily{$e->{DATA}->{TYPE}}->{DECL}->($e->{DATA}, $t, $name, $varname); } @@ -2273,7 +2347,7 @@ sub ParsePipePushChunk($$) my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "push", $name, $varname); - $self->fn_declare("push", $struct, "enum ndr_err_code ndr_push_$name(struct ndr_push *$ndr, int ndr_flags, $args)") or return; + $self->fn_declare("push", $struct, "enum ndr_err_code ndr_push_$name(struct ndr_push *$ndr, ndr_flags_type ndr_flags, $args)") or return; return if has_property($t, "nopush"); @@ -2306,7 +2380,7 @@ sub ParsePipePullChunk($$) my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "pull", $name, $varname); - $self->fn_declare("pull", $struct, "enum ndr_err_code ndr_pull_$name(struct ndr_pull *$ndr, int ndr_flags, $args)") or return; + $self->fn_declare("pull", $struct, "enum ndr_err_code ndr_pull_$name(struct ndr_pull *$ndr, ndr_flags_type ndr_flags, $args)") or return; return if has_property($struct, "nopull"); @@ -2359,11 +2433,11 @@ sub ParseFunctionPrint($$) my($self, $fn) = @_; my $ndr = "ndr"; - $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r);"); + $self->pidl_hdr("void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, ndr_flags_type flags, const struct $fn->{NAME} *r);"); return if has_property($fn, "noprint"); - $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, int flags, const struct $fn->{NAME} *r)"); + $self->pidl("_PUBLIC_ void ndr_print_$fn->{NAME}(struct ndr_print *$ndr, const char *name, ndr_flags_type flags, const struct $fn->{NAME} *r)"); $self->pidl("{"); $self->indent; @@ -2394,7 +2468,7 @@ sub ParseFunctionPrint($$) $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); - + $self->pidl("if (flags & NDR_OUT) {"); $self->indent; $self->pidl("ndr_print_struct($ndr, \"out\", \"$fn->{NAME}\");"); @@ -2412,7 +2486,7 @@ sub ParseFunctionPrint($$) $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); - + $self->pidl("$ndr->depth--;"); $self->deindent; $self->pidl("}"); @@ -2422,18 +2496,18 @@ sub ParseFunctionPrint($$) ##################################################################### # parse a function sub ParseFunctionPush($$) -{ +{ my($self, $fn) = @_; my $ndr = "ndr"; - $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *$ndr, int flags, const struct $fn->{NAME} *r)") or return; + $self->fn_declare("push", $fn, "enum ndr_err_code ndr_push_$fn->{NAME}(struct ndr_push *$ndr, ndr_flags_type flags, const struct $fn->{NAME} *r)") or return; return if has_property($fn, "nopush"); $self->pidl("{"); $self->indent; - foreach my $e (@{$fn->{ELEMENTS}}) { + foreach my $e (@{$fn->{ELEMENTS}}) { $self->DeclareArrayVariables($e); } @@ -2482,7 +2556,7 @@ sub ParseFunctionPush($$) if ($fn->{RETURN_TYPE}) { $self->pidl("NDR_CHECK(ndr_push_$fn->{RETURN_TYPE}($ndr, NDR_SCALARS, r->out.result));"); } - + $self->deindent; $self->pidl("}"); $self->pidl("return NDR_ERR_SUCCESS;"); @@ -2496,8 +2570,8 @@ sub AllocateArrayLevel($$$$$$) my ($self,$e,$l,$ndr,$var,$size) = @_; my $pl = GetPrevLevel($e, $l); - if (defined($pl) and - $pl->{TYPE} eq "POINTER" and + if (defined($pl) and + $pl->{TYPE} eq "POINTER" and $pl->{POINTER_TYPE} eq "ref" and not $l->{IS_ZERO_TERMINATED}) { $self->pidl("if ($ndr->flags & LIBNDR_FLAG_REF_ALLOC) {"); @@ -2516,18 +2590,18 @@ sub AllocateArrayLevel($$$$$$) ##################################################################### # parse a function sub ParseFunctionPull($$) -{ +{ my($self,$fn) = @_; my $ndr = "ndr"; # pull function args - $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *$ndr, int flags, struct $fn->{NAME} *r)") or return; + $self->fn_declare("pull", $fn, "enum ndr_err_code ndr_pull_$fn->{NAME}(struct ndr_pull *$ndr, ndr_flags_type flags, struct $fn->{NAME} *r)") or return; $self->pidl("{"); $self->indent; # declare any internal pointers we need - foreach my $e (@{$fn->{ELEMENTS}}) { + foreach my $e (@{$fn->{ELEMENTS}}) { $self->DeclarePtrVariables($e); $self->DeclareArrayVariables($e, "pull"); } @@ -2551,7 +2625,7 @@ sub ParseFunctionPull($$) # out to be too tricky (tridge) foreach my $e (@{$fn->{ELEMENTS}}) { next unless grep(/out/, @{$e->{DIRECTION}}); - $self->pidl("ZERO_STRUCT(r->out);"); + $self->pidl("NDR_ZERO_STRUCT(r->out);"); $self->pidl(""); last; } @@ -2568,12 +2642,12 @@ sub ParseFunctionPull($$) foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/out/, @{$e->{DIRECTION}})); - next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and + next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref"); - next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and - ($e->{LEVELS}[1]->{DATA_TYPE} eq "string")); + next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and + (Parse::Pidl::Typelist::is_string_type($e->{LEVELS}[1]->{DATA_TYPE}))); next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE"); - next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") + next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}); if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { @@ -2596,11 +2670,11 @@ sub ParseFunctionPull($$) } } else { $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});"); - + if (grep(/in/, @{$e->{DIRECTION}})) { $self->pidl("*r->out.$e->{NAME} = *r->in.$e->{NAME};"); } else { - $self->pidl("ZERO_STRUCTP(r->out.$e->{NAME});"); + $self->pidl("NDR_ZERO_STRUCTP(r->out.$e->{NAME});"); } } } @@ -2608,10 +2682,35 @@ sub ParseFunctionPull($$) $self->add_deferred(); $self->deindent; $self->pidl("}"); - + $self->pidl("if (flags & NDR_OUT) {"); $self->indent; + $self->pidl("#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"); + + # This is for fuzzers of ndr_pull where the out elements refer to + # in elements in size_is or length_is. + # + # Not actually very harmful but also not useful outside a fuzzer + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/in/, @{$e->{DIRECTION}})); + next unless ($e->{LEVELS}[0]->{TYPE} eq "POINTER" and + $e->{LEVELS}[0]->{POINTER_TYPE} eq "ref"); + next if (($e->{LEVELS}[1]->{TYPE} eq "DATA") and + (Parse::Pidl::Typelist::is_string_type($e->{LEVELS}[1]->{DATA_TYPE}))); + next if ($e->{LEVELS}[1]->{TYPE} eq "PIPE"); + next if ($e->{LEVELS}[1]->{TYPE} eq "ARRAY"); + + $self->pidl("if (r->in.$e->{NAME} == NULL) {"); + $self->indent; + $self->pidl("NDR_PULL_ALLOC($ndr, r->in.$e->{NAME});"); + $self->pidl("NDR_ZERO_STRUCTP(r->in.$e->{NAME});"); + $self->deindent; + $self->pidl("}"); + } + + $self->pidl("#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */"); + $env = GenerateFunctionOutEnv($fn); foreach my $e (@{$fn->{ELEMENTS}}) { next unless grep(/out/, @{$e->{DIRECTION}}); @@ -2676,7 +2775,7 @@ sub ParseGeneratePipeArray($$$) $self->deindent; $self->pidl("},"); } - $self->pidl("{ NULL, NULL, 0, NULL, NULL, NULL }"); + $self->pidl("{ .name = NULL }"); $self->deindent; $self->pidl("};"); $self->pidl(""); @@ -2752,27 +2851,57 @@ sub FunctionCallEntry($$) return 1; } +sub StructEntry($$) +{ + my ($self, $d) = @_; + my $type_decl = $typefamily{$d->{TYPE}}->{DECL}->($d, "base", $d->{NAME}, ""); + + $self->pidl("\t{"); + $self->pidl("\t\t.name = \"$d->{NAME}\","); + $self->pidl("\t\t.struct_size = sizeof($type_decl),"); + $self->pidl("\t\t.ndr_push = (ndr_push_flags_fn_t) ndr_push_$d->{NAME},"); + $self->pidl("\t\t.ndr_pull = (ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"); + $self->pidl("\t\t.ndr_print = (ndr_print_function_t) ndr_print_flags_$d->{NAME},"); + $self->pidl("\t},"); + return 1; +} + ##################################################################### # produce a function call table sub FunctionTable($$) { my($self,$interface) = @_; my $count = 0; + my $count_public_structs = 0; my $uname = uc $interface->{NAME}; - return if ($#{$interface->{FUNCTIONS}}+1 == 0); - return unless defined ($interface->{PROPERTIES}->{uuid}); + foreach my $d (@{$interface->{TYPES}}) { + next unless (is_public_struct($d)); + $count_public_structs += 1; + } + return if ($#{$interface->{FUNCTIONS}}+1 == 0 and + $count_public_structs == 0); foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) { $self->FunctionCallPipes($d); } + $self->pidl("static const struct ndr_interface_public_struct $interface->{NAME}\_public_structs[] = {"); + + foreach my $d (@{$interface->{TYPES}}) { + next unless (is_public_struct($d)); + $self->StructEntry($d); + } + $self->pidl("\t{ .name = NULL }"); + $self->pidl("};"); + $self->pidl(""); + $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {"); foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) { $count += $self->FunctionCallEntry($d); } - $self->pidl("\t{ NULL, 0, NULL, NULL, NULL }"); + $self->pidl("\t{ .name = NULL }"); $self->pidl("};"); $self->pidl(""); @@ -2781,7 +2910,7 @@ sub FunctionTable($$) $self->pidl("\t$ep, "); } my $endpoint_count = $#{$interface->{ENDPOINTS}}+1; - + $self->pidl("};"); $self->pidl(""); @@ -2795,18 +2924,22 @@ sub FunctionTable($$) $interface->{PROPERTIES}->{authservice} = "\"host\""; } - $self->AuthServiceStruct($interface->{NAME}, + $self->AuthServiceStruct($interface->{NAME}, $interface->{PROPERTIES}->{authservice}); $self->pidl("\nconst struct ndr_interface_table ndr_table_$interface->{NAME} = {"); $self->pidl("\t.name\t\t= \"$interface->{NAME}\","); - $self->pidl("\t.syntax_id\t= {"); - $self->pidl("\t\t" . print_uuid($interface->{UUID}) .","); - $self->pidl("\t\tNDR_$uname\_VERSION"); - $self->pidl("\t},"); - $self->pidl("\t.helpstring\t= NDR_$uname\_HELPSTRING,"); + if (defined $interface->{PROPERTIES}->{uuid}) { + $self->pidl("\t.syntax_id\t= {"); + $self->pidl("\t\t" . print_uuid($interface->{UUID}) .","); + $self->pidl("\t\tNDR_$uname\_VERSION"); + $self->pidl("\t},"); + $self->pidl("\t.helpstring\t= NDR_$uname\_HELPSTRING,"); + } $self->pidl("\t.num_calls\t= $count,"); $self->pidl("\t.calls\t\t= $interface->{NAME}\_calls,"); + $self->pidl("\t.num_public_structs\t= $count_public_structs,"); + $self->pidl("\t.public_structs\t\t= $interface->{NAME}\_public_structs,"); $self->pidl("\t.endpoints\t= &$interface->{NAME}\_endpoints,"); $self->pidl("\t.authservices\t= &$interface->{NAME}\_authservices"); $self->pidl("};"); @@ -2840,7 +2973,7 @@ sub HeaderInclude ##################################################################### # generate prototypes and defines for the interface definitions -# FIXME: these prototypes are for the DCE/RPC client functions, not the +# FIXME: these prototypes are for the DCE/RPC client functions, not the # NDR parser and so do not belong here, technically speaking sub HeaderInterface($$$) { @@ -2862,7 +2995,7 @@ sub HeaderInterface($$$) if (defined $interface->{PROPERTIES}->{uuid}) { my $name = uc $interface->{NAME}; - $self->pidl_hdr("#define NDR_$name\_UUID " . + $self->pidl_hdr("#define NDR_$name\_UUID " . Parse::Pidl::Util::make_str(lc($interface->{UUID}))); $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{VERSION}"); @@ -2871,7 +3004,15 @@ sub HeaderInterface($$$) if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; } $self->pidl_hdr("#define NDR_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}"); + } + my $count_public_structs = 0; + foreach my $d (@{$interface->{TYPES}}) { + next unless (has_property($d, "public")); + $count_public_structs += 1; + } + if ($#{$interface->{FUNCTIONS}}+1 > 0 or + $count_public_structs > 0) { $self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$interface->{NAME};"); } @@ -2879,12 +3020,12 @@ sub HeaderInterface($$$) next if has_property($_, "noopnum"); next if grep(/^$_->{NAME}$/,@{$interface->{INHERITED_FUNCTIONS}}); my $u_name = uc $_->{NAME}; - + my $val = sprintf("0x%02x", $count); if (defined($interface->{BASE})) { $val .= " + NDR_" . uc $interface->{BASE} . "_CALL_COUNT"; } - + $self->pidl_hdr("#define NDR_$u_name ($val)"); $self->pidl_hdr(""); @@ -2919,7 +3060,7 @@ sub ParseTypePushFunction($$$) my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "push", $e->{NAME}, $varname); - $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *$ndr, int ndr_flags, $args)") or return; + $self->fn_declare("push", $e, "enum ndr_err_code ".TypeFunctionName("ndr_push", $e)."(struct ndr_push *$ndr, ndr_flags_type ndr_flags, $args)") or return; $self->pidl("{"); $self->indent; @@ -2948,7 +3089,7 @@ sub ParseTypePullFunction($$) my $args = $typefamily{$e->{TYPE}}->{DECL}->($e, "pull", $e->{NAME}, $varname); - $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *$ndr, int ndr_flags, $args)") or return; + $self->fn_declare("pull", $e, "enum ndr_err_code ".TypeFunctionName("ndr_pull", $e)."(struct ndr_pull *$ndr, ndr_flags_type ndr_flags, $args)") or return; $self->pidl("{"); $self->indent; @@ -2975,6 +3116,18 @@ sub ParseTypePrintFunction($$$) $self->pidl_hdr("void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *ndr, const char *name, $args);"); + if (is_public_struct($e)) { + $self->pidl("static void ".TypeFunctionName("ndr_print_flags", $e). + "(struct ndr_print *$ndr, const char *name, ndr_flags_type unused, $args)" + ); + $self->pidl("{"); + $self->indent; + $self->pidl(TypeFunctionName("ndr_print", $e)."($ndr, name, $varname);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + } + return if (has_property($e, "noprint")); $self->pidl("_PUBLIC_ void ".TypeFunctionName("ndr_print", $e)."(struct ndr_print *$ndr, const char *name, $args)"); @@ -3040,8 +3193,8 @@ sub ParseInterface($$$) ($needed->{TypeFunctionName("ndr_print", $d)}) && $self->ParseTypePrintFunction($d, "r"); # Make sure we don't generate a function twice... - $needed->{TypeFunctionName("ndr_push", $d)} = - $needed->{TypeFunctionName("ndr_pull", $d)} = + $needed->{TypeFunctionName("ndr_push", $d)} = + $needed->{TypeFunctionName("ndr_pull", $d)} = $needed->{TypeFunctionName("ndr_print", $d)} = 0; ($needed->{"ndr_size_$d->{NAME}"}) && $self->ParseTypeNdrSize($d); @@ -3054,7 +3207,16 @@ sub ParseInterface($$$) ($needed->{"ndr_print_$d->{NAME}"}) && $self->ParseFunctionPrint($d); } + # Allow compilation of generated files where replacement functions + # for structures declared nopull/nopush have not been provided. + # + # This makes sense when only the print functions are used + # + # Otherwise the ndr_table XXX will reference these + + $self->pidl("#ifndef SKIP_NDR_TABLE_$interface->{NAME}"); $self->FunctionTable($interface); + $self->pidl("#endif /* SKIP_NDR_TABLE_$interface->{NAME} */"); $self->pidl_hdr("#endif /* _HEADER_NDR_$interface->{NAME} */"); } @@ -3116,7 +3278,7 @@ sub NeededElement($$$) return if ($e->{TYPE} eq "EMPTY"); - return if (ref($e->{TYPE}) eq "HASH" and + return if (ref($e->{TYPE}) eq "HASH" and not defined($e->{TYPE}->{NAME})); my ($t, $rt); @@ -3180,7 +3342,7 @@ sub NeededType($$$) return unless defined($t->{ELEMENTS}); for my $e (@{$t->{ELEMENTS}}) { $e->{PARENT} = $t; - if (has_property($e, "compression")) { + if (has_property($e, "compression")) { $needed->{"compression"} = 1; } NeededElement($e, $req, $needed); @@ -3198,7 +3360,7 @@ sub NeededInterface($$) foreach (reverse @{$interface->{TYPES}}) { if (has_property($_, "public")) { - $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = + $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = $needed->{TypeFunctionName("ndr_print", $_)} = 1; } @@ -3215,7 +3377,7 @@ sub TypeFunctionName($$) { my ($prefix, $t) = @_; - return "$prefix\_$t->{NAME}" if (ref($t) eq "HASH" and + return "$prefix\_$t->{NAME}" if (ref($t) eq "HASH" and $t->{TYPE} eq "TYPEDEF"); return "$prefix\_$t->{TYPE}_$t->{NAME}" if (ref($t) eq "HASH"); return "$prefix\_$t"; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm index ad36f000..73359987 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm @@ -7,6 +7,7 @@ package Parse::Pidl::Samba4::NDR::Server; use strict; +use warnings; use Parse::Pidl::Util; use vars qw($VERSION); @@ -81,10 +82,10 @@ sub Boilerplate_Iface($) my $if_version = $interface->{VERSION}; pidl " -static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version) +static NTSTATUS $name\__op_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface) { #ifdef DCESRV_INTERFACE_$uname\_BIND - return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); + return DCESRV_INTERFACE_$uname\_BIND(context,iface); #else return NT_STATUS_OK; #endif @@ -120,9 +121,6 @@ static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_C /* unravel the NDR for the packet */ ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - dcerpc_log_packet(dce_call->conn->packet_log_dir, - &ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); dce_call->fault_code = DCERPC_FAULT_NDR; return NT_STATUS_NET_WRITE_FAULT; } @@ -145,9 +143,6 @@ pidl " } if (dce_call->fault_code != 0) { - dcerpc_log_packet(dce_call->conn->packet_log_dir, - &ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); return NT_STATUS_NET_WRITE_FAULT; } @@ -169,9 +164,6 @@ pidl " } if (dce_call->fault_code != 0) { - dcerpc_log_packet(dce_call->conn->packet_log_dir, - &ndr_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); return NT_STATUS_NET_WRITE_FAULT; } @@ -201,6 +193,7 @@ static const struct dcesrv_interface dcesrv\_$name\_interface = { .dispatch = $name\__op_dispatch, .reply = $name\__op_reply, .ndr_push = $name\__op_ndr_push, + .local = NULL, #ifdef DCESRV_INTERFACE_$uname\_FLAGS .flags = DCESRV_INTERFACE_$uname\_FLAGS #else @@ -223,12 +216,22 @@ sub Boilerplate_Ep_Server($) static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) { int i; +#ifdef DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT + const char *ncacn_np_secondary_endpoint = + DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT; +#else + const char *ncacn_np_secondary_endpoint = NULL; +#endif for (i=0;i<ndr_table_$name.endpoints->count;i++) { NTSTATUS ret; const char *name = ndr_table_$name.endpoints->names[i]; - ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$name\_interface, NULL); + ret = dcesrv_interface_register(dce_ctx, + name, + ncacn_np_secondary_endpoint, + &dcesrv_$name\_interface, + NULL); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name)); return ret; @@ -238,6 +241,11 @@ static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const str return NT_STATUS_OK; } +static NTSTATUS $name\__op_shutdown_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) +{ + return NT_STATUS_OK; +} + static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version) { if (dcesrv_$name\_interface.syntax_id.if_version == if_version && @@ -266,12 +274,20 @@ NTSTATUS dcerpc_server_$name\_init(TALLOC_CTX *ctx) /* fill in our name */ .name = \"$name\", + /* Initialization flag */ + .initialized = false, + /* fill in all the operations */ #ifdef DCESRV_INTERFACE_$uname\_INIT_SERVER .init_server = DCESRV_INTERFACE_$uname\_INIT_SERVER, #else .init_server = $name\__op_init_server, #endif +#ifdef DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER + .shutdown_server = DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER, +#else + .shutdown_server = $name\__op_shutdown_server, +#endif .interface_by_uuid = $name\__op_interface_by_uuid, .interface_by_name = $name\__op_interface_by_name }; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/ServerCompat.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/ServerCompat.pm new file mode 100644 index 00000000..aaa10ffd --- /dev/null +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/ServerCompat.pm @@ -0,0 +1,624 @@ +################################################### +# server boilerplate generator +# Copyright tridge@samba.org 2003 +# Copyright metze@samba.org 2004 +# Copyright scabrero@samba.org 2019 +# released under the GNU GPL + +package Parse::Pidl::Samba4::NDR::ServerCompat; + +use Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(Parse); + +use Parse::Pidl::Util qw(print_uuid has_property ParseExpr); +use Parse::Pidl::Typelist qw(mapTypeName); +use Parse::Pidl qw(error fatal); +use Parse::Pidl::NDR qw(ContainsPipe GetNextLevel); +use Parse::Pidl::Samba4 qw(ElementStars); +use Parse::Pidl::Samba4::Header qw(GenerateFunctionOutEnv); + +use vars qw($VERSION); +$VERSION = '1.0'; + +use strict; + +sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; } +sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); } +sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; } +sub pidlnoindent($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$txt\n" : "\n"; } +sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; } +sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; } + +sub new($) +{ + my ($class) = shift; + my $self = { res => "", res_hdr => "", tabs => "" }; + bless($self, $class); +} + +sub decl_level($$) +{ + my ($self, $e, $l) = @_; + my $res = ""; + + if (has_property($e, "charset")) { + $res .= "const char"; + } else { + $res .= mapTypeName($e->{TYPE}); + } + + my $stars = ElementStars($e, $l); + + $res .= " ".$stars unless ($stars eq ""); + + return $res; +} + +sub alloc_out_var($$$$$) +{ + my ($self, $e, $mem_ctx, $name, $env, $alloc_error_block) = @_; + + my $l = $e->{LEVELS}[0]; + + # we skip pointer to arrays + if ($l->{TYPE} eq "POINTER") { + my $nl = GetNextLevel($e, $l); + $l = $nl if ($nl->{TYPE} eq "ARRAY"); + } elsif + + # we don't support multi-dimensional arrays yet + ($l->{TYPE} eq "ARRAY") { + my $nl = GetNextLevel($e, $l); + if ($nl->{TYPE} eq "ARRAY") { + fatal($e->{ORIGINAL},"multi-dimensional [out] arrays are not supported!"); + } + } else { + # neither pointer nor array, no need to alloc something. + return; + } + + if ($l->{TYPE} eq "ARRAY") { + unless(defined($l->{SIZE_IS})) { + error($e->{ORIGINAL}, "No size known for array `$e->{NAME}'"); + $self->pidl("#error No size known for array `$e->{NAME}'"); + } else { + my $size = ParseExpr($l->{SIZE_IS}, $env, $e); + $self->pidl("$name = talloc_zero_array($mem_ctx, " . $self->decl_level($e, 1) . ", $size);"); + } + } else { + $self->pidl("$name = talloc_zero($mem_ctx, " . $self->decl_level($e, 1) . ");"); + } + + $self->pidl("if ($name == NULL) {"); + $self->indent(); + foreach (@{$alloc_error_block}) { + $self->pidl($_); + } + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); +} + +sub gen_fn_out($$) +{ + my ($self, $fn, $alloc_error_block) = @_; + + my $hasout = 0; + foreach (@{$fn->{ELEMENTS}}) { + if (grep(/out/, @{$_->{DIRECTION}})) { + $hasout = 1; + } + } + + if ($hasout) { + $self->pidl("NDR_ZERO_STRUCT(r2->out);"); + } + + foreach (@{$fn->{ELEMENTS}}) { + my @dir = @{$_->{DIRECTION}}; + if (grep(/in/, @dir) and grep(/out/, @dir)) { + $self->pidl("r2->out.$_->{NAME} = r2->in.$_->{NAME};"); + } + } + + foreach (@{$fn->{ELEMENTS}}) { + next if ContainsPipe($_, $_->{LEVELS}[0]); + + my @dir = @{$_->{DIRECTION}}; + + if (grep(/in/, @dir) and grep(/out/, @dir)) { + # noop + } elsif (grep(/out/, @dir) and not has_property($_, "represent_as")) { + my $env = GenerateFunctionOutEnv($fn, "r2->"); + $self->alloc_out_var($_, "r2", "r2->out.$_->{NAME}", $env, $alloc_error_block); + } + + } +} + +##################################################### +# generate the switch statement for function dispatch +sub gen_dispatch_switch($) +{ + my ($self, $interface) = @_; + + my @alloc_error_block = ("status = NT_STATUS_NO_MEMORY;", + "p->fault_state = DCERPC_FAULT_CANT_PERFORM;", + "goto fail;"); + foreach my $fn (@{$interface->{FUNCTIONS}}) { + next if not defined($fn->{OPNUM}); + + my $fname = $fn->{NAME}; + my $ufname = uc($fname); + + $self->pidl("case $fn->{OPNUM}: { /* $fn->{NAME} */"); + $self->indent(); + $self->pidl("struct $fname *r2 = (struct $fname *)r;"); + $self->pidl("if (DEBUGLEVEL >= 10) {"); + $self->indent(); + $self->pidl("NDR_PRINT_FUNCTION_DEBUG($fname, NDR_IN, r2);"); + $self->deindent(); + $self->pidl("}"); + + $self->gen_fn_out($fn, \@alloc_error_block); + + $self->pidl_hdr("struct $fname;"); + + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + $self->pidl_hdr(mapTypeName($fn->{RETURN_TYPE}) . " _$fname(struct pipes_struct *p, struct $fname *r);"); + $self->pidl("r2->out.result = _$fname(p, r2);"); + } else { + $self->pidl_hdr("void _$fname(struct pipes_struct *p, struct $fname *r);"); + $self->pidl("_$fname(p, r2);"); + } + + $self->pidl("break;"); + $self->deindent(); + $self->pidl("}"); + } +} + +##################################################### +# generate the switch statement for function reply +sub gen_reply_switch($) +{ + my ($self, $interface) = @_; + + foreach my $fn (@{$interface->{FUNCTIONS}}) { + next if not defined($fn->{OPNUM}); + + $self->pidl("case $fn->{OPNUM}: { /* $fn->{NAME} */"); + $self->indent(); + $self->pidl("struct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;"); + $self->pidl("if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {"); + $self->indent(); + $self->pidl("DEBUG(5,(\"function $fn->{NAME} replied async\\n\"));"); + $self->deindent(); + $self->pidl("}"); + $self->pidl("if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {"); + $self->indent(); + $self->pidl("NDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);"); + $self->deindent(); + $self->pidl("}"); + $self->pidl("if (dce_call->fault_code != 0) {"); + $self->indent(); + $self->pidl("DBG_WARNING(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code));"); + $self->deindent(); + $self->pidl("}"); + $self->pidl("break;"); + $self->deindent(); + $self->pidl("}"); + } +} + +##################################################################### +# produce boilerplate code for a interface +sub boilerplate_iface($) +{ + my ($self, $interface) = @_; + + my $name = $interface->{NAME}; + my $uname = uc $name; + my $uuid = lc($interface->{UUID}); + my $if_version = $interface->{VERSION}; + + $self->pidl("static NTSTATUS $name\__op_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)"); + $self->pidl("{"); + $self->indent(); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_BIND"); + $self->pidl("return DCESRV_INTERFACE_$uname\_BIND(context,iface);"); + $self->pidlnoindent("#else"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("#endif"); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)"); + $self->pidl("{"); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_UNBIND"); + $self->indent(); + $self->pidl("DCESRV_INTERFACE_$uname\_UNBIND(context, iface);"); + $self->pidlnoindent("#else"); + $self->pidl("return;"); + $self->pidlnoindent("#endif"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl_hdr("NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r);"); + $self->pidl("NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("enum ndr_err_code ndr_err;"); + $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;"); + $self->pidl(""); + $self->pidl("dce_call->fault_code = 0;"); + $self->pidl(""); + $self->pidl("if (opnum >= ndr_table_$name.num_calls) {"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;"); + $self->pidl("return NT_STATUS_NET_WRITE_FAULT;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("*r = talloc_named(mem_ctx, ndr_table_$name.calls[opnum].struct_size, \"struct %s\", ndr_table_$name.calls[opnum].name);"); + $self->pidl("NT_STATUS_HAVE_NO_MEMORY(*r);"); + $self->pidl(""); + $self->pidl("/* unravel the NDR for the packet */"); + $self->pidl("ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);"); + $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_NDR;"); + $self->pidl("return NT_STATUS_NET_WRITE_FAULT;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static NTSTATUS $name\__op_dispatch_internal(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r, enum s3compat_rpc_dispatch dispatch)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;"); + $self->pidl("struct pipes_struct *p = NULL;"); + $self->pidl("NTSTATUS status = NT_STATUS_OK;"); + $self->pidl("bool impersonated = false;"); + $self->pidl(""); + $self->pidl("/* Retrieve pipes struct */"); + $self->pidl("p = dcesrv_get_pipes_struct(dce_call->conn);"); + $self->pidl("p->dce_call = dce_call;"); + $self->pidl("p->mem_ctx = mem_ctx;"); + $self->pidl("/* Reset pipes struct fault state */"); + $self->pidl("p->fault_state = 0;"); + $self->pidl(""); + + $self->pidl("/* Impersonate */"); + $self->pidl("if (dispatch == S3COMPAT_RPC_DISPATCH_EXTERNAL) {"); + $self->indent(); + $self->pidl("impersonated = become_authenticated_pipe_user(dce_call->auth_state->session_info);"); + $self->pidl("if (!impersonated) {"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;"); + $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;"); + $self->pidl("goto fail;"); + $self->deindent(); + $self->pidl("}"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("switch (opnum) {"); + $self->gen_dispatch_switch($interface); + $self->pidl("default:"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;"); + $self->pidl("break;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidlnoindent("fail:"); + $self->pidl("/* Unimpersonate */"); + $self->pidl("if (impersonated) {"); + $self->indent(); + $self->pidl("unbecome_authenticated_pipe_user();"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("p->dce_call = NULL;"); + $self->pidl("p->mem_ctx = NULL;"); + $self->pidl("/* Check pipes struct fault state */"); + $self->pidl("if (p->fault_state != 0) {"); + $self->indent(); + $self->pidl("dce_call->fault_code = p->fault_state;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl("if (dce_call->fault_code != 0) {"); + $self->indent(); + $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("return status;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl_hdr("NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r);"); + $self->pidl("NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("return $name\__op_dispatch_internal(dce_call, mem_ctx, r, S3COMPAT_RPC_DISPATCH_EXTERNAL);"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl_hdr("NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r);"); + $self->pidl("NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;"); + $self->pidl(""); + $self->pidl("switch (opnum) {"); + $self->gen_reply_switch($interface); + $self->pidl("default:"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;"); + $self->pidl("break;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("if (dce_call->fault_code != 0) {"); + $self->indent(); + $self->pidl("return NT_STATUS_NET_WRITE_FAULT;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl_hdr("NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r);"); + $self->pidl("NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("enum ndr_err_code ndr_err;"); + $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;"); + $self->pidl(""); + $self->pidl("ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);"); + $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {"); + $self->indent(); + $self->pidl("dce_call->fault_code = DCERPC_FAULT_NDR;"); + $self->pidl("return NT_STATUS_NET_WRITE_FAULT;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + ############################## + #### LOCAL DISPATCH #### + ############################## + $self->pidl_hdr("NTSTATUS $name\__op_local(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r);"); + $self->pidl("NTSTATUS $name\__op_local(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("return $name\__op_dispatch_internal(dce_call, mem_ctx, r, S3COMPAT_RPC_DISPATCH_INTERNAL);"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static const struct dcesrv_interface dcesrv\_$name\_interface = {"); + $self->indent(); + $self->pidl(".name = \"$name\","); + $self->pidl(".syntax_id = {".print_uuid($uuid).",$if_version},"); + $self->pidl(".bind = $name\__op_bind,"); + $self->pidl(".unbind = $name\__op_unbind,"); + $self->pidl(".ndr_pull = $name\__op_ndr_pull,"); + $self->pidl(".dispatch = $name\__op_dispatch,"); + $self->pidl(".reply = $name\__op_reply,"); + $self->pidl(".ndr_push = $name\__op_ndr_push,"); + $self->pidl(".local = $name\__op_local,"); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_FLAGS"); + $self->pidl(".flags = DCESRV_INTERFACE_$uname\_FLAGS"); + $self->pidlnoindent("#else"); + $self->pidl(".flags = 0"); + $self->pidlnoindent("#endif"); + $self->deindent(); + $self->pidl("};"); + $self->pidl(""); +} + +##################################################################### +# produce boilerplate code for an endpoint server +sub boilerplate_ep_server($) +{ + my ($self, $interface) = @_; + my $name = $interface->{NAME}; + my $uname = uc $name; + + $self->pidl("static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("uint32_t i;"); + $self->pidl("NTSTATUS ret;"); + $self->pidl(""); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT"); + $self->pidl("const char *ncacn_np_secondary_endpoint = DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT;"); + $self->pidlnoindent("#else"); + $self->pidl("const char *ncacn_np_secondary_endpoint = NULL;"); + $self->pidlnoindent("#endif"); + $self->pidl(""); + $self->pidl("for (i=0;i<ndr_table_$name.endpoints->count;i++) {"); + $self->indent(); + $self->pidl("const char *name = ndr_table_$name.endpoints->names[i];"); + $self->pidl(""); + $self->pidl("ret = dcesrv_interface_register(dce_ctx, name, ncacn_np_secondary_endpoint, &dcesrv_$name\_interface, NULL);"); + $self->pidl("if (!NT_STATUS_IS_OK(ret)) {"); + $self->indent(); + $self->pidl("DBG_ERR(\"Failed to register endpoint \'%s\'\\n\",name);"); + $self->pidl("return ret;"); + $self->deindent(); + $self->pidl("}"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static NTSTATUS $name\__op_shutdown_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("if (dcesrv_$name\_interface.syntax_id.if_version == if_version && GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {"); + $self->indent(); + $self->pidl("memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));"); + $self->pidl("return true;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return false;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("if (strcmp(dcesrv_$name\_interface.name, name)==0) {"); + $self->indent(); + $self->pidl("memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface));"); + $self->pidl("return true;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + $self->pidl("return false;"); + $self->deindent(); + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("static const struct dcesrv_endpoint_server $name\_ep_server = {"); + $self->indent(); + $self->pidl("/* fill in our name */"); + $self->pidl(".name = \"$name\","); + $self->pidl(""); + $self->pidl("/* Initialization flag */"); + $self->pidl(".initialized = false,"); + $self->pidl(""); + $self->pidl("/* fill in all the operations */"); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_INIT_SERVER"); + $self->pidl(".init_server = DCESRV_INTERFACE_$uname\_INIT_SERVER,"); + $self->pidlnoindent("#else"); + $self->pidl(".init_server = $name\__op_init_server,"); + $self->pidlnoindent("#endif"); + $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER"); + $self->pidl(".shutdown_server = DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER,"); + $self->pidlnoindent("#else"); + $self->pidl(".shutdown_server = $name\__op_shutdown_server,"); + $self->pidlnoindent("#endif"); + $self->pidl(".interface_by_uuid = $name\__op_interface_by_uuid,"); + $self->pidl(".interface_by_name = $name\__op_interface_by_name"); + $self->deindent(); + $self->pidl("};"); + $self->pidl(""); + + $self->pidl("const struct dcesrv_endpoint_server *$name\_get_ep_server(void)"); + $self->pidl("{"); + $self->indent(); + $self->pidl("return &$name\_ep_server;"); + $self->deindent(); + $self->pidl("}"); +} + +##################################################################### +# dcerpc server boilerplate from a parsed IDL structure +sub parse_interface($) +{ + my ($self, $interface) = @_; + my $count = 0; + my $uif = uc($interface->{NAME}); + + + $self->pidl_hdr("#ifndef __NDR_${uif}_SCOMPAT_H__"); + $self->pidl_hdr("#define __NDR_${uif}_SCOMPAT_H__"); + $self->pidl_hdr(""); + $self->pidl_hdr("struct pipes_struct;"); + $self->pidl_hdr("struct dcesrv_endpoint_server;"); + $self->pidl_hdr("struct dcesrv_call_state;"); + $self->pidl_hdr(""); + $self->pidl_hdr("const struct dcesrv_endpoint_server *$interface->{NAME}\_get_ep_server(void);"); + $self->pidl_hdr(""); + + if (!defined $interface->{PROPERTIES}->{uuid}) { + $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */"); + return; + } + + if (!defined $interface->{PROPERTIES}->{version}) { + $interface->{PROPERTIES}->{version} = "0.0"; + } + + foreach my $fn (@{$interface->{FUNCTIONS}}) { + if (defined($fn->{OPNUM})) { $count++; } + } + + if ($count == 0) { + $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */"); + return; + } + + $self->pidl("/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */"); + $self->boilerplate_iface($interface); + $self->boilerplate_ep_server($interface); + + $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */"); +} + +sub Parse($$) +{ + my ($self, $ndr, $h_scompat, $header) = @_; + + $self->pidl("/* s3 compat server functions auto-generated by pidl */"); + $self->pidl("#include \"$header\""); + $self->pidl("#include \"$h_scompat\""); + + $self->pidl("#include <librpc/rpc/dcesrv_core.h>"); + $self->pidl("#include <rpc_server/rpc_config.h>"); + $self->pidl("#include <rpc_server/rpc_server.h>"); + $self->pidl("#include <util/debug.h>"); + $self->pidl(""); + $self->pidl("enum s3compat_rpc_dispatch {"); + $self->indent(); + $self->pidl("S3COMPAT_RPC_DISPATCH_EXTERNAL = 0x00000001,"); + $self->pidl("S3COMPAT_RPC_DISPATCH_INTERNAL = 0x00000002,"); + $self->deindent(); + $self->pidl("};"); + $self->pidl(""); + + foreach my $x (@{$ndr}) { + $self->parse_interface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object})); + } + + return ($self->{res}, $self->{res_hdr}); +} + +1; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm index f418ac48..d7ccf830 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -4,11 +4,10 @@ # released under the GNU GPL package Parse::Pidl::Samba4::Python; - -use Exporter; -@ISA = qw(Exporter); +use parent Parse::Pidl::Base; use strict; +use warnings; use Parse::Pidl qw(warning fatal error); use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias bitmap_type_fn enum_type_fn); use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); @@ -17,6 +16,7 @@ use Parse::Pidl::CUtil qw(get_value_of get_pointer_to); use Parse::Pidl::Samba4 qw(ArrayDynamicallyAllocated); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); + use vars qw($VERSION); $VERSION = '0.01'; @@ -34,41 +34,11 @@ sub new($) { bless($self, $class); } -sub pidl_hdr ($$) -{ - my $self = shift; - $self->{res_hdr} .= shift; -} - -sub pidl($$) -{ - my ($self, $d) = @_; - if ($d) { - if ((!($d =~ /^#/))) { - $self->{res} .= $self->{tabs}; - } - $self->{res} .= $d; - } - $self->{res} .= "\n"; -} - -sub indent($) -{ - my ($self) = @_; - $self->{tabs} .= "\t"; -} - -sub deindent($) -{ - my ($self) = @_; - $self->{tabs} = substr($self->{tabs}, 0, -1); -} - sub PrettifyTypeName($$) { my ($name, $basename) = @_; - $basename =~ s/^.*\.([^.]+)$/\1/; + $basename =~ s/^.*\.([^.]+)$/$1/; $name =~ s/^$basename\_//; @@ -83,7 +53,7 @@ sub Import foreach (@imports) { $_ = unmake_str($_); s/\.idl$//; - $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\"\n"); + $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\""); $self->register_module_import("samba.dcerpc.$_"); } } @@ -199,8 +169,16 @@ sub PythonElementGetSet($$$$$$) { $self->pidl("static PyObject *py_$name\_get_$e->{NAME}(PyObject *obj, void *closure)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(obj);"); $self->pidl("PyObject *py_$e->{NAME};"); + my $l = $e->{LEVELS}[0]; + if ($l->{TYPE} eq "POINTER") { + $self->pidl("if ($varname == NULL) {"); + $self->indent; + $self->pidl("Py_RETURN_NONE;"); + $self->deindent; + $self->pidl("}"); + } $self->ConvertObjectToPython("pytalloc_get_mem_ctx(obj)", $env, $e, $varname, "py_$e->{NAME}", "return NULL;"); $self->pidl("return py_$e->{NAME};"); $self->deindent; @@ -210,9 +188,8 @@ sub PythonElementGetSet($$$$$$) { $self->pidl("static int py_$name\_set_$e->{NAME}(PyObject *py_obj, PyObject *value, void *closure)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); my $mem_ctx = "pytalloc_get_mem_ctx(py_obj)"; - my $l = $e->{LEVELS}[0]; my $nl = GetNextLevel($e, $l); if ($l->{TYPE} eq "POINTER" and not ($nl->{TYPE} eq "ARRAY" and ($nl->{IS_FIXED} or is_charset_array($e, $nl))) and @@ -279,10 +256,10 @@ sub PythonStruct($$$$$$) # If the struct is not public there ndr_pull/ndr_push functions will # be static so not callable from here if (has_property($d, "public")) { - $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); $self->pidl("PyObject *ret = NULL;"); $self->pidl("DATA_BLOB blob;"); $self->pidl("enum ndr_err_code err;"); @@ -312,8 +289,8 @@ sub PythonStruct($$$$$$) $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, PyObject *args, PyObject *kwargs)"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); - $self->pidl("DATA_BLOB blob;"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); + $self->pidl("DATA_BLOB blob = {.data = NULL, .length = 0};"); $self->pidl("Py_ssize_t blob_length = 0;"); $self->pidl("enum ndr_err_code err;"); $self->pidl("const char * const kwnames[] = { \"data_blob\", \"allow_remaining\", NULL };"); @@ -359,15 +336,15 @@ sub PythonStruct($$$$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; - $self->pidl("$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"); + $self->pidl("$cname *object = pytalloc_get_ptr(py_obj);"); $self->pidl("PyObject *ret;"); $self->pidl("char *retstr;"); $self->pidl(""); $self->pidl("retstr = ndr_print_struct_string(pytalloc_get_mem_ctx(py_obj), (ndr_print_fn_t)ndr_print_$name, \"$name\", object);"); - $self->pidl("ret = PyStr_FromString(retstr);"); + $self->pidl("ret = PyUnicode_FromString(retstr);"); $self->pidl("talloc_free(retstr);"); $self->pidl(""); $self->pidl("return ret;"); @@ -379,7 +356,7 @@ sub PythonStruct($$$$$$) $self->pidl("static PyMethodDef $py_methods\[] = {"); $self->indent; $self->pidl("{ \"__ndr_pack__\", (PyCFunction)py_$name\_ndr_pack, METH_NOARGS, \"S.ndr_pack(object) -> blob\\nNDR pack\" },"); - $self->pidl("{ \"__ndr_unpack__\", (PyCFunction)py_$name\_ndr_unpack, METH_VARARGS|METH_KEYWORDS, \"S.ndr_unpack(class, blob, allow_remaining=False) -> None\\nNDR unpack\" },"); + $self->pidl("{ \"__ndr_unpack__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack), METH_VARARGS|METH_KEYWORDS, \"S.ndr_unpack(class, blob, allow_remaining=False) -> None\\nNDR unpack\" },"); $self->pidl("{ \"__ndr_print__\", (PyCFunction)py_$name\_ndr_print, METH_NOARGS, \"S.ndr_print(object) -> None\\nNDR print\" },"); $self->pidl("{ NULL, NULL, 0, NULL }"); $self->deindent; @@ -387,7 +364,7 @@ sub PythonStruct($$$$$$) $self->pidl(""); } - $self->pidl_hdr("static PyTypeObject $name\_Type;\n"); + $self->pidl_hdr("static PyTypeObject $name\_Type;"); $self->pidl(""); my $docstring = $self->DocString($d, $name); my $typeobject = "$name\_Type"; @@ -491,7 +468,62 @@ sub PythonFunctionStruct($$$$) $self->pidl("static PyObject *py_$name\_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)"); $self->pidl("{"); $self->indent; - $self->pidl("return pytalloc_new($cname, type);"); + + # This creates a new, zeroed C structure and python object. + # These may not be valid or sensible values, but this is as + # well as we can do. + + $self->pidl("PyObject *self = pytalloc_new($cname, type);"); + + # If there are any children that are ref pointers, we need to + # allocate something for them to point to just as the pull + # routine will when parsing the structure from NDR. + # + # We then make those pointers point to zeroed memory + # + # A ref pointer is a pointer in the C structure but a scalar + # on the wire. It is for a remote function like: + # + # int foo(int *i) + # + # This may be called with the pointer by reference eg foo(&i) + # + # That is why this only goes as far as the next level; deeply + # nested pointer chains will end in a NULL. + + my @ref_elements; + foreach my $e (@{$fn->{ELEMENTS}}) { + if (has_property($e, "ref") && ! has_property($e, "charset")) { + if (!has_property($e, 'in') && !has_property($e, 'out')) { + die "ref pointer that is not in or out"; + } + push @ref_elements, $e; + } + } + if (@ref_elements) { + $self->pidl("$cname *_self = ($cname *)pytalloc_get_ptr(self);"); + $self->pidl("TALLOC_CTX *mem_ctx = pytalloc_get_mem_ctx(self);"); + foreach my $e (@ref_elements) { + my $ename = $e->{NAME}; + my $t = mapTypeName($e->{TYPE}); + my $p = $e->{ORIGINAL}->{POINTERS} // 1; + if ($p > 1) { + $self->pidl("/* a pointer to a NULL pointer */"); + $t .= ' ' . '*' x ($p - 1); + } + + # We checked in the loop above that each ref + # pointer is in or out (or both) + if (has_property($e, 'in')) { + $self->pidl("_self->in.$ename = talloc_zero(mem_ctx, $t);"); + } + + if (has_property($e, 'out')) { + $self->pidl("_self->out.$ename = talloc_zero(mem_ctx, $t);"); + } + } + } + $self->pidl("return self;"); $self->deindent; $self->pidl("}"); $self->pidl(""); @@ -499,19 +531,19 @@ sub PythonFunctionStruct($$$$) my $py_methods = "NULL"; my $ndr_call = "const struct ndr_interface_call *call = NULL;"; - my $object_ptr = "$cname *object = ($cname *)pytalloc_get_ptr(py_obj);"; + my $object_ptr = "$cname *object = pytalloc_get_ptr(py_obj);"; - $self->pidl("static PyObject *py_$name\_ndr_opnum(PyTypeObject *type)"); + $self->pidl("static PyObject *py_$name\_ndr_opnum(PyTypeObject *type, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl(""); $self->pidl(""); - $self->pidl("return PyInt_FromLong($fn->{OPNUM});"); + $self->pidl("return PyLong_FromLong($fn->{OPNUM});"); $self->deindent; $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, int ndr_inout_flags, uint32_t ndr_push_flags)"); + $self->pidl("static PyObject *py_$name\_ndr_pack(PyObject *py_obj, ndr_flags_type ndr_inout_flags, libndr_flags ndr_push_flags)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -562,7 +594,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl("libndr_flags ndr_push_flags = 0;"); $self->pidl(""); $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_in__\","); $self->indent; @@ -597,7 +629,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"bigendian\", \"ndr64\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_push_flags = 0;"); + $self->pidl("libndr_flags ndr_push_flags = 0;"); $self->pidl(""); $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"|OO:__ndr_pack_out__\","); $self->indent; @@ -626,7 +658,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, const DATA_BLOB *blob, int ndr_inout_flags, uint32_t ndr_pull_flags, bool allow_remaining)"); + $self->pidl("static PyObject *py_$name\_ndr_unpack(PyObject *py_obj, const DATA_BLOB *blob, ndr_flags_type ndr_inout_flags, libndr_flags ndr_pull_flags, bool allow_remaining)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -703,7 +735,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("libndr_flags ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); $self->pidl("PyObject *allow_remaining_obj = NULL;"); $self->pidl("bool allow_remaining = false;"); $self->pidl(""); @@ -751,7 +783,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("const char * const kwnames[] = { \"data_blob\", \"bigendian\", \"ndr64\", \"allow_remaining\", NULL };"); $self->pidl("PyObject *bigendian_obj = NULL;"); $self->pidl("PyObject *ndr64_obj = NULL;"); - $self->pidl("uint32_t ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); + $self->pidl("libndr_flags ndr_pull_flags = LIBNDR_FLAG_REF_ALLOC;"); $self->pidl("PyObject *allow_remaining_obj = NULL;"); $self->pidl("bool allow_remaining = false;"); $self->pidl(""); @@ -791,7 +823,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, const char *name, int ndr_inout_flags)"); + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj, const char *name, ndr_flags_type ndr_inout_flags)"); $self->pidl("{"); $self->indent; $self->pidl("$ndr_call"); @@ -809,7 +841,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("call = &ndr_table_$iface\.calls[$fn->{OPNUM}];"); $self->pidl(""); $self->pidl("retstr = ndr_print_function_string(pytalloc_get_mem_ctx(py_obj), call->ndr_print, name, ndr_inout_flags, object);"); - $self->pidl("ret = PyStr_FromString(retstr);"); + $self->pidl("ret = PyUnicode_FromString(retstr);"); $self->pidl("TALLOC_FREE(retstr);"); $self->pidl(""); $self->pidl("return ret;"); @@ -817,7 +849,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print_in(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print_in(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_in\", NDR_IN);"); @@ -825,7 +857,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("static PyObject *py_$name\_ndr_print_out(PyObject *py_obj)"); + $self->pidl("static PyObject *py_$name\_ndr_print_out(PyObject *py_obj, PyObject *Py_UNUSED(ignored))"); $self->pidl("{"); $self->indent; $self->pidl("return py_$name\_ndr_print(py_obj, \"$name\_out\", NDR_OUT);"); @@ -840,19 +872,19 @@ sub PythonFunctionStruct($$$$) $self->indent; $self->pidl("\"$modulename.$prettyname.opnum() -> ".sprintf("%d (0x%02x)", $fn->{OPNUM}, $fn->{OPNUM})." \" },"); $self->deindent; - $self->pidl("{ \"__ndr_pack_in__\", (PyCFunction)py_$name\_ndr_pack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_pack_in__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_pack_in), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_pack_in(object, bigendian=False, ndr64=False) -> blob\\nNDR pack input\" },"); $self->deindent; - $self->pidl("{ \"__ndr_pack_out__\", (PyCFunction)py_$name\_ndr_pack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_pack_out__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_pack_out), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_pack_out(object, bigendian=False, ndr64=False) -> blob\\nNDR pack output\" },"); $self->deindent; - $self->pidl("{ \"__ndr_unpack_in__\", (PyCFunction)py_$name\_ndr_unpack_in, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_unpack_in__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack_in), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_unpack_in(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack input\" },"); $self->deindent; - $self->pidl("{ \"__ndr_unpack_out__\", (PyCFunction)py_$name\_ndr_unpack_out, METH_VARARGS|METH_KEYWORDS,"); + $self->pidl("{ \"__ndr_unpack_out__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$name\_ndr_unpack_out), METH_VARARGS|METH_KEYWORDS,"); $self->indent; $self->pidl("\"S.ndr_unpack_out(class, blob, bigendian=False, ndr64=False, allow_remaining=False) -> None\\nNDR unpack output\" },"); $self->deindent; @@ -863,7 +895,7 @@ sub PythonFunctionStruct($$$$) $self->pidl("};"); $self->pidl(""); - $self->pidl_hdr("static PyTypeObject $name\_Type;\n"); + $self->pidl_hdr("static PyTypeObject $name\_Type;"); $self->pidl(""); my $docstring = $self->DocString($fn, $name); my $typeobject = "$name\_Type"; @@ -1235,7 +1267,7 @@ sub PythonType($$$$) $self->pidl("PyObject *in = NULL;"); $self->pidl("$typename *out = NULL;"); $self->pidl(""); - $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:import\","); + $self->pidl("if (!PyArg_ParseTupleAndKeywords(args, kwargs, \"OiO:export\","); $self->indent; $self->pidl("discard_const_p(char *, kwnames),"); $self->pidl("&mem_ctx_obj,"); @@ -1269,12 +1301,12 @@ sub PythonType($$$$) $py_methods = "py_$d->{NAME}_methods"; $self->pidl("static PyMethodDef $py_methods\[] = {"); $self->indent; - $self->pidl("{ \"__import__\", (PyCFunction)py_$d->{NAME}\_import,"); + $self->pidl("{ \"__import__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$d->{NAME}\_import),"); $self->indent; $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,"); $self->pidl("\"T.__import__(mem_ctx, level, in) => ret.\" },"); $self->deindent; - $self->pidl("{ \"__export__\", (PyCFunction)py_$d->{NAME}\_export,"); + $self->pidl("{ \"__export__\", PY_DISCARD_FUNC_SIG(PyCFunction,py_$d->{NAME}\_export),"); $self->indent; $self->pidl("METH_VARARGS|METH_KEYWORDS|METH_CLASS,"); $self->pidl("\"T.__export__(mem_ctx, level, in) => ret.\" },"); @@ -1294,7 +1326,7 @@ sub PythonType($$$$) $self->pidl(""); $self->pidl(""); - $self->pidl_hdr("static PyTypeObject $typeobject;\n"); + $self->pidl_hdr("static PyTypeObject $typeobject;"); $self->pidl("static PyTypeObject $typeobject = {"); $self->indent; $self->pidl("PyVarObject_HEAD_INIT(NULL, 0)"); @@ -1349,7 +1381,7 @@ sub Interface($$$) } if (defined $interface->{PROPERTIES}->{uuid}) { - $self->pidl_hdr("static PyTypeObject $interface->{NAME}_InterfaceType;\n"); + $self->pidl_hdr("static PyTypeObject $interface->{NAME}_InterfaceType;"); $self->pidl(""); my @fns = (); @@ -1387,7 +1419,7 @@ sub Interface($$$) my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d; $self->pidl("{ \"$prettyname\", $docstring, (py_dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },"); } - $self->pidl("{ NULL }"); + $self->pidl("{0}"); $self->deindent; $self->pidl("};"); $self->pidl(""); @@ -1446,9 +1478,9 @@ sub Interface($$$) $self->pidl(""); - my $signature = "\"$interface->{NAME}_abstract_syntax()\\n\""; + $signature = "\"$interface->{NAME}_abstract_syntax()\\n\""; - my $docstring = $self->DocString($interface, $interface->{NAME}."_syntax"); + $docstring = $self->DocString($interface, $interface->{NAME}."_syntax"); if ($docstring) { $docstring = "$signature$docstring"; @@ -1482,7 +1514,7 @@ sub Interface($$$) ""]); } - $self->pidl_hdr("\n"); + $self->pidl_hdr(""); } sub register_module_method($$$$$) @@ -1635,7 +1667,6 @@ sub ConvertStringFromPythonData($$$$$) $self->pidl("unicode = PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\");"); $self->pidl("if (unicode == NULL) {"); $self->indent; - $self->pidl("PyErr_NoMemory();"); $self->pidl("$fail"); $self->deindent; $self->pidl("}"); @@ -1669,6 +1700,27 @@ sub ConvertStringFromPythonData($$$$$) $self->pidl("}"); } +sub ConvertU16StringFromPythonData($$$$$) +{ + my ($self, $mem_ctx, $py_var, $target, $fail) = @_; + + $self->pidl("{"); + $self->indent; + $self->pidl("unsigned char *str = NULL;"); + $self->pidl(""); + $self->pidl("str = PyUtf16String_FromBytes("); + $self->pidl(" $mem_ctx, $py_var);"); + $self->pidl("if (str == NULL) {"); + $self->indent; + $self->pidl("$fail"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $self->pidl("$target = str;"); + $self->deindent; + $self->pidl("}"); +} + sub ConvertObjectFromPythonData($$$$$$;$$) { my ($self, $mem_ctx, $cvar, $ctype, $target, $fail, $location, $switch) = @_; @@ -1715,21 +1767,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var > uint_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %llu\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); - $self->pidl($fail); - $self->deindent; - $self->pidl("}"); - $self->pidl("$target = test_var;"); - $self->deindent; - $self->pidl("} else if (PyInt_Check($cvar)) {"); - $self->indent; - $self->pidl("long test_var;"); - $self->pidl("test_var = PyInt_AsLong($cvar);"); - $self->pidl("if (test_var < 0 || test_var > uint_max) {"); - $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range 0 - %llu, got %ld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, uint_max, test_var);"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range 0 - %llu, got %llu\","); + $self->pidl(" PyLong_Type.tp_name, uint_max, test_var);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1737,8 +1776,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); + $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1767,21 +1806,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->pidl("}"); $self->pidl("if (test_var < int_min || test_var > int_max) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %lld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); - $self->pidl($fail); - $self->deindent; - $self->pidl("}"); - $self->pidl("$target = test_var;"); - $self->deindent; - $self->pidl("} else if (PyInt_Check($cvar)) {"); - $self->indent; - $self->pidl("long test_var;"); - $self->pidl("test_var = PyInt_AsLong($cvar);"); - $self->pidl("if (test_var < int_min || test_var > int_max) {"); - $self->indent; - $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s or %s within range %lld - %lld, got %ld\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name, int_min, int_max, test_var);"); + $self->pidl("PyErr_Format(PyExc_OverflowError, \"Expected type %s within range %lld - %lld, got %lld\","); + $self->pidl(" PyLong_Type.tp_name, int_min, int_max, test_var);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1789,8 +1815,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) $self->deindent; $self->pidl("} else {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s or %s\",\\"); - $self->pidl(" PyInt_Type.tp_name, PyLong_Type.tp_name);"); + $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected type %s\","); + $self->pidl(" PyLong_Type.tp_name);"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1803,7 +1829,8 @@ sub ConvertObjectFromPythonData($$$$$$;$$) my $ctype_name = $self->use_type_variable($ctype); unless (defined ($ctype_name)) { error($location, "Unable to determine origin of type `" . mapTypeName($ctype) . "'"); - $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " from Python\");"); + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Cannot convert Python object to NDR $target\");"); + $self->pidl("$fail"); return; } $self->pidl("PY_CHECK_TYPE($ctype_name, $cvar, $fail);"); @@ -1849,18 +1876,24 @@ sub ConvertObjectFromPythonData($$$$$$;$$) return; } + if ($actual_ctype->{TYPE} eq "SCALAR" and + $actual_ctype->{NAME} eq "u16string") { + $self->ConvertU16StringFromPythonData($mem_ctx, $cvar, $target, $fail); + return; + } + if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") { - $self->pidl("$target = NT_STATUS(PyInt_AsLong($cvar));"); + $self->pidl("$target = NT_STATUS(PyLong_AsLong($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "WERROR") { - $self->pidl("$target = W_ERROR(PyInt_AsLong($cvar));"); + $self->pidl("$target = W_ERROR(PyLong_AsLong($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "HRESULT") { - $self->pidl("$target = HRES_ERROR(PyInt_AsLong($cvar));"); + $self->pidl("$target = HRES_ERROR(PyLong_AsLong($cvar));"); return; } @@ -1893,8 +1926,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) if ($recurse == 0) { $self->pidl("if ($py_var == NULL) {"); $self->indent; - $self->pidl("PyErr_Format(PyExc_AttributeError, \"Cannot delete NDR object: " . - mapTypeName($var_name) . "\");"); + $self->pidl("PyErr_Format(PyExc_AttributeError, \"Cannot delete NDR object: $var_name\");"); $self->pidl($fail); $self->deindent; $self->pidl("}"); @@ -1902,6 +1934,9 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $recurse = $recurse + 1; if ($l->{TYPE} eq "POINTER") { + my $need_deindent = 0; + my $need_deref = 0; + if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($py_var == Py_None) {"); $self->indent; @@ -1909,10 +1944,13 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $self->deindent; $self->pidl("} else {"); $self->indent; + $need_deindent = 1; + if ($nl->{TYPE} eq "POINTER") { + $need_deref = 1; + } } - # if we want to handle more than one level of pointer in python interfaces - # then this is where we would need to allocate it - if ($l->{POINTER_TYPE} eq "ref") { + + if ($l->{POINTER_TYPE} eq "ref" or $need_deref == 1) { $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); $self->pidl("if ($var_name == NULL) {"); $self->indent; @@ -1932,11 +1970,20 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) } else { $self->pidl("$var_name = NULL;"); } + if ($need_deref == 1) { + my $ndr_pointer_typename = $self->import_type_variable("samba.dcerpc.base", "ndr_pointer"); + $self->pidl("$py_var = py_dcerpc_ndr_pointer_deref($ndr_pointer_typename, $py_var);"); + $self->pidl("if ($py_var == NULL) {"); + $self->indent; + $self->pidl($fail); + $self->deindent; + $self->pidl("}"); + } unless ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { $var_name = get_value_of($var_name); } $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail, $recurse); - if ($l->{POINTER_TYPE} ne "ref") { + if ($need_deindent == 1) { $self->deindent; $self->pidl("}"); } @@ -1955,7 +2002,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) $self->pidl("int $counter;"); if (ArrayDynamicallyAllocated($e, $l)) { $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_GET_SIZE($py_var));"); - $self->pidl("if (!$var_name) { $fail; }"); + $self->pidl("if (!$var_name) { $fail }"); $self->pidl("talloc_set_name_const($var_name, \"ARRAY: $var_name\");"); } else { $self->pidl("if (ARRAY_SIZE($var_name) != PyList_GET_SIZE($py_var)) {"); @@ -1967,7 +2014,11 @@ sub ConvertObjectFromPythonLevel($$$$$$$$$) } $self->pidl("for ($counter = 0; $counter < PyList_GET_SIZE($py_var); $counter++) {"); $self->indent; - $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, $var_name."[$counter]", $fail, 0); + if (ArrayDynamicallyAllocated($e, $l)) { + $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, "($var_name)"."[$counter]", $fail, 0); + } else { + $self->ConvertObjectFromPythonLevel($env, $mem_ctx, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, "($var_name)"."[$counter]", $fail, 0); + } $self->deindent; $self->pidl("}"); $self->deindent; @@ -2015,15 +2066,15 @@ sub ConvertScalarToPython($$$$) $ctypename = expandAlias($ctypename); if ($ctypename =~ /^(int64|dlong)$/) { - return "ndr_PyLong_FromLongLong($cvar)"; + return "PyLong_FromLongLong($cvar)"; } if ($ctypename =~ /^(uint64|hyper|NTTIME_hyper|NTTIME|NTTIME_1sec|udlong|udlongr|uid_t|gid_t)$/) { - return "ndr_PyLong_FromUnsignedLongLong($cvar)"; + return "PyLong_FromUnsignedLongLong($cvar)"; } if ($ctypename =~ /^(char|int|int8|int16|int32|time_t)$/) { - return "PyInt_FromLong($cvar)"; + return "PyLong_FromLong($cvar)"; } # Needed to ensure unsigned values in a 32 or 16 bit enum is @@ -2031,11 +2082,11 @@ sub ConvertScalarToPython($$$$) # possibly 64 bit unsigned long. (enums are signed in C, # unsigned in NDR) if ($ctypename =~ /^(uint32|uint3264)$/) { - return "ndr_PyLong_FromUnsignedLongLong((uint32_t)$cvar)"; + return "PyLong_FromUnsignedLongLong((uint32_t)($cvar))"; } if ($ctypename =~ /^(uint|uint8|uint16|uint1632)$/) { - return "PyInt_FromLong((uint16_t)$cvar)"; + return "PyLong_FromLong((uint16_t)($cvar))"; } if ($ctypename eq "DATA_BLOB") { @@ -2062,6 +2113,10 @@ sub ConvertScalarToPython($$$$) return "PyString_FromStringOrNULL($cvar)"; } + if ($ctypename eq "u16string") { + return "PyBytes_FromUtf16StringOrNULL($cvar)"; + } + # Not yet supported if ($ctypename eq "string_array") { return "pytalloc_GenericObject_reference_ex($mem_ctx, $cvar)"; @@ -2138,6 +2193,10 @@ sub ConvertObjectToPythonLevel($$$$$$$) } if ($l->{TYPE} eq "POINTER") { + my $need_wrap = 0; + if ($l->{POINTER_TYPE} ne "ref" and $nl->{TYPE} eq "POINTER") { + $need_wrap = 1; + } if ($l->{POINTER_TYPE} ne "ref") { if ($recurse == 0) { $self->pidl("if ($var_name == NULL) {"); @@ -2164,6 +2223,19 @@ sub ConvertObjectToPythonLevel($$$$$$$) $self->deindent; $self->pidl("}"); } + if ($need_wrap) { + my $py_var_wrap = undef; + $need_wrap = 1; + $self->pidl("{"); + $self->indent; + $py_var_wrap = "py_$e->{NAME}_level_$l->{LEVEL_INDEX}"; + $self->pidl("PyObject *$py_var_wrap = $py_var;"); + my $ndr_pointer_typename = $self->import_type_variable("samba.dcerpc.base", "ndr_pointer"); + $self->pidl("$py_var = py_dcerpc_ndr_pointer_wrap($ndr_pointer_typename, $py_var_wrap);"); + $self->pidl("Py_XDECREF($py_var_wrap);"); + $self->deindent; + $self->pidl("}"); + } } elsif ($l->{TYPE} eq "ARRAY") { if ($pl && $pl->{TYPE} eq "POINTER") { $var_name = get_pointer_to($var_name); @@ -2199,7 +2271,11 @@ sub ConvertObjectToPythonLevel($$$$$$$) $self->indent; my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}"; $self->pidl("PyObject *$member_var;"); - $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name."[$counter]", $member_var, $fail, $recurse); + if (ArrayDynamicallyAllocated($e, $l)) { + $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, "($var_name)"."[$counter]", $member_var, $fail, $recurse); + } else { + $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, "($var_name)"."[$counter]", $member_var, $fail, $recurse); + } $self->pidl("PyList_SetItem($py_var, $counter, $member_var);"); $self->deindent; $self->pidl("}"); @@ -2219,6 +2295,10 @@ sub ConvertObjectToPythonLevel($$$$$$$) } my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name, $e->{ORIGINAL}); $self->pidl("$py_var = $conv;"); + if ($conv eq "NULL") { + $self->pidl("PyErr_SetString(PyExc_NotImplementedError, \"Cannot convert NDR $var_name to Python\");"); + $self->pidl("$fail"); + } } elsif ($l->{TYPE} eq "SUBCONTEXT") { $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, $var_name, $py_var, $fail, $recurse); } else { @@ -2240,19 +2320,37 @@ sub Parse($$$$$) $self->{BASENAME} = $basename; + my $ndr_hdr_include = ""; + if (defined($ndr_hdr)) { + $ndr_hdr_include = "#include \"$ndr_hdr\""; + } $self->pidl_hdr(" /* Python wrapper functions auto-generated by pidl */ #define PY_SSIZE_T_CLEAN 1 /* We use Py_ssize_t for PyArg_ParseTupleAndKeywords */ -#include <Python.h> +#include \"lib/replace/system/python.h\" #include \"python/py3compat.h\" #include \"includes.h\" +#include \"python/modules.h\" #include <pytalloc.h> #include \"librpc/rpc/pyrpc.h\" #include \"librpc/rpc/pyrpc_util.h\" #include \"$hdr\" -#include \"$ndr_hdr\" +$ndr_hdr_include /* + * Suppress compiler warnings if the generated code does not call these + * functions + */ +#ifndef _MAYBE_UNUSED_ +#ifdef __has_attribute +#if __has_attribute(unused) +#define _MAYBE_UNUSED_ __attribute__ ((unused)) +#else +#define _MAYBE_UNUSED_ +#endif +#endif +#endif +/* * These functions are here to ensure they can be optimized out by * the compiler based on the constant input values */ @@ -2273,7 +2371,7 @@ static inline unsigned long long ndr_sizeof2uintmax(size_t var_size) return 0; } -static inline long long ndr_sizeof2intmax(size_t var_size) +static inline _MAYBE_UNUSED_ long long ndr_sizeof2intmax(size_t var_size) { switch (var_size) { case 8: @@ -2288,25 +2386,6 @@ static inline long long ndr_sizeof2intmax(size_t var_size) return 0; } - -static inline PyObject *ndr_PyLong_FromLongLong(long long v) -{ - if (v > LONG_MAX || v < LONG_MIN) { - return PyLong_FromLongLong(v); - } else { - return PyInt_FromLong(v); - } -} - -static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) -{ - if (v > LONG_MAX) { - return PyLong_FromUnsignedLongLong(v); - } else { - return PyInt_FromLong(v); - } -} - "); foreach my $x (@$ndr) { @@ -2340,9 +2419,9 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("MODULE_INIT_FUNC($basename)"); $self->pidl("{"); $self->indent; - $self->pidl("PyObject *m;"); + $self->pidl("PyObject *m = NULL;"); foreach my $h (@{$self->{module_imports}}) { - $self->pidl("PyObject *$h->{'key'};"); + $self->pidl("PyObject *$h->{'key'} = NULL;"); } $self->pidl(""); @@ -2351,20 +2430,20 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) my $module_path = $h->{'val'}; $self->pidl("$var_name = PyImport_ImportModule(\"$module_path\");"); $self->pidl("if ($var_name == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } foreach my $h (@{$self->{type_imports}}) { my $type_var = "$h->{'key'}\_Type"; my $module_path = $h->{'val'}; - $self->pidl_hdr("static PyTypeObject *$type_var;\n"); + $self->pidl_hdr("static PyTypeObject *$type_var;"); my $pretty_name = PrettifyTypeName($h->{'key'}, $module_path); my $module_var = "dep_$module_path"; $module_var =~ s/\./_/g; $self->pidl("$type_var = (PyTypeObject *)PyObject_GetAttrString($module_var, \"$pretty_name\");"); $self->pidl("if ($type_var == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); } @@ -2372,7 +2451,7 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) foreach (@{$self->{ready_types}}) { $self->pidl("if (PyType_Ready($_) < 0)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); } $self->pidl($_) foreach (@{$self->{postreadycode}}); @@ -2388,16 +2467,16 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("m = PyModule_Create(&moduledef);"); $self->pidl("if (m == NULL)"); - $self->pidl("\treturn NULL;"); + $self->pidl("\tgoto out;"); $self->pidl(""); foreach my $h (@{$self->{constants}}) { my $pretty_name = PrettifyTypeName($h->{'key'}, $basename); my $py_obj; my ($ctype, $cvar) = @{$h->{'val'}}; if ($cvar =~ /^[0-9]+$/ or $cvar =~ /^0x[0-9a-fA-F]+$/) { - $py_obj = "ndr_PyLong_FromUnsignedLongLong($cvar)"; + $py_obj = "PyLong_FromUnsignedLongLong($cvar)"; } elsif ($cvar =~ /^".*"$/) { - $py_obj = "PyStr_FromString($cvar)"; + $py_obj = "PyUnicode_FromString($cvar)"; } else { $py_obj = $self->ConvertObjectToPythonData("NULL", expandAlias($ctype), $cvar, undef); } @@ -2414,7 +2493,11 @@ static inline PyObject *ndr_PyLong_FromUnsignedLongLong(unsigned long long v) $self->pidl("#ifdef PY_MOD_".uc($basename)."_PATCH"); $self->pidl("PY_MOD_".uc($basename)."_PATCH(m);"); $self->pidl("#endif"); - + $self->pidl("out:"); + foreach my $h (@{$self->{module_imports}}) { + my $mod_var = $h->{'key'}; + $self->pidl("Py_XDECREF($mod_var);"); + } $self->pidl("return m;"); $self->pidl(""); $self->deindent; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm b/tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm index c0749304..c3282879 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm @@ -9,25 +9,20 @@ use Parse::Pidl::Util qw(has_property ParseExpr is_constant); use Parse::Pidl::Samba4 qw(is_intree choose_header); use Parse::Pidl::Typelist qw(mapTypeName); -use Exporter; -@ISA = qw(Exporter); -@EXPORT_OK = qw(ParserType $ret $ret_hdr); +use base Parse::Pidl::Base; use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; sub new($) { my ($class) = shift; - my $self = { ret => "", ret_hdr => "", tabs => "" }; + my $self = { res => "", res_hdr => "", tabs => "" }; bless($self, $class); } -sub indent($) { my $self = shift; $self->{tabs}.="\t"; } -sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); } -sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; } -sub pidl_hdr($$) { my $self = shift; $self->{ret_hdr} .= (shift)."\n"; } sub typearg($) { my $t = shift; return(", const char *name") if ($t eq "print"); @@ -277,7 +272,7 @@ sub Parser($$$$) $self->pidl_hdr(""); foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); } - return ($self->{ret_hdr}, $self->{ret}); + return ($self->{res_hdr}, $self->{res}); } 1; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Template.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Template.pm index 175bb124..870d2388 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Template.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Template.pm @@ -11,6 +11,7 @@ $VERSION = '0.01'; use Parse::Pidl::Util qw(genpad); use strict; +use warnings; my($res); diff --git a/tools/pidl/lib/Parse/Pidl/Typelist.pm b/tools/pidl/lib/Parse/Pidl/Typelist.pm index 774554f0..2a98a16b 100644 --- a/tools/pidl/lib/Parse/Pidl/Typelist.pm +++ b/tools/pidl/lib/Parse/Pidl/Typelist.pm @@ -7,27 +7,30 @@ package Parse::Pidl::Typelist; require Exporter; @ISA = qw(Exporter); -@EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias +@EXPORT_OK = qw(hasType getType resolveType mapTypeName mapTypeSpecifier scalar_is_reference expandAlias mapScalarType addType typeIs is_signed is_scalar enum_type_fn bitmap_type_fn mapType typeHasBody is_fixed_size_scalar + is_string_type ); use vars qw($VERSION); $VERSION = '0.01'; use Parse::Pidl::Util qw(has_property); use strict; +use warnings; my %types = (); my @reference_scalars = ( "string", "string_array", "nbt_string", "dns_string", "wrepl_nbt_name", "dnsp_name", "dnsp_string", - "ipv4address", "ipv6address" + "ipv4address", "ipv6address", "u16string" ); my @non_fixed_size_scalars = ( "string", "string_array", "nbt_string", "dns_string", - "wrepl_nbt_name", "dnsp_name", "dnsp_string" + "wrepl_nbt_name", "dnsp_name", "dnsp_string", + "u16string" ); # a list of known scalar types @@ -45,6 +48,7 @@ my %scalars = ( "int3264" => "int32_t", "uint3264" => "uint32_t", "hyper" => "uint64_t", + "int64" => "int64_t", "dlong" => "int64_t", "udlong" => "uint64_t", "udlongr" => "uint64_t", @@ -52,6 +56,7 @@ my %scalars = ( "pointer" => "void*", "DATA_BLOB" => "DATA_BLOB", "string" => "const char *", + "u16string" => "const unsigned char *", "string_array" => "const char **", "time_t" => "time_t", "uid_t" => "uid_t", @@ -70,6 +75,8 @@ my %scalars = ( "ipv6address" => "const char *", "dnsp_name" => "const char *", "dnsp_string" => "const char *", + "libndr_flags" => "libndr_flags", + "ndr_flags_type"=> "ndr_flags_type", ); my %aliases = ( @@ -87,6 +94,18 @@ my %aliases = ( "mode_t" => "uint32", ); +my %format_specifiers = ( + "char" => "c", + "int8_t", => "\"PRId8\"", + "int16_t", => "\"PRId16\"", + "int32_t", => "\"PRId32\"", + "int64_t", => "\"PRId64\"", + "uint8_t", => "\"PRIu8\"", + "uint16_t", => "\"PRIu16\"", + "uint32_t", => "\"PRIu32\"", + "uint64_t", => "\"PRIu64\"" +); + sub expandAlias($) { my $name = shift; @@ -119,8 +138,18 @@ sub resolveType($) my ($ctype) = @_; if (not hasType($ctype)) { - # assume struct typedef - return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } }; + if (! ref $ctype) { + # it looks like a name. + # assume struct typedef + return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } }; + } + if ($ctype->{NAME} && ($ctype->{TYPE} eq "STRUCT")) { + return { + TYPE => "TYPEDEF", + NAME => $ctype->{NAME}, + DATA => $ctype + }; + } } else { return getType($ctype); } @@ -158,7 +187,7 @@ sub hasType($) my $t = shift; if (ref($t) eq "HASH") { return 1 if (not defined($t->{NAME})); - return 1 if (defined($types{$t->{NAME}}) and + return 1 if (defined($types{$t->{NAME}}) and $types{$t->{NAME}}->{TYPE} eq $t->{TYPE}); return 0; } @@ -184,13 +213,13 @@ sub is_scalar($) sub is_scalar($); my $type = shift; - return 1 if (ref($type) eq "HASH" and - ($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or + return 1 if (ref($type) eq "HASH" and + ($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or $type->{TYPE} eq "BITMAP")); if (my $dt = getType($type)) { return is_scalar($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF"); - return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or + return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or $dt->{TYPE} eq "BITMAP"); } @@ -214,6 +243,13 @@ sub scalar_is_reference($) return 0; } +sub is_string_type +{ + my ($t) = @_; + + return ($t eq "string" or $t eq "u16string"); +} + sub RegisterScalars() { foreach (keys %scalars) { @@ -314,6 +350,14 @@ sub mapTypeName($) } +sub mapTypeSpecifier($) +{ + my $t = shift; + return undef unless defined($t); + + return $format_specifiers{$t}; +} + sub LoadIdl($;$) { my $idl = shift; diff --git a/tools/pidl/lib/Parse/Pidl/Util.pm b/tools/pidl/lib/Parse/Pidl/Util.pm index 83e23937..7a6039ba 100644 --- a/tools/pidl/lib/Parse/Pidl/Util.pm +++ b/tools/pidl/lib/Parse/Pidl/Util.pm @@ -6,11 +6,12 @@ package Parse::Pidl::Util; require Exporter; @ISA = qw(Exporter); -@EXPORT = qw(has_property property_matches ParseExpr ParseExprExt is_constant make_str unmake_str print_uuid MyDumper genpad); +@EXPORT = qw(has_property property_matches ParseExpr ParseExprExt is_constant make_str unmake_str print_uuid MyDumper genpad parse_int parse_range); use vars qw($VERSION); $VERSION = '0.01'; use strict; +use warnings; use Parse::Pidl::Expr; use Parse::Pidl qw(error); @@ -190,6 +191,41 @@ sub genpad($) return "\t"x($nt)." "x($ns); } +=item B<parse_int> + +Try to convert hex and octal strings to numbers. If a string doesn't +look hexish or octish it will be left as is. If the unconverted string +is actually a decimal number, Perl is likely to handle it correctly. + +=cut + +sub parse_int { + my $s = shift; + if ($s =~ /^0[xX][0-9A-Fa-f]+$/) { + return hex $s; + } + if ($s =~ /^0[0-7]+$/) { + return oct $s; + } + return $s; +} + +=item B<parse_range> + +Read a range specification that might contain hex or octal numbers, +and work out what those numbers are. + +=cut + +sub parse_range { + my $range = shift; + my ($low, $high) = split(/,/, $range, 2); + $low = parse_int($low); + $high = parse_int($high); + return ($low, $high); +} + + =back =cut diff --git a/tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm b/tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm index 01a8c473..7f7ef184 100644 --- a/tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm +++ b/tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm @@ -115,6 +115,7 @@ $VERSION = '0.01'; @EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type); use strict; +use warnings; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property); diff --git a/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm b/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm index ada8dd66..6f672330 100644 --- a/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm @@ -21,8 +21,9 @@ use Exporter; @EXPORT_OK = qw(field2name %res PrintIdl StripPrefixes RegisterInterfaceHandoff register_hf_field CheckUsed ProcessImport ProcessInclude find_type DumpEttList DumpEttDeclaration DumpHfList DumpHfDeclaration DumpFunctionTable register_type register_ett); use strict; +use warnings; use Parse::Pidl qw(error warning); -use Parse::Pidl::Typelist qw(getType); +use Parse::Pidl::Typelist qw(getType mapScalarType); use Parse::Pidl::Util qw(has_property property_matches make_str); use Parse::Pidl::NDR qw(ContainsString GetNextLevel); use Parse::Pidl::Dump qw(DumpType DumpFunction); @@ -41,6 +42,26 @@ my %ptrtype_mappings = ( "ptr" => "NDR_POINTER_PTR" ); +my %variable_scalars = ( + "int1632" => "int32_t", + "uint1632" => "uint32_t", + "int3264" => "int64_t", + "uint3264" => "uint64_t", +); + +# map from an IDL type to a C header type, using the on-the-wire length. +# Produces different results than mapScalarType in Parse::Pidl::Typelist +# for the types that have different wire lengths in NDR and NDR64 (i.e., +# includes the padding for uint1632 and uint3264, unlike that function.) +sub mapWireScalarType($) +{ + my ($name) = shift; + + return $variable_scalars{$name} if defined($variable_scalars{$name}); + + return mapScalarType($name); +} + sub StripPrefixes($$) { my ($s, $prefixes) = @_; @@ -151,7 +172,7 @@ sub Enum($$$$) } $self->pidl_hdr("extern const value_string $valsstring\[];"); - $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, g$e->{BASE_TYPE} *param _U_);"); + $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, " . mapWireScalarType($e->{BASE_TYPE}) ." *param _U_);"); $self->pidl_def("const value_string ".$valsstring."[] = {"); foreach (@{$e->{ELEMENTS}}) { @@ -164,10 +185,10 @@ sub Enum($$$$) $self->pidl_fn_start($dissectorname); $self->pidl_code("int"); - $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, g$e->{BASE_TYPE} *param _U_)"); + $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, " . mapWireScalarType($e->{BASE_TYPE}) . " *param _U_)"); $self->pidl_code("{"); $self->indent; - $self->pidl_code("g$e->{BASE_TYPE} parameter=0;"); + $self->pidl_code(mapWireScalarType($e->{BASE_TYPE}) . " parameter=0;"); $self->pidl_code("if (param) {"); $self->indent; $self->pidl_code("parameter = *param;"); @@ -186,7 +207,9 @@ sub Enum($$$$) my $enum_size = $e->{BASE_TYPE}; $enum_size =~ s/uint//g; - $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);", "FT_UINT$enum_size", "BASE_DEC", "0", "VALS($valsstring)", $enum_size / 8); + my $ws_base = "BASE_DEC"; + $ws_base = "BASE_HEX" if (property_matches($e, "flag", ".*LIBNDR_PRINT_ARRAY_HEX.*")); + $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);", "FT_UINT$enum_size", $ws_base, "0", "VALS($valsstring)", $enum_size / 8); } sub Pipe($$$$) @@ -205,11 +228,11 @@ sub Bitmap($$$$) $self->register_ett("ett_$ifname\_$name"); - $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);"); + $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, uint32_t param _U_);"); $self->pidl_fn_start($dissectorname); $self->pidl_code("int"); - $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)"); + $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, uint32_t param _U_)"); $self->pidl_code("{"); $self->indent; foreach (@{$e->{ELEMENTS}}) { @@ -236,7 +259,7 @@ sub Bitmap($$$$) $self->pidl_code("};"); } - $self->pidl_code("g$e->{BASE_TYPE} flags;"); + $self->pidl_code(mapWireScalarType($e->{BASE_TYPE}) . " flags;"); if ($e->{ALIGN} > 1) { $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); } @@ -335,9 +358,10 @@ sub ElementLevel($$$$$$$$) $self->pidl_code("offset = dissect_ndr_u" . $type . "array(tvb, offset, pinfo, tree, di, drep, $myname\_);"); } else { my $nl = GetNextLevel($e,$l); + my $nl_ctype = mapScalarType($nl->{DATA_TYPE}); $self->pidl_code("char *data;"); $self->pidl_code(""); - $self->pidl_code("offset = dissect_ndr_$type" . "string(tvb, offset, pinfo, tree, di, drep, sizeof(g$nl->{DATA_TYPE}), $hf, FALSE, &data);"); + $self->pidl_code("offset = dissect_ndr_$type" . "string(tvb, offset, pinfo, tree, di, drep, sizeof($nl_ctype), $hf, false, &data);"); $self->pidl_code("proto_item_append_text(tree, \": %s\", data);"); } } @@ -350,10 +374,10 @@ sub ElementLevel($$$$$$$$) if (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*") and property_matches($e, "flag", ".*LIBNDR_FLAG_STR_LEN4.*")) { $self->pidl_code("char *data;\n"); - $self->pidl_code("offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, $bs, $hf, FALSE, &data);"); + $self->pidl_code("offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, $bs, $hf, false, &data);"); $self->pidl_code("proto_item_append_text(tree, \": %s\", data);"); } elsif (property_matches($e, "flag", ".*LIBNDR_FLAG_STR_SIZE4.*")) { - $self->pidl_code("offset = dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep, $bs, $hf, FALSE, NULL);"); + $self->pidl_code("offset = dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep, $bs, $hf, false, NULL);"); } elsif (property_matches($e, "flag", ".*STR_NULLTERM.*")) { if ($bs == 2) { $self->pidl_code("offset = dissect_null_term_wstring(tvb, offset, pinfo, tree, drep, $hf , 0);") @@ -405,7 +429,7 @@ sub ElementLevel($$$$$$$$) my $hf2 = $self->register_hf_field($hf."_", "Subcontext length", "$ifname.$pn.$_->{NAME}subcontext", "FT_UINT$num_bits", "BASE_HEX", "NULL", 0, ""); $num_bits = 3264 if ($num_bits == 32); $self->{hf_used}->{$hf2} = 1; - $self->pidl_code("guint$num_bits size;"); + $self->pidl_code("uint${num_bits}_t size;"); $self->pidl_code("int conformant = di->conformant_run;"); $self->pidl_code("tvbuff_t *subtvb;"); $self->pidl_code(""); @@ -413,14 +437,14 @@ sub ElementLevel($$$$$$$$) # and conformant run skips the dissections of scalars ... $self->pidl_code("if (!conformant) {"); $self->indent; - $self->pidl_code("guint32 saved_flags = di->call_data->flags;"); + $self->pidl_code("uint32_t saved_flags = di->call_data->flags;"); $self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, di, drep, $hf2, &size);"); # This is a subcontext, there is normally no such thing as # 64 bit NDR is subcontext so we clear the flag so that we can # continue to dissect handmarshalled stuff with pidl $self->pidl_code("di->call_data->flags &= ~DCERPC_IS_NDR64;"); - $self->pidl_code("subtvb = tvb_new_subset_length_caplen(tvb, offset, (const gint)size, -1);"); + $self->pidl_code("subtvb = tvb_new_subset_length_caplen(tvb, offset, (const int)size, -1);"); if ($param ne 0) { $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, di, drep, $param);"); } else { @@ -477,7 +501,7 @@ sub Element($$$$$$) if (not defined($switch_raw_type)) { die("Unknown type[$type]\n"); } - my $switch_type = "g${switch_raw_type}"; + my $switch_type = mapWireScalarType(${switch_raw_type}); if ($name ne "") { $moreparam = ", $switch_type *".$name; @@ -552,10 +576,10 @@ sub Element($$$$$$) } next if ($_->{TYPE} eq "SWITCH"); next if (defined($self->{conformance}->{noemit}->{"$dissectorname$add"})); - $self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_$moreparam);"); + $self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_$moreparam);"); $self->pidl_fn_start("$dissectorname$add"); $self->pidl_code("static int"); - $self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_$moreparam)"); + $self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_$moreparam)"); $self->pidl_code("{"); $self->indent; @@ -583,7 +607,7 @@ sub Function($$$) my %dissectornames; foreach (@{$fn->{ELEMENTS}}) { - $dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname, undef, undef) if not defined($dissectornames{$_->{NAME}}); + $dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname, undef, ()) if not defined($dissectornames{$_->{NAME}}); } my $fn_name = $_->{NAME}; @@ -592,18 +616,18 @@ sub Function($$$) $self->PrintIdl(DumpFunction($fn->{ORIGINAL})); $self->pidl_fn_start("$ifname\_dissect\_$fn_name\_response"); $self->pidl_code("static int"); - $self->pidl_code("$ifname\_dissect\_${fn_name}_response(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_)"); + $self->pidl_code("$ifname\_dissect\_${fn_name}_response(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_)"); $self->pidl_code("{"); $self->indent; if ( not defined($fn->{RETURN_TYPE})) { } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS" or $fn->{RETURN_TYPE} eq "WERROR" or $fn->{RETURN_TYPE} eq "HRESULT") { - $self->pidl_code("guint32 status;\n"); + $self->pidl_code("uint32_t status;\n"); } elsif (my $type = getType($fn->{RETURN_TYPE})) { if ($type->{DATA}->{TYPE} eq "ENUM") { - $self->pidl_code("g".Parse::Pidl::Typelist::enum_type_fn($type->{DATA}) . " status;\n"); + $self->pidl_code(Parse::Pidl::Typelist::enum_type_fn($type->{DATA}) . "_t status;\n"); } elsif ($type->{DATA}->{TYPE} eq "SCALAR") { - $self->pidl_code("g$fn->{RETURN_TYPE} status;\n"); + $self->pidl_code(mapWireScalarType($fn->{RETURN_TYPE}) . " status;\n"); } else { error($fn, "return type `$fn->{RETURN_TYPE}' not yet supported"); } @@ -624,22 +648,21 @@ sub Function($$$) } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") { $self->pidl_code("offset = dissect_ntstatus(tvb, offset, pinfo, tree, di, drep, hf\_$ifname\_status, &status);\n"); $self->pidl_code("if (status != 0)"); - $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str(status, NT_errors, \"Unknown NT status 0x%08x\"));\n"); + $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str_ext(status, &NT_errors_ext, \"Unknown NT status 0x%08x\"));\n"); $return_types{$ifname}->{"status"} = ["NTSTATUS", "NT Error"]; } elsif ($fn->{RETURN_TYPE} eq "WERROR") { $self->pidl_code("offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf\_$ifname\_werror, &status);\n"); $self->pidl_code("if (status != 0)"); - $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str(status, WERR_errors, \"Unknown DOS error 0x%08x\"));\n"); + $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str_ext(status, &WERR_errors_ext, \"Unknown DOS error 0x%08x\"));\n"); $return_types{$ifname}->{"werror"} = ["WERROR", "Windows Error"]; } elsif ($fn->{RETURN_TYPE} eq "HRESULT") { $self->pidl_code("offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hf\_$ifname\_hresult, &status);\n"); $self->pidl_code("if (status != 0)"); - $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str(status, HRES_errors, \"Unknown HRES error 0x%08x\"));\n"); + $self->pidl_code("\tcol_append_fstr(pinfo->cinfo, COL_INFO, \", Error: %s\", val_to_str_ext(status, &HRES_errors_ext, \"Unknown HRES error 0x%08x\"));\n"); $return_types{$ifname}->{"hresult"} = ["HRESULT", "HRES Windows Error"]; } elsif (my $type = getType($fn->{RETURN_TYPE})) { if ($type->{DATA}->{TYPE} eq "ENUM") { - my $return_type = "g".Parse::Pidl::Typelist::enum_type_fn($type->{DATA}); my $return_dissect = "dissect_ndr_" .Parse::Pidl::Typelist::enum_type_fn($type->{DATA}); $self->pidl_code("offset = $return_dissect(tvb, offset, pinfo, tree, di, drep, hf\_$ifname\_$fn->{RETURN_TYPE}_status, &status);"); @@ -661,7 +684,7 @@ sub Function($$$) $self->pidl_fn_start("$ifname\_dissect\_$fn_name\_request"); $self->pidl_code("static int"); - $self->pidl_code("$ifname\_dissect\_${fn_name}_request(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, guint8 *drep _U_)"); + $self->pidl_code("$ifname\_dissect\_${fn_name}_request(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_)"); $self->pidl_code("{"); $self->indent; $self->pidl_code("di->dcerpc_procedure_name=\"${fn_name}\";"); @@ -709,7 +732,7 @@ sub Struct($$$$) if (not defined($switch_raw_type)) { die("Unknown type[$_->{TYPE}]\n"); } - my $switch_type = "g${switch_raw_type}"; + my $switch_type = mapWireScalarType(${switch_raw_type}); if ($switch_type ne "") { push @$vars, "$switch_type $v = 0;"; @@ -733,11 +756,11 @@ sub Struct($$$$) $doalign = 0; } - $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);"); + $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, uint32_t param _U_);"); $self->pidl_fn_start($dissectorname); $self->pidl_code("int"); - $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)"); + $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, uint32_t param _U_)"); $self->pidl_code("{"); $self->indent; $self->pidl_code($_) foreach (@$vars); @@ -746,7 +769,7 @@ sub Struct($$$$) $self->pidl_code("proto_tree *tree = NULL;"); } if (defined($doalign) and $doalign == 0) { - $self->pidl_code("gboolean oldalign = di->no_align;"); + $self->pidl_code("bool oldalign = di->no_align;"); } $self->pidl_code("int old_offset;"); $self->pidl_code(""); @@ -756,7 +779,7 @@ sub Struct($$$$) $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); } if ($doalign == 0) { - $self->pidl_code("di->no_align = TRUE;"); + $self->pidl_code("di->no_align = true;"); } $self->pidl_code(""); } @@ -813,7 +836,7 @@ sub Union($$$$) foreach (@{$e->{ELEMENTS}}) { $res.="\n\t\t$_->{CASE}:\n"; if ($_->{TYPE} ne "EMPTY") { - $res.="\t\t\t".$self->Element($_, $name, $ifname, undef, undef)."\n"; + $res.="\t\t\t".$self->Element($_, $name, $ifname, undef, ())."\n"; } $res.="\t\tbreak;\n"; } @@ -822,20 +845,20 @@ sub Union($$$$) my $switch_dissect = undef; my $switch_raw_type = SwitchType($e, $e->{SWITCH_TYPE}); if (defined($switch_raw_type)) { - $switch_type = "g${switch_raw_type}"; + $switch_type = mapWireScalarType(${switch_raw_type}); $switch_dissect = "dissect_ndr_${switch_raw_type}"; } $self->pidl_fn_start($dissectorname); $self->pidl_code("static int"); - $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)"); + $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, dcerpc_info* di _U_, uint8_t *drep _U_, int hf_index _U_, uint32_t param _U_)"); $self->pidl_code("{"); $self->indent; $self->pidl_code("proto_item *item = NULL;"); $self->pidl_code("proto_tree *tree = NULL;"); $self->pidl_code("int old_offset;"); if (!defined $switch_type) { - $self->pidl_code("guint32 level = param;"); + $self->pidl_code("uint32_t level = param;"); } else { $self->pidl_code("$switch_type level;"); } @@ -1009,7 +1032,7 @@ sub ProcessInterface($$) $self->pidl_hdr("#define $define"); $self->pidl_hdr(""); - $self->pidl_def("static gint proto_dcerpc_$x->{NAME} = -1;"); + $self->pidl_def("static int proto_dcerpc_$x->{NAME};"); $self->register_ett("ett_dcerpc_$x->{NAME}"); $self->register_hf_field("hf_$x->{NAME}_opnum", "Operation", "$x->{NAME}.opnum", "FT_UINT16", "BASE_DEC", "NULL", 0, ""); @@ -1034,7 +1057,7 @@ sub ProcessInterface($$) my $maj = 0x0000FFFF & $x->{VERSION}; $maj =~ s/\.(.*)$//g; - $self->pidl_def("static guint16 ver_dcerpc_$x->{NAME} = $maj;"); + $self->pidl_def("static uint16_t ver_dcerpc_$x->{NAME} = $maj;"); $self->pidl_def(""); } @@ -1047,7 +1070,7 @@ sub ProcessInterface($$) my ($type, $desc) = @{$return_types{$x->{NAME}}->{$_}}; my $dt = $self->find_type($type); $dt or die("Unable to find information about return type `$type'"); - $self->register_hf_field("hf_$x->{NAME}_$_", $desc, "$x->{NAME}.$_", $dt->{FT_TYPE}, "BASE_HEX", $dt->{VALSSTRING}, 0, ""); + $self->register_hf_field("hf_$x->{NAME}_$_", $desc, "$x->{NAME}.$_", $dt->{FT_TYPE}, $dt->{BASE_TYPE}, $dt->{VALSSTRING}, 0, ""); $self->{hf_used}->{"hf_$x->{NAME}_$_"} = 1; } @@ -1105,6 +1128,7 @@ sub Initialize($$) $self->register_type("uint3264", "offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep, \@HF\@, NULL);", "FT_UINT32", "BASE_DEC", 0, "NULL", 8); $self->register_type("hyper", "offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, di, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 8); + $self->register_type("int64", "offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, di, drep, \@HF\@, NULL);", "FT_INT64", "BASE_DEC", 0, "NULL", 8); $self->register_type("udlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 4); $self->register_type("bool8", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1); $self->register_type("char", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1); @@ -1113,19 +1137,19 @@ sub Initialize($$) $self->register_type("GUID", "offset = dissect_ndr_uuid_t(tvb, offset, pinfo, tree, di, drep, \@HF\@, NULL);","FT_GUID", "BASE_NONE", 0, "NULL", 4); $self->register_type("policy_handle", "offset = PIDL_dissect_policy_hnd(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_BYTES", "BASE_NONE", 0, "NULL", 4); $self->register_type("NTTIME", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, \@HF\@);","FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); - $self->register_type("NTTIME_hyper", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, \@HF\@);","FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); + $self->register_type("NTTIME_hyper", "offset = dissect_ndr_nt_NTTIME_hyper(tvb, offset, pinfo, tree, di, drep, \@HF\@);","FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); $self->register_type("time_t", "offset = dissect_ndr_time_t(tvb, offset, pinfo,tree, di, drep, \@HF\@, NULL);","FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); - $self->register_type("NTTIME_1sec", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, di, drep, \@HF\@);", "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); + $self->register_type("NTTIME_1sec", "offset = dissect_ndr_nt_NTTIME_1sec(tvb, offset, pinfo, tree, di, drep, \@HF\@);", "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); $self->register_type("dom_sid28", "offset = dissect_ndr_nt_SID28(tvb, offset, pinfo, tree, di, drep, \@HF\@);", "FT_STRING", "BASE_NONE", 0, "NULL", 4); $self->register_type("SID", "offset = dissect_ndr_nt_SID_with_options(tvb, offset, pinfo, tree, di, drep, param, \@HF\@);","FT_STRING", "BASE_NONE", 0, "NULL", 4); $self->register_type("WERROR", - "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_DEC", 0, "VALS(WERR_errors)", 4); + "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_HEX|BASE_EXT_STRING", 0, "&WERR_errors_ext", 4); $self->register_type("NTSTATUS", - "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_DEC", 0, "VALS(NT_errors)", 4); + "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_HEX|BASE_EXT_STRING", 0, "&NT_errors_ext", 4); $self->register_type("HRESULT", - "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_DEC", 0, "VALS(HRES_errors)", 4); + "offset = PIDL_dissect_uint32(tvb, offset, pinfo, tree, di, drep, \@HF\@, \@PARAM\@);","FT_UINT32", "BASE_HEX|BASE_EXT_STRING", 0, "&HRES_errors_ext", 4); $self->register_type("ipv6address", "proto_tree_add_item(tree, \@HF\@, tvb, offset, 16, ENC_NA); offset += 16;", "FT_IPv6", "BASE_NONE", 0, "NULL", 16); $self->register_type("ipv4address", "proto_tree_add_item(tree, \@HF\@, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4;", "FT_IPv4", "BASE_NONE", 0, "NULL", 4); @@ -1149,7 +1173,7 @@ sub Parse($$$$$) Pidl is a perl based IDL compiler for DCE/RPC idl files. It is maintained by the Samba team, not the Wireshark team. Instructions on how to download and install Pidl can be - found at https://gitlab.com/wireshark/wireshark/-/wikis/Pidl + found at https://wiki.wireshark.org/Pidl */ "; @@ -1157,9 +1181,10 @@ sub Parse($$$$$) $self->{res}->{headers} = "\n"; $self->{res}->{headers} .= "#include \"config.h\"\n"; - $self->{res}->{headers} .= "#include <glib.h>\n"; $self->{res}->{headers} .= "#include <string.h>\n"; - $self->{res}->{headers} .= "#include <epan/packet.h>\n\n"; + $self->{res}->{headers} .= "#include <wsutil/array.h>\n"; + $self->{res}->{headers} .= "#include <epan/packet.h>\n"; + $self->{res}->{headers} .= "#include <epan/tfs.h>\n\n"; $self->{res}->{headers} .= "#include \"packet-dcerpc.h\"\n"; $self->{res}->{headers} .= "#include \"packet-dcerpc-nt.h\"\n"; @@ -1217,7 +1242,7 @@ sub register_ett($$) sub DumpEttList { my ($ett) = @_; - my $res = "\tstatic gint *ett[] = {\n"; + my $res = "\tstatic int *ett[] = {\n"; foreach (@$ett) { $res .= "\t\t&$_,\n"; } @@ -1230,7 +1255,7 @@ sub DumpEttDeclaration my ($ett) = @_; my $res = "\n/* Ett declarations */\n"; foreach (@$ett) { - $res .= "static gint $_ = -1;\n"; + $res .= "static int $_;\n"; } return "$res\n"; @@ -1296,7 +1321,7 @@ sub DumpHfDeclaration($) foreach (sort(keys %{$self->{conformance}->{header_fields}})) { - $res .= "static gint $_ = -1;\n"; + $res .= "static int $_;\n"; } return "$res\n"; @@ -1339,7 +1364,7 @@ sub DumpFunctionTable($) { my $if = shift; - my $res = "static dcerpc_sub_dissector $if->{NAME}\_dissectors[] = {\n"; + my $res = "static const dcerpc_sub_dissector $if->{NAME}\_dissectors[] = {\n"; foreach (@{$if->{FUNCTIONS}}) { my $fn_name = $_->{NAME}; $fn_name =~ s/^$if->{NAME}_//; diff --git a/tools/pidl/lib/Parse/Yapp/Driver.pm b/tools/pidl/lib/Parse/Yapp/Driver.pm deleted file mode 100644 index 3652be06..00000000 --- a/tools/pidl/lib/Parse/Yapp/Driver.pm +++ /dev/null @@ -1,471 +0,0 @@ -# -# Module Parse::Yapp::Driver -# -# This module is part of the Parse::Yapp package available on your -# nearest CPAN -# -# Any use of this module in a standalone parser make the included -# text under the same copyright as the Parse::Yapp module itself. -# -# This notice should remain unchanged. -# -# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved. -# (see the pod text in Parse::Yapp module for use and distribution rights) -# - -package Parse::Yapp::Driver; - -require 5.004; - -use strict; - -use vars qw ( $VERSION $COMPATIBLE $FILENAME ); - -$VERSION = '1.05'; -$COMPATIBLE = '0.07'; -$FILENAME=__FILE__; - -use Carp; - -#Known parameters, all starting with YY (leading YY will be discarded) -my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '', - YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => ''); -#Mandatory parameters -my(@params)=('LEX','RULES','STATES'); - -sub new { - my($class)=shift; - my($errst,$nberr,$token,$value,$check,$dotpos); - my($self)={ ERROR => \&_Error, - ERRST => \$errst, - NBERR => \$nberr, - TOKEN => \$token, - VALUE => \$value, - DOTPOS => \$dotpos, - STACK => [], - DEBUG => 0, - CHECK => \$check }; - - _CheckParams( [], \%params, \@_, $self ); - - exists($$self{VERSION}) - and $$self{VERSION} < $COMPATIBLE - and croak "Yapp driver version $VERSION ". - "incompatible with version $$self{VERSION}:\n". - "Please recompile parser module."; - - ref($class) - and $class=ref($class); - - bless($self,$class); -} - -sub YYParse { - my($self)=shift; - my($retval); - - _CheckParams( \@params, \%params, \@_, $self ); - - if($$self{DEBUG}) { - _DBLoad(); - $retval = eval '$self->_DBParse()';#Do not create stab entry on compile - $@ and die $@; - } - else { - $retval = $self->_Parse(); - } - $retval -} - -sub YYData { - my($self)=shift; - - exists($$self{USER}) - or $$self{USER}={}; - - $$self{USER}; - -} - -sub YYErrok { - my($self)=shift; - - ${$$self{ERRST}}=0; - undef; -} - -sub YYNberr { - my($self)=shift; - - ${$$self{NBERR}}; -} - -sub YYRecovering { - my($self)=shift; - - ${$$self{ERRST}} != 0; -} - -sub YYAbort { - my($self)=shift; - - ${$$self{CHECK}}='ABORT'; - undef; -} - -sub YYAccept { - my($self)=shift; - - ${$$self{CHECK}}='ACCEPT'; - undef; -} - -sub YYError { - my($self)=shift; - - ${$$self{CHECK}}='ERROR'; - undef; -} - -sub YYSemval { - my($self)=shift; - my($index)= $_[0] - ${$$self{DOTPOS}} - 1; - - $index < 0 - and -$index <= @{$$self{STACK}} - and return $$self{STACK}[$index][1]; - - undef; #Invalid index -} - -sub YYCurtok { - my($self)=shift; - - @_ - and ${$$self{TOKEN}}=$_[0]; - ${$$self{TOKEN}}; -} - -sub YYCurval { - my($self)=shift; - - @_ - and ${$$self{VALUE}}=$_[0]; - ${$$self{VALUE}}; -} - -sub YYExpect { - my($self)=shift; - - keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}} -} - -sub YYLexer { - my($self)=shift; - - $$self{LEX}; -} - - -################# -# Private stuff # -################# - - -sub _CheckParams { - my($mandatory,$checklist,$inarray,$outhash)=@_; - my($prm,$value); - my($prmlst)={}; - - while(($prm,$value)=splice(@$inarray,0,2)) { - $prm=uc($prm); - exists($$checklist{$prm}) - or croak("Unknown parameter '$prm'"); - ref($value) eq $$checklist{$prm} - or croak("Invalid value for parameter '$prm'"); - $prm=unpack('@2A*',$prm); - $$outhash{$prm}=$value; - } - for (@$mandatory) { - exists($$outhash{$_}) - or croak("Missing mandatory parameter '".lc($_)."'"); - } -} - -sub _Error { - print "Parse error.\n"; -} - -sub _DBLoad { - { - no strict 'refs'; - - exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ? - and return; - } - my($fname)=__FILE__; - my(@drv); - open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname"; - while(<DRV>) { - /^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/ - and do { - s/^#DBG>//; - push(@drv,$_); - } - } - close(DRV); - - $drv[0]=~s/_P/_DBP/; - eval join('',@drv); -} - -#Note that for loading debugging version of the driver, -#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive. -#So, DO NOT remove comment at end of sub !!! -sub _Parse { - my($self)=shift; - - my($rules,$states,$lex,$error) - = @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' }; - my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos) - = @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' }; - -#DBG> my($debug)=$$self{DEBUG}; -#DBG> my($dbgerror)=0; - -#DBG> my($ShowCurToken) = sub { -#DBG> my($tok)='>'; -#DBG> for (split('',$$token)) { -#DBG> $tok.= (ord($_) < 32 or ord($_) > 126) -#DBG> ? sprintf('<%02X>',ord($_)) -#DBG> : $_; -#DBG> } -#DBG> $tok.='<'; -#DBG> }; - - $$errstatus=0; - $$nberror=0; - ($$token,$$value)=(undef,undef); - @$stack=( [ 0, undef ] ); - $$check=''; - - while(1) { - my($actions,$act,$stateno); - - $stateno=$$stack[-1][0]; - $actions=$$states[$stateno]; - -#DBG> print STDERR ('-' x 40),"\n"; -#DBG> $debug & 0x2 -#DBG> and print STDERR "In state $stateno:\n"; -#DBG> $debug & 0x08 -#DBG> and print STDERR "Stack:[". -#DBG> join(',',map { $$_[0] } @$stack). -#DBG> "]\n"; - - - if (exists($$actions{ACTIONS})) { - - defined($$token) - or do { - ($$token,$$value)=&$lex($self); -#DBG> $debug & 0x01 -#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n"; - }; - - $act= exists($$actions{ACTIONS}{$$token}) - ? $$actions{ACTIONS}{$$token} - : exists($$actions{DEFAULT}) - ? $$actions{DEFAULT} - : undef; - } - else { - $act=$$actions{DEFAULT}; -#DBG> $debug & 0x01 -#DBG> and print STDERR "Don't need token.\n"; - } - - defined($act) - and do { - - $act > 0 - and do { #shift - -#DBG> $debug & 0x04 -#DBG> and print STDERR "Shift and go to state $act.\n"; - - $$errstatus - and do { - --$$errstatus; - -#DBG> $debug & 0x10 -#DBG> and $dbgerror -#DBG> and $$errstatus == 0 -#DBG> and do { -#DBG> print STDERR "**End of Error recovery.\n"; -#DBG> $dbgerror=0; -#DBG> }; - }; - - - push(@$stack,[ $act, $$value ]); - - $$token ne '' #Don't eat the eof - and $$token=$$value=undef; - next; - }; - - #reduce - my($lhs,$len,$code,@sempar,$semval); - ($lhs,$len,$code)=@{$$rules[-$act]}; - -#DBG> $debug & 0x04 -#DBG> and $act -#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): "; - - $act - or $self->YYAccept(); - - $$dotpos=$len; - - unpack('A1',$lhs) eq '@' #In line rule - and do { - $lhs =~ /^\@[0-9]+\-([0-9]+)$/ - or die "In line rule name '$lhs' ill formed: ". - "report it as a BUG.\n"; - $$dotpos = $1; - }; - - @sempar = $$dotpos - ? map { $$_[1] } @$stack[ -$$dotpos .. -1 ] - : (); - - $semval = $code ? &$code( $self, @sempar ) - : @sempar ? $sempar[0] : undef; - - splice(@$stack,-$len,$len); - - $$check eq 'ACCEPT' - and do { - -#DBG> $debug & 0x04 -#DBG> and print STDERR "Accept.\n"; - - return($semval); - }; - - $$check eq 'ABORT' - and do { - -#DBG> $debug & 0x04 -#DBG> and print STDERR "Abort.\n"; - - return(undef); - - }; - -#DBG> $debug & 0x04 -#DBG> and print STDERR "Back to state $$stack[-1][0], then "; - - $$check eq 'ERROR' - or do { -#DBG> $debug & 0x04 -#DBG> and print STDERR -#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n"; - -#DBG> $debug & 0x10 -#DBG> and $dbgerror -#DBG> and $$errstatus == 0 -#DBG> and do { -#DBG> print STDERR "**End of Error recovery.\n"; -#DBG> $dbgerror=0; -#DBG> }; - - push(@$stack, - [ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]); - $$check=''; - next; - }; - -#DBG> $debug & 0x04 -#DBG> and print STDERR "Forced Error recovery.\n"; - - $$check=''; - - }; - - #Error - $$errstatus - or do { - - $$errstatus = 1; - &$error($self); - $$errstatus # if 0, then YYErrok has been called - or next; # so continue parsing - -#DBG> $debug & 0x10 -#DBG> and do { -#DBG> print STDERR "**Entering Error recovery.\n"; -#DBG> ++$dbgerror; -#DBG> }; - - ++$$nberror; - - }; - - $$errstatus == 3 #The next token is not valid: discard it - and do { - $$token eq '' # End of input: no hope - and do { -#DBG> $debug & 0x10 -#DBG> and print STDERR "**At eof: aborting.\n"; - return(undef); - }; - -#DBG> $debug & 0x10 -#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n"; - - $$token=$$value=undef; - }; - - $$errstatus=3; - - while( @$stack - and ( not exists($$states[$$stack[-1][0]]{ACTIONS}) - or not exists($$states[$$stack[-1][0]]{ACTIONS}{error}) - or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) { - -#DBG> $debug & 0x10 -#DBG> and print STDERR "**Pop state $$stack[-1][0].\n"; - - pop(@$stack); - } - - @$stack - or do { - -#DBG> $debug & 0x10 -#DBG> and print STDERR "**No state left on stack: aborting.\n"; - - return(undef); - }; - - #shift the error token - -#DBG> $debug & 0x10 -#DBG> and print STDERR "**Shift \$error token and go to state ". -#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}. -#DBG> ".\n"; - - push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]); - - } - - #never reached - croak("Error in driver logic. Please, report it as a BUG"); - -}#_Parse -#DO NOT remove comment - -1; - diff --git a/tools/pidl/lib/wscript_build b/tools/pidl/lib/wscript_build deleted file mode 100644 index 54b3170c..00000000 --- a/tools/pidl/lib/wscript_build +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -# install the pidl modules -bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR, - ''' - Parse/Pidl.pm - Parse/Pidl/Samba4.pm - Parse/Pidl/CUtil.pm - Parse/Pidl/Expr.pm - Parse/Pidl/Wireshark/Conformance.pm - Parse/Pidl/Wireshark/NDR.pm - Parse/Pidl/ODL.pm - Parse/Pidl/Dump.pm - Parse/Pidl/Util.pm - Parse/Pidl/Samba4/Header.pm - Parse/Pidl/Samba4/COM/Header.pm - Parse/Pidl/Samba4/COM/Proxy.pm - Parse/Pidl/Samba4/COM/Stub.pm - Parse/Pidl/Samba4/TDR.pm - Parse/Pidl/Samba4/NDR/Server.pm - Parse/Pidl/Samba4/NDR/Client.pm - Parse/Pidl/Samba4/NDR/Parser.pm - Parse/Pidl/Samba4/Python.pm - Parse/Pidl/Samba4/Template.pm - Parse/Pidl/IDL.pm - Parse/Pidl/Typelist.pm - Parse/Pidl/Samba3/ClientNDR.pm - Parse/Pidl/Samba3/ServerNDR.pm - Parse/Pidl/Compat.pm - Parse/Pidl/NDR.pm - ''', - flat=False) - -if not bld.CONFIG_SET('USING_SYSTEM_PARSE_YAPP_DRIVER'): - bld.INSTALL_FILES(bld.env.PERL_LIB_INSTALL_DIR, - 'Parse/Yapp/Driver.pm', - flat=False) diff --git a/tools/pidl/pidl b/tools/pidl/pidl index e8e6941f..762824e6 100755 --- a/tools/pidl/pidl +++ b/tools/pidl/pidl @@ -382,7 +382,7 @@ usesgetlasterror, vararg, vi_progid, wire_marshal. =head1 SEE ALSO L<https://msdn.microsoft.com/en-us/library/windows/desktop/aa373864%28v=vs.85%29.aspx> -L<https://gitlab.com/wireshark/wireshark/-/wikis/DCE/RPC>, +L<https://wiki.wireshark.org/DCE/RPC>, L<https://www.samba.org/>, L<yapp(1)> @@ -402,6 +402,7 @@ pidl README by Andrew Tridgell. use strict; +use warnings; use FindBin qw($RealBin $Script); use lib "$RealBin/lib"; use Getopt::Long; @@ -474,6 +475,7 @@ my($opt_template) = 0; my($opt_client); my($opt_typelib); my($opt_server); +my($opt_server_compat); my($opt_ndr_parser); my($opt_tdr_parser); my($opt_ws_parser); @@ -559,6 +561,7 @@ my $result = GetOptions ( 'samba3-template' => \$opt_samba3_template, 'header:s' => \$opt_header, 'server:s' => \$opt_server, + 'server-compat:s' => \$opt_server_compat, 'typelib:s' => \$opt_typelib, 'tdr-parser:s' => \$opt_tdr_parser, 'template' => \$opt_template, @@ -669,6 +672,7 @@ sub process_file($) if (defined($opt_ws_parser) or defined($opt_client) or defined($opt_server) or + defined($opt_server_compat) or defined($opt_header) or defined($opt_ndr_parser) or defined($opt_python) or @@ -712,8 +716,11 @@ sub process_file($) if (defined($opt_python)) { require Parse::Pidl::Samba4::Python; my $generator = new Parse::Pidl::Samba4::Python(); + if (!defined($opt_client)) { + $c_header = undef; + } my ($prsr) = $generator->Parse($basename, $ndr, - "$outputdir/ndr_$basename\_c.h", $h_filename); + $c_header, $h_filename); FileSave("$outputdir/py_$basename.c", $prsr); } @@ -794,6 +801,19 @@ sub process_file($) FileSave($header, $h_code); } + if (defined($opt_server_compat)) { + require Parse::Pidl::Samba4::NDR::ServerCompat; + + my $c_scompat = ($opt_server_compat or "$outputdir/ndr_$basename\_scompat.c"); + my $h_scompat = $c_scompat; + $h_scompat =~ s/\.c$/.h/; + + my $generator = new Parse::Pidl::Samba4::NDR::ServerCompat(); + my ($source, $header) = $generator->Parse($ndr, $h_scompat, $h_filename); + + FileSave($c_scompat, $source); + FileSave($h_scompat, $header); + } } if (scalar(@ARGV) == 0) { diff --git a/tools/pidl/tests/Util.pm b/tools/pidl/tests/Util.pm index 86b521bf..a7b5a63f 100644 --- a/tools/pidl/tests/Util.pm +++ b/tools/pidl/tests/Util.pm @@ -9,6 +9,7 @@ require Exporter; @EXPORT = qw(test_samba4_ndr test_warnings test_errors); use strict; +use warnings; use FindBin qw($RealBin); use lib "$RealBin/../lib"; diff --git a/tools/pidl/tests/header.pl b/tools/pidl/tests/header.pl index db594844..dc8bbd7a 100755 --- a/tools/pidl/tests/header.pl +++ b/tools/pidl/tests/header.pl @@ -4,7 +4,7 @@ use strict; use warnings; -use Test::More tests => 27; +use Test::More tests => 30; use FindBin qw($RealBin); use lib "$RealBin"; use Util; @@ -23,6 +23,16 @@ sub parse_idl($) return Parse::Pidl::Samba4::Header::Parse($ndr); } +sub load_and_parse_idl($) +{ + my $text = shift; + my $ndr; + my $idl = Parse::Pidl::IDL::parse_string($text, "nofile"); + Parse::Pidl::Typelist::LoadIdl($idl, "noname"); + $ndr = Parse::Pidl::NDR::Parse($idl); + return Parse::Pidl::Samba4::Header::Parse($ndr); +} + like(parse_idl(""), qr/\/\* header auto-generated by pidl \*\/\n/sm, "includes work"); like(parse_idl("interface x {}"), qr/\/\* header auto-generated by pidl \*\/\n/sm, "simple empty interface doesn't cause overhead"); like(parse_idl("interface p { typedef struct { int y; } x; };"), @@ -59,6 +69,15 @@ like(parse_idl("interface p { typedef struct x { int p; } x; };"), like(parse_idl("cpp_quote(\"some-foo\")"), qr/some-foo/sm, "cpp quote"); +like(load_and_parse_idl("interface hang {typedef [public] struct { wsp_cbasestoragevariant a[SINGLE]; } foo; typedef [public,nodiscriminant,switch_type(uint16)] union { [case(VT_I1)] int8 vt_i1; [case(VT_VARIANT)] foo b; } variant_types; typedef [public] struct { [switch_is(vtype)] variant_types vvalue; } bar;};"), + qr/struct foo.*{.*struct wsp_cbasestoragevariant \*a.*struct bar \{.*union variant_types vvalue.*;/sm,"test for hang with nested struct with union"); + +like(load_and_parse_idl("interface hang { typedef struct { uint32 count; bar a[count];} foo ; typedef struct { foo b; } bar; };"), + qr/struct foo.*{.*struct bar \*a;/sm,"test for hang with nested struct"); + +like(load_and_parse_idl("interface hang { typedef struct { bar a; } foo ; typedef struct { foo b; } bar; };"), + qr/struct foo.*{.*struct bar a;/sm,"test for hang with uncompilable nested struct"); + # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] }; is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn)); diff --git a/tools/pidl/tests/ndr.pl b/tools/pidl/tests/ndr.pl index b6fd4899..8f845452 100755 --- a/tools/pidl/tests/ndr.pl +++ b/tools/pidl/tests/ndr.pl @@ -4,7 +4,7 @@ use strict; use warnings; -use Test::More tests => 47; +use Test::More tests => 48; use FindBin qw($RealBin); use lib "$RealBin"; use Util; @@ -480,6 +480,7 @@ $ne = ParseElement($e, undef, 0); is($ne->{REPRESENTATION_TYPE}, "uint8"); is(align_type("hyper"), 8); +is(align_type("int64"), 8); is(align_type("double"), 8); is(align_type("uint32"), 4); is(align_type("uint16"), 2); diff --git a/tools/pidl/tests/ndr_align.pl b/tools/pidl/tests/ndr_align.pl index cc089eaa..80d61158 100755 --- a/tools/pidl/tests/ndr_align.pl +++ b/tools/pidl/tests/ndr_align.pl @@ -2,6 +2,7 @@ # NDR alignment tests # (C) 2005 Jelmer Vernooij. Published under the GNU GPL use strict; +use warnings; use Test::More tests => 5 * 8; use FindBin qw($RealBin); @@ -16,7 +17,7 @@ test_samba4_ndr('align-uint8-uint16', } bla; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct bla r; uint8_t expected[] = { 0x0D, 0x00, 0xef, 0xbe }; DATA_BLOB expected_blob = { expected, 4 }; @@ -41,7 +42,7 @@ test_samba4_ndr('align-uint8-uint32', } bla; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct bla r; uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xef, 0xbe }; DATA_BLOB expected_blob = { expected, 8 }; @@ -67,7 +68,7 @@ test_samba4_ndr('align-uint8-hyper', } bla; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct bla r; uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe }; @@ -93,7 +94,7 @@ test_samba4_ndr('noalignflag-uint8-uint16', } bla; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct bla r; uint8_t expected[] = { 0x0D, 0xef, 0xbe }; DATA_BLOB expected_blob = { expected, 3 }; @@ -121,7 +122,7 @@ test_samba4_ndr('align-blob-align2', } blie; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct blie r; uint8_t data[] = { 0x01, 0x02 }; uint8_t expected[] = { 0x0D, 0x00, 0x0E }; diff --git a/tools/pidl/tests/ndr_alloc.pl b/tools/pidl/tests/ndr_alloc.pl index 399fbd21..c708c3b5 100755 --- a/tools/pidl/tests/ndr_alloc.pl +++ b/tools/pidl/tests/ndr_alloc.pl @@ -2,6 +2,7 @@ # NDR allocation tests # (C) 2005 Jelmer Vernooij. Published under the GNU GPL use strict; +use warnings; use Test::More tests => 5 * 8; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_array.pl b/tools/pidl/tests/ndr_array.pl index 2a6b5bbd..46ab83ec 100755 --- a/tools/pidl/tests/ndr_array.pl +++ b/tools/pidl/tests/ndr_array.pl @@ -3,6 +3,7 @@ # (C) 2005 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; +use warnings; use Test::More tests => 8; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_compat.pl b/tools/pidl/tests/ndr_compat.pl index 355e7f67..06f7efb4 100755 --- a/tools/pidl/tests/ndr_compat.pl +++ b/tools/pidl/tests/ndr_compat.pl @@ -2,6 +2,7 @@ # (C) 2007 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; +use warnings; use Test::More tests => 2; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_fullptr.pl b/tools/pidl/tests/ndr_fullptr.pl index cc6fca7a..109b368e 100755 --- a/tools/pidl/tests/ndr_fullptr.pl +++ b/tools/pidl/tests/ndr_fullptr.pl @@ -3,6 +3,7 @@ # (C) 2006 Jelmer Vernooij <jelmer@samba.org>. # Published under the GNU General Public License. use strict; +use warnings; use Test::More tests => 1 * 8; use FindBin qw($RealBin); @@ -17,7 +18,7 @@ test_samba4_ndr("fullptr-push-dup", [public] uint16 echo_TestFull([in,ptr] uint32 *x, [in,ptr] uint32 *y); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); uint32_t v = 13; struct echo_TestFull r; r.in.x = &v; diff --git a/tools/pidl/tests/ndr_refptr.pl b/tools/pidl/tests/ndr_refptr.pl index d5dd8395..94676a80 100755 --- a/tools/pidl/tests/ndr_refptr.pl +++ b/tools/pidl/tests/ndr_refptr.pl @@ -4,6 +4,7 @@ # (C) 2005 Jelmer Vernooij <jelmer@samba.org>. # Published under the GNU General Public License. use strict; +use warnings; use Test::More tests => 22 * 8; use FindBin qw($RealBin); @@ -18,7 +19,7 @@ test_samba4_ndr("noptr-push", [public] uint16 echo_TestRef([in] xstruct foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); uint16_t v = 13; struct echo_TestRef r; r.in.foo.x = v; @@ -48,7 +49,7 @@ test_samba4_ndr("ptr-embedded-push", ', ' uint16_t v = 13; - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo.x = &v; @@ -74,7 +75,7 @@ test_samba4_ndr("ptr-embedded-push-null", [public] uint16 echo_TestRef([in] xstruct foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo.x = NULL; @@ -99,7 +100,7 @@ test_samba4_ndr("refptr-embedded-push", ', ' uint16_t v = 13; - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo.x = &v; @@ -126,7 +127,7 @@ test_samba4_ndr("refptr-embedded-push-null", [public] uint16 echo_TestRef([in] xstruct foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo.x = NULL; @@ -144,7 +145,7 @@ test_samba4_ndr("ptr-top-push", [public] uint16 echo_TestRef([in] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; struct xstruct s; s.x = 13; @@ -169,7 +170,7 @@ test_samba4_ndr("ptr-top-push-null", [public] uint16 echo_TestRef([in] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo = NULL; @@ -189,7 +190,7 @@ test_samba4_ndr("refptr-top-push", [public] uint16 echo_TestRef([in,ref] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; struct xstruct s; s.x = 13; @@ -214,7 +215,7 @@ test_samba4_ndr("refptr-top-push-null", [public] uint16 echo_TestRef([in,ref] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo = NULL; @@ -233,7 +234,7 @@ test_samba4_ndr("uniqueptr-top-push", [public] uint16 echo_TestRef([in,unique] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; struct xstruct s; s.x = 13; @@ -261,7 +262,7 @@ test_samba4_ndr("uniqueptr-top-push-null", [public] uint16 echo_TestRef([in,unique] xstruct *foo); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo = NULL; @@ -381,7 +382,7 @@ test_samba4_ndr("ptr-top-push-double", ' [public] void echo_TestRef([in] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; uint16_t v = 13; uint16_t *pv = &v; @@ -408,7 +409,7 @@ test_samba4_ndr("ptr-top-push-double-sndnull", ' [public] void echo_TestRef([in] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; uint16_t *pv = NULL; r.in.foo = &pv; @@ -429,7 +430,7 @@ test_samba4_ndr("ptr-top-push-double-fstnull", ' [public] void echo_TestRef([in] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo = NULL; @@ -445,7 +446,7 @@ test_samba4_ndr("refptr-top-push-double", ' [public] void echo_TestRef([in,ref] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; uint16_t v = 13; uint16_t *pv = &v; @@ -473,7 +474,7 @@ test_samba4_ndr("refptr-top-push-double-sndnull", ' [public] void echo_TestRef([in,ref] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; uint16_t *pv = NULL; r.in.foo = &pv; @@ -494,7 +495,7 @@ test_samba4_ndr("refptr-top-push-double-fstnull", ' [public] void echo_TestRef([in,ref] uint16 **foo); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; r.in.foo = NULL; @@ -511,7 +512,7 @@ test_samba4_ndr("ignore-ptr", ' [public] void echo_TestRef([in,ignore] uint16 *foo, [in] uint16 *bar); ', -' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); +' struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct echo_TestRef r; uint16_t v = 10; r.in.foo = &v; diff --git a/tools/pidl/tests/ndr_represent.pl b/tools/pidl/tests/ndr_represent.pl index 2d65fb92..af9a92b6 100755 --- a/tools/pidl/tests/ndr_represent.pl +++ b/tools/pidl/tests/ndr_represent.pl @@ -2,6 +2,7 @@ # NDR represent_as() / transmit_as() tests # (C) 2006 Jelmer Vernooij. Published under the GNU GPL use strict; +use warnings; use Test::More tests => 2 * 8; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_simple.pl b/tools/pidl/tests/ndr_simple.pl index 15e07d56..c5c32445 100755 --- a/tools/pidl/tests/ndr_simple.pl +++ b/tools/pidl/tests/ndr_simple.pl @@ -3,6 +3,7 @@ # (C) 2005 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; +use warnings; use Test::More tests => 8; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_string.pl b/tools/pidl/tests/ndr_string.pl index 8e8b8ecb..aa5fd8b5 100755 --- a/tools/pidl/tests/ndr_string.pl +++ b/tools/pidl/tests/ndr_string.pl @@ -3,6 +3,7 @@ # (C) 2005 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; +use warnings; use Test::More tests => 6 * 8; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/ndr_tagtype.pl b/tools/pidl/tests/ndr_tagtype.pl index 3f9b717b..fa09cf77 100755 --- a/tools/pidl/tests/ndr_tagtype.pl +++ b/tools/pidl/tests/ndr_tagtype.pl @@ -2,7 +2,7 @@ # Support for tagged types # (C) 2005 Jelmer Vernooij. Published under the GNU GPL use strict; - +use warnings; use Test::More tests => 3 * 8; use FindBin qw($RealBin); use lib "$RealBin"; @@ -10,7 +10,7 @@ use Util qw(test_samba4_ndr); test_samba4_ndr('struct-notypedef', '[public] struct bla { uint8 x; }; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct bla r; uint8_t expected[] = { 0x0D }; DATA_BLOB expected_blob = { expected, 1 }; @@ -29,7 +29,7 @@ test_samba4_ndr('struct-notypedef', '[public] struct bla { uint8 x; }; ', test_samba4_ndr('struct-notypedef-used', '[public] struct bla { uint8 x; }; [public] void myfn([in] struct bla r); ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct myfn fn; uint8_t expected[] = { 0x0D }; DATA_BLOB expected_blob = { expected, 1 }; @@ -49,7 +49,7 @@ test_samba4_ndr('struct-notypedef-used', '[public] struct bla { uint8 x; }; test_samba4_ndr('struct-notypedef-embedded', 'struct bla { uint8 x; }; [public] struct myst { struct bla r; }; ', ' - struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL); + struct ndr_push *ndr = ndr_push_init_ctx(NULL); struct myst st; uint8_t expected[] = { 0x0D }; DATA_BLOB expected_blob = { expected, 1 }; diff --git a/tools/pidl/tests/parse_idl.pl b/tools/pidl/tests/parse_idl.pl index 14138a37..caf701b3 100755 --- a/tools/pidl/tests/parse_idl.pl +++ b/tools/pidl/tests/parse_idl.pl @@ -3,7 +3,7 @@ # (C) 2005 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; - +use warnings; use Test::More tests => 65 * 2 + 7; use FindBin qw($RealBin); use lib "$RealBin"; diff --git a/tools/pidl/tests/samba-ndr.pl b/tools/pidl/tests/samba-ndr.pl index 7c53cbc7..54a4e46d 100755 --- a/tools/pidl/tests/samba-ndr.pl +++ b/tools/pidl/tests/samba-ndr.pl @@ -8,7 +8,6 @@ use Test::More tests => 31; use FindBin qw($RealBin); use lib "$RealBin"; use Util; -use strict; use Parse::Pidl::Util qw(MyDumper); use Parse::Pidl::Samba4::NDR::Parser qw(check_null_pointer NeededFunction NeededElement NeededType diff --git a/tools/pidl/tests/samba3-cli.pl b/tools/pidl/tests/samba3-cli.pl index c758ef45..4349abb3 100755 --- a/tools/pidl/tests/samba3-cli.pl +++ b/tools/pidl/tests/samba3-cli.pl @@ -9,7 +9,7 @@ use FindBin qw($RealBin); use lib "$RealBin"; use Util; use Parse::Pidl::Util qw(MyDumper); -use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction); +use Parse::Pidl::Samba3::ClientNDR; use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work diff --git a/tools/pidl/tests/tdr.pl b/tools/pidl/tests/tdr.pl index d6cd7a03..41a560c8 100755 --- a/tools/pidl/tests/tdr.pl +++ b/tools/pidl/tests/tdr.pl @@ -13,18 +13,18 @@ use Parse::Pidl::Samba4::TDR qw(ParserType); my $tdr = new Parse::Pidl::Samba4::TDR(); $tdr->ParserType({TYPE => "STRUCT", NAME => "foo", PROPERTIES => {public => 1}}, "pull"); -is($tdr->{ret}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v) +is($tdr->{res}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v) { return NT_STATUS_OK; } "); -is($tdr->{ret_hdr}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v);\n"); +is($tdr->{res_hdr}, "NTSTATUS tdr_pull_foo (struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, struct foo *v);\n"); $tdr = new Parse::Pidl::Samba4::TDR(); $tdr->ParserType({TYPE => "UNION", NAME => "bar", PROPERTIES => {public => 1}}, "pull"); -is($tdr->{ret}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v) +is($tdr->{res}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v) { switch (level) { } @@ -33,11 +33,11 @@ is($tdr->{ret}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx } "); -is($tdr->{ret_hdr}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v);\n"); +is($tdr->{res_hdr}, "NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v);\n"); $tdr = new Parse::Pidl::Samba4::TDR(); $tdr->ParserType({TYPE => "UNION", NAME => "bar", PROPERTIES => {}}, "pull"); -is($tdr->{ret}, "static NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v) +is($tdr->{res}, "static NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX *mem_ctx, int level, union bar *v) { switch (level) { } @@ -46,4 +46,4 @@ is($tdr->{ret}, "static NTSTATUS tdr_pull_bar(struct tdr_pull *tdr, TALLOC_CTX * } "); -is($tdr->{ret_hdr}, ""); +is($tdr->{res_hdr}, ""); diff --git a/tools/pidl/tests/test_util.pl b/tools/pidl/tests/test_util.pl index 2d59f628..93addcea 100755 --- a/tools/pidl/tests/test_util.pl +++ b/tools/pidl/tests/test_util.pl @@ -2,6 +2,7 @@ # (C) 2007 Jelmer Vernooij <jelmer@samba.org> # Published under the GNU General Public License use strict; +use warnings; use Test::More tests => 6; use FindBin qw($RealBin); diff --git a/tools/pidl/tests/typelist.pl b/tools/pidl/tests/typelist.pl index 681c0eac..e012c806 100755 --- a/tools/pidl/tests/typelist.pl +++ b/tools/pidl/tests/typelist.pl @@ -4,7 +4,7 @@ use strict; use warnings; -use Test::More tests => 56; +use Test::More tests => 58; use FindBin qw($RealBin); use lib "$RealBin"; use Util; @@ -21,6 +21,7 @@ is("int32", expandAlias("int32")); is("uint32_t", mapScalarType("uint32")); is("void", mapScalarType("void")); is("uint64_t", mapScalarType("hyper")); +is("int64_t", mapScalarType("int64")); is("double", mapScalarType("double")); my $x = { TYPE => "ENUM", NAME => "foo", EXTRADATA => 1 }; @@ -66,6 +67,7 @@ is(1, is_scalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM" }})); is(1, is_scalar("mytypedef")); is(1, scalar_is_reference("string")); +is(1, scalar_is_reference("u16string")); is(0, scalar_is_reference("uint32")); is(0, scalar_is_reference({TYPE => "STRUCT", NAME => "echo_foobar"})); diff --git a/tools/pidl/tests/wireshark-ndr.pl b/tools/pidl/tests/wireshark-ndr.pl index 229315b0..0edb0ec2 100755 --- a/tools/pidl/tests/wireshark-ndr.pl +++ b/tools/pidl/tests/wireshark-ndr.pl @@ -45,7 +45,7 @@ is($x->{res}->{code}, 'void proto_reg_handoff_dcerpc_bla(void) is($x->{hf_used}->{hf_bla_opnum}, 1); $x->{conformance} = {}; -is("hf_bla_idx", +is("hf_bla_idx", $x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, undef)); is_deeply($x->{conformance}, { header_fields => { @@ -68,7 +68,7 @@ $x->{conformance} = { fielddescription => { hf_bla_idx => { DESCRIPTION => "Some is("hf_bla_idx", $x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, undef)); is_deeply($x->{conformance}, { - fielddescription => { + fielddescription => { hf_bla_idx => { DESCRIPTION => "Some Description", USED => 1 @@ -91,10 +91,10 @@ is_deeply($x->{conformance}, { $x->{conformance} = { fielddescription => { hf_bla_idx => { DESCRIPTION => "Some Description" }}}; is("hf_bla_idx", - $x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, + $x->register_hf_field("hf_bla_idx", "bla", "my.filter", "FT_UINT32", "BASE_HEX", "NULL", 0xF, "Actual Description")); is_deeply($x->{conformance}, { - fielddescription => { + fielddescription => { hf_bla_idx => { DESCRIPTION => "Some Description" } }, header_fields => { @@ -120,14 +120,14 @@ is_deeply($x->{conformance}, { hf_renames => { hf_bla_idx => { USED => 1, NEWNAME => "hf_bloe_idx" } } }); $x->{hf_used} = { hf_bla => 1 }; -test_warnings("", sub { +test_warnings("", sub { $x->CheckUsed({ header_fields => { foo => { INDEX => "hf_bla" }}})}); $x->{hf_used} = { }; -test_warnings("hf field `hf_bla' not used\n", sub { +test_warnings("hf field `hf_bla' not used\n", sub { $x->CheckUsed({ header_fields => { foo => { INDEX => "hf_bla" }}})}); -test_warnings("hf field `hf_id' not used\n", +test_warnings("hf field `hf_id' not used\n", sub { $x->CheckUsed({ hf_renames => { hf_id => { @@ -171,7 +171,7 @@ test_warnings("nofile:1: type never used\n", types => { bla => { USED => 0, - POS => { FILE => "nofile", LINE => 1 } + POS => { FILE => "nofile", LINE => 1 } } } }); } ); @@ -191,39 +191,39 @@ is($x->{res}->{hdr}, "#include \"packet-dcerpc-bla.h\"\n\n"); $x = new Parse::Pidl::Wireshark::NDR(); $x->ProcessImport("\"bla.idl\"", "\"foo.idl\""); -is($x->{res}->{hdr}, "#include \"packet-dcerpc-bla.h\"\n" . +is($x->{res}->{hdr}, "#include \"packet-dcerpc-bla.h\"\n" . "#include \"packet-dcerpc-foo.h\"\n\n"); $x = new Parse::Pidl::Wireshark::NDR(); $x->ProcessInclude("foo.h", "bla.h", "bar.h"); -is($x->{res}->{hdr}, "#include \"foo.h\"\n" . - "#include \"bla.h\"\n" . +is($x->{res}->{hdr}, "#include \"foo.h\"\n" . + "#include \"bla.h\"\n" . "#include \"bar.h\"\n\n"); - + $x->{conformance} = {types => { bla => "brainslug" } }; is("brainslug", $x->find_type("bla")); -is(DumpEttList(["ett_t1", "ett_bla"]), - "\tstatic gint *ett[] = {\n" . +is(DumpEttList(["ett_t1", "ett_bla"]), + "\tstatic int *ett[] = {\n" . "\t\t&ett_t1,\n" . "\t\t&ett_bla,\n" . "\t};\n"); -is(DumpEttList(), "\tstatic gint *ett[] = {\n\t};\n"); -is(DumpEttList(["bla"]), "\tstatic gint *ett[] = {\n\t\t&bla,\n\t};\n"); +is(DumpEttList(), "\tstatic int *ett[] = {\n\t};\n"); +is(DumpEttList(["bla"]), "\tstatic int *ett[] = {\n\t\t&bla,\n\t};\n"); -is(DumpEttDeclaration(["void", "zoid"]), - "\n/* Ett declarations */\n" . - "static gint void = -1;\n" . - "static gint zoid = -1;\n" . +is(DumpEttDeclaration(["void", "zoid"]), + "\n/* Ett declarations */\n" . + "static int void;\n" . + "static int zoid;\n" . "\n"); is(DumpEttDeclaration(), "\n/* Ett declarations */\n\n"); $x->{conformance} = { header_fields => { - hf_bla => { INDEX => "hf_bla", NAME => "Bla", FILTER => "bla.field", FT_TYPE => "FT_UINT32", BASE_TYPE => "BASE_DEC", VALSSTRING => "NULL", MASK => 0xFF, BLURB => "NULL" } - } + hf_bla => { INDEX => "hf_bla", NAME => "Bla", FILTER => "bla.field", FT_TYPE => "FT_UINT32", BASE_TYPE => "BASE_DEC", VALSSTRING => "NULL", MASK => 0xFF, BLURB => "NULL" } + } }; is($x->DumpHfList(), "\tstatic hf_register_info hf[] = { @@ -234,14 +234,14 @@ is($x->DumpHfList(), "\tstatic hf_register_info hf[] = { is($x->DumpHfDeclaration(), " /* Header field declarations */ -static gint hf_bla = -1; +static int hf_bla; "); is(DumpFunctionTable({ NAME => "someif", FUNCTIONS => [ { NAME => "fn1", OPNUM => 3 }, { NAME => "someif_fn2", OPNUM => 2 } ] }), -'static dcerpc_sub_dissector someif_dissectors[] = { +'static const dcerpc_sub_dissector someif_dissectors[] = { { 3, "fn1", someif_dissect_fn1_request, someif_dissect_fn1_response}, { 2, "fn2", diff --git a/tools/pidl/wscript b/tools/pidl/wscript index f4ff9028..01f8f5e4 100644 --- a/tools/pidl/wscript +++ b/tools/pidl/wscript @@ -1,77 +1,36 @@ #!/usr/bin/env python -import os, Logs -from samba_utils import MODE_755 +from waflib import Logs, Errors # This function checks if a perl module is installed on the system. def check_system_perl_module(conf, module, version=None): - bundle_name = module.replace('::', '_') module_check = module # Create module string with version if version: module_check = module + ' ' + str(version) - # Check if we have to bundle it. - if conf.LIB_MUST_BE_BUNDLED(bundle_name.lower()): - return False - # Check for system perl module - if not conf.check_perl_module(module_check): + if conf.check_perl_module(module_check) is None: return False - conf.define('USING_SYSTEM_%s' % bundle_name.upper(), 1) - return True -def set_options(opt): +def options(opt): return def configure(conf): # Check if perl(Parse::Yapp::Driver) is available. - check_system_perl_module(conf, "Parse::Yapp::Driver", 1.05) - - # we need a recent version of MakeMaker to get the right man page names - if conf.CHECK_PERL_MANPAGE(): - conf.env.PERLMAN1EXT = conf.CHECK_PERL_MANPAGE(section='1') - conf.env.PERLMAN3EXT = conf.CHECK_PERL_MANPAGE(section='3') - conf.DEFINE('HAVE_PERL_MAKEMAKER', 1) + if not check_system_perl_module(conf, + "Parse::Yapp::Driver", + 1.05): + raise Errors.WafError('perl module "Parse::Yapp::Driver" not found') # yapp is used for building the parser - conf.find_program('yapp', var='YAPP') - conf.find_program('pod2man', var='POD2MAN') + if not conf.find_program('yapp', var='YAPP'): + raise Errors.WafError('yapp not found') def build(bld): - bld.INSTALL_FILES('${BINDIR}', 'pidl', chmod=MODE_755, perl_fixup=True) - - bld.RECURSE('lib') - - if not bld.CONFIG_SET('HAVE_PERL_MAKEMAKER'): - return - - pidl_manpages = { - 'pidl': 'man1/pidl.${PERLMAN1EXT}', - 'lib/Parse/Pidl/NDR.pm': 'man3/Parse::Pidl::NDR.${PERLMAN3EXT}', - 'lib/Parse/Pidl/Wireshark/Conformance.pm': 'man3/Parse::Pidl::Wireshark::Conformance.${PERLMAN3EXT}', - 'lib/Parse/Pidl/Dump.pm': 'man3/Parse::Pidl::Dump.${PERLMAN3EXT}', - 'lib/Parse/Pidl/Util.pm': 'man3/Parse::Pidl::Util.${PERLMAN3EXT}', - 'lib/Parse/Pidl/Wireshark/NDR.pm': 'man3/Parse::Pidl::Wireshark::NDR.${PERLMAN3EXT}' - } - - for k, v in pidl_manpages.iteritems(): - pidl_manpages[k] = bld.EXPAND_VARIABLES(v) - - # use perl to build the manpages - bld.env.pidl_srcdir = os.path.join(bld.srcnode.abspath(), 'pidl') - - bld.SET_BUILD_GROUP('final') - if 'POD2MAN' in bld.env and bld.env['POD2MAN'] != '': - for src, manpage in pidl_manpages.iteritems(): - bld(rule='${POD2MAN} -c "Samba Documentation" ${SRC} ${TGT}', - shell=True, - source=src, - install_path=os.path.dirname(bld.EXPAND_VARIABLES('${MANDIR}/'+manpage)), - target=os.path.basename(manpage)) # we want to prefer the git version of the parsers if we can. # Only if the source has changed do we want to re-run yapp @@ -95,9 +54,8 @@ $ git add lib/Parse/Pidl/IDL.pm lib/Parse/Pidl/Expr.pm $ git commit $ cd - -If your 100% sure you haven't changed idl.yp and expr.yp +If you're 100% sure you haven't changed idl.yp and expr.yp try this to avoid this message: $ touch ../pidl/lib/Parse/Pidl/IDL.pm ../pidl/lib/Parse/Pidl/Expr.pm ''') - |