From 07213ad32930d6f59ddc47cc70766b0fbadb322f Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 11 Aug 2011 06:12:39 +0000 Subject: [PATCH] Sync up to the latest PIDL with Mathieu's wireshark patches svn path=/trunk/; revision=38470 --- tools/pidl/idl.yp | 36 ++- tools/pidl/lib/Parse/Pidl/Expr.pm | 72 ++--- tools/pidl/lib/Parse/Pidl/IDL.pm | 96 ++++-- tools/pidl/lib/Parse/Pidl/NDR.pm | 215 ++++++++++--- tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 11 + tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm | 7 + tools/pidl/lib/Parse/Pidl/Samba4.pm | 9 +- tools/pidl/lib/Parse/Pidl/Samba4/Header.pm | 26 ++ .../pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm | 123 +++---- .../pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 303 ++++++++++++++++-- .../pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm | 11 +- tools/pidl/lib/Parse/Pidl/Samba4/Python.pm | 93 ++++-- tools/pidl/lib/Parse/Pidl/Typelist.pm | 36 ++- tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm | 146 +++++++-- 14 files changed, 911 insertions(+), 273 deletions(-) diff --git a/tools/pidl/idl.yp b/tools/pidl/idl.yp index 30247f9ef3..b5c5185fbe 100644 --- a/tools/pidl/idl.yp +++ b/tools/pidl/idl.yp @@ -387,7 +387,31 @@ pipe: {{ "TYPE" => "PIPE", "PROPERTIES" => $_[1], - "DATA" => $_[3], + "NAME" => undef, + "DATA" => { + "TYPE" => "STRUCT", + "PROPERTIES" => $_[1], + "NAME" => undef, + "ELEMENTS" => [{ + "NAME" => "count", + "PROPERTIES" => $_[1], + "POINTERS" => 0, + "ARRAY_LEN" => [], + "TYPE" => "uint3264", + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + },{ + "NAME" => "array", + "PROPERTIES" => $_[1], + "POINTERS" => 0, + "ARRAY_LEN" => [ "count" ], + "TYPE" => $_[3], + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + }], + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + }, "FILE" => $_[0]->YYData->{FILE}, "LINE" => $_[0]->YYData->{LINE}, }} @@ -653,11 +677,17 @@ sub parse_file($$) my $saved_delim = $/; undef $/; my $cpp = $ENV{CPP}; + my $options = ""; if (! defined $cpp) { - $cpp = "cpp"; + if (defined $ENV{CC}) { + $cpp = "$ENV{CC}"; + $options = "-E"; + } else { + $cpp = "cpp"; + } } my $includes = join('',map { " -I$_" } @$incdirs); - my $data = `$cpp -D__PIDL__$includes -xc "$filename"`; + my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`; $/ = $saved_delim; return parse_string($data, $filename); diff --git a/tools/pidl/lib/Parse/Pidl/Expr.pm b/tools/pidl/lib/Parse/Pidl/Expr.pm index 1230a71a2b..24581d29f4 100644 --- a/tools/pidl/lib/Parse/Pidl/Expr.pm +++ b/tools/pidl/lib/Parse/Pidl/Expr.pm @@ -1127,7 +1127,7 @@ sub new { [#Rule 2 'exp', 1, sub -#line 24 "./../pidl/expr.yp" +#line 24 "expr.yp" { "\"$_[1]\"" } ], [#Rule 3 @@ -1139,199 +1139,199 @@ sub [#Rule 5 'exp', 2, sub -#line 30 "./../pidl/expr.yp" +#line 30 "expr.yp" { "~$_[2]" } ], [#Rule 6 'exp', 3, sub -#line 32 "./../pidl/expr.yp" +#line 32 "expr.yp" { "$_[1] + $_[3]" } ], [#Rule 7 'exp', 3, sub -#line 34 "./../pidl/expr.yp" +#line 34 "expr.yp" { "$_[1] - $_[3]" } ], [#Rule 8 'exp', 3, sub -#line 36 "./../pidl/expr.yp" +#line 36 "expr.yp" { "$_[1] * $_[3]" } ], [#Rule 9 'exp', 3, sub -#line 38 "./../pidl/expr.yp" +#line 38 "expr.yp" { "$_[1] % $_[3]" } ], [#Rule 10 'exp', 3, sub -#line 40 "./../pidl/expr.yp" +#line 40 "expr.yp" { "$_[1] < $_[3]" } ], [#Rule 11 'exp', 3, sub -#line 42 "./../pidl/expr.yp" +#line 42 "expr.yp" { "$_[1] > $_[3]" } ], [#Rule 12 'exp', 3, sub -#line 44 "./../pidl/expr.yp" +#line 44 "expr.yp" { "$_[1] | $_[3]" } ], [#Rule 13 'exp', 3, sub -#line 46 "./../pidl/expr.yp" +#line 46 "expr.yp" { "$_[1] == $_[3]" } ], [#Rule 14 'exp', 3, sub -#line 48 "./../pidl/expr.yp" +#line 48 "expr.yp" { "$_[1] <= $_[3]" } ], [#Rule 15 'exp', 3, sub -#line 50 "./../pidl/expr.yp" +#line 50 "expr.yp" { "$_[1] => $_[3]" } ], [#Rule 16 'exp', 3, sub -#line 52 "./../pidl/expr.yp" +#line 52 "expr.yp" { "$_[1] << $_[3]" } ], [#Rule 17 'exp', 3, sub -#line 54 "./../pidl/expr.yp" +#line 54 "expr.yp" { "$_[1] >> $_[3]" } ], [#Rule 18 'exp', 3, sub -#line 56 "./../pidl/expr.yp" +#line 56 "expr.yp" { "$_[1] != $_[3]" } ], [#Rule 19 'exp', 3, sub -#line 58 "./../pidl/expr.yp" +#line 58 "expr.yp" { "$_[1] || $_[3]" } ], [#Rule 20 'exp', 3, sub -#line 60 "./../pidl/expr.yp" +#line 60 "expr.yp" { "$_[1] && $_[3]" } ], [#Rule 21 'exp', 3, sub -#line 62 "./../pidl/expr.yp" +#line 62 "expr.yp" { "$_[1] & $_[3]" } ], [#Rule 22 'exp', 5, sub -#line 64 "./../pidl/expr.yp" +#line 64 "expr.yp" { "$_[1]?$_[3]:$_[5]" } ], [#Rule 23 'exp', 2, sub -#line 66 "./../pidl/expr.yp" +#line 66 "expr.yp" { "~$_[1]" } ], [#Rule 24 'exp', 2, sub -#line 68 "./../pidl/expr.yp" +#line 68 "expr.yp" { "not $_[1]" } ], [#Rule 25 'exp', 3, sub -#line 70 "./../pidl/expr.yp" +#line 70 "expr.yp" { "$_[1] / $_[3]" } ], [#Rule 26 'exp', 2, sub -#line 72 "./../pidl/expr.yp" +#line 72 "expr.yp" { "-$_[2]" } ], [#Rule 27 'exp', 2, sub -#line 74 "./../pidl/expr.yp" +#line 74 "expr.yp" { "&$_[2]" } ], [#Rule 28 'exp', 3, sub -#line 76 "./../pidl/expr.yp" +#line 76 "expr.yp" { "$_[1]^$_[3]" } ], [#Rule 29 'exp', 3, sub -#line 78 "./../pidl/expr.yp" +#line 78 "expr.yp" { "($_[2])" } ], [#Rule 30 'possible_pointer', 1, sub -#line 82 "./../pidl/expr.yp" +#line 82 "expr.yp" { $_[0]->_Lookup($_[1]) } ], [#Rule 31 'possible_pointer', 2, sub -#line 84 "./../pidl/expr.yp" +#line 84 "expr.yp" { $_[0]->_Dereference($_[2]); "*$_[2]" } ], [#Rule 32 'var', 1, sub -#line 88 "./../pidl/expr.yp" +#line 88 "expr.yp" { $_[0]->_Use($_[1]) } ], [#Rule 33 'var', 3, sub -#line 90 "./../pidl/expr.yp" +#line 90 "expr.yp" { $_[0]->_Use("$_[1].$_[3]") } ], [#Rule 34 'var', 3, sub -#line 92 "./../pidl/expr.yp" +#line 92 "expr.yp" { "($_[2])" } ], [#Rule 35 'var', 3, sub -#line 94 "./../pidl/expr.yp" +#line 94 "expr.yp" { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] } ], [#Rule 36 'func', 4, sub -#line 99 "./../pidl/expr.yp" +#line 99 "expr.yp" { "$_[1]($_[3])" } ], [#Rule 37 'opt_args', 0, sub -#line 104 "./../pidl/expr.yp" +#line 104 "expr.yp" { "" } ], [#Rule 38 @@ -1349,7 +1349,7 @@ sub [#Rule 42 'args', 3, sub -#line 118 "./../pidl/expr.yp" +#line 118 "expr.yp" { "$_[1], $_[3]" } ] ], @@ -1357,7 +1357,7 @@ sub bless($self,$class); } -#line 121 "./../pidl/expr.yp" +#line 121 "expr.yp" package Parse::Pidl::Expr; diff --git a/tools/pidl/lib/Parse/Pidl/IDL.pm b/tools/pidl/lib/Parse/Pidl/IDL.pm index de605c7024..d4820ffe92 100644 --- a/tools/pidl/lib/Parse/Pidl/IDL.pm +++ b/tools/pidl/lib/Parse/Pidl/IDL.pm @@ -2249,7 +2249,31 @@ sub {{ "TYPE" => "PIPE", "PROPERTIES" => $_[1], - "DATA" => $_[3], + "NAME" => undef, + "DATA" => { + "TYPE" => "STRUCT", + "PROPERTIES" => $_[1], + "NAME" => undef, + "ELEMENTS" => [{ + "NAME" => "count", + "PROPERTIES" => $_[1], + "POINTERS" => 0, + "ARRAY_LEN" => [], + "TYPE" => "uint3264", + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + },{ + "NAME" => "array", + "PROPERTIES" => $_[1], + "POINTERS" => 0, + "ARRAY_LEN" => [ "count" ], + "TYPE" => $_[3], + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + }], + "FILE" => $_[0]->YYData->{FILE}, + "LINE" => $_[0]->YYData->{LINE}, + }, "FILE" => $_[0]->YYData->{FILE}, "LINE" => $_[0]->YYData->{LINE}, }} @@ -2257,13 +2281,13 @@ sub [#Rule 78 'element_list1', 0, sub -#line 398 "idl.yp" +#line 422 "idl.yp" { [] } ], [#Rule 79 'element_list1', 3, sub -#line 400 "idl.yp" +#line 424 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 80 @@ -2281,13 +2305,13 @@ sub [#Rule 84 'element_list2', 2, sub -#line 414 "idl.yp" +#line 438 "idl.yp" { [ $_[2] ] } ], [#Rule 85 'element_list2', 4, sub -#line 416 "idl.yp" +#line 440 "idl.yp" { push(@{$_[1]}, $_[4]); $_[1] } ], [#Rule 86 @@ -2296,13 +2320,13 @@ sub [#Rule 87 'array_len', 3, sub -#line 422 "idl.yp" +#line 446 "idl.yp" { push(@{$_[3]}, "*"); $_[3] } ], [#Rule 88 'array_len', 4, sub -#line 424 "idl.yp" +#line 448 "idl.yp" { push(@{$_[4]}, "$_[2]"); $_[4] } ], [#Rule 89 @@ -2311,31 +2335,31 @@ sub [#Rule 90 'property_list', 4, sub -#line 430 "idl.yp" +#line 454 "idl.yp" { FlattenHash([$_[1],$_[3]]); } ], [#Rule 91 'properties', 1, sub -#line 434 "idl.yp" +#line 458 "idl.yp" { $_[1] } ], [#Rule 92 'properties', 3, sub -#line 436 "idl.yp" +#line 460 "idl.yp" { FlattenHash([$_[1], $_[3]]); } ], [#Rule 93 'property', 1, sub -#line 440 "idl.yp" +#line 464 "idl.yp" {{ "$_[1]" => "1" }} ], [#Rule 94 'property', 4, sub -#line 442 "idl.yp" +#line 466 "idl.yp" {{ "$_[1]" => "$_[3]" }} ], [#Rule 95 @@ -2344,13 +2368,13 @@ sub [#Rule 96 'commalisttext', 3, sub -#line 448 "idl.yp" +#line 472 "idl.yp" { "$_[1],$_[3]" } ], [#Rule 97 'anytext', 0, sub -#line 453 "idl.yp" +#line 477 "idl.yp" { "" } ], [#Rule 98 @@ -2365,91 +2389,91 @@ sub [#Rule 101 'anytext', 3, sub -#line 461 "idl.yp" +#line 485 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 102 'anytext', 3, sub -#line 463 "idl.yp" +#line 487 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 103 'anytext', 3, sub -#line 465 "idl.yp" +#line 489 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 104 'anytext', 3, sub -#line 467 "idl.yp" +#line 491 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 105 'anytext', 3, sub -#line 469 "idl.yp" +#line 493 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 106 'anytext', 3, sub -#line 471 "idl.yp" +#line 495 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 107 'anytext', 3, sub -#line 473 "idl.yp" +#line 497 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 108 'anytext', 3, sub -#line 475 "idl.yp" +#line 499 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 109 'anytext', 3, sub -#line 477 "idl.yp" +#line 501 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 110 'anytext', 3, sub -#line 479 "idl.yp" +#line 503 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 111 'anytext', 3, sub -#line 481 "idl.yp" +#line 505 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 112 'anytext', 3, sub -#line 483 "idl.yp" +#line 507 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 113 'anytext', 3, sub -#line 485 "idl.yp" +#line 509 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 114 'anytext', 5, sub -#line 487 "idl.yp" +#line 511 "idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 115 'anytext', 5, sub -#line 489 "idl.yp" +#line 513 "idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 116 @@ -2467,7 +2491,7 @@ sub [#Rule 120 'text', 1, sub -#line 507 "idl.yp" +#line 531 "idl.yp" { "\"$_[1]\"" } ], [#Rule 121 @@ -2481,7 +2505,7 @@ sub bless($self,$class); } -#line 519 "idl.yp" +#line 543 "idl.yp" use Parse::Pidl qw(error); @@ -2619,11 +2643,17 @@ sub parse_file($$) my $saved_delim = $/; undef $/; my $cpp = $ENV{CPP}; + my $options = ""; if (! defined $cpp) { - $cpp = "cpp"; + if (defined $ENV{CC}) { + $cpp = "$ENV{CC}"; + $options = "-E"; + } else { + $cpp = "cpp"; + } } my $includes = join('',map { " -I$_" } @$incdirs); - my $data = `$cpp -D__PIDL__$includes -xc "$filename"`; + my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`; $/ = $saved_delim; return parse_string($data, $filename); diff --git a/tools/pidl/lib/Parse/Pidl/NDR.pm b/tools/pidl/lib/Parse/Pidl/NDR.pm index 21b75687a7..db776ae3ef 100644 --- a/tools/pidl/lib/Parse/Pidl/NDR.pm +++ b/tools/pidl/lib/Parse/Pidl/NDR.pm @@ -34,12 +34,12 @@ require Exporter; use vars qw($VERSION); $VERSION = '0.01'; @ISA = qw(Exporter); -@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsString); +@EXPORT = qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe ContainsString); @EXPORT_OK = qw(GetElementLevelTable ParseElement ValidElement align_type mapToScalar ParseType can_contain_deferred is_charset_array); use strict; use Parse::Pidl qw(warning fatal); -use Parse::Pidl::Typelist qw(hasType getType expandAlias mapScalarType); +use Parse::Pidl::Typelist qw(hasType getType typeIs expandAlias mapScalarType is_fixed_size_scalar); use Parse::Pidl::Util qw(has_property property_matches); # Alignment of the built-in scalar types @@ -66,6 +66,8 @@ my $scalar_alignment = { 'string' => 4, 'string_array' => 4, #??? 'time_t' => 4, + 'uid_t' => 8, + 'gid_t' => 8, 'NTTIME' => 4, 'NTTIME_1sec' => 4, 'NTTIME_hyper' => 8, @@ -81,9 +83,9 @@ my $scalar_alignment = { 'dnsp_string' => 1 }; -sub GetElementLevelTable($$) +sub GetElementLevelTable($$$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; my $order = []; my $is_deferred = 0; @@ -113,6 +115,51 @@ sub GetElementLevelTable($$) warning($e, "[out] argument `$e->{NAME}' not a pointer") if ($needptrs > $e->{POINTERS}); } + my $allow_pipe = ($e->{PARENT}->{TYPE} eq "FUNCTION"); + my $is_pipe = typeIs($e->{TYPE}, "PIPE"); + + if ($is_pipe) { + if (not $allow_pipe) { + fatal($e, "argument `$e->{NAME}' is a pipe and not allowed on $e->{PARENT}->{TYPE}"); + } + + if ($e->{POINTERS} > 1) { + fatal($e, "$e->{POINTERS} are not allowed on pipe element $e->{NAME}"); + } + + if ($e->{POINTERS} < 0) { + fatal($e, "pipe element $e->{NAME} needs pointer"); + } + + if ($e->{POINTERS} == 1 and pointer_type($e) ne "ref") { + fatal($e, "pointer should be 'ref' on pipe element $e->{NAME}"); + } + + if (scalar(@size_is) > 0) { + fatal($e, "size_is() on pipe element"); + } + + if (scalar(@length_is) > 0) { + fatal($e, "length_is() on pipe element"); + } + + if (scalar(@bracket_array) > 0) { + fatal($e, "brackets on pipe element"); + } + + if (defined(has_property($e, "subcontext"))) { + fatal($e, "subcontext on pipe element"); + } + + if (has_property($e, "switch_is")) { + fatal($e, "switch_is on pipe element"); + } + + if (can_contain_deferred($e->{TYPE})) { + fatal($e, "$e->{TYPE} can_contain_deferred - not allowed on pipe element"); + } + } + # Parse the [][][][] style array stuff for my $i (0 .. $#bracket_array) { my $d = $bracket_array[$#bracket_array - $i]; @@ -257,6 +304,19 @@ sub GetElementLevelTable($$) } } + if ($is_pipe) { + push (@$order, { + TYPE => "PIPE", + IS_DEFERRED => 0, + CONTAINS_DEFERRED => 0, + }); + + my $i = 0; + foreach (@$order) { $_->{LEVEL_INDEX} = $i; $i+=1; } + + return $order; + } + if (defined(has_property($e, "subcontext"))) { my $hdr_size = has_property($e, "subcontext"); my $subsize = has_property($e, "subcontext_size"); @@ -307,9 +367,9 @@ sub GetElementLevelTable($$) return $order; } -sub GetTypedefLevelTable($$$) +sub GetTypedefLevelTable($$$$) { - my ($e, $data, $pointer_default) = @_; + my ($e, $data, $pointer_default, $ms_union) = @_; my $order = []; @@ -427,35 +487,37 @@ sub align_type($) # Struct/union without body: assume 4 return 4 unless (defined($dt->{ELEMENTS})); return find_largest_alignment($dt); + } elsif (($dt->{TYPE} eq "PIPE")) { + return 5; } die("Unknown data type type $dt->{TYPE}"); } -sub ParseElement($$) +sub ParseElement($$$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; $e->{TYPE} = expandAlias($e->{TYPE}); if (ref($e->{TYPE}) eq "HASH") { - $e->{TYPE} = ParseType($e->{TYPE}, $pointer_default); + $e->{TYPE} = ParseType($e->{TYPE}, $pointer_default, $ms_union); } return { NAME => $e->{NAME}, TYPE => $e->{TYPE}, PROPERTIES => $e->{PROPERTIES}, - LEVELS => GetElementLevelTable($e, $pointer_default), + LEVELS => GetElementLevelTable($e, $pointer_default, $ms_union), REPRESENTATION_TYPE => ($e->{PROPERTIES}->{represent_as} or $e->{TYPE}), ALIGN => align_type($e->{TYPE}), ORIGINAL => $e }; } -sub ParseStruct($$) +sub ParseStruct($$$) { - my ($struct, $pointer_default) = @_; + my ($struct, $pointer_default, $ms_union) = @_; my @elements = (); my $surrounding = undef; @@ -473,7 +535,7 @@ sub ParseStruct($$) foreach my $x (@{$struct->{ELEMENTS}}) { - my $e = ParseElement($x, $pointer_default); + my $e = ParseElement($x, $pointer_default, $ms_union); if ($x != $struct->{ELEMENTS}[-1] and $e->{LEVELS}[0]->{IS_SURROUNDING}) { fatal($x, "conformant member not at end of struct"); @@ -510,8 +572,10 @@ sub ParseStruct($$) sub ParseUnion($$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; my @elements = (); + my $is_ms_union = $ms_union; + $is_ms_union = 1 if has_property($e, "ms_union"); my $hasdefault = 0; my $switch_type = has_property($e, "switch_type"); unless (defined($switch_type)) { $switch_type = "uint32"; } @@ -524,6 +588,7 @@ sub ParseUnion($$) ELEMENTS => undef, PROPERTIES => $e->{PROPERTIES}, HAS_DEFAULT => $hasdefault, + IS_MS_UNION => $is_ms_union, ORIGINAL => $e, ALIGN => undef } unless defined($e->{ELEMENTS}); @@ -536,7 +601,7 @@ sub ParseUnion($$) if ($x->{TYPE} eq "EMPTY") { $t = { TYPE => "EMPTY" }; } else { - $t = ParseElement($x, $pointer_default); + $t = ParseElement($x, $pointer_default, $ms_union); } if (has_property($x, "default")) { $t->{CASE} = "default"; @@ -561,6 +626,7 @@ sub ParseUnion($$) ELEMENTS => \@elements, PROPERTIES => $e->{PROPERTIES}, HAS_DEFAULT => $hasdefault, + IS_MS_UNION => $is_ms_union, ORIGINAL => $e, ALIGN => $align }; @@ -568,7 +634,7 @@ sub ParseUnion($$) sub ParseEnum($$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; return { TYPE => "ENUM", @@ -580,9 +646,9 @@ sub ParseEnum($$) }; } -sub ParseBitmap($$) +sub ParseBitmap($$$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; return { TYPE => "BITMAP", @@ -594,9 +660,60 @@ sub ParseBitmap($$) }; } -sub ParseType($$) +sub ParsePipe($$$) { - my ($d, $pointer_default) = @_; + my ($pipe, $pointer_default, $ms_union) = @_; + + my $pname = $pipe->{NAME}; + $pname = $pipe->{PARENT}->{NAME} unless defined $pname; + + if (not defined($pipe->{PROPERTIES}) + and defined($pipe->{PARENT}->{PROPERTIES})) { + $pipe->{PROPERTIES} = $pipe->{PARENT}->{PROPERTIES}; + } + + if (ref($pipe->{DATA}) eq "HASH") { + if (not defined($pipe->{DATA}->{PROPERTIES}) + and defined($pipe->{PROPERTIES})) { + $pipe->{DATA}->{PROPERTIES} = $pipe->{PROPERTIES}; + } + } + + my $struct = ParseStruct($pipe->{DATA}, $pointer_default, $ms_union); + $struct->{ALIGN} = 5; + $struct->{NAME} = "$pname\_chunk"; + + # 'count' is element [0] and 'array' [1] + my $e = $struct->{ELEMENTS}[1]; + # level [0] is of type "ARRAY" + my $l = $e->{LEVELS}[1]; + + # here we check that pipe elements have a fixed size type + while (defined($l)) { + my $cl = $l; + $l = GetNextLevel($e, $cl); + if ($cl->{TYPE} ne "DATA") { + fatal($pipe, el_name($pipe) . ": pipe contains non DATA level"); + } + + # for now we only support scalars + next if is_fixed_size_scalar($cl->{DATA_TYPE}); + + fatal($pipe, el_name($pipe) . ": pipe contains non fixed size type[$cl->{DATA_TYPE}]"); + } + + return { + TYPE => "PIPE", + NAME => $pipe->{NAME}, + DATA => $struct, + PROPERTIES => $pipe->{PROPERTIES}, + ORIGINAL => $pipe, + }; +} + +sub ParseType($$$) +{ + my ($d, $pointer_default, $ms_union) = @_; my $data = { STRUCT => \&ParseStruct, @@ -604,14 +721,15 @@ sub ParseType($$) ENUM => \&ParseEnum, BITMAP => \&ParseBitmap, TYPEDEF => \&ParseTypedef, - }->{$d->{TYPE}}->($d, $pointer_default); + PIPE => \&ParsePipe, + }->{$d->{TYPE}}->($d, $pointer_default, $ms_union); return $data; } sub ParseTypedef($$) { - my ($d, $pointer_default) = @_; + my ($d, $pointer_default, $ms_union) = @_; my $data; @@ -621,7 +739,7 @@ sub ParseTypedef($$) $d->{PROPERTIES} = $d->{DATA}->{PROPERTIES}; } - $data = ParseType($d->{DATA}, $pointer_default); + $data = ParseType($d->{DATA}, $pointer_default, $ms_union); $data->{ALIGN} = align_type($d->{NAME}); } else { $data = getType($d->{DATA}); @@ -631,7 +749,7 @@ sub ParseTypedef($$) NAME => $d->{NAME}, TYPE => $d->{TYPE}, PROPERTIES => $d->{PROPERTIES}, - LEVELS => GetTypedefLevelTable($d, $data, $pointer_default), + LEVELS => GetTypedefLevelTable($d, $data, $pointer_default, $ms_union), DATA => $data, ORIGINAL => $d }; @@ -644,9 +762,9 @@ sub ParseConst($$) return $d; } -sub ParseFunction($$$) +sub ParseFunction($$$$) { - my ($ndr,$d,$opnum) = @_; + my ($ndr,$d,$opnum,$ms_union) = @_; my @elements = (); my $rettype = undef; my $thisopnum = undef; @@ -659,7 +777,7 @@ sub ParseFunction($$$) } foreach my $x (@{$d->{ELEMENTS}}) { - my $e = ParseElement($x, $ndr->{PROPERTIES}->{pointer_default}); + my $e = ParseElement($x, $ndr->{PROPERTIES}->{pointer_default}, $ms_union); push (@{$e->{DIRECTION}}, "in") if (has_property($x, "in")); push (@{$e->{DIRECTION}}, "out") if (has_property($x, "out")); @@ -720,6 +838,8 @@ sub ParseInterface($) my @endpoints; my $opnum = 0; my $version; + my $ms_union = 0; + $ms_union = 1 if has_property($idl, "ms_union"); if (not has_property($idl, "pointer_default")) { # MIDL defaults to "ptr" in DCE compatible mode (/osf) @@ -729,11 +849,11 @@ sub ParseInterface($) foreach my $d (@{$idl->{DATA}}) { if ($d->{TYPE} eq "FUNCTION") { - push (@functions, ParseFunction($idl, $d, \$opnum)); + push (@functions, ParseFunction($idl, $d, \$opnum, $ms_union)); } elsif ($d->{TYPE} eq "CONST") { push (@consts, ParseConst($idl, $d)); } else { - push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default})); + push (@types, ParseType($d, $idl->{PROPERTIES}->{pointer_default}, $ms_union)); FindNestedTypes(\@types, $d); } } @@ -823,6 +943,9 @@ sub ContainsString($) { my ($e) = @_; + if (property_matches($e, "flag", ".*STR_NULLTERM.*")) { + return 1; + } foreach my $l (@{$e->{LEVELS}}) { return 1 if ($l->{TYPE} eq "ARRAY" and $l->{IS_ZERO_TERMINATED}); } @@ -845,6 +968,20 @@ sub ContainsDeferred($$) return 0; } +sub ContainsPipe($$) +{ + my ($e,$l) = @_; + + return 1 if ($l->{TYPE} eq "PIPE"); + + while ($l = GetNextLevel($e,$l)) + { + return 1 if ($l->{TYPE} eq "PIPE"); + } + + return 0; +} + sub el_name($) { my $e = shift; @@ -920,14 +1057,14 @@ my %property_list = ( "gensize" => ["TYPEDEF", "STRUCT", "UNION"], "value" => ["ELEMENT"], - "flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "flag" => ["ELEMENT", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], # generic - "public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], - "nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], - "nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], + "public" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], + "nopush" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], + "nopull" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "PIPE"], "nosize" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], - "noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT"], + "noprint" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP", "ELEMENT", "PIPE"], "nopython" => ["FUNCTION", "TYPEDEF", "STRUCT", "UNION", "ENUM", "BITMAP"], "todo" => ["FUNCTION"], @@ -935,6 +1072,7 @@ my %property_list = ( "switch_is" => ["ELEMENT"], "switch_type" => ["ELEMENT", "UNION"], "nodiscriminant" => ["UNION"], + "ms_union" => ["INTERFACE", "UNION"], "case" => ["ELEMENT"], "default" => ["ELEMENT"], @@ -1155,11 +1293,16 @@ sub ValidUnion($) sub ValidPipe($) { my ($pipe) = @_; - my $data = $pipe->{DATA}; + my $struct = $pipe->{DATA}; ValidProperties($pipe, "PIPE"); - fatal($pipe, $pipe->{NAME} . ": 'pipe' is not yet supported by pidl"); + $struct->{PARENT} = $pipe; + + $struct->{FILE} = $pipe->{FILE} unless defined($struct->{FILE}); + $struct->{LINE} = $pipe->{LINE} unless defined($struct->{LINE}); + + ValidType($struct); } ##################################################################### diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 67051a8783..8142b35699 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -14,6 +14,7 @@ use Exporter; use strict; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(ContainsPipe); use Parse::Pidl::Typelist qw(mapTypeName); use Parse::Pidl::Samba4 qw(DeclLong); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); @@ -378,6 +379,16 @@ sub ParseInterface($$) foreach my $fn (@{$if->{FUNCTIONS}}) { next if has_property($fn, "noopnum"); next if has_property($fn, "todo"); + + my $skip = 0; + foreach my $e (@{$fn->{ELEMENTS}}) { + if (ContainsPipe($e, $e->{LEVELS}[0])) { + $skip = 1; + last; + } + } + next if $skip; + $self->ParseFunction($if->{NAME}, $fn); } $self->pidl_hdr("#endif /* __CLI_$uif\__ */"); diff --git a/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm b/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm index 0ebccf552c..c4374baf7c 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm @@ -199,6 +199,12 @@ sub ParseFunction($$) pidl "\treturn false;"; pidl "}"; pidl ""; + pidl "/*"; + pidl " * carry over the pointer count to the reply in case we are"; + pidl " * using full pointer. See NDR specification for full pointers"; + pidl " */"; + pidl "push->ptr_count = pull->ptr_count;"; + pidl ""; pidl "ndr_err = call->ndr_push(push, NDR_OUT, r);"; pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {"; pidl "\ttalloc_free(r);"; @@ -288,6 +294,7 @@ sub Parse($$$) pidl " */"; pidl ""; pidl "#include \"includes.h\""; + pidl "#include \"ntdomain.h\""; pidl "#include \"$header\""; pidl_hdr "#include \"$ndr_header\""; pidl ""; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4.pm b/tools/pidl/lib/Parse/Pidl/Samba4.pm index 1deb708689..b720ab9015 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4.pm @@ -18,12 +18,17 @@ use strict; use vars qw($VERSION); $VERSION = '0.01'; + +# return true if we are using pidl within the samba source tree. This changes +# the names of include files, as some include files (such as ntstatus.h) have +# different paths when installed to the patch in the source tree sub is_intree() { my $srcdir = $ENV{srcdir}; $srcdir = $srcdir ? "$srcdir/" : ""; - return 4 if (-f "${srcdir}kdc/kdc.c"); - return 3 if (-f "${srcdir}include/smb.h"); + return 1 if (-f "${srcdir}kdc/kdc.c"); + return 1 if (-d "${srcdir}source4"); + return 1 if (-f "${srcdir}include/smb.h"); return 0; } diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm index 9788b2c123..3736315120 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Header.pm @@ -215,6 +215,30 @@ sub HeaderUnion($$;$) pidl $tail if defined($tail); } +##################################################################### +# parse a pipe +sub HeaderPipe($$;$) +{ + my($pipe,$name,$tail) = @_; + + my $struct = $pipe->{DATA}; + my $e = $struct->{ELEMENTS}[1]; + + pidl "struct $name;\n"; + pidl "struct $struct->{NAME} {\n"; + $tab_depth++; + pidl tabs()."uint32_t count;\n"; + pidl tabs().mapTypeName($e->{TYPE})." *array;\n"; + $tab_depth--; + pidl "}"; + + if (defined $struct->{PROPERTIES}) { + HeaderProperties($struct->{PROPERTIES}, []); + } + + pidl $tail if defined($tail); +} + ##################################################################### # parse a type sub HeaderType($$$;$) @@ -225,6 +249,7 @@ sub HeaderType($$$;$) ($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name); ($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail); ($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail); + ($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail); return; } @@ -385,6 +410,7 @@ sub HeaderInterface($) HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION"); HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM"); HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP"); + HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE"); } foreach my $fn (@{$interface->{FUNCTIONS}}) { diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm index 32309580f4..c796b466ad 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm @@ -12,6 +12,7 @@ use Exporter; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property ParseExpr); +use Parse::Pidl::NDR qw(ContainsPipe); use Parse::Pidl::Typelist qw(mapTypeName); use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); @@ -44,6 +45,17 @@ sub new($) bless($self, $class); } +sub ParseFunctionHasPipes($$) +{ + my ($self, $fn) = @_; + + foreach my $e (@{$fn->{ELEMENTS}}) { + return 1 if ContainsPipe($e, $e->{LEVELS}[0]); + } + + return 0; +} + sub ParseFunction_r_State($$$$) { my ($self, $if, $fn, $name) = @_; @@ -89,10 +101,11 @@ sub ParseFunction_r_Send($$$$) $self->pidl(""); my $out_params = 0; - foreach (@{$fn->{ELEMENTS}}) { - if (grep(/out/, @{$_->{DIRECTION}})) { - $out_params++; - } + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless grep(/out/, @{$e->{DIRECTION}}); + next if ContainsPipe($e, $e->{LEVELS}[0]); + $out_params++; + } my $submem; @@ -200,6 +213,17 @@ sub ParseFunction_r_Sync($$$$) my ($self, $if, $fn, $name) = @_; my $uname = uc $name; + if ($self->ParseFunctionHasPipes($fn)) { + $self->pidl_both("/*"); + $self->pidl_both(" * The following function is skipped because"); + $self->pidl_both(" * it uses pipes:"); + $self->pidl_both(" *"); + $self->pidl_both(" * dcerpc_$name\_r()"); + $self->pidl_both(" */"); + $self->pidl_both(""); + return; + } + my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)"; $self->fn_declare($proto); @@ -220,49 +244,6 @@ sub ParseFunction_r_Sync($$$$) $self->pidl(""); } -sub ParseFunction_Compat_Sync($$$$) -{ - my ($self, $if, $fn, $name) = @_; - my $uname = uc $name; - - my $proto = "NTSTATUS dcerpc_$name\_compat(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)"; - - $self->pidl_hdr("#ifdef DCERPC_CALL_$uname\_COMPAT"); - $self->pidl_hdr("#define dcerpc_$name(p, m, r) dcerpc_$name\_compat(p, m, r)"); - $self->pidl_hdr("#endif /* DCERPC_CALL_$uname\_COMPAT */"); - - $self->fn_declare($proto); - $self->pidl("{"); - $self->indent; - $self->pidl("NTSTATUS status;"); - $self->pidl(""); - - $self->pidl("status = dcerpc_$name\_r(p->binding_handle, mem_ctx, r);"); - $self->pidl(""); - - $self->pidl("if (NT_STATUS_IS_RPC(status)) {"); - $self->indent; - $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); - - if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") { - $self->pidl("if (NT_STATUS_IS_OK(status)) {"); - $self->indent; - $self->pidl("status = r->out.result;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); - } - - $self->pidl("return status;"); - - $self->deindent; - $self->pidl("}"); - $self->pidl(""); -} - sub ElementDirection($) { my ($e) = @_; @@ -510,6 +491,9 @@ sub ParseFunction_Send($$$$) next unless grep(/out/, @{$e->{DIRECTION}}); $self->ParseCopyArgument($fn, $e, "state->orig.out.", "_"); + + next if ContainsPipe($e, $e->{LEVELS}[0]); + $out_params++; } $self->pidl(""); @@ -589,6 +573,7 @@ sub ParseFunction_Done($$$$) $self->pidl("/* Copy out parameters */"); foreach my $e (@{$fn->{ELEMENTS}}) { + next if ContainsPipe($e, $e->{LEVELS}[0]); next unless (grep(/out/, @{$e->{DIRECTION}})); $self->ParseOutputArgument($fn, $e, @@ -665,6 +650,17 @@ sub ParseFunction_Sync($$$$) { my ($self, $if, $fn, $name) = @_; + if ($self->ParseFunctionHasPipes($fn)) { + $self->pidl_both("/*"); + $self->pidl_both(" * The following function is skipped because"); + $self->pidl_both(" * it uses pipes:"); + $self->pidl_both(" *"); + $self->pidl_both(" * dcerpc_$name()"); + $self->pidl_both(" */"); + $self->pidl_both(""); + return; + } + my $uname = uc $name; my $fn_args = ""; my $fn_str = "NTSTATUS dcerpc_$name"; @@ -682,9 +678,7 @@ sub ParseFunction_Sync($$$$) $fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result"; } - $self->pidl_hdr("#ifndef DCERPC_CALL_$uname\_COMPAT"); $self->fn_declare("$fn_str($fn_args)"); - $self->pidl_hdr("#endif /* DCERPC_CALL_$uname\_COMPAT */"); $self->pidl("{"); $self->indent; $self->pidl("struct $name r;"); @@ -709,6 +703,7 @@ sub ParseFunction_Sync($$$$) $self->pidl("/* Return variables */"); foreach my $e (@{$fn->{ELEMENTS}}) { + next if ContainsPipe($e, $e->{LEVELS}[0]); next unless (grep(/out/, @{$e->{DIRECTION}})); $self->ParseOutputArgument($fn, $e, "r.", "_", "sync"); @@ -734,14 +729,30 @@ sub ParseFunction($$$) { my ($self, $if, $fn) = @_; + if ($self->ParseFunctionHasPipes($fn)) { + $self->pidl_both("/*"); + $self->pidl_both(" * The following function is skipped because"); + $self->pidl_both(" * it uses pipes:"); + $self->pidl_both(" *"); + $self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()"); + $self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()"); + $self->pidl_both(" * dcerpc_$fn->{NAME}_r()"); + $self->pidl_both(" *"); + $self->pidl_both(" * dcerpc_$fn->{NAME}_send()"); + $self->pidl_both(" * dcerpc_$fn->{NAME}_recv()"); + $self->pidl_both(" * dcerpc_$fn->{NAME}()"); + $self->pidl_both(" */"); + $self->pidl_both(""); + warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet"); + return; + } + $self->ParseFunction_r_State($if, $fn, $fn->{NAME}); $self->ParseFunction_r_Send($if, $fn, $fn->{NAME}); $self->ParseFunction_r_Done($if, $fn, $fn->{NAME}); $self->ParseFunction_r_Recv($if, $fn, $fn->{NAME}); $self->ParseFunction_r_Sync($if, $fn, $fn->{NAME}); - $self->ParseFunction_Compat_Sync($if, $fn, $fn->{NAME}); - foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/out/, @{$e->{DIRECTION}})); @@ -811,16 +822,6 @@ sub ParseInterface($$) $self->pidl_hdr(""); } - $self->pidl_hdr("#ifdef DCERPC_IFACE_$ifu\_COMPAT"); - foreach my $fn (@{$if->{FUNCTIONS}}) { - next if has_property($fn, "noopnum"); - next if has_property($fn, "todo"); - my $fnu = uc($fn->{NAME}); - $self->pidl_hdr("#define DCERPC_CALL_$fnu\_COMPAT 1"); - } - $self->pidl_hdr("#endif /* DCERPC_IFACE_$ifu\_COMPAT */"); - $self->pidl_hdr(""); - $self->pidl("/* $if->{NAME} - client functions generated by pidl */"); $self->pidl(""); diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index 09518f7cee..3d31366abf 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -15,7 +15,7 @@ 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 Parse::Pidl::CUtil qw(get_pointer_to get_value_of get_array_element); -use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); use Parse::Pidl::Samba4 qw(is_intree choose_header ArrayDynamicallyAllocated); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv); use Parse::Pidl qw(warning); @@ -198,6 +198,12 @@ sub ParseArrayPushHeader($$$$$$) } else { $size = $length = "ndr_string_length($var_name, sizeof(*$var_name))"; } + if (defined($l->{SIZE_IS})) { + $size = ParseExpr($l->{SIZE_IS}, $env, $e); + } + if (defined($l->{LENGTH_IS})) { + $length = ParseExpr($l->{LENGTH_IS}, $env, $e); + } } else { $size = ParseExpr($l->{SIZE_IS}, $env, $e); $length = ParseExpr($l->{LENGTH_IS}, $env, $e); @@ -206,11 +212,11 @@ sub ParseArrayPushHeader($$$$$$) if ((!$l->{IS_SURROUNDING}) and $l->{IS_CONFORMANT}) { $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $size));"); } - + if ($l->{IS_VARYING}) { $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, 0));"); # array offset $self->pidl("NDR_CHECK(ndr_push_uint3264($ndr, NDR_SCALARS, $length));"); - } + } return $length; } @@ -352,7 +358,7 @@ sub ParseArrayPullHeader($$$$$$) $self->pidl("}"); } - if ($l->{IS_CONFORMANT} and not $l->{IS_ZERO_TERMINATED}) { + if ($l->{IS_CONFORMANT} and (defined($l->{SIZE_IS}) or not $l->{IS_ZERO_TERMINATED})) { $self->defer("if ($var_name) {"); $self->defer_indent; my $size = ParseExprExt($l->{SIZE_IS}, $env, $e->{ORIGINAL}, @@ -364,7 +370,7 @@ sub ParseArrayPullHeader($$$$$$) $self->defer("}"); } - if ($l->{IS_VARYING} and not $l->{IS_ZERO_TERMINATED}) { + 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}, @@ -630,6 +636,8 @@ sub ParseElementPush($$$$$$) my $var_name = $env->{$e->{NAME}}; + return if ContainsPipe($e, $e->{LEVELS}[0]); + return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0])); # Representation type is different from transmit_as @@ -683,6 +691,9 @@ sub ParsePtrPush($$$$$) $self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));"); } elsif ($l->{POINTER_TYPE} eq "full") { $self->pidl("NDR_CHECK(ndr_push_full_ptr($ndr, $var_name));"); + } elsif ($l->{POINTER_TYPE} eq "ignore") { + # We don't want this pointer to appear on the wire at all + $self->pidl("NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, 0));"); } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } @@ -770,7 +781,7 @@ sub ParseElementPrint($$$$$) $var_name = get_pointer_to($var_name); } - if ($l->{IS_ZERO_TERMINATED}) { + 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}, @@ -945,6 +956,7 @@ sub ParseMemCtxPullFlags($$$$) if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) { 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")); @@ -1149,6 +1161,8 @@ sub ParseElementPull($$$$$$) my $represent_name; my $transmit_name; + return if ContainsPipe($e, $e->{LEVELS}[0]); + return unless $primitives or ($deferred and ContainsDeferred($e, $e->{LEVELS}[0])); if ($e->{REPRESENTATION_TYPE} ne $e->{TYPE}) { @@ -1194,7 +1208,7 @@ sub ParsePtrPull($$$$$) $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}));"); @@ -1204,6 +1218,10 @@ sub ParsePtrPull($$$$$) $self->pidl("NDR_CHECK(ndr_pull_generic_ptr($ndr, &_ptr_$e->{NAME}));"); } elsif ($l->{POINTER_TYPE} eq "relative_short") { $self->pidl("NDR_CHECK(ndr_pull_relative_ptr_short($ndr, &_ptr_$e->{NAME}));"); + } elsif ($l->{POINTER_TYPE} eq "ignore") { + #We want to consume the pointer bytes, but ignore the pointer value + $self->pidl("NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &_ptr_$e->{NAME}));"); + $self->pidl("_ptr_$e->{NAME} = 0;"); } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } @@ -1211,16 +1229,22 @@ sub ParsePtrPull($$$$$) $self->pidl("if (_ptr_$e->{NAME}) {"); $self->indent; - # 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);"); + if ($l->{POINTER_TYPE} eq "ignore") { + # Don't do anything, we don't want to do the + # allocation, as we forced it to NULL just above, and + # we may not know the declared type anyway. } else { - # FIXME: Yes, this is nasty. - # We allocate an array twice - # - once just to indicate that it's there, - # - then the real allocation... - $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); + # 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);"); + } else { + # FIXME: Yes, this is nasty. + # We allocate an array twice + # - once just to indicate that it's there, + # - then the real allocation... + $self->pidl("NDR_PULL_ALLOC($ndr, $var_name);"); + } } #$self->pidl("memset($var_name, 0, sizeof($var_name));"); @@ -1255,6 +1279,9 @@ sub ParseStructPushPrimitives($$$$$) } else { $size = "ndr_string_length($varname->$e->{NAME}, sizeof(*$varname->$e->{NAME}))"; } + if (defined($e->{LEVELS}[0]->{SIZE_IS})) { + $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL}); + } } else { $size = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e->{ORIGINAL}); } @@ -1688,16 +1715,21 @@ sub ParseUnionPushPrimitives($$$$) $self->pidl("uint32_t level = ndr_push_get_switch_value($ndr, $varname);"); - if (defined($e->{ALIGN})) { - $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));"); - } - if (defined($e->{SWITCH_TYPE})) { + if (defined($e->{ALIGN})) { + $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));"); + } + $self->pidl("NDR_CHECK(ndr_push_$e->{SWITCH_TYPE}($ndr, NDR_SCALARS, level));"); } if (defined($e->{ALIGN})) { - $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));"); + if ($e->{IS_MS_UNION}) { + $self->pidl("/* ms_union is always aligned to the largest union arm*/"); + $self->pidl("NDR_CHECK(ndr_push_align($ndr, $e->{ALIGN}));"); + } else { + $self->pidl("NDR_CHECK(ndr_push_union_align($ndr, $e->{ALIGN}));"); + } } $self->pidl("switch (level) {"); @@ -1837,11 +1869,12 @@ sub ParseUnionPullPrimitives($$$$$) my ($self,$e,$ndr,$varname,$switch_type) = @_; my $have_default = 0; - if (defined($e->{ALIGN})) { - $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));"); - } if (defined($switch_type)) { + if (defined($e->{ALIGN})) { + $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));"); + } + $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__);"); @@ -1849,7 +1882,12 @@ sub ParseUnionPullPrimitives($$$$$) } if (defined($e->{ALIGN})) { - $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));"); + if ($e->{IS_MS_UNION}) { + $self->pidl("/* ms_union is always aligned to the largest union arm*/"); + $self->pidl("NDR_CHECK(ndr_pull_align($ndr, $e->{ALIGN}));"); + } else { + $self->pidl("NDR_CHECK(ndr_pull_union_align($ndr, $e->{ALIGN}));"); + } } $self->pidl("switch (level) {"); @@ -2051,6 +2089,99 @@ $typefamily{TYPEDEF} = { SIZE_FN_BODY => \&ParseTypedefNdrSize, }; +sub ParsePipePushChunk($$) +{ + my ($self, $t) = @_; + + my $pipe = $t; + $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF"); + my $struct = $pipe->{DATA}; + + my $name = "$struct->{NAME}"; + my $ndr = "ndr"; + my $varname = "r"; + + 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; + + return if has_property($t, "nopush"); + + $self->pidl("{"); + $self->indent; + + $self->ParseStructPush($struct, $ndr, $varname); + $self->pidl(""); + + $self->pidl("NDR_CHECK(ndr_push_pipe_chunk_trailer(ndr, ndr_flags, $varname->count));"); + $self->pidl(""); + + $self->pidl("return NDR_ERR_SUCCESS;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipePullChunk($$) +{ + my ($self, $t) = @_; + + my $pipe = $t; + $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF"); + my $struct = $pipe->{DATA}; + + my $name = "$struct->{NAME}"; + my $ndr = "ndr"; + my $varname = "r"; + + 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; + + return if has_property($struct, "nopull"); + + $self->pidl("{"); + $self->indent; + + $self->ParseStructPull($struct, $ndr, $varname); + $self->pidl(""); + + $self->pidl("NDR_CHECK(ndr_check_pipe_chunk_trailer($ndr, ndr_flags, $varname->count));"); + $self->pidl(""); + + $self->pidl("return NDR_ERR_SUCCESS;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipePrintChunk($$) +{ + my ($self, $t) = @_; + + my $pipe = $t; + $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF"); + my $struct = $pipe->{DATA}; + + my $name = "$struct->{NAME}"; + my $ndr = "ndr"; + my $varname = "r"; + + my $args = $typefamily{$struct->{TYPE}}->{DECL}->($struct, "print", $name, $varname); + + $self->pidl_hdr("void ndr_print_$name(struct ndr_print *ndr, const char *name, $args);"); + + return if (has_property($t, "noprint")); + + $self->pidl("_PUBLIC_ void ndr_print_$name(struct ndr_print *$ndr, const char *name, $args)"); + $self->pidl("{"); + $self->indent; + $self->ParseTypePrint($struct, $ndr, $varname); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + ##################################################################### # parse a function - print side sub ParseFunctionPrint($$) @@ -2253,6 +2384,7 @@ sub ParseFunctionPull($$) $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 "PIPE"); next if (($e->{LEVELS}[1]->{TYPE} eq "ARRAY") and $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}); @@ -2268,6 +2400,12 @@ sub ParseFunctionPull($$) } else { $self->pidl("memset(r->out.$e->{NAME}, 0, ($size) * sizeof(*r->out.$e->{NAME}));"); } + } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY") { + if (grep(/in/, @{$e->{DIRECTION}})) { + $self->pidl("r->out.$e->{NAME} = r->in.$e->{NAME};"); + } else { + $self->pidl("r->out.$e->{NAME} = NULL;"); + } } else { $self->pidl("NDR_PULL_ALLOC($ndr, r->out.$e->{NAME});"); @@ -2326,16 +2464,102 @@ sub AuthServiceStruct($$$) $self->pidl(""); } +sub ParseGeneratePipeArray($$$) +{ + my ($self, $fn, $direction) = @_; + + $self->pidl("static const struct ndr_interface_call_pipe $fn->{NAME}\_$direction\_pipes[] = {"); + $self->indent; + + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless ContainsPipe($e, $e->{LEVELS}[0]); + next unless (grep(/$direction/, @{$e->{DIRECTION}})); + + my $cname = "$e->{TYPE}_chunk"; + + $self->pidl("{"); + $self->indent; + $self->pidl("\"$direction.$e->{NAME}\","); + $self->pidl("\"$cname\","); + $self->pidl("sizeof(struct $cname),"); + $self->pidl("(ndr_push_flags_fn_t) ndr_push_$cname,"); + $self->pidl("(ndr_pull_flags_fn_t) ndr_pull_$cname,"); + $self->pidl("(ndr_print_fn_t) ndr_print_$cname,"); + $self->deindent; + $self->pidl("},"); + } + $self->pidl("{ NULL, NULL, 0, NULL, NULL, NULL }"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); +} + +sub FunctionCallPipes($$) +{ + my ($self, $d) = @_; + return if not defined($d->{OPNUM}); + + my $in_pipes = 0; + my $out_pipes = 0; + + foreach my $e (@{$d->{ELEMENTS}}) { + next unless ContainsPipe($e, $e->{LEVELS}[0]); + + if (grep(/in/, @{$e->{DIRECTION}})) { + $in_pipes++; + } + if (grep(/out/, @{$e->{DIRECTION}})) { + $out_pipes++; + } + } + + if ($in_pipes) { + $self->ParseGeneratePipeArray($d, "in"); + } + + if ($out_pipes) { + $self->ParseGeneratePipeArray($d, "out"); + } +} + sub FunctionCallEntry($$) { my ($self, $d) = @_; return 0 if not defined($d->{OPNUM}); + + my $in_pipes = 0; + my $out_pipes = 0; + + foreach my $e (@{$d->{ELEMENTS}}) { + next unless ContainsPipe($e, $e->{LEVELS}[0]); + + if (grep(/in/, @{$e->{DIRECTION}})) { + $in_pipes++; + } + if (grep(/out/, @{$e->{DIRECTION}})) { + $out_pipes++; + } + } + + my $in_pipes_ptr = "NULL"; + my $out_pipes_ptr = "NULL"; + + if ($in_pipes) { + $in_pipes_ptr = "$d->{NAME}_in_pipes"; + } + + if ($out_pipes) { + $out_pipes_ptr = "$d->{NAME}_out_pipes"; + } + $self->pidl("\t{"); $self->pidl("\t\t\"$d->{NAME}\","); $self->pidl("\t\tsizeof(struct $d->{NAME}),"); $self->pidl("\t\t(ndr_push_flags_fn_t) ndr_push_$d->{NAME},"); $self->pidl("\t\t(ndr_pull_flags_fn_t) ndr_pull_$d->{NAME},"); $self->pidl("\t\t(ndr_print_function_t) ndr_print_$d->{NAME},"); + $self->pidl("\t\t{ $in_pipes, $in_pipes_ptr },"); + $self->pidl("\t\t{ $out_pipes, $out_pipes_ptr },"); $self->pidl("\t},"); return 1; } @@ -2351,6 +2575,10 @@ sub FunctionTable($$) return if ($#{$interface->{FUNCTIONS}}+1 == 0); return unless defined ($interface->{PROPERTIES}->{uuid}); + foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) { + $self->FunctionCallPipes($d); + } + $self->pidl("static const struct ndr_interface_call $interface->{NAME}\_calls[] = {"); foreach my $d (@{$interface->{INHERITED_FUNCTIONS}},@{$interface->{FUNCTIONS}}) { @@ -2447,10 +2675,9 @@ sub HeaderInterface($$$) if (defined $interface->{PROPERTIES}->{uuid}) { my $name = uc $interface->{NAME}; $self->pidl_hdr("#define NDR_$name\_UUID " . - Parse::Pidl::Util::make_str(lc($interface->{PROPERTIES}->{uuid}))); + Parse::Pidl::Util::make_str(lc($interface->{UUID}))); - if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; } - $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{PROPERTIES}->{version}"); + $self->pidl_hdr("#define NDR_$name\_VERSION $interface->{VERSION}"); $self->pidl_hdr("#define NDR_$name\_NAME \"$interface->{NAME}\""); @@ -2604,6 +2831,20 @@ sub ParseInterface($$$) # Typedefs foreach my $d (@{$interface->{TYPES}}) { + if (Parse::Pidl::Typelist::typeIs($d, "PIPE")) { + ($needed->{TypeFunctionName("ndr_push", $d)}) && + $self->ParsePipePushChunk($d); + ($needed->{TypeFunctionName("ndr_pull", $d)}) && + $self->ParsePipePullChunk($d); + ($needed->{TypeFunctionName("ndr_print", $d)}) && + $self->ParsePipePrintChunk($d); + + $needed->{TypeFunctionName("ndr_pull", $d)} = 0; + $needed->{TypeFunctionName("ndr_push", $d)} = 0; + $needed->{TypeFunctionName("ndr_print", $d)} = 0; + next; + } + next unless(typeHasBody($d)); ($needed->{TypeFunctionName("ndr_push", $d)}) && $self->ParseTypePushFunction($d, "r"); @@ -2623,10 +2864,6 @@ sub ParseInterface($$$) ($needed->{"ndr_push_$d->{NAME}"}) && $self->ParseFunctionPush($d); ($needed->{"ndr_pull_$d->{NAME}"}) && $self->ParseFunctionPull($d); ($needed->{"ndr_print_$d->{NAME}"}) && $self->ParseFunctionPrint($d); - - # Make sure we don't generate a function twice... - $needed->{"ndr_push_$d->{NAME}"} = $needed->{"ndr_pull_$d->{NAME}"} = - $needed->{"ndr_print_$d->{NAME}"} = 0; } $self->FunctionTable($interface); @@ -2749,6 +2986,7 @@ sub NeededType($$$) my ($t,$needed,$req) = @_; NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "TYPEDEF"); + NeededType($t->{DATA}, $needed, $req) if ($t->{TYPE} eq "PIPE"); if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "UNION") { return unless defined($t->{ELEMENTS}); @@ -2770,6 +3008,7 @@ sub NeededInterface($$) my ($interface,$needed) = @_; NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}}); foreach (reverse @{$interface->{TYPES}}) { + if (has_property($_, "public")) { $needed->{TypeFunctionName("ndr_pull", $_)} = $needed->{TypeFunctionName("ndr_push", $_)} = $needed->{TypeFunctionName("ndr_print", $_)} = 1; diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm index 20c94c89e0..1d51fa1526 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm @@ -77,8 +77,8 @@ sub Boilerplate_Iface($) my($interface) = shift; my $name = $interface->{NAME}; my $uname = uc $name; - my $uuid = lc($interface->{PROPERTIES}->{uuid}); - my $if_version = $interface->{PROPERTIES}->{version}; + my $uuid = lc($interface->{UUID}); + 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) @@ -251,9 +251,9 @@ static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const c return true; } - return false; + return false; } - + NTSTATUS dcerpc_server_$name\_init(void) { NTSTATUS ret; @@ -289,6 +289,9 @@ sub ParseInterface($) my($interface) = shift; my $count = 0; + $res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n"; + $res .= "\n"; + if (!defined $interface->{PROPERTIES}->{uuid}) { return $res; } diff --git a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm index 3e9178b7e8..db2d79d2f6 100644 --- a/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/tools/pidl/lib/Parse/Pidl/Samba4/Python.pm @@ -12,7 +12,7 @@ use strict; use Parse::Pidl qw(warning fatal error); use Parse::Pidl::Typelist qw(hasType resolveType getType mapTypeName expandAlias); use Parse::Pidl::Util qw(has_property ParseExpr unmake_str); -use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred is_charset_array); +use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred ContainsPipe is_charset_array); 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); @@ -297,9 +297,14 @@ sub PythonStruct($$$$$$) $self->pidl("{"); $self->indent; $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);"); + $self->pidl("PyObject *ret;"); $self->pidl("char *retstr;"); + $self->pidl(""); $self->pidl("retstr = ndr_print_struct_string(py_talloc_get_mem_ctx(py_obj), (ndr_print_fn_t)ndr_print_$name, \"$name\", object);"); - $self->pidl("return PyString_FromString(retstr);"); + $self->pidl("ret = PyString_FromString(retstr);"); + $self->pidl("talloc_free(retstr);"); + $self->pidl(""); + $self->pidl("return ret;"); $self->deindent; $self->pidl("}"); $self->pidl(""); @@ -662,6 +667,15 @@ sub Interface($$$) next if has_property($d, "nopython"); next if has_property($d, "todo"); + my $skip = 0; + foreach my $e (@{$d->{ELEMENTS}}) { + if (ContainsPipe($e, $e->{LEVELS}[0])) { + $skip = 1; + last; + } + } + next if $skip; + my $prettyname = $d->{NAME}; $prettyname =~ s/^$interface->{NAME}_//; @@ -890,7 +904,7 @@ sub ConvertObjectFromPythonData($$$$$$;$) $self->pidl("}"); return; } - if (expandAlias($actual_ctype->{NAME}) =~ /^(char|u?int[0-9]*|time_t)$/) { + if (expandAlias($actual_ctype->{NAME}) =~ /^(char|u?int[0-9]*|time_t|uid_t|gid_t)$/) { $self->pidl("PY_CHECK_TYPE(&PyInt_Type, $cvar, $fail);"); $self->pidl("$target = PyInt_AsLong($cvar);"); return; @@ -979,12 +993,15 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) { my ($self, $env, $mem_ctx, $py_var, $e, $l, $var_name, $fail) = @_; my $nl = GetNextLevel($e, $l); + if ($nl and $nl->{TYPE} eq "SUBCONTEXT") { + $nl = GetNextLevel($e, $nl); + } + my $pl = GetPrevLevel($e, $l); + if ($pl and $pl->{TYPE} eq "SUBCONTEXT") { + $pl = GetPrevLevel($e, $pl); + } if ($l->{TYPE} eq "POINTER") { - if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { - $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail); - return; - } if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($py_var == Py_None) {"); $self->indent; @@ -997,16 +1014,21 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) # then this is where we would need to allocate it if ($l->{POINTER_TYPE} eq "ref") { $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); + } elsif ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::is_scalar($nl->{DATA_TYPE}) + and not Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { + $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); } else { $self->pidl("$var_name = NULL;"); } - $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, get_value_of($var_name), $fail); + 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); if ($l->{POINTER_TYPE} ne "ref") { $self->deindent; $self->pidl("}"); } } elsif ($l->{TYPE} eq "ARRAY") { - my $pl = GetPrevLevel($e, $l); if ($pl && $pl->{TYPE} eq "POINTER") { $var_name = get_pointer_to($var_name); } @@ -1024,7 +1046,7 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) $self->pidl("} else {"); $self->indent; $self->pidl("PyErr_Format(PyExc_TypeError, \"Expected string or unicode object, got %s\", Py_TYPE($py_var)->tp_name);"); - $self->pidl("$fail;"); + $self->pidl("$fail"); $self->deindent; $self->pidl("}"); } else { @@ -1040,7 +1062,7 @@ 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, GetNextLevel($e, $l), $var_name."[$counter]", $fail); + $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GET_ITEM($py_var, $counter)", $e, $nl, $var_name."[$counter]", $fail); $self->deindent; $self->pidl("}"); $self->deindent; @@ -1057,15 +1079,15 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) my $switch_ptr = "$e->{NAME}_switch_$l->{LEVEL_INDEX}"; $self->pidl("{"); $self->indent; - my $union_type = mapTypeName(GetNextLevel($e, $l)->{DATA_TYPE}); + my $union_type = mapTypeName($nl->{DATA_TYPE}); $self->pidl("$union_type *$switch_ptr;"); - $self->pidl("$switch_ptr = py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var);"); - $self->pidl("if ($switch_ptr == NULL) { $fail }"); + $self->pidl("$switch_ptr = py_export_" . $nl->{DATA_TYPE} . "($mem_ctx, $switch, $py_var);"); + $self->fail_on_null($switch_ptr, $fail); $self->assign($var_name, "$switch_ptr"); $self->deindent; $self->pidl("}"); } elsif ($l->{TYPE} eq "SUBCONTEXT") { - $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, GetNextLevel($e, $l), $var_name, $fail); + $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, $var_name, $fail); } else { fatal($e->{ORIGINAL}, "unknown level type $l->{TYPE}"); } @@ -1090,7 +1112,7 @@ sub ConvertScalarToPython($$$) return "PyLong_FromLongLong($cvar)"; } - if ($ctypename =~ /^(char|u?int[0-9]*|time_t)$/) { + if ($ctypename =~ /^(char|u?int[0-9]*|time_t|uid_t|gid_t)$/) { return "PyInt_FromLong($cvar)"; } @@ -1107,19 +1129,19 @@ sub ConvertScalarToPython($$$) } if (($ctypename eq "string" or $ctypename eq "nbt_string" or $ctypename eq "nbt_name" or $ctypename eq "wrepl_nbt_name")) { - return "PyString_FromString_check_null($cvar)"; + return "PyString_FromStringOrNULL($cvar)"; } if (($ctypename eq "dns_string" or $ctypename eq "dns_name")) { - return "PyString_FromString_check_null($cvar)"; + return "PyString_FromStringOrNULL($cvar)"; } # Not yet supported if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; } - if ($ctypename eq "ipv4address") { return "PyString_FromString_check_null($cvar)"; } - if ($ctypename eq "ipv6address") { return "PyString_FromString_check_null($cvar)"; } - if ($ctypename eq "dnsp_name") { return "PyString_FromString_check_null($cvar)"; } - if ($ctypename eq "dnsp_string") { return "PyString_FromString_check_null($cvar)"; } + if ($ctypename eq "ipv4address") { return "PyString_FromStringOrNULL($cvar)"; } + if ($ctypename eq "ipv6address") { return "PyString_FromStringOrNULL($cvar)"; } + if ($ctypename eq "dnsp_name") { return "PyString_FromStringOrNULL($cvar)"; } + if ($ctypename eq "dnsp_string") { return "PyString_FromStringOrNULL($cvar)"; } if ($ctypename eq "pointer") { return "PyCObject_FromTallocPtr($cvar)"; } @@ -1174,12 +1196,15 @@ sub ConvertObjectToPythonLevel($$$$$$) { my ($self, $mem_ctx, $env, $e, $l, $var_name, $py_var, $fail) = @_; my $nl = GetNextLevel($e, $l); + if ($nl and $nl->{TYPE} eq "SUBCONTEXT") { + $nl = GetNextLevel($e, $nl); + } + my $pl = GetPrevLevel($e, $l); + if ($pl and $pl->{TYPE} eq "SUBCONTEXT") { + $pl = GetPrevLevel($e, $pl); + } if ($l->{TYPE} eq "POINTER") { - if ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { - $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name, $py_var, $fail); - return; - } if ($l->{POINTER_TYPE} ne "ref") { $self->pidl("if ($var_name == NULL) {"); $self->indent; @@ -1189,13 +1214,16 @@ sub ConvertObjectToPythonLevel($$$$$$) $self->pidl("} else {"); $self->indent; } - $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, get_value_of($var_name), $py_var, $fail); + my $var_name2 = $var_name; + unless ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE})) { + $var_name2 = get_value_of($var_name); + } + $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name2, $py_var, $fail); if ($l->{POINTER_TYPE} ne "ref") { $self->deindent; $self->pidl("}"); } } elsif ($l->{TYPE} eq "ARRAY") { - my $pl = GetPrevLevel($e, $l); if ($pl && $pl->{TYPE} eq "POINTER") { $var_name = get_pointer_to($var_name); } @@ -1230,7 +1258,7 @@ sub ConvertObjectToPythonLevel($$$$$$) $self->indent; my $member_var = "py_$e->{NAME}_$l->{LEVEL_INDEX}"; $self->pidl("PyObject *$member_var;"); - $self->ConvertObjectToPythonLevel($var_name, $env, $e, GetNextLevel($e, $l), $var_name."[$counter]", $member_var, $fail); + $self->ConvertObjectToPythonLevel($var_name, $env, $e, $nl, $var_name."[$counter]", $member_var, $fail); $self->pidl("PyList_SetItem($py_var, $counter, $member_var);"); $self->deindent; $self->pidl("}"); @@ -1240,7 +1268,7 @@ sub ConvertObjectToPythonLevel($$$$$$) } elsif ($l->{TYPE} eq "SWITCH") { $var_name = get_pointer_to($var_name); my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e); - $self->pidl("$py_var = py_import_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);"); + $self->pidl("$py_var = py_import_" . $nl->{DATA_TYPE} . "($mem_ctx, $switch, $var_name);"); $self->fail_on_null($py_var, $fail); } elsif ($l->{TYPE} eq "DATA") { @@ -1250,7 +1278,7 @@ sub ConvertObjectToPythonLevel($$$$$$) my $conv = $self->ConvertObjectToPythonData($mem_ctx, $l->{DATA_TYPE}, $var_name, $e->{ORIGINAL}); $self->pidl("$py_var = $conv;"); } elsif ($l->{TYPE} eq "SUBCONTEXT") { - $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, GetNextLevel($e, $l), $var_name, $py_var, $fail); + $self->ConvertObjectToPythonLevel($mem_ctx, $env, $e, $nl, $var_name, $py_var, $fail); } else { fatal($e->{ORIGINAL}, "Unknown level type $l->{TYPE} $var_name"); } @@ -1273,7 +1301,7 @@ sub Parse($$$$$) /* Python wrapper functions auto-generated by pidl */ #include #include \"includes.h\" -#include \"lib/talloc/pytalloc.h\" +#include #include \"librpc/rpc/pyrpc.h\" #include \"librpc/rpc/pyrpc_util.h\" #include \"$hdr\" @@ -1299,6 +1327,7 @@ sub Parse($$$$$) $self->pidl(""); + $self->pidl_hdr("void init$basename(void);"); $self->pidl("void init$basename(void)"); $self->pidl("{"); $self->indent; diff --git a/tools/pidl/lib/Parse/Pidl/Typelist.pm b/tools/pidl/lib/Parse/Pidl/Typelist.pm index 4733f91565..4f26a92ed2 100644 --- a/tools/pidl/lib/Parse/Pidl/Typelist.pm +++ b/tools/pidl/lib/Parse/Pidl/Typelist.pm @@ -8,8 +8,8 @@ package Parse::Pidl::Typelist; require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias - mapScalarType addType typeIs is_signed is_scalar enum_type_fn - bitmap_type_fn mapType typeHasBody + mapScalarType addType typeIs is_signed is_scalar enum_type_fn + bitmap_type_fn mapType typeHasBody is_fixed_size_scalar ); use vars qw($VERSION); $VERSION = '0.01'; @@ -21,7 +21,13 @@ my %types = (); my @reference_scalars = ( "string", "string_array", "nbt_string", "dns_string", - "wrepl_nbt_name", "ipv4address", "ipv6address" + "wrepl_nbt_name", "dnsp_name", "dnsp_string", + "ipv4address", "ipv6address" +); + +my @non_fixed_size_scalars = ( + "string", "string_array", "nbt_string", "dns_string", + "wrepl_nbt_name", "dnsp_name", "dnsp_string" ); # a list of known scalar types @@ -48,6 +54,8 @@ my %scalars = ( "string" => "const char *", "string_array" => "const char **", "time_t" => "time_t", + "uid_t" => "uid_t", + "gid_t" => "gid_t", "NTTIME" => "NTTIME", "NTTIME_1sec" => "NTTIME", "NTTIME_hyper" => "NTTIME", @@ -128,6 +136,7 @@ sub getType($) return $types{$t}; } +sub typeIs($$); sub typeIs($$) { my ($t,$tt) = @_; @@ -187,6 +196,15 @@ sub is_scalar($) return 0; } +sub is_fixed_size_scalar($) +{ + my $name = shift; + + return 0 unless is_scalar($name); + return 0 if (grep(/^$name$/, @non_fixed_size_scalars)); + return 1; +} + sub scalar_is_reference($) { my $name = shift; @@ -273,6 +291,7 @@ sub mapType($$) return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE"); return "union $n" if ($t->{TYPE} eq "UNION"); return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP"); + return "struct $n" if ($t->{TYPE} eq "PIPE"); die("Unknown type $t->{TYPE}"); } @@ -311,11 +330,12 @@ sub LoadIdl($;$) }) if (has_property($x, "object")); foreach my $y (@{$x->{DATA}}) { - if ($y->{TYPE} eq "TYPEDEF" - or $y->{TYPE} eq "UNION" - or $y->{TYPE} eq "STRUCT" - or $y->{TYPE} eq "ENUM" - or $y->{TYPE} eq "BITMAP") { + if ($y->{TYPE} eq "TYPEDEF" + or $y->{TYPE} eq "UNION" + or $y->{TYPE} eq "STRUCT" + or $y->{TYPE} eq "ENUM" + or $y->{TYPE} eq "BITMAP" + or $y->{TYPE} eq "PIPE") { $y->{BASEFILE} = $basename; addType($y); } diff --git a/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm b/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm index 64b8dcf18c..46c9850b56 100644 --- a/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm +++ b/tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm @@ -270,11 +270,9 @@ sub Bitmap($$$$) $self->register_type($name, "offset = $dissectorname(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_UINT$size", "BASE_HEX", "0", "NULL", $size/8); } -sub ElementLevel($$$$$$$) +sub ElementLevel($$$$$$$$) { - my ($self,$e,$l,$hf,$myname,$pn,$ifname) = @_; - - my $param = 0; + my ($self,$e,$l,$hf,$myname,$pn,$ifname,$param) = @_; if (defined($self->{conformance}->{dissectorparams}->{$myname})) { $param = $self->{conformance}->{dissectorparams}->{$myname}->{PARAM}; @@ -323,9 +321,19 @@ sub ElementLevel($$$$$$$) $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, 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);") + } else { + $self->pidl_code("offset = dissect_null_term_string(tvb, offset, pinfo, tree, drep, $hf , 0);") + } } else { warn("Unable to handle string with flags $e->{PROPERTIES}->{flag}"); } + } elsif ($l->{DATA_TYPE} eq "DATA_BLOB") { + my $remain = 0; + $remain = 1 if (property_matches($e->{ORIGINAL}, "flag", ".*LIBNDR_FLAG_REMAINING.*")); + $self->pidl_code("offset = dissect_ndr_datablob(tvb, offset, pinfo, tree, drep, $hf, $remain);"); } else { my $call; @@ -350,27 +358,65 @@ sub ElementLevel($$$$$$$) $self->pidl_code($call); } } elsif ($_->{TYPE} eq "SUBCONTEXT") { + my $varswitch; + if (has_property($e, "switch_is")) { + $varswitch = $e->{PROPERTIES}->{switch_is}; + } my $num_bits = ($l->{HEADER_SIZE}*8); + my $hf2 = $self->register_hf_field($hf."_", "Subcontext length", "$ifname.$pn.$_->{NAME}subcontext", "FT_UINT$num_bits", "BASE_HEX", "NULL", 0, ""); + $self->{hf_used}->{$hf2} = 1; + $self->pidl_code("dcerpc_info *di = pinfo->private_data;"); $self->pidl_code("guint$num_bits size;"); - $self->pidl_code("int start_offset = offset;"); + $self->pidl_code("int conformant = di->conformant_run;"); $self->pidl_code("tvbuff_t *subtvb;"); - $self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf, &size);"); - $self->pidl_code("proto_tree_add_text(tree, tvb, start_offset, offset - start_offset + size, \"Subcontext size\");"); + $self->pidl_code(""); + # We need to be able to dissect the length of the context in every case + # and conformant run skips the dissections of scalars ... + $self->pidl_code("if (!conformant) {"); + $self->indent; + $self->pidl_code("offset = dissect_ndr_uint$num_bits(tvb, offset, pinfo, tree, drep, $hf2, &size);"); $self->pidl_code("subtvb = tvb_new_subset(tvb, offset, size, -1);"); - $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);"); + if ($param ne 0) { + $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep, $param);"); + } else { + $self->pidl_code("$myname\_(subtvb, 0, pinfo, tree, drep);"); + } + $self->pidl_code("offset += size;"); + $self->deindent; + $self->pidl_code("}"); } else { die("Unknown type `$_->{TYPE}'"); } } -sub Element($$$) +sub Element($$$$$) { - my ($self,$e,$pn,$ifname) = @_; + my ($self,$e,$pn,$ifname,$isoruseswitch) = @_; my $dissectorname = "$ifname\_dissect\_element\_".StripPrefixes($pn, $self->{conformance}->{strip_prefixes})."\_".StripPrefixes($e->{NAME}, $self->{conformance}->{strip_prefixes}); - my $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);"; + my ($call_code, $moreparam); + my $param = 0; + if (defined $isoruseswitch) { + my $type = $isoruseswitch->[0]; + my $name = $isoruseswitch->[1]; + + my $switch_dt = getType($type); + my $switch_type; + if ($switch_dt->{DATA}->{TYPE} eq "ENUM") { + $switch_type = "g".Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA}); + } elsif ($switch_dt->{DATA}->{TYPE} eq "SCALAR") { + $switch_type = "g$e->{SWITCH_TYPE}"; + } + $moreparam = ", $switch_type *".$name; + $param = $name; + $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep, &$name);"; + } else { + $moreparam = ""; + $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);"; + } + my $type = $self->find_type($e->{TYPE}); @@ -403,16 +449,24 @@ sub Element($$$) my $add = ""; + my $oldparam = undef; foreach (@{$e->{LEVELS}}) { + if (defined $_->{SWITCH_IS}) { + $oldparam = $param; + $param = "*$param"; + } next if ($_->{TYPE} eq "SWITCH"); - $self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_);"); + $self->pidl_def("static int $dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *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_, guint8 *drep _U_)"); + $self->pidl_code("$dissectorname$add(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *tree _U_, guint8 *drep _U_$moreparam)"); $self->pidl_code("{"); $self->indent; - $self->ElementLevel($e,$_,$hf,$dissectorname.$add,$pn,$ifname); + $self->ElementLevel($e,$_,$hf,$dissectorname.$add,$pn,$ifname,$param); + if (defined $oldparam) { + $param = $oldparam; + } $self->pidl_code(""); $self->pidl_code("return offset;"); @@ -433,7 +487,7 @@ sub Function($$$) my %dissectornames; foreach (@{$fn->{ELEMENTS}}) { - $dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname) if not defined($dissectornames{$_->{NAME}}); + $dissectornames{$_->{NAME}} = $self->Element($_, $fn->{NAME}, $ifname, undef) if not defined($dissectornames{$_->{NAME}}); } my $fn_name = $_->{NAME}; @@ -534,7 +588,40 @@ sub Struct($$$$) $self->register_ett("ett_$ifname\_$name"); my $res = ""; - ($res.="\t".$self->Element($_, $name, $ifname)."\n\n") foreach (@{$e->{ELEMENTS}}); + my $varswitchs = {}; + # will contain the switch var declaration; + my $vars = []; + foreach (@{$e->{ELEMENTS}}) { + if (has_property($_, "switch_is")) { + $varswitchs->{$_->{PROPERTIES}->{switch_is}} = []; + } + } + foreach (@{$e->{ELEMENTS}}) { + my $switch_info = undef; + + my $v = $_->{NAME}; + if (scalar(grep {/$v/} keys(%$varswitchs)) == 1) { + # This element is one of the switch attribute + my $switch_dt = getType($_->{TYPE}); + my $switch_type; + if ($switch_dt->{DATA}->{TYPE} eq "ENUM") { + $switch_type = "g".Parse::Pidl::Typelist::enum_type_fn($switch_dt->{DATA}); + } elsif ($switch_dt->{DATA}->{TYPE} eq "SCALAR") { + $switch_type = "g$e->{SWITCH_TYPE}"; + } + + push @$vars, "$switch_type $v;"; + $switch_info = [ $_->{TYPE}, $v ]; + $varswitchs->{$v} = $switch_info; + } + + if (has_property($_, "switch_is")) { + my $varswitch = $_->{PROPERTIES}->{switch_is}; + $switch_info = $varswitchs->{$varswitch}; + } + + $res.="\t".$self->Element($_, $name, $ifname, $switch_info)."\n\n"; + } $self->pidl_hdr("int $dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_);"); @@ -543,6 +630,7 @@ sub Struct($$$$) $self->pidl_code("$dissectorname(tvbuff_t *tvb _U_, int offset _U_, packet_info *pinfo _U_, proto_tree *parent_tree _U_, guint8 *drep _U_, int hf_index _U_, guint32 param _U_)"); $self->pidl_code("{"); $self->indent; + $self->pidl_code($_) foreach (@$vars); $self->pidl_code("proto_item *item = NULL;"); $self->pidl_code("proto_tree *tree = NULL;"); if ($e->{ALIGN} > 1) { @@ -551,7 +639,7 @@ sub Struct($$$$) $self->pidl_code("int old_offset;"); $self->pidl_code(""); - if ($e->{ALIGN} > 1) { + if ($e->{ALIGN} > 1 and not property_matches($e, "flag", ".*LIBNDR_FLAG_NOALIGN.*")) { $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); } $self->pidl_code(""); @@ -599,7 +687,7 @@ sub Union($$$$) foreach (@{$e->{ELEMENTS}}) { $res.="\n\t\t$_->{CASE}:\n"; if ($_->{TYPE} ne "EMPTY") { - $res.="\t\t\t".$self->Element($_, $name, $ifname)."\n"; + $res.="\t\t\t".$self->Element($_, $name, $ifname, undef)."\n"; } $res.="\t\tbreak;\n"; } @@ -623,7 +711,11 @@ sub Union($$$$) $self->pidl_code("proto_item *item = NULL;"); $self->pidl_code("proto_tree *tree = NULL;"); $self->pidl_code("int old_offset;"); - $self->pidl_code("$switch_type level;"); + if (!defined $switch_type) { + $self->pidl_code("guint32 level = param;"); + } else { + $self->pidl_code("$switch_type level;"); + } $self->pidl_code(""); $self->pidl_code("old_offset = offset;"); @@ -636,11 +728,13 @@ sub Union($$$$) $self->pidl_code(""); - $self->pidl_code("offset = $switch_dissect(tvb, offset, pinfo, tree, drep, hf_index, &level);"); + if (defined $switch_type) { + $self->pidl_code("offset = $switch_dissect(tvb, offset, pinfo, tree, drep, hf_index, &level);"); - if ($e->{ALIGN} > 1) { - $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); - $self->pidl_code(""); + if ($e->{ALIGN} > 1) { + $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); + $self->pidl_code(""); + } } @@ -770,8 +864,8 @@ sub ProcessImport my @imports = @_; foreach (@imports) { next if($_ eq "security"); - s/\.idl\"$//; s/^\"//; + s/\.idl"?$//; $self->pidl_hdr("#include \"packet-dcerpc-$_\.h\""); } $self->pidl_hdr(""); @@ -811,7 +905,7 @@ sub ProcessInterface($$) . ", 0x" . substr($if_uuid, 35, 2) . " }"); $self->pidl_def("};"); - my $maj = $x->{VERSION}; + my $maj = 0x0000FFFF & $x->{VERSION}; $maj =~ s/\.(.*)$//g; $self->pidl_def("static guint16 ver_dcerpc_$x->{NAME} = $maj;"); $self->pidl_def(""); @@ -820,7 +914,6 @@ sub ProcessInterface($$) $return_types{$x->{NAME}} = {}; $self->Interface($x); - $self->pidl_code("\n".DumpFunctionTable($x)); foreach (keys %{$return_types{$x->{NAME}}}) { @@ -879,6 +972,7 @@ sub Initialize($$) $self->register_type("int$bits", "offset = PIDL_dissect_uint$bits(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);", "FT_INT$bits", "BASE_DEC", 0, "NULL", $bytes); } + $self->register_type("hyper", "offset = dissect_ndr_uint64(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 8); $self->register_type("udlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);", "FT_UINT64", "BASE_DEC", 0, "NULL", 4); $self->register_type("bool8", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1); $self->register_type("char", "offset = PIDL_dissect_uint8(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_INT8", "BASE_DEC", 0, "NULL", 1);