diff options
author | bubulle <bubulle@alioth.debian.org> | 2011-11-12 13:00:54 +0000 |
---|---|---|
committer | bubulle <bubulle@alioth.debian.org> | 2011-11-12 13:00:54 +0000 |
commit | 6fba685eec3a1165ec0b82d72d3ae71e946a1404 (patch) | |
tree | f3c0543c8f9df4a22ed62e3bd99d9d7bc1054c14 /pidl | |
parent | 77a7925c0509068d5cd2affd94a3996d0a86035a (diff) | |
download | samba-6fba685eec3a1165ec0b82d72d3ae71e946a1404.tar.gz |
Merge upstream 3.6.1 source
git-svn-id: svn://svn.debian.org/svn/pkg-samba/trunk/samba@3972 fc4039ab-9d04-0410-8cac-899223bdd6b0
Diffstat (limited to 'pidl')
28 files changed, 2345 insertions, 1046 deletions
diff --git a/pidl/config.m4 b/pidl/config.m4 deleted file mode 100644 index 8b8bc5acf0..0000000000 --- a/pidl/config.m4 +++ /dev/null @@ -1,9 +0,0 @@ -# Check whether ExtUtils::ExtMaker is available - -if perl -e "use ExtUtils::MakeMaker" 2>/dev/null; then - HAVE_PERL_EXTUTILS_MAKEMAKER=1 -else - HAVE_PERL_EXTUTILS_MAKEMAKER=0 -fi - -AC_SUBST(HAVE_PERL_EXTUTILS_MAKEMAKER) diff --git a/pidl/config.mk b/pidl/config.mk deleted file mode 100644 index d7a84e3fcc..0000000000 --- a/pidl/config.mk +++ /dev/null @@ -1,34 +0,0 @@ -PIDL = $(PERL) $(pidldir)/pidl - -$(pidldir)/Makefile: $(pidldir)/Makefile.PL - @cd $(pidldir) && $(PERL) Makefile.PL PREFIX=$(prefix) - -pidl-testcov: $(pidldir)/Makefile - cd $(pidldir) && cover -test - -installpidl:: $(pidldir)/Makefile - @$(MAKE) -C $(pidldir) install_vendor VENDORPREFIX=$(prefix) \ - INSTALLVENDORLIB=$(datarootdir)/perl5 \ - INSTALLVENDORBIN=$(bindir) \ - INSTALLVENDORSCRIPT=$(bindir) \ - INSTALLVENDORMAN1DIR=$(mandir)/man1 \ - INSTALLVENDORMAN3DIR=$(mandir)/man3 - -ifeq ($(HAVE_PERL_EXTUTILS_MAKEMAKER),1) -install:: installpidl -endif - -$(pidldir)/lib/Parse/Pidl/IDL.pm: $(pidldir)/idl.yp - -$(YAPP) -m 'Parse::Pidl::IDL' -o $(pidldir)/lib/Parse/Pidl/IDL.pm $(pidldir)/idl.yp ||\ - touch $(pidldir)/lib/Parse/Pidl/IDL.pm - -$(pidldir)/lib/Parse/Pidl/Expr.pm: $(pidldir)/idl.yp - -$(YAPP) -m 'Parse::Pidl::Expr' -o $(pidldir)/lib/Parse/Pidl/Expr.pm $(pidldir)/expr.yp ||\ - touch $(pidldir)/lib/Parse/Pidl/Expr.pm - -testcov-html:: pidl-testcov - -pidl-clean: - /bin/rm -f $(pidldir)/Makefile - -clean:: pidl-clean diff --git a/pidl/idl.yp b/pidl/idl.yp index dc8e293f76..b5c5185fbe 100644 --- a/pidl/idl.yp +++ b/pidl/idl.yp @@ -169,13 +169,14 @@ function: ; typedef: - property_list 'typedef' type identifier array_len ';' + property_list 'typedef' type pointers identifier array_len ';' {{ "TYPE" => "TYPEDEF", "PROPERTIES" => $_[1], - "NAME" => $_[4], + "NAME" => $_[5], "DATA" => $_[3], - "ARRAY_LEN" => $_[5], + "POINTERS" => $_[4], + "ARRAY_LEN" => $_[6], "FILE" => $_[0]->YYData->{FILE}, "LINE" => $_[0]->YYData->{LINE}, }} @@ -386,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}, }} @@ -652,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/pidl/lib/Parse/Pidl/Compat.pm b/pidl/lib/Parse/Pidl/Compat.pm index 1b49c439c4..b8abcb8819 100644 --- a/pidl/lib/Parse/Pidl/Compat.pm +++ b/pidl/lib/Parse/Pidl/Compat.pm @@ -19,6 +19,7 @@ my %supported_properties = ( "uuid" => ["INTERFACE"], "endpoint" => ["INTERFACE"], "pointer_default" => ["INTERFACE"], + "no_srv_register" => ["INTERFACE"], # dcom "object" => ["INTERFACE"], @@ -44,6 +45,7 @@ my %supported_properties = ( "nopush" => ["FUNCTION", "TYPEDEF"], "nopull" => ["FUNCTION", "TYPEDEF"], "noprint" => ["FUNCTION", "TYPEDEF"], + "nopython" => ["FUNCTION", "TYPEDEF"], # union "switch_is" => ["ELEMENT"], @@ -125,6 +127,10 @@ sub CheckElement($) warning($e, "relative() pointer property not supported"); } + if (has_property($e, "relative_short")) { + warning($e, "relative_short() pointer property not supported"); + } + if (has_property($e, "flag")) { warning($e, "ignoring flag() property"); } diff --git a/pidl/lib/Parse/Pidl/Expr.pm b/pidl/lib/Parse/Pidl/Expr.pm index 1230a71a2b..24581d29f4 100644 --- a/pidl/lib/Parse/Pidl/Expr.pm +++ b/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/pidl/lib/Parse/Pidl/IDL.pm b/pidl/lib/Parse/Pidl/IDL.pm index 1a3c59d35c..d4820ffe92 100644 --- a/pidl/lib/Parse/Pidl/IDL.pm +++ b/pidl/lib/Parse/Pidl/IDL.pm @@ -1065,11 +1065,9 @@ sub new { DEFAULT => -16 }, {#State 125 - ACTIONS => { - 'IDENTIFIER' => 26 - }, + DEFAULT => -75, GOTOS => { - 'identifier' => 137 + 'pointers' => 137 } }, {#State 126 @@ -1165,11 +1163,11 @@ sub new { }, {#State 137 ACTIONS => { - "[" => 155 + 'IDENTIFIER' => 26, + "*" => 152 }, - DEFAULT => -86, GOTOS => { - 'array_len' => 156 + 'identifier' => 155 } }, {#State 138 @@ -1178,7 +1176,7 @@ sub new { {#State 139 DEFAULT => -68, GOTOS => { - 'union_elements' => 157 + 'union_elements' => 156 } }, {#State 140 @@ -1190,7 +1188,7 @@ sub new { {#State 142 DEFAULT => -78, GOTOS => { - 'element_list1' => 158 + 'element_list1' => 157 } }, {#State 143 @@ -1201,9 +1199,9 @@ sub new { 'IDENTIFIER' => 26 }, GOTOS => { - 'identifier' => 159, - 'enum_element' => 160, - 'enum_elements' => 161 + 'identifier' => 158, + 'enum_element' => 159, + 'enum_elements' => 160 } }, {#State 145 @@ -1221,10 +1219,10 @@ sub new { }, DEFAULT => -57, GOTOS => { - 'identifier' => 164, - 'bitmap_element' => 163, - 'bitmap_elements' => 162, - 'opt_bitmap_elements' => 165 + 'identifier' => 163, + 'bitmap_element' => 162, + 'bitmap_elements' => 161, + 'opt_bitmap_elements' => 164 } }, {#State 149 @@ -1233,19 +1231,19 @@ sub new { {#State 150 ACTIONS => { "," => -82, - "void" => 169, - "const" => 167, + "void" => 168, + "const" => 166, ")" => -82 }, DEFAULT => -80, GOTOS => { - 'optional_const' => 166, - 'element_list2' => 168 + 'optional_const' => 165, + 'element_list2' => 167 } }, {#State 151 ACTIONS => { - "[" => 155, + "[" => 169, "=" => 171 }, GOTOS => { @@ -1288,97 +1286,101 @@ sub new { }, {#State 155 ACTIONS => { - 'CONSTANT' => 48, - 'TEXT' => 16, - "]" => 172, - 'IDENTIFIER' => 26 + "[" => 169 }, - DEFAULT => -97, + DEFAULT => -86, GOTOS => { - 'identifier' => 50, - 'anytext' => 173, - 'text' => 51, - 'constant' => 47 + 'array_len' => 172 } }, {#State 156 ACTIONS => { - ";" => 174 - } - }, - {#State 157 - ACTIONS => { - "}" => 175 + "}" => 173 }, DEFAULT => -89, GOTOS => { - 'optional_base_element' => 177, - 'property_list' => 176 + 'optional_base_element' => 175, + 'property_list' => 174 } }, - {#State 158 + {#State 157 ACTIONS => { - "}" => 178 + "}" => 176 }, DEFAULT => -89, GOTOS => { - 'base_element' => 179, - 'property_list' => 180 + 'base_element' => 177, + 'property_list' => 178 } }, - {#State 159 + {#State 158 ACTIONS => { - "=" => 181 + "=" => 179 }, DEFAULT => -49 }, - {#State 160 + {#State 159 DEFAULT => -47 }, - {#State 161 + {#State 160 ACTIONS => { - "}" => 182, - "," => 183 + "}" => 180, + "," => 181 } }, - {#State 162 + {#State 161 ACTIONS => { - "," => 184 + "," => 182 }, DEFAULT => -58 }, - {#State 163 + {#State 162 DEFAULT => -55 }, - {#State 164 + {#State 163 ACTIONS => { - "=" => 185 + "=" => 183 } }, - {#State 165 + {#State 164 ACTIONS => { - "}" => 186 + "}" => 184 } }, - {#State 166 + {#State 165 DEFAULT => -89, GOTOS => { - 'base_element' => 187, - 'property_list' => 180 + 'base_element' => 185, + 'property_list' => 178 } }, - {#State 167 + {#State 166 DEFAULT => -81 }, - {#State 168 + {#State 167 ACTIONS => { - "," => 188, - ")" => 189 + "," => 186, + ")" => 187 } }, - {#State 169 + {#State 168 DEFAULT => -83 }, + {#State 169 + ACTIONS => { + 'CONSTANT' => 48, + 'TEXT' => 16, + "]" => 188, + 'IDENTIFIER' => 26 + }, + DEFAULT => -97, + GOTOS => { + 'identifier' => 50, + 'anytext' => 189, + 'text' => 51, + 'constant' => 47 + } + }, {#State 170 ACTIONS => { "=" => 190 @@ -1400,63 +1402,36 @@ sub new { }, {#State 172 ACTIONS => { - "[" => 155 - }, - DEFAULT => -86, - GOTOS => { - 'array_len' => 192 + ";" => 192 } }, {#State 173 - ACTIONS => { - "-" => 69, - ":" => 68, - "?" => 70, - "<" => 71, - "+" => 73, - "~" => 72, - "&" => 75, - "{" => 74, - "/" => 76, - "=" => 77, - "|" => 79, - "(" => 78, - "*" => 80, - "." => 81, - "]" => 193, - ">" => 82 - } - }, - {#State 174 - DEFAULT => -29 - }, - {#State 175 DEFAULT => -70 }, - {#State 176 + {#State 174 ACTIONS => { "[" => 20 }, DEFAULT => -89, GOTOS => { - 'base_or_empty' => 194, - 'base_element' => 195, - 'empty_element' => 196, - 'property_list' => 197 + 'base_or_empty' => 193, + 'base_element' => 194, + 'empty_element' => 195, + 'property_list' => 196 } }, - {#State 177 + {#State 175 DEFAULT => -69 }, - {#State 178 + {#State 176 DEFAULT => -60 }, - {#State 179 + {#State 177 ACTIONS => { - ";" => 198 + ";" => 197 } }, - {#State 180 + {#State 178 ACTIONS => { 'IDENTIFIER' => 26, "signed" => 100, @@ -1474,12 +1449,12 @@ sub new { 'identifier' => 96, 'struct' => 62, 'enum' => 65, - 'type' => 199, + 'type' => 198, 'union' => 67, 'sign' => 97 } }, - {#State 181 + {#State 179 ACTIONS => { 'CONSTANT' => 48, 'TEXT' => 16, @@ -1488,33 +1463,33 @@ sub new { DEFAULT => -97, GOTOS => { 'identifier' => 50, - 'anytext' => 200, + 'anytext' => 199, 'text' => 51, 'constant' => 47 } }, - {#State 182 + {#State 180 DEFAULT => -43 }, - {#State 183 + {#State 181 ACTIONS => { 'IDENTIFIER' => 26 }, GOTOS => { - 'identifier' => 159, - 'enum_element' => 201 + 'identifier' => 158, + 'enum_element' => 200 } }, - {#State 184 + {#State 182 ACTIONS => { 'IDENTIFIER' => 26 }, GOTOS => { - 'identifier' => 164, - 'bitmap_element' => 202 + 'identifier' => 163, + 'bitmap_element' => 201 } }, - {#State 185 + {#State 183 ACTIONS => { 'CONSTANT' => 48, 'TEXT' => 16, @@ -1523,29 +1498,58 @@ sub new { DEFAULT => -97, GOTOS => { 'identifier' => 50, - 'anytext' => 203, + 'anytext' => 202, 'text' => 51, 'constant' => 47 } }, - {#State 186 + {#State 184 DEFAULT => -51 }, - {#State 187 + {#State 185 DEFAULT => -84 }, - {#State 188 + {#State 186 ACTIONS => { - "const" => 167 + "const" => 166 }, DEFAULT => -80, GOTOS => { - 'optional_const' => 204 + 'optional_const' => 203 + } + }, + {#State 187 + ACTIONS => { + ";" => 204 + } + }, + {#State 188 + ACTIONS => { + "[" => 169 + }, + DEFAULT => -86, + GOTOS => { + 'array_len' => 205 } }, {#State 189 ACTIONS => { - ";" => 205 + "-" => 69, + ":" => 68, + "?" => 70, + "<" => 71, + "+" => 73, + "~" => 72, + "&" => 75, + "{" => 74, + "/" => 76, + "=" => 77, + "|" => 79, + "(" => 78, + "*" => 80, + "." => 81, + "]" => 206, + ">" => 82 } }, {#State 190 @@ -1557,7 +1561,7 @@ sub new { DEFAULT => -97, GOTOS => { 'identifier' => 50, - 'anytext' => 206, + 'anytext' => 207, 'text' => 51, 'constant' => 47 } @@ -1568,7 +1572,7 @@ sub new { ":" => 68, "?" => 70, "<" => 71, - ";" => 207, + ";" => 208, "+" => 73, "~" => 72, "&" => 75, @@ -1583,29 +1587,20 @@ sub new { } }, {#State 192 - DEFAULT => -87 + DEFAULT => -29 }, {#State 193 - ACTIONS => { - "[" => 155 - }, - DEFAULT => -86, - GOTOS => { - 'array_len' => 208 - } - }, - {#State 194 DEFAULT => -67 }, - {#State 195 + {#State 194 ACTIONS => { ";" => 209 } }, - {#State 196 + {#State 195 DEFAULT => -66 }, - {#State 197 + {#State 196 ACTIONS => { 'IDENTIFIER' => 26, "signed" => 100, @@ -1624,21 +1619,21 @@ sub new { 'identifier' => 96, 'struct' => 62, 'enum' => 65, - 'type' => 199, + 'type' => 198, 'union' => 67, 'sign' => 97 } }, - {#State 198 + {#State 197 DEFAULT => -79 }, - {#State 199 + {#State 198 DEFAULT => -75, GOTOS => { 'pointers' => 211 } }, - {#State 200 + {#State 199 ACTIONS => { "-" => 69, ":" => 68, @@ -1658,13 +1653,13 @@ sub new { }, DEFAULT => -50 }, - {#State 201 + {#State 200 DEFAULT => -48 }, - {#State 202 + {#State 201 DEFAULT => -56 }, - {#State 203 + {#State 202 ACTIONS => { "-" => 69, ":" => 68, @@ -1684,23 +1679,35 @@ sub new { }, DEFAULT => -59 }, - {#State 204 + {#State 203 DEFAULT => -89, GOTOS => { 'base_element' => 212, - 'property_list' => 180 + 'property_list' => 178 } }, - {#State 205 + {#State 204 DEFAULT => -28 }, + {#State 205 + DEFAULT => -87 + }, {#State 206 ACTIONS => { + "[" => 169 + }, + DEFAULT => -86, + GOTOS => { + 'array_len' => 213 + } + }, + {#State 207 + ACTIONS => { "-" => 69, ":" => 68, "?" => 70, "<" => 71, - ";" => 213, + ";" => 214, "+" => 73, "~" => 72, "&" => 75, @@ -1714,11 +1721,8 @@ sub new { ">" => 82 } }, - {#State 207 - DEFAULT => -26 - }, {#State 208 - DEFAULT => -88 + DEFAULT => -26 }, {#State 209 DEFAULT => -65 @@ -1732,25 +1736,28 @@ sub new { "*" => 152 }, GOTOS => { - 'identifier' => 214 + 'identifier' => 215 } }, {#State 212 DEFAULT => -85 }, {#State 213 - DEFAULT => -27 + DEFAULT => -88 }, {#State 214 + DEFAULT => -27 + }, + {#State 215 ACTIONS => { - "[" => 155 + "[" => 169 }, DEFAULT => -86, GOTOS => { - 'array_len' => 215 + 'array_len' => 216 } }, - {#State 215 + {#State 216 DEFAULT => -74 } ], @@ -1765,43 +1772,43 @@ sub new { [#Rule 2 'idl', 2, sub -#line 20 "./../pidl/idl.yp" +#line 20 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 3 'idl', 2, sub -#line 22 "./../pidl/idl.yp" +#line 22 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 4 'idl', 2, sub -#line 24 "./../pidl/idl.yp" +#line 24 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 5 'idl', 2, sub -#line 26 "./../pidl/idl.yp" +#line 26 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 6 'idl', 2, sub -#line 28 "./../pidl/idl.yp" +#line 28 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 7 'idl', 2, sub -#line 30 "./../pidl/idl.yp" +#line 30 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 8 'import', 3, sub -#line 35 "./../pidl/idl.yp" +#line 35 "idl.yp" {{ "TYPE" => "IMPORT", "PATHS" => $_[2], @@ -1812,7 +1819,7 @@ sub [#Rule 9 'include', 3, sub -#line 45 "./../pidl/idl.yp" +#line 45 "idl.yp" {{ "TYPE" => "INCLUDE", "PATHS" => $_[2], @@ -1823,7 +1830,7 @@ sub [#Rule 10 'importlib', 3, sub -#line 55 "./../pidl/idl.yp" +#line 55 "idl.yp" {{ "TYPE" => "IMPORTLIB", "PATHS" => $_[2], @@ -1834,19 +1841,19 @@ sub [#Rule 11 'commalist', 1, sub -#line 64 "./../pidl/idl.yp" +#line 64 "idl.yp" { [ $_[1] ] } ], [#Rule 12 'commalist', 3, sub -#line 66 "./../pidl/idl.yp" +#line 66 "idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 13 'coclass', 7, sub -#line 71 "./../pidl/idl.yp" +#line 71 "idl.yp" {{ "TYPE" => "COCLASS", "PROPERTIES" => $_[1], @@ -1862,13 +1869,13 @@ sub [#Rule 15 'interface_names', 4, sub -#line 84 "./../pidl/idl.yp" +#line 84 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 16 'interface', 8, sub -#line 89 "./../pidl/idl.yp" +#line 89 "idl.yp" {{ "TYPE" => "INTERFACE", "PROPERTIES" => $_[1], @@ -1885,13 +1892,13 @@ sub [#Rule 18 'base_interface', 2, sub -#line 103 "./../pidl/idl.yp" +#line 103 "idl.yp" { $_[2] } ], [#Rule 19 'cpp_quote', 4, sub -#line 109 "./../pidl/idl.yp" +#line 109 "idl.yp" {{ "TYPE" => "CPP_QUOTE", "DATA" => $_[3], @@ -1902,13 +1909,13 @@ sub [#Rule 20 'definitions', 1, sub -#line 118 "./../pidl/idl.yp" +#line 118 "idl.yp" { [ $_[1] ] } ], [#Rule 21 'definitions', 2, sub -#line 120 "./../pidl/idl.yp" +#line 120 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 22 @@ -1926,7 +1933,7 @@ sub [#Rule 26 'const', 7, sub -#line 135 "./../pidl/idl.yp" +#line 135 "idl.yp" {{ "TYPE" => "CONST", "DTYPE" => $_[2], @@ -1940,7 +1947,7 @@ sub [#Rule 27 'const', 8, sub -#line 146 "./../pidl/idl.yp" +#line 146 "idl.yp" {{ "TYPE" => "CONST", "DTYPE" => $_[2], @@ -1955,7 +1962,7 @@ sub [#Rule 28 'function', 7, sub -#line 160 "./../pidl/idl.yp" +#line 160 "idl.yp" {{ "TYPE" => "FUNCTION", "NAME" => $_[3], @@ -1967,15 +1974,16 @@ sub }} ], [#Rule 29 - 'typedef', 6, + 'typedef', 7, sub -#line 173 "./../pidl/idl.yp" +#line 173 "idl.yp" {{ "TYPE" => "TYPEDEF", "PROPERTIES" => $_[1], - "NAME" => $_[4], + "NAME" => $_[5], "DATA" => $_[3], - "ARRAY_LEN" => $_[5], + "POINTERS" => $_[4], + "ARRAY_LEN" => $_[6], "FILE" => $_[0]->YYData->{FILE}, "LINE" => $_[0]->YYData->{LINE}, }} @@ -1998,7 +2006,7 @@ sub [#Rule 35 'typedecl', 2, sub -#line 197 "./../pidl/idl.yp" +#line 198 "idl.yp" { $_[1] } ], [#Rule 36 @@ -2010,7 +2018,7 @@ sub [#Rule 38 'existingtype', 2, sub -#line 207 "./../pidl/idl.yp" +#line 208 "idl.yp" { ($_[1]?$_[1]:"signed") ." $_[2]" } ], [#Rule 39 @@ -2025,13 +2033,13 @@ sub [#Rule 42 'type', 1, sub -#line 217 "./../pidl/idl.yp" +#line 218 "idl.yp" { "void" } ], [#Rule 43 'enum_body', 3, sub -#line 221 "./../pidl/idl.yp" +#line 222 "idl.yp" { $_[2] } ], [#Rule 44 @@ -2043,7 +2051,7 @@ sub [#Rule 46 'enum', 4, sub -#line 232 "./../pidl/idl.yp" +#line 233 "idl.yp" {{ "TYPE" => "ENUM", "PROPERTIES" => $_[1], @@ -2056,13 +2064,13 @@ sub [#Rule 47 'enum_elements', 1, sub -#line 243 "./../pidl/idl.yp" +#line 244 "idl.yp" { [ $_[1] ] } ], [#Rule 48 'enum_elements', 3, sub -#line 245 "./../pidl/idl.yp" +#line 246 "idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 49 @@ -2071,13 +2079,13 @@ sub [#Rule 50 'enum_element', 3, sub -#line 251 "./../pidl/idl.yp" +#line 252 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 51 'bitmap_body', 3, sub -#line 255 "./../pidl/idl.yp" +#line 256 "idl.yp" { $_[2] } ], [#Rule 52 @@ -2089,7 +2097,7 @@ sub [#Rule 54 'bitmap', 4, sub -#line 266 "./../pidl/idl.yp" +#line 267 "idl.yp" {{ "TYPE" => "BITMAP", "PROPERTIES" => $_[1], @@ -2102,13 +2110,13 @@ sub [#Rule 55 'bitmap_elements', 1, sub -#line 277 "./../pidl/idl.yp" +#line 278 "idl.yp" { [ $_[1] ] } ], [#Rule 56 'bitmap_elements', 3, sub -#line 279 "./../pidl/idl.yp" +#line 280 "idl.yp" { push(@{$_[1]}, $_[3]); $_[1] } ], [#Rule 57 @@ -2120,13 +2128,13 @@ sub [#Rule 59 'bitmap_element', 3, sub -#line 289 "./../pidl/idl.yp" +#line 290 "idl.yp" { "$_[1] ( $_[3] )" } ], [#Rule 60 'struct_body', 3, sub -#line 293 "./../pidl/idl.yp" +#line 294 "idl.yp" { $_[2] } ], [#Rule 61 @@ -2138,7 +2146,7 @@ sub [#Rule 63 'struct', 4, sub -#line 304 "./../pidl/idl.yp" +#line 305 "idl.yp" {{ "TYPE" => "STRUCT", "PROPERTIES" => $_[1], @@ -2151,7 +2159,7 @@ sub [#Rule 64 'empty_element', 2, sub -#line 316 "./../pidl/idl.yp" +#line 317 "idl.yp" {{ "NAME" => "", "TYPE" => "EMPTY", @@ -2171,7 +2179,7 @@ sub [#Rule 67 'optional_base_element', 2, sub -#line 333 "./../pidl/idl.yp" +#line 334 "idl.yp" { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] } ], [#Rule 68 @@ -2180,13 +2188,13 @@ sub [#Rule 69 'union_elements', 2, sub -#line 339 "./../pidl/idl.yp" +#line 340 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 70 'union_body', 3, sub -#line 343 "./../pidl/idl.yp" +#line 344 "idl.yp" { $_[2] } ], [#Rule 71 @@ -2198,7 +2206,7 @@ sub [#Rule 73 'union', 4, sub -#line 354 "./../pidl/idl.yp" +#line 355 "idl.yp" {{ "TYPE" => "UNION", "PROPERTIES" => $_[1], @@ -2211,7 +2219,7 @@ sub [#Rule 74 'base_element', 5, sub -#line 366 "./../pidl/idl.yp" +#line 367 "idl.yp" {{ "NAME" => $_[4], "TYPE" => $_[2], @@ -2225,24 +2233,47 @@ sub [#Rule 75 'pointers', 0, sub -#line 379 "./../pidl/idl.yp" +#line 380 "idl.yp" { 0 } ], [#Rule 76 'pointers', 2, sub -#line 381 "./../pidl/idl.yp" +#line 382 "idl.yp" { $_[1]+1 } ], [#Rule 77 'pipe', 3, sub -#line 386 "./../pidl/idl.yp" +#line 387 "idl.yp" {{ "TYPE" => "PIPE", "PROPERTIES" => $_[1], - "NAME" => $_[4], - "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}, }} @@ -2250,13 +2281,13 @@ sub [#Rule 78 'element_list1', 0, sub -#line 398 "./../pidl/idl.yp" +#line 422 "idl.yp" { [] } ], [#Rule 79 'element_list1', 3, sub -#line 400 "./../pidl/idl.yp" +#line 424 "idl.yp" { push(@{$_[1]}, $_[2]); $_[1] } ], [#Rule 80 @@ -2274,13 +2305,13 @@ sub [#Rule 84 'element_list2', 2, sub -#line 414 "./../pidl/idl.yp" +#line 438 "idl.yp" { [ $_[2] ] } ], [#Rule 85 'element_list2', 4, sub -#line 416 "./../pidl/idl.yp" +#line 440 "idl.yp" { push(@{$_[1]}, $_[4]); $_[1] } ], [#Rule 86 @@ -2289,13 +2320,13 @@ sub [#Rule 87 'array_len', 3, sub -#line 422 "./../pidl/idl.yp" +#line 446 "idl.yp" { push(@{$_[3]}, "*"); $_[3] } ], [#Rule 88 'array_len', 4, sub -#line 424 "./../pidl/idl.yp" +#line 448 "idl.yp" { push(@{$_[4]}, "$_[2]"); $_[4] } ], [#Rule 89 @@ -2304,31 +2335,31 @@ sub [#Rule 90 'property_list', 4, sub -#line 430 "./../pidl/idl.yp" +#line 454 "idl.yp" { FlattenHash([$_[1],$_[3]]); } ], [#Rule 91 'properties', 1, sub -#line 434 "./../pidl/idl.yp" +#line 458 "idl.yp" { $_[1] } ], [#Rule 92 'properties', 3, sub -#line 436 "./../pidl/idl.yp" +#line 460 "idl.yp" { FlattenHash([$_[1], $_[3]]); } ], [#Rule 93 'property', 1, sub -#line 440 "./../pidl/idl.yp" +#line 464 "idl.yp" {{ "$_[1]" => "1" }} ], [#Rule 94 'property', 4, sub -#line 442 "./../pidl/idl.yp" +#line 466 "idl.yp" {{ "$_[1]" => "$_[3]" }} ], [#Rule 95 @@ -2337,13 +2368,13 @@ sub [#Rule 96 'commalisttext', 3, sub -#line 448 "./../pidl/idl.yp" +#line 472 "idl.yp" { "$_[1],$_[3]" } ], [#Rule 97 'anytext', 0, sub -#line 453 "./../pidl/idl.yp" +#line 477 "idl.yp" { "" } ], [#Rule 98 @@ -2358,91 +2389,91 @@ sub [#Rule 101 'anytext', 3, sub -#line 461 "./../pidl/idl.yp" +#line 485 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 102 'anytext', 3, sub -#line 463 "./../pidl/idl.yp" +#line 487 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 103 'anytext', 3, sub -#line 465 "./../pidl/idl.yp" +#line 489 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 104 'anytext', 3, sub -#line 467 "./../pidl/idl.yp" +#line 491 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 105 'anytext', 3, sub -#line 469 "./../pidl/idl.yp" +#line 493 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 106 'anytext', 3, sub -#line 471 "./../pidl/idl.yp" +#line 495 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 107 'anytext', 3, sub -#line 473 "./../pidl/idl.yp" +#line 497 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 108 'anytext', 3, sub -#line 475 "./../pidl/idl.yp" +#line 499 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 109 'anytext', 3, sub -#line 477 "./../pidl/idl.yp" +#line 501 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 110 'anytext', 3, sub -#line 479 "./../pidl/idl.yp" +#line 503 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 111 'anytext', 3, sub -#line 481 "./../pidl/idl.yp" +#line 505 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 112 'anytext', 3, sub -#line 483 "./../pidl/idl.yp" +#line 507 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 113 'anytext', 3, sub -#line 485 "./../pidl/idl.yp" +#line 509 "idl.yp" { "$_[1]$_[2]$_[3]" } ], [#Rule 114 'anytext', 5, sub -#line 487 "./../pidl/idl.yp" +#line 511 "idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 115 'anytext', 5, sub -#line 489 "./../pidl/idl.yp" +#line 513 "idl.yp" { "$_[1]$_[2]$_[3]$_[4]$_[5]" } ], [#Rule 116 @@ -2460,7 +2491,7 @@ sub [#Rule 120 'text', 1, sub -#line 507 "./../pidl/idl.yp" +#line 531 "idl.yp" { "\"$_[1]\"" } ], [#Rule 121 @@ -2474,7 +2505,7 @@ sub bless($self,$class); } -#line 519 "./../pidl/idl.yp" +#line 543 "idl.yp" use Parse::Pidl qw(error); @@ -2612,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/pidl/lib/Parse/Pidl/NDR.pm b/pidl/lib/Parse/Pidl/NDR.pm index fbd54693bc..d91c324b53 100644 --- a/pidl/lib/Parse/Pidl/NDR.pm +++ b/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); +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 @@ -54,6 +54,8 @@ my $scalar_alignment = { 'uint1632' => 3, 'int32' => 4, 'uint32' => 4, + 'int3264' => 5, + 'uint3264' => 5, 'hyper' => 8, 'double' => 8, 'pointer' => 8, @@ -64,20 +66,26 @@ 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, 'WERROR' => 4, 'NTSTATUS' => 4, 'COMRESULT' => 4, + 'dns_string' => 4, 'nbt_string' => 4, 'wrepl_nbt_name' => 4, - 'ipv4address' => 4 + 'ipv4address' => 4, + 'ipv6address' => 4, #16? + 'dnsp_name' => 1, + 'dnsp_string' => 1 }; -sub GetElementLevelTable($$) +sub GetElementLevelTable($$$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; my $order = []; my $is_deferred = 0; @@ -101,12 +109,57 @@ sub GetElementLevelTable($$) if (has_property($e, "out")) { my $needptrs = 1; - if (has_property($e, "string")) { $needptrs++; } + if (has_property($e, "string") and not has_property($e, "in")) { $needptrs++; } if ($#bracket_array >= 0) { $needptrs = 0; } 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]; @@ -122,6 +175,10 @@ sub GetElementLevelTable($$) if ($d eq "*") { $is_conformant = 1; if ($size = shift @size_is) { + if ($e->{POINTERS} < 1 and has_property($e, "string")) { + $is_string = 1; + delete($e->{PROPERTIES}->{string}); + } } elsif ((scalar(@size_is) == 0) and has_property($e, "string")) { $is_string = 1; delete($e->{PROPERTIES}->{string}); @@ -247,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"); @@ -297,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 = []; @@ -349,6 +419,7 @@ sub pointer_type($) return "sptr" if (has_property($e, "sptr")); return "unique" if (has_property($e, "unique")); return "relative" if (has_property($e, "relative")); + return "relative_short" if (has_property($e, "relative_short")); return "ignore" if (has_property($e, "ignore")); return undef; @@ -406,6 +477,8 @@ sub align_type($) if ($dt->{TYPE} eq "TYPEDEF") { return align_type($dt->{DATA}); + } elsif ($dt->{TYPE} eq "CONFORMANCE") { + return $dt->{DATA}->{ALIGN}; } elsif ($dt->{TYPE} eq "ENUM") { return align_type(Parse::Pidl::Typelist::enum_type_fn($dt)); } elsif ($dt->{TYPE} eq "BITMAP") { @@ -414,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; @@ -460,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"); @@ -497,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"; } @@ -511,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}); @@ -523,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"; @@ -548,6 +626,7 @@ sub ParseUnion($$) ELEMENTS => \@elements, PROPERTIES => $e->{PROPERTIES}, HAS_DEFAULT => $hasdefault, + IS_MS_UNION => $is_ms_union, ORIGINAL => $e, ALIGN => $align }; @@ -555,7 +634,7 @@ sub ParseUnion($$) sub ParseEnum($$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; return { TYPE => "ENUM", @@ -567,9 +646,9 @@ sub ParseEnum($$) }; } -sub ParseBitmap($$) +sub ParseBitmap($$$) { - my ($e, $pointer_default) = @_; + my ($e, $pointer_default, $ms_union) = @_; return { TYPE => "BITMAP", @@ -581,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, @@ -591,27 +721,35 @@ 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) = @_; - if (defined($d->{DATA}->{PROPERTIES}) && !defined($d->{PROPERTIES})) { - $d->{PROPERTIES} = $d->{DATA}->{PROPERTIES}; - } + my $data; + + if (ref($d->{DATA}) eq "HASH") { + if (defined($d->{DATA}->{PROPERTIES}) + and not defined($d->{PROPERTIES})) { + $d->{PROPERTIES} = $d->{DATA}->{PROPERTIES}; + } - my $data = ParseType($d->{DATA}, $pointer_default); - $data->{ALIGN} = align_type($d->{NAME}); + $data = ParseType($d->{DATA}, $pointer_default, $ms_union); + $data->{ALIGN} = align_type($d->{NAME}); + } else { + $data = getType($d->{DATA}); + } return { 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 }; @@ -624,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; @@ -639,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")); @@ -650,14 +788,10 @@ sub ParseFunction($$$) $rettype = expandAlias($d->{RETURN_TYPE}); } - my $async = 0; - if (has_property($d, "async")) { $async = 1; } - return { NAME => $d->{NAME}, TYPE => "FUNCTION", OPNUM => $thisopnum, - ASYNC => $async, RETURN_TYPE => $rettype, PROPERTIES => $d->{PROPERTIES}, ELEMENTS => \@elements, @@ -704,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) @@ -713,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); } } @@ -829,6 +965,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; @@ -877,7 +1027,8 @@ my %property_list = ( "helper" => ["INTERFACE"], "pyhelper" => ["INTERFACE"], "authservice" => ["INTERFACE"], - "restricted" => ["INTERFACE"], + "restricted" => ["INTERFACE"], + "no_srv_register" => ["INTERFACE"], # dcom "object" => ["INTERFACE"], @@ -890,33 +1041,35 @@ my %property_list = ( "noopnum" => ["FUNCTION"], "in" => ["ELEMENT"], "out" => ["ELEMENT"], - "async" => ["FUNCTION"], # pointer - "ref" => ["ELEMENT"], - "ptr" => ["ELEMENT"], - "unique" => ["ELEMENT"], + "ref" => ["ELEMENT", "TYPEDEF"], + "ptr" => ["ELEMENT", "TYPEDEF"], + "unique" => ["ELEMENT", "TYPEDEF"], "ignore" => ["ELEMENT"], - "relative" => ["ELEMENT"], - "null_is_ffffffff" => ["ELEMENT"], + "relative" => ["ELEMENT", "TYPEDEF"], + "relative_short" => ["ELEMENT", "TYPEDEF"], + "null_is_ffffffff" => ["ELEMENT"], "relative_base" => ["TYPEDEF", "STRUCT", "UNION"], "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"], # union "switch_is" => ["ELEMENT"], "switch_type" => ["ELEMENT", "UNION"], "nodiscriminant" => ["UNION"], + "ms_union" => ["INTERFACE", "UNION"], "case" => ["ELEMENT"], "default" => ["ELEMENT"], @@ -1006,13 +1159,13 @@ sub ValidElement($) my $discriminator_type = has_property($type->{DATA}, "switch_type"); $discriminator_type = "uint32" unless defined ($discriminator_type); - my $t1 = mapToScalar($discriminator_type); + my $t1 = mapScalarType(mapToScalar($discriminator_type)); if (not defined($t1)) { fatal($e, el_name($e) . ": unable to map discriminator type '$discriminator_type' to scalar"); } - my $t2 = mapToScalar($e2->{TYPE}); + my $t2 = mapScalarType(mapToScalar($e2->{TYPE})); if (not defined($t2)) { fatal($e, el_name($e) . ": unable to map variable used for switch_is() to scalar"); } @@ -1055,6 +1208,7 @@ sub ValidElement($) has_property($e, "ptr") or has_property($e, "unique") or 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"); } @@ -1136,11 +1290,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); } ##################################################################### @@ -1152,12 +1311,14 @@ sub ValidTypedef($) ValidProperties($typedef, "TYPEDEF"); + return unless (ref($data) eq "HASH"); + $data->{PARENT} = $typedef; $data->{FILE} = $typedef->{FILE} unless defined($data->{FILE}); $data->{LINE} = $typedef->{LINE} unless defined($data->{LINE}); - ValidType($data) if (ref($data) eq "HASH"); + ValidType($data); } ##################################################################### diff --git a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 17384241c9..8142b35699 100644 --- a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -9,11 +9,13 @@ package Parse::Pidl::Samba3::ClientNDR; use Exporter; @ISA = qw(Exporter); -@EXPORT_OK = qw(ParseFunction $res $res_hdr ParseOutputArgument); +@EXPORT_OK = qw(ParseFunction $res $res_hdr); 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); @@ -85,78 +87,6 @@ sub ParseInvalidResponse($$) } } -sub ParseOutputArgument($$$;$$$) -{ - my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_; - my $level = 0; - $r = "r." unless defined($r); - $o = "" unless defined($o); - $invalid_response_type = "sync" unless defined($invalid_response_type); - - if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") { - $self->pidl("return NT_STATUS_NOT_SUPPORTED;"); - error($e->{ORIGINAL}, "[out] argument is not a pointer or array"); - return; - } - - if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { - $level = 1; - if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") { - $self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {"); - $self->indent; - } - } - - if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") { - # This is a call to GenerateFunctionInEnv intentionally. - # Since the data is being copied into a user-provided data - # structure, the user should be able to know the size beforehand - # to allocate a structure of the right size. - my $in_env = GenerateFunctionInEnv($fn, $r); - my $out_env = GenerateFunctionOutEnv($fn, $r); - my $l = $e->{LEVELS}[$level]; - unless (defined($l->{SIZE_IS})) { - $self->pidl('#error No size known for [out] array `$e->{NAME}'); - error($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'"); - } else { - my $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL}); - my $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL}); - my $out_length_is = $out_size_is; - if (defined($l->{LENGTH_IS})) { - $out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL}); - } - if ($out_size_is ne $in_size_is) { - $self->pidl("if (($out_size_is) > ($in_size_is)) {"); - $self->indent; - $self->ParseInvalidResponse($invalid_response_type); - $self->deindent; - $self->pidl("}"); - } - if ($out_length_is ne $out_size_is) { - $self->pidl("if (($out_length_is) > ($out_size_is)) {"); - $self->indent; - $self->ParseInvalidResponse($invalid_response_type); - $self->deindent; - $self->pidl("}"); - } - if (has_property($e, "charset")) { - $self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));"); - } else { - $self->pidl("memcpy($o$e->{NAME}, ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));"); - } - } - } else { - $self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};"); - } - - if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { - if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") { - $self->deindent; - $self->pidl("}"); - } - } -} - sub ParseFunctionAsyncState($$$) { my ($self, $if, $fn) = @_; @@ -166,10 +96,10 @@ sub ParseFunctionAsyncState($$$) $self->pidl("$state_str {"); $self->indent; - $self->pidl("struct $fn->{NAME} orig;"); - $self->pidl("struct $fn->{NAME} tmp;"); $self->pidl("TALLOC_CTX *out_mem_ctx;"); - $self->pidl("NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx);"); + if (defined($fn->{RETURN_TYPE})) { + $self->pidl(mapTypeName($fn->{RETURN_TYPE}). " result;"); + } $self->deindent; $self->pidl("};"); $self->pidl(""); @@ -215,32 +145,14 @@ sub ParseFunctionAsyncSend($$$) $self->deindent; $self->pidl("}"); $self->pidl("state->out_mem_ctx = NULL;"); - $self->pidl("state->dispatch_recv = cli->dispatch_recv;"); - $self->pidl(""); - - $self->pidl("/* In parameters */"); - foreach (@{$fn->{ELEMENTS}}) { - if (grep(/in/, @{$_->{DIRECTION}})) { - $self->pidl("state->orig.in.$_->{NAME} = _$_->{NAME};"); - } - } $self->pidl(""); my $out_params = 0; - $self->pidl("/* Out parameters */"); foreach (@{$fn->{ELEMENTS}}) { if (grep(/out/, @{$_->{DIRECTION}})) { - $self->pidl("state->orig.out.$_->{NAME} = _$_->{NAME};"); $out_params++; } } - $self->pidl(""); - - if (defined($fn->{RETURN_TYPE})) { - $self->pidl("/* Result */"); - $self->pidl("ZERO_STRUCT(state->orig.out.result);"); - $self->pidl(""); - } if ($out_params > 0) { $self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,"); @@ -253,14 +165,14 @@ sub ParseFunctionAsyncSend($$$) $self->pidl(""); } - $self->pidl("/* make a temporary copy, that we pass to the dispatch function */"); - $self->pidl("state->tmp = state->orig;"); - $self->pidl(""); + $fn_str = "subreq = dcerpc_$fn->{NAME}_send"; + $pad = "\t" . genpad($fn_str); + $fn_args = "state,\n" . $pad . "ev,\n" . $pad . "cli->binding_handle"; + foreach (@{$fn->{ELEMENTS}}) { + $fn_args .= ",\n" . $pad . "_". $_->{NAME}; + } - $self->pidl("subreq = cli->dispatch_send(state, ev, cli,"); - $self->pidl("\t\t\t &ndr_table_$if,"); - $self->pidl("\t\t\t $ufn,"); - $self->pidl("\t\t\t &state->tmp);"); + $self->pidl("$fn_str($fn_args);"); $self->pidl("if (tevent_req_nomem(subreq, req)) {"); $self->indent; $self->pidl("return tevent_req_post(req, ev);"); @@ -302,7 +214,14 @@ sub ParseFunctionAsyncDone($$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("status = state->dispatch_recv(subreq, mem_ctx);"); + my $fn_str = "status = dcerpc_$fn->{NAME}_recv"; + my $pad = "\t" . genpad($fn_str); + my $fn_args = "subreq,\n" . $pad . "mem_ctx"; + if (defined($fn->{RETURN_TYPE})) { + $fn_args .= ",\n" . $pad . "&state->result"; + } + + $self->pidl("$fn_str($fn_args);"); $self->pidl("TALLOC_FREE(subreq);"); $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); $self->indent; @@ -312,27 +231,6 @@ sub ParseFunctionAsyncDone($$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("/* Copy out parameters */"); - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep(/out/, @{$e->{DIRECTION}})); - - $self->ParseOutputArgument($fn, $e, - "state->tmp.", - "state->orig.out.", - "async"); - } - $self->pidl(""); - - if (defined($fn->{RETURN_TYPE})) { - $self->pidl("/* Copy result */"); - $self->pidl("state->orig.out.result = state->tmp.out.result;"); - $self->pidl(""); - } - - $self->pidl("/* Reset temporary structure */"); - $self->pidl("ZERO_STRUCT(state->tmp);"); - $self->pidl(""); - $self->pidl("tevent_req_done(req);"); $self->deindent; $self->pidl("}"); @@ -369,13 +267,13 @@ sub ParseFunctionAsyncRecv($$$) $self->pidl("}"); $self->pidl(""); - $self->pidl("/* Steal possbile out parameters to the callers context */"); + $self->pidl("/* Steal possible out parameters to the callers context */"); $self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);"); $self->pidl(""); if (defined($fn->{RETURN_TYPE})) { $self->pidl("/* Return result */"); - $self->pidl("*result = state->orig.out.result;"); + $self->pidl("*result = state->result;"); $self->pidl(""); } @@ -401,7 +299,7 @@ sub ParseFunctionSync($$$) foreach (@{$fn->{ELEMENTS}}) { my $dir = ElementDirection($_); my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]); - $fn_args .= ",\n" . $pad . DeclLong($_) . " /* $dir $prop */"; + $fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */"; } if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) { @@ -411,60 +309,43 @@ sub ParseFunctionSync($$$) $self->fn_declare("$fn_str($fn_args)"); $self->pidl("{"); $self->indent; - $self->pidl("struct $fn->{NAME} r;"); + if (defined($fn->{RETURN_TYPE})) { + $self->pidl(mapTypeName($fn->{RETURN_TYPE})." result;"); + } $self->pidl("NTSTATUS status;"); $self->pidl(""); - $self->pidl("/* In parameters */"); + $fn_str = "status = dcerpc_$fn->{NAME}"; + $pad = "\t" . genpad($fn_str); + $fn_args = "cli->binding_handle,\n" . $pad . "mem_ctx"; foreach (@{$fn->{ELEMENTS}}) { - if (grep(/in/, @{$_->{DIRECTION}})) { - $self->pidl("r.in.$_->{NAME} = $_->{NAME};"); - } + $fn_args .= ",\n" . $pad . "_". $_->{NAME}; + } + if (defined($fn->{RETURN_TYPE})) { + $fn_args .= ",\n" . $pad . "&result"; } - $self->pidl(""); - $self->pidl("status = cli->dispatch(cli,"); - $self->pidl("\t\t\tmem_ctx,"); - $self->pidl("\t\t\t&ndr_table_$if,"); - $self->pidl("\t\t\t$ufn,"); - $self->pidl("\t\t\t&r);"); - $self->pidl(""); - + $self->pidl("$fn_str($fn_args);"); $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); $self->indent; $self->pidl("return status;"); $self->deindent; $self->pidl("}"); - $self->pidl(""); - $self->pidl("if (NT_STATUS_IS_ERR(status)) {"); - $self->indent; - $self->pidl("return status;"); - $self->deindent; - $self->pidl("}"); - $self->pidl(""); - $self->pidl("/* Return variables */"); - foreach my $e (@{$fn->{ELEMENTS}}) { - next unless (grep(/out/, @{$e->{DIRECTION}})); - - $self->ParseOutputArgument($fn, $e); - - } - $self->pidl(""); $self->pidl("/* Return result */"); if (not $fn->{RETURN_TYPE}) { $self->pidl("return NT_STATUS_OK;"); } elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") { - $self->pidl("return r.out.result;"); + $self->pidl("return result;"); } elsif ($fn->{RETURN_TYPE} eq "WERROR") { $self->pidl("if (werror) {"); $self->indent; - $self->pidl("*werror = r.out.result;"); + $self->pidl("*werror = result;"); $self->deindent; $self->pidl("}"); $self->pidl(""); - $self->pidl("return werror_to_ntstatus(r.out.result);"); + $self->pidl("return werror_to_ntstatus(result);"); } else { warning($fn->{ORIGINAL}, "Unable to convert $fn->{RETURN_TYPE} to NTSTATUS"); $self->pidl("return NT_STATUS_OK;"); @@ -495,16 +376,27 @@ sub ParseInterface($$) $self->pidl_hdr("#ifndef __CLI_$uif\__"); $self->pidl_hdr("#define __CLI_$uif\__"); - foreach (@{$if->{FUNCTIONS}}) { - next if ($_->{PROPERTIES}{noopnum}); - $self->ParseFunction($if->{NAME}, $_); + 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\__ */"); } sub Parse($$$$) { - my($self,$ndr,$header,$ndr_header) = @_; + my($self,$ndr,$header,$c_header) = @_; $self->pidl("/*"); $self->pidl(" * Unix SMB/CIFS implementation."); @@ -513,7 +405,7 @@ sub Parse($$$$) $self->pidl(""); $self->pidl("#include \"includes.h\""); $self->pidl("#include \"$header\""); - $self->pidl_hdr("#include \"$ndr_header\""); + $self->pidl_hdr("#include \"$c_header\""); $self->pidl(""); foreach (@$ndr) { diff --git a/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm b/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm index 5599de9d79..c4374baf7c 100644 --- a/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm +++ b/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm @@ -100,7 +100,7 @@ sub CallWithStruct($$$$) pidl "ZERO_STRUCT(r->out);" if ($hasout); - my $proto = "_$fn->{NAME}(pipes_struct *p, struct $fn->{NAME} *r"; + my $proto = "_$fn->{NAME}(struct pipes_struct *p, struct $fn->{NAME} *r"; my $ret = "_$fn->{NAME}($pipes_struct, r"; foreach (@{$fn->{ELEMENTS}}) { my @dir = @{$_->{DIRECTION}}; @@ -138,14 +138,13 @@ sub ParseFunction($$) my $op = "NDR_".uc($fn->{NAME}); - pidl "static bool api_$fn->{NAME}(pipes_struct *p)"; + pidl "static bool api_$fn->{NAME}(struct pipes_struct *p)"; pidl "{"; indent; pidl "const struct ndr_interface_call *call;"; pidl "struct ndr_pull *pull;"; pidl "struct ndr_push *push;"; pidl "enum ndr_err_code ndr_err;"; - pidl "DATA_BLOB blob;"; pidl "struct $fn->{NAME} *r;"; pidl ""; pidl "call = &ndr_table_$if->{NAME}.calls[$op];"; @@ -155,18 +154,16 @@ sub ParseFunction($$) pidl "\treturn false;"; pidl "}"; pidl ""; - pidl "if (!prs_data_blob(&p->in_data.data, &blob, r)) {"; - pidl "\ttalloc_free(r);"; - pidl "\treturn false;"; - pidl "}"; - pidl ""; - pidl "pull = ndr_pull_init_blob(&blob, r, NULL);"; + pidl "pull = ndr_pull_init_blob(&p->in_data.data, r);"; pidl "if (pull == NULL) {"; pidl "\ttalloc_free(r);"; pidl "\treturn false;"; pidl "}"; pidl ""; pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;"; + pidl "if (p->endian) {"; + pidl "\tpull->flags |= LIBNDR_FLAG_BIGENDIAN;"; + pidl "}"; pidl "ndr_err = call->ndr_pull(pull, NDR_IN, r);"; pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {"; pidl "\ttalloc_free(r);"; @@ -174,7 +171,7 @@ sub ParseFunction($$) pidl "}"; pidl ""; pidl "if (DEBUGLEVEL >= 10) {"; - pidl "\tNDR_PRINT_IN_DEBUG($fn->{NAME}, r);"; + pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r);"; pidl "}"; pidl ""; @@ -193,26 +190,29 @@ sub ParseFunction($$) pidl "}"; pidl ""; pidl "if (DEBUGLEVEL >= 10) {"; - pidl "\tNDR_PRINT_OUT_DEBUG($fn->{NAME}, r);"; + pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r);"; pidl "}"; pidl ""; - pidl "push = ndr_push_init_ctx(r, NULL);"; + pidl "push = ndr_push_init_ctx(r);"; pidl "if (push == NULL) {"; pidl "\ttalloc_free(r);"; 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);"; pidl "\treturn false;"; pidl "}"; pidl ""; - pidl "blob = ndr_push_blob(push);"; - pidl "if (!prs_copy_data_in(&p->out_data.rdata, (const char *)blob.data, (uint32_t)blob.length)) {"; - pidl "\ttalloc_free(r);"; - pidl "\treturn false;"; - pidl "}"; + pidl "p->out_data.rdata = ndr_push_blob(push);"; + pidl "talloc_steal(p->mem_ctx, p->out_data.rdata.data);"; pidl ""; pidl "talloc_free(r);"; pidl ""; @@ -222,45 +222,6 @@ sub ParseFunction($$) pidl ""; } -sub ParseDispatchFunction($) -{ - my ($if) = @_; - - pidl_hdr "NTSTATUS rpc_$if->{NAME}_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *r);"; - pidl "NTSTATUS rpc_$if->{NAME}_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *_r)"; - pidl "{"; - indent; - pidl "if (cli->pipes_struct == NULL) {"; - pidl "\treturn NT_STATUS_INVALID_PARAMETER;"; - pidl "}"; - pidl ""; - pidl "switch (opnum)"; - pidl "{"; - indent; - foreach my $fn (@{$if->{FUNCTIONS}}) { - next if ($fn->{PROPERTIES}{noopnum}); - my $op = "NDR_".uc($fn->{NAME}); - pidl "case $op: {"; - indent; - pidl "struct $fn->{NAME} *r = (struct $fn->{NAME} *)_r;"; - CallWithStruct("cli->pipes_struct", "mem_ctx", $fn, - sub { pidl "return NT_STATUS_NO_MEMORY;"; }); - pidl "return NT_STATUS_OK;"; - deindent; - pidl "}"; - pidl ""; - } - - pidl "default:"; - pidl "\treturn NT_STATUS_NOT_IMPLEMENTED;"; - deindent; - pidl "}"; - deindent; - pidl "}"; - - pidl ""; -} - sub ParseInterface($) { my $if = shift; @@ -301,14 +262,22 @@ sub ParseInterface($) pidl "}"; pidl ""; - ParseDispatchFunction($if); - - pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(void);"; - pidl "NTSTATUS rpc_$if->{NAME}_init(void)"; - pidl "{"; - pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct));"; - pidl "}"; - + if (not has_property($if, "no_srv_register")) { + pidl_hdr "struct rpc_srv_callbacks;"; + pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb);"; + pidl "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb)"; + pidl "{"; + pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct), rpc_srv_cb);"; + pidl "}"; + + pidl ""; + + pidl_hdr "NTSTATUS rpc_$if->{NAME}_shutdown(void);"; + pidl "NTSTATUS rpc_$if->{NAME}_shutdown(void)"; + pidl "{"; + pidl "\treturn rpc_srv_unregister(\&ndr_table_$if->{NAME});"; + pidl "}"; + } pidl_hdr "#endif /* __SRV_$uif\__ */"; } @@ -325,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/pidl/lib/Parse/Pidl/Samba4.pm b/pidl/lib/Parse/Pidl/Samba4.pm index 1deb708689..b720ab9015 100644 --- a/pidl/lib/Parse/Pidl/Samba4.pm +++ b/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/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm b/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm index 150acbfde9..239f5baaee 100644 --- a/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm +++ b/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm @@ -89,7 +89,7 @@ sub Boilerplate_Iface($) my $if_version = $interface->{PROPERTIES}->{version}; pidl " -static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) +static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version) { #ifdef DCESRV_INTERFACE_$uname\_BIND return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); diff --git a/pidl/lib/Parse/Pidl/Samba4/Header.pm b/pidl/lib/Parse/Pidl/Samba4/Header.pm index be1df4b118..3736315120 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Header.pm +++ b/pidl/lib/Parse/Pidl/Samba4/Header.pm @@ -5,7 +5,6 @@ # released under the GNU GPL package Parse::Pidl::Samba4::Header; - require Exporter; @ISA = qw(Exporter); @@ -217,6 +216,30 @@ sub HeaderUnion($$;$) } ##################################################################### +# 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($$$;$) { @@ -226,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; } @@ -386,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}}) { @@ -412,6 +437,20 @@ sub Parse($) $res = ""; %headerstructs = (); pidl "/* header auto-generated by pidl */\n\n"; + + my $ifacename = ""; + + # work out a unique interface name + foreach (@{$ndr}) { + if ($_->{TYPE} eq "INTERFACE") { + $ifacename = $_->{NAME}; + last; + } + } + + pidl "#ifndef _PIDL_HEADER_$ifacename\n"; + pidl "#define _PIDL_HEADER_$ifacename\n\n"; + if (!is_intree()) { pidl "#include <util/data_blob.h>\n"; } @@ -428,6 +467,8 @@ sub Parse($) ($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}}); } + pidl "#endif /* _PIDL_HEADER_$ifacename */\n"; + return $res; } diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm index 9d3ccaf8c8..c796b466ad 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm @@ -6,156 +6,870 @@ package Parse::Pidl::Samba4::NDR::Client; -use Parse::Pidl::Samba4 qw(choose_header is_intree); -use Parse::Pidl::Util qw(has_property); +use Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(Parse); + +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); use vars qw($VERSION); $VERSION = '0.01'; use strict; -my($res,$res_hdr); +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 ParseFunctionSend($$$) +sub genpad($) { - my ($interface, $fn, $name) = @_; + my ($s) = @_; + my $nt = int((length($s)+1)/8); + my $lt = ($nt*8)-1; + my $ns = (length($s)-$lt); + return "\t"x($nt)." "x($ns); +} + +sub new($) +{ + my ($class) = shift; + my $self = { res => "", res_hdr => "", tabs => "" }; + 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) = @_; my $uname = uc $name; - my $proto = "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)"; + $self->pidl("struct dcerpc_$name\_r_state {"); + $self->indent; + $self->pidl("TALLOC_CTX *out_mem_ctx;"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + $self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);"); + $self->pidl(""); +} - $res_hdr .= "\n$proto;\n"; +sub ParseFunction_r_Send($$$$) +{ + my ($self, $if, $fn, $name) = @_; + my $uname = uc $name; - $res .= "$proto\n{\n"; + my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n"; + $proto .= "\tstruct tevent_context *ev,\n", + $proto .= "\tstruct dcerpc_binding_handle *h,\n", + $proto .= "\tstruct $name *r)"; + + $self->fn_declare($proto); + + $self->pidl("{"); + $self->indent; + + $self->pidl("struct tevent_req *req;"); + $self->pidl("struct dcerpc_$name\_r_state *state;"); + $self->pidl("struct tevent_req *subreq;"); + $self->pidl(""); + + $self->pidl("req = tevent_req_create(mem_ctx, &state,"); + $self->pidl("\t\t\tstruct dcerpc_$name\_r_state);"); + $self->pidl("if (req == NULL) {"); + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + my $out_params = 0; + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless grep(/out/, @{$e->{DIRECTION}}); + next if ContainsPipe($e, $e->{LEVELS}[0]); + $out_params++; - if (has_property($fn, "todo")) { - $res .= "\treturn NULL;\n"; - } else { - $res .= " - if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) { - NDR_PRINT_IN_DEBUG($name, r); } - return dcerpc_ndr_request_send(p, NULL, &ndr_table_$interface->{NAME}, - NDR_$uname, true, mem_ctx, r); -"; + my $submem; + if ($out_params > 0) { + $self->pidl("state->out_mem_ctx = talloc_new(state);"); + $self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $submem = "state->out_mem_ctx"; + } else { + $self->pidl("state->out_mem_ctx = NULL;"); + $submem = "state"; } + $self->pidl(""); + + $self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,"); + $self->pidl("\t\tNULL, &ndr_table_$if->{NAME},"); + $self->pidl("\t\tNDR_$uname, $submem, r);"); + $self->pidl("if (tevent_req_nomem(subreq, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);"); + $self->pidl(""); + + $self->pidl("return req;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} - $res .= "}\n\n"; +sub ParseFunction_r_Done($$$$) +{ + my ($self, $if, $fn, $name) = @_; + my $uname = uc $name; + + my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)"; + + $self->pidl("$proto"); + $self->pidl("{"); + $self->indent; + + $self->pidl("struct tevent_req *req ="); + $self->pidl("\ttevent_req_callback_data(subreq,"); + $self->pidl("\tstruct tevent_req);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("status = dcerpc_binding_handle_call_recv(subreq);"); + $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); + $self->indent; + $self->pidl("tevent_req_nterror(req, status);"); + $self->pidl("return;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("tevent_req_done(req);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); } -sub ParseFunctionSync($$$) +sub ParseFunction_r_Recv($$$$) { - my ($interface, $fn, $name) = @_; + my ($self, $if, $fn, $name) = @_; my $uname = uc $name; - my $proto = "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)"; + my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)"; + + $self->fn_declare($proto); + + $self->pidl("{"); + $self->indent; + + $self->pidl("struct dcerpc_$name\_r_state *state ="); + $self->pidl("\ttevent_req_data(req,"); + $self->pidl("\tstruct dcerpc_$name\_r_state);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); - $res_hdr .= "\n$proto;\n"; - $res .= "$proto\n{\n"; + $self->pidl("if (tevent_req_is_nterror(req, &status)) {"); + $self->indent; + $self->pidl("tevent_req_received(req);"); + $self->pidl("return status;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); - if (has_property($fn, "todo")) { - $res .= "\treturn NT_STATUS_NOT_IMPLEMENTED;\n"; + $self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);"); + $self->pidl(""); + + $self->pidl("tevent_req_received(req);"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +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); + + $self->pidl("{"); + $self->indent; + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("status = dcerpc_binding_handle_call(h,"); + $self->pidl("\t\tNULL, &ndr_table_$if->{NAME},"); + $self->pidl("\t\tNDR_$uname, mem_ctx, r);"); + $self->pidl(""); + $self->pidl("return status;"); + + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ElementDirection($) +{ + my ($e) = @_; + + return "[in,out]" if (has_property($e, "in") and has_property($e, "out")); + return "[in]" if (has_property($e, "in")); + return "[out]" if (has_property($e, "out")); + return "[in,out]"; +} + +sub HeaderProperties($$) +{ + my($props,$ignores) = @_; + my $ret = ""; + + foreach my $d (keys %{$props}) { + next if (grep(/^$d$/, @$ignores)); + if($props->{$d} ne "1") { + $ret.= "$d($props->{$d}),"; + } else { + $ret.="$d,"; + } + } + + if ($ret) { + return "[" . substr($ret, 0, -1) . "]"; + } +} + +sub ParseCopyArgument($$$$$) +{ + my ($self, $fn, $e, $r, $i) = @_; + my $l = $e->{LEVELS}[0]; + + if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED} == 1) { + $self->pidl("memcpy(${r}$e->{NAME}, ${i}$e->{NAME}, sizeof(${r}$e->{NAME}));"); } else { - $res .= " - NTSTATUS status; + $self->pidl("${r}$e->{NAME} = ${i}$e->{NAME};"); + } +} + +sub ParseInvalidResponse($$) +{ + my ($self, $type) = @_; - if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) { - NDR_PRINT_IN_DEBUG($name, r); + if ($type eq "sync") { + $self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;"); + } elsif ($type eq "async") { + $self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);"); + $self->pidl("return;"); + } else { + die("ParseInvalidResponse($type)"); } +} + +sub ParseOutputArgument($$$$$$) +{ + my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_; + my $level = 0; - status = dcerpc_ndr_request(p, NULL, &ndr_table_$interface->{NAME}, - NDR_$uname, mem_ctx, r); + if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") { + fatal($e->{ORIGINAL}, "[out] argument is not a pointer or array"); + return; + } - if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) { - NDR_PRINT_OUT_DEBUG($name, r); + if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { + $level = 1; + if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") { + $self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {"); + $self->indent; + } } -"; - - if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") { - $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; - } - $res .= -" - return status; -"; + + if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") { + # This is a call to GenerateFunctionInEnv intentionally. + # Since the data is being copied into a user-provided data + # structure, the user should be able to know the size beforehand + # to allocate a structure of the right size. + my $in_env = GenerateFunctionInEnv($fn, $r); + my $out_env = GenerateFunctionOutEnv($fn, $r); + my $l = $e->{LEVELS}[$level]; + + my $in_var = undef; + if (grep(/in/, @{$e->{DIRECTION}})) { + $in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL}); + } + my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL}); + + my $in_size_is = undef; + my $out_size_is = undef; + my $out_length_is = undef; + + my $avail_len = undef; + my $needed_len = undef; + + $self->pidl("{"); + $self->indent; + my $copy_len_var = "_copy_len_$e->{NAME}"; + $self->pidl("size_t $copy_len_var;"); + + if (not defined($l->{SIZE_IS})) { + if (not $l->{IS_ZERO_TERMINATED}) { + fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'"); + } + if (has_property($e, "charset")) { + $avail_len = "ndr_charset_length($in_var, CH_UNIX)"; + $needed_len = "ndr_charset_length($out_var, CH_UNIX)"; + } else { + $avail_len = "ndr_string_length($in_var, sizeof(*$in_var))"; + $needed_len = "ndr_string_length($out_var, sizeof(*$out_var))"; + } + $in_size_is = ""; + $out_size_is = ""; + $out_length_is = ""; + } else { + $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL}); + $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL}); + $out_length_is = $out_size_is; + if (defined($l->{LENGTH_IS})) { + $out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL}); + } + if (has_property($e, "charset")) { + if (defined($in_var)) { + $avail_len = "ndr_charset_length($in_var, CH_UNIX)"; + } else { + $avail_len = $out_length_is; + } + $needed_len = "ndr_charset_length($out_var, CH_UNIX)"; + } + } + + if ($out_size_is ne $in_size_is) { + $self->pidl("if (($out_size_is) > ($in_size_is)) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } + if ($out_length_is ne $out_size_is) { + $self->pidl("if (($out_length_is) > ($out_size_is)) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } + if (defined($needed_len)) { + $self->pidl("$copy_len_var = $needed_len;"); + $self->pidl("if ($copy_len_var > $avail_len) {"); + $self->indent; + $self->ParseInvalidResponse($invalid_response_type); + $self->deindent; + $self->pidl("}"); + } else { + $self->pidl("$copy_len_var = $out_length_is;"); + } + + if (has_property($e, "charset")) { + $self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));"); + } else { + $self->pidl("memcpy($o$e->{NAME}, $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));"); + } + + $self->deindent; + $self->pidl("}"); + } else { + $self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};"); } - $res .= "}\n\n"; + if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { + if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") { + $self->deindent; + $self->pidl("}"); + } + } +} + +sub ParseFunction_State($$$$) +{ + my ($self, $if, $fn, $name) = @_; + + my $state_str = "struct dcerpc_$name\_state"; + my $done_fn = "dcerpc_$name\_done"; + + $self->pidl("$state_str {"); + $self->indent; + $self->pidl("struct $name orig;"); + $self->pidl("struct $name tmp;"); + $self->pidl("TALLOC_CTX *out_mem_ctx;"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + $self->pidl("static void $done_fn(struct tevent_req *subreq);"); + $self->pidl(""); +} + +sub ParseFunction_Send($$$$) +{ + my ($self, $if, $fn, $name) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$name\_state"; + my $done_fn = "dcerpc_$name\_done"; + my $out_mem_ctx = "dcerpc_$name\_out_memory"; + my $fn_str = "struct tevent_req *dcerpc_$name\_send"; + my $pad = genpad($fn_str); + + $fn_args .= "TALLOC_CTX *mem_ctx"; + $fn_args .= ",\n" . $pad . "struct tevent_context *ev"; + $fn_args .= ",\n" . $pad . "struct dcerpc_binding_handle *h"; + + foreach (@{$fn->{ELEMENTS}}) { + my $dir = ElementDirection($_); + my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]); + $fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */"; + } + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req;"); + $self->pidl("$state_str *state;"); + $self->pidl("struct tevent_req *subreq;"); + $self->pidl(""); + $self->pidl("req = tevent_req_create(mem_ctx, &state,"); + $self->pidl("\t\t\t$state_str);"); + $self->pidl("if (req == NULL) {"); + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("state->out_mem_ctx = NULL;"); + $self->pidl(""); + + $self->pidl("/* In parameters */"); + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/in/, @{$e->{DIRECTION}})); + + $self->ParseCopyArgument($fn, $e, "state->orig.in.", "_"); + } + $self->pidl(""); + + my $out_params = 0; + $self->pidl("/* Out parameters */"); + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless grep(/out/, @{$e->{DIRECTION}}); + + $self->ParseCopyArgument($fn, $e, "state->orig.out.", "_"); + + next if ContainsPipe($e, $e->{LEVELS}[0]); + + $out_params++; + } + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Result */"); + $self->pidl("ZERO_STRUCT(state->orig.out.result);"); + $self->pidl(""); + } + + if ($out_params > 0) { + $self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,"); + $self->pidl("\t\t \"$out_mem_ctx\");"); + $self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + } + + $self->pidl("/* make a temporary copy, that we pass to the dispatch function */"); + $self->pidl("state->tmp = state->orig;"); + $self->pidl(""); + + $self->pidl("subreq = dcerpc_$name\_r_send(state, ev, h, &state->tmp);"); + $self->pidl("if (tevent_req_nomem(subreq, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl("tevent_req_set_callback(subreq, $done_fn, req);"); + $self->pidl("return req;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParseFunction_Done($$$$) +{ + my ($self, $if, $fn, $name) = @_; + + my $state_str = "struct dcerpc_$name\_state"; + my $done_fn = "dcerpc_$name\_done"; + + $self->pidl("static void $done_fn(struct tevent_req *subreq)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req = tevent_req_callback_data("); + $self->pidl("\tsubreq, struct tevent_req);"); + $self->pidl("$state_str *state = tevent_req_data("); + $self->pidl("\treq, $state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl("TALLOC_CTX *mem_ctx;"); + $self->pidl(""); + + $self->pidl("if (state->out_mem_ctx) {"); + $self->indent; + $self->pidl("mem_ctx = state->out_mem_ctx;"); + $self->deindent; + $self->pidl("} else {"); + $self->indent; + $self->pidl("mem_ctx = state;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("status = dcerpc_$name\_r_recv(subreq, mem_ctx);"); + $self->pidl("TALLOC_FREE(subreq);"); + $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); + $self->indent; + $self->pidl("tevent_req_nterror(req, status);"); + $self->pidl("return;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $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, + "state->tmp.", + "state->orig.out.", + "async"); + } + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Copy result */"); + $self->pidl("state->orig.out.result = state->tmp.out.result;"); + $self->pidl(""); + } + + $self->pidl("/* Reset temporary structure */"); + $self->pidl("ZERO_STRUCT(state->tmp);"); + $self->pidl(""); + + $self->pidl("tevent_req_done(req);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParseFunction_Recv($$$$) +{ + my ($self, $if, $fn, $name) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$name\_state"; + my $fn_str = "NTSTATUS dcerpc_$name\_recv"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx"; + + if (defined($fn->{RETURN_TYPE})) { + $fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result"; + } + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$state_str *state = tevent_req_data("); + $self->pidl("\treq, $state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + $self->pidl("if (tevent_req_is_nterror(req, &status)) {"); + $self->indent; + $self->pidl("tevent_req_received(req);"); + $self->pidl("return status;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("/* Steal possible out parameters to the callers context */"); + $self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);"); + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Return result */"); + $self->pidl("*result = state->orig.out.result;"); + $self->pidl(""); + } + + $self->pidl("tevent_req_received(req);"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +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"; + my $pad = genpad($fn_str); + + $fn_args .= "struct dcerpc_binding_handle *h,\n" . $pad . "TALLOC_CTX *mem_ctx"; + + foreach (@{$fn->{ELEMENTS}}) { + my $dir = ElementDirection($_); + my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]); + $fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */"; + } + + if (defined($fn->{RETURN_TYPE})) { + $fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result"; + } + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct $name r;"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("/* In parameters */"); + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/in/, @{$e->{DIRECTION}})); + + $self->ParseCopyArgument($fn, $e, "r.in.", "_"); + } + $self->pidl(""); + + $self->pidl("status = dcerpc_$name\_r(h, mem_ctx, &r);"); + $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); + $self->indent; + $self->pidl("return status;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $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"); + } + $self->pidl(""); + + $self->pidl("/* Return result */"); + if ($fn->{RETURN_TYPE}) { + $self->pidl("*result = r.out.result;"); + } + $self->pidl(""); + + $self->pidl("return NT_STATUS_OK;"); + + $self->deindent; + $self->pidl("}"); + $self->pidl(""); } ##################################################################### # parse a function -sub ParseFunction($$) +sub ParseFunction($$$) { - my ($interface, $fn) = @_; + 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}); + + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/out/, @{$e->{DIRECTION}})); + + my $reason = "is not a pointer or array"; + + # 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'"; + } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and + $e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) { + next; + } elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and + not defined($e->{LEVELS}[1]->{SIZE_IS})) { + $reason = "is a pointer to an unsized array"; + } else { + next; + } + } + if ($e->{LEVELS}[0]->{TYPE} eq "ARRAY") { + if (not defined($e->{LEVELS}[0]->{SIZE_IS})) { + $reason = "is an unsized array"; + } else { + next; + } + } + + $self->pidl_both("/*"); + $self->pidl_both(" * The following functions are skipped because"); + $self->pidl_both(" * an [out] argument $e->{NAME} $reason:"); + $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(""); + + error($e->{ORIGINAL}, "$fn->{NAME}: [out] argument '$e->{NAME}' $reason, skip client functions"); + return; + } + + $self->ParseFunction_State($if, $fn, $fn->{NAME}); + $self->ParseFunction_Send($if, $fn, $fn->{NAME}); + $self->ParseFunction_Done($if, $fn, $fn->{NAME}); + $self->ParseFunction_Recv($if, $fn, $fn->{NAME}); + $self->ParseFunction_Sync($if, $fn, $fn->{NAME}); - ParseFunctionSend($interface, $fn, $fn->{NAME}); - ParseFunctionSync($interface, $fn, $fn->{NAME}); + $self->pidl_hdr(""); } my %done; ##################################################################### # parse the interface definitions -sub ParseInterface($) +sub ParseInterface($$) { - my($interface) = shift; + my ($self, $if) = @_; + my $ifu = uc($if->{NAME}); - $res_hdr .= "#ifndef _HEADER_RPC_$interface->{NAME}\n"; - $res_hdr .= "#define _HEADER_RPC_$interface->{NAME}\n\n"; + $self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}"); + $self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}"); + $self->pidl_hdr(""); - if (defined $interface->{PROPERTIES}->{uuid}) { - $res_hdr .= "extern const struct ndr_interface_table ndr_table_$interface->{NAME};\n"; + if (defined $if->{PROPERTIES}->{uuid}) { + $self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};"); + $self->pidl_hdr(""); } - $res .= "/* $interface->{NAME} - client functions generated by pidl */\n\n"; + $self->pidl("/* $if->{NAME} - client functions generated by pidl */"); + $self->pidl(""); - foreach my $fn (@{$interface->{FUNCTIONS}}) { - next if not defined($fn->{OPNUM}); + foreach my $fn (@{$if->{FUNCTIONS}}) { next if defined($done{$fn->{NAME}}); - ParseFunction($interface, $fn); + next if has_property($fn, "noopnum"); + next if has_property($fn, "todo"); + $self->ParseFunction($if, $fn); $done{$fn->{NAME}} = 1; } - $res_hdr .= "#endif /* _HEADER_RPC_$interface->{NAME} */\n"; - - return $res; + $self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */"); } -sub Parse($$$$) +sub Parse($$$$$$) { - my($ndr,$header,$ndr_header,$client_header) = @_; - - $res = ""; - $res_hdr = ""; + my($self,$ndr,$header,$ndr_header,$client_header) = @_; - $res .= "/* client functions auto-generated by pidl */\n"; - $res .= "\n"; + $self->pidl("/* client functions auto-generated by pidl */"); + $self->pidl(""); if (is_intree()) { - $res .= "#include \"includes.h\"\n"; + $self->pidl("#include \"includes.h\""); } else { - $res .= "#ifndef _GNU_SOURCE\n"; - $res .= "#define _GNU_SOURCE\n"; - $res .= "#endif\n"; - $res .= "#include <stdio.h>\n"; - $res .= "#include <stdbool.h>\n"; - $res .= "#include <stdlib.h>\n"; - $res .= "#include <stdint.h>\n"; - $res .= "#include <stdarg.h>\n"; - $res .= "#include <core/ntstatus.h>\n"; - } - $res .= "#include \"$ndr_header\"\n"; - $res .= "#include \"$client_header\"\n"; - $res .= "\n"; - - $res_hdr .= choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."\n"; - $res_hdr .= "#include \"$header\"\n"; + $self->pidl("#ifndef _GNU_SOURCE"); + $self->pidl("#define _GNU_SOURCE"); + $self->pidl("#endif"); + $self->pidl("#include <stdio.h>"); + $self->pidl("#include <stdbool.h>"); + $self->pidl("#include <stdlib.h>"); + $self->pidl("#include <stdint.h>"); + $self->pidl("#include <stdarg.h>"); + $self->pidl("#include <string.h>"); + $self->pidl("#include <core/ntstatus.h>"); + } + $self->pidl("#include <tevent.h>"); + $self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h").""); + $self->pidl("#include \"$ndr_header\""); + $self->pidl("#include \"$client_header\""); + $self->pidl(""); + + $self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h").""); + $self->pidl_hdr("#include \"$header\""); foreach my $x (@{$ndr}) { - ($x->{TYPE} eq "INTERFACE") && ParseInterface($x); + ($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x); } - return ($res,$res_hdr); + return ($self->{res},$self->{res_hdr}); } 1; diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index da536beef4..7cda2729fc 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/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); @@ -206,11 +206,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; } @@ -574,6 +574,9 @@ sub ParseElementPushLevel if ($l->{POINTER_TYPE} eq "relative") { $self->pidl("NDR_CHECK(ndr_push_relative_ptr2_start($ndr, $rel_var_name));"); } + if ($l->{POINTER_TYPE} eq "relative_short") { + $self->pidl("NDR_CHECK(ndr_push_short_relative_ptr2($ndr, $var_name));"); + } } $var_name = get_value_of($var_name); $self->ParseElementPushLevel($e, GetNextLevel($e, $l), $ndr, $var_name, $env, 1, 1); @@ -627,6 +630,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 @@ -674,6 +679,8 @@ sub ParsePtrPush($$$$$) } } elsif ($l->{POINTER_TYPE} eq "relative") { $self->pidl("NDR_CHECK(ndr_push_relative_ptr1($ndr, $var_name));"); + } elsif ($l->{POINTER_TYPE} eq "relative_short") { + $self->pidl("NDR_CHECK(ndr_push_short_relative_ptr1($ndr, $var_name));"); } elsif ($l->{POINTER_TYPE} eq "unique") { $self->pidl("NDR_CHECK(ndr_push_unique_ptr($ndr, $var_name));"); } elsif ($l->{POINTER_TYPE} eq "full") { @@ -786,9 +793,6 @@ sub ParseElementPrint($$$$$) $self->pidl("$ndr->depth++;"); $self->pidl("for ($counter=0;$counter<$length;$counter++) {"); $self->indent; - $self->pidl("char *idx_$l->{LEVEL_INDEX}=NULL;"); - $self->pidl("if (asprintf(&idx_$l->{LEVEL_INDEX}, \"[\%d]\", $counter) != -1) {"); - $self->indent; $var_name = get_array_element($var_name, $counter); } @@ -811,9 +815,6 @@ sub ParseElementPrint($$$$$) } elsif (($l->{TYPE} eq "ARRAY") and not is_charset_array($e,$l) and not has_fast_array($e,$l)) { - $self->pidl("free(idx_$l->{LEVEL_INDEX});"); - $self->deindent; - $self->pidl("}"); $self->deindent; $self->pidl("}"); $self->pidl("$ndr->depth--;"); @@ -865,7 +866,10 @@ sub ParseDataPull($$$$$$$) $self->pidl("NDR_CHECK(".TypeFunctionName("ndr_pull", $l->{DATA_TYPE})."($ndr, $ndr_flags, $var_name));"); - if (my $range = has_property($e, "range")) { + my $pl = GetPrevLevel($e, $l); + + my $range = has_property($e, "range"); + if ($range and $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); @@ -943,12 +947,11 @@ sub ParseMemCtxPullFlags($$$$) if (($l->{TYPE} eq "POINTER") and ($l->{POINTER_TYPE} eq "ref")) { 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")); - if ($next_is_array or $next_is_string) { - return undef; - } elsif ($l->{LEVEL} eq "TOP") { + 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")); + + if ($l->{LEVEL} eq "TOP") { $mem_flags = "LIBNDR_FLAG_REF_ALLOC"; } } @@ -1010,6 +1013,20 @@ sub ParseElementPullLevel } elsif ($l->{TYPE} eq "ARRAY") { my $length = $self->ParseArrayPullHeader($e, $l, $ndr, $var_name, $env); + if (my $range = has_property($e, "range")) { + my ($low, $high) = split(/,/, $range, 2); + if ($low < 0) { + warning(0, "$low is invalid for the range of an array size"); + } + if ($low == 0) { + $self->pidl("if ($length > $high) {"); + } else { + $self->pidl("if ($length < $low || $length > $high) {"); + } + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); + $self->pidl("}"); + } + my $nl = GetNextLevel($e, $l); if (is_charset_array($e,$l)) { @@ -1042,7 +1059,7 @@ sub ParseElementPullLevel $self->pidl("if ($var_name) {"); $self->indent; - if ($l->{POINTER_TYPE} eq "relative") { + if ($l->{POINTER_TYPE} eq "relative" or $l->{POINTER_TYPE} eq "relative_short") { $self->pidl("uint32_t _relative_save_offset;"); $self->pidl("_relative_save_offset = $ndr->offset;"); $self->pidl("NDR_CHECK(ndr_pull_relative_ptr2($ndr, $var_name));"); @@ -1057,7 +1074,12 @@ sub ParseElementPullLevel $self->ParseMemCtxPullEnd($e, $l, $ndr); if ($l->{POINTER_TYPE} ne "ref") { - if ($l->{POINTER_TYPE} eq "relative") { + if ($l->{POINTER_TYPE} eq "relative") { + $self->pidl("if ($ndr->offset > $ndr->relative_highest_offset) {"); + $self->indent; + $self->pidl("$ndr->relative_highest_offset = $ndr->offset;"); + $self->deindent; + $self->pidl("}"); $self->pidl("$ndr->offset = _relative_save_offset;"); } $self->deindent; @@ -1073,6 +1095,20 @@ sub ParseElementPullLevel $length = "ndr_get_array_length($ndr, " . get_pointer_to($var_name) .")"; } + if (my $range = has_property($e, "range")) { + my ($low, $high) = split(/,/, $range, 2); + if ($low < 0) { + warning(0, "$low is invalid for the range of an array size"); + } + if ($low == 0) { + $self->pidl("if ($length > $high) {"); + } else { + $self->pidl("if ($length < $low || $length > $high) {"); + } + $self->pidl("\treturn ndr_pull_error($ndr, NDR_ERR_RANGE, \"value out of range\");"); + $self->pidl("}"); + } + $var_name = get_array_element($var_name, $counter); $self->ParseMemCtxPullStart($e, $l, $ndr, $array_name); @@ -1116,6 +1152,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}) { @@ -1161,7 +1199,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}));"); @@ -1169,6 +1207,8 @@ sub ParsePtrPull($$$$$) ($l->{POINTER_TYPE} eq "relative") or ($l->{POINTER_TYPE} eq "full")) { $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}));"); } else { die("Unhandled pointer type $l->{POINTER_TYPE}"); } @@ -1189,7 +1229,7 @@ sub ParsePtrPull($$$$$) } #$self->pidl("memset($var_name, 0, sizeof($var_name));"); - if ($l->{POINTER_TYPE} eq "relative") { + if ($l->{POINTER_TYPE} eq "relative" or $l->{POINTER_TYPE} eq "relative_short") { $self->pidl("NDR_CHECK(ndr_pull_relative_ptr1($ndr, $var_name, _ptr_$e->{NAME}));"); } $self->deindent; @@ -1454,6 +1494,7 @@ sub ParseStructPrint($$$$$) $self->DeclareArrayVariables($_) foreach (@{$struct->{ELEMENTS}}); $self->pidl("ndr_print_struct($ndr, name, \"$name\");"); + $self->pidl("if (r == NULL) { ndr_print_null($ndr); return; }"); $self->start_flags($struct, $ndr); @@ -1470,9 +1511,13 @@ sub DeclarePtrVariables($$) { my ($self,$e) = @_; foreach my $l (@{$e->{LEVELS}}) { + my $size = 32; if ($l->{TYPE} eq "POINTER" and not ($l->{POINTER_TYPE} eq "ref" and $l->{LEVEL} eq "TOP")) { - $self->pidl("uint32_t _ptr_$e->{NAME};"); + if ($l->{POINTER_TYPE} eq "relative_short") { + $size = 16; + } + $self->pidl("uint${size}_t _ptr_$e->{NAME};"); last; } } @@ -1602,7 +1647,7 @@ sub ParseStructNdrSize($$$$) if (my $flags = has_property($t, "flag")) { $self->pidl("flags |= $flags;"); } - $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name, ic);"); + $self->pidl("return ndr_size_struct($varname, flags, (ndr_push_flags_fn_t)ndr_push_$name);"); } sub DeclStruct($$$$) @@ -1614,7 +1659,7 @@ sub DeclStruct($$$$) sub ArgsStructNdrSize($$$) { my ($d, $name, $varname) = @_; - return "const struct $name *$varname, struct smb_iconv_convenience *ic, int flags"; + return "const struct $name *$varname, int flags"; } $typefamily{STRUCT} = { @@ -1637,7 +1682,7 @@ sub ParseUnionNdrSize($$$) $self->pidl("flags |= $flags;"); } - $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name, ic);"); + $self->pidl("return ndr_size_union($varname, flags, level, (ndr_push_flags_fn_t)ndr_push_$name);"); } sub ParseUnionPushPrimitives($$$$) @@ -1646,14 +1691,23 @@ sub ParseUnionPushPrimitives($$$$) my $have_default = 0; - $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); + $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}));"); + } + $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) {"); @@ -1693,7 +1747,7 @@ sub ParseUnionPushDeferred($$$$) my $have_default = 0; - $self->pidl("int level = ndr_push_get_switch_value($ndr, $varname);"); + $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 @@ -1752,7 +1806,7 @@ sub ParseUnionPrint($$$$$) my ($self,$e,$ndr,$name,$varname) = @_; my $have_default = 0; - $self->pidl("int level;"); + $self->pidl("uint32_t level;"); foreach my $el (@{$e->{ELEMENTS}}) { $self->DeclareArrayVariables($el); } @@ -1793,7 +1847,12 @@ sub ParseUnionPullPrimitives($$$$$) my ($self,$e,$ndr,$varname,$switch_type) = @_; my $have_default = 0; + 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__);"); @@ -1801,7 +1860,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) {"); @@ -1879,7 +1943,7 @@ sub ParseUnionPull($$$$) my ($self,$e,$ndr,$varname) = @_; my $switch_type = $e->{SWITCH_TYPE}; - $self->pidl("int level;"); + $self->pidl("uint32_t level;"); if (defined($switch_type)) { if (Parse::Pidl::Typelist::typeIs($switch_type, "ENUM")) { $switch_type = Parse::Pidl::Typelist::enum_type_fn(getType($switch_type)->{DATA}); @@ -1925,7 +1989,7 @@ sub DeclUnion($$$$) sub ArgsUnionNdrSize($$) { my ($d,$name) = @_; - return "const union $name *r, uint32_t level, struct smb_iconv_convenience *ic, int flags"; + return "const union $name *r, uint32_t level, int flags"; } $typefamily{UNION} = { @@ -2003,6 +2067,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($$) @@ -2023,6 +2180,7 @@ sub ParseFunctionPrint($$) } $self->pidl("ndr_print_struct($ndr, name, \"$fn->{NAME}\");"); + $self->pidl("if (r == NULL) { ndr_print_null($ndr); return; }"); $self->pidl("$ndr->depth++;"); $self->pidl("if (flags & NDR_SET_VALUES) {"); @@ -2204,6 +2362,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}); @@ -2219,6 +2378,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});"); @@ -2277,17 +2442,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".($d->{ASYNC}?"true":"false").","); + $self->pidl("\t\t{ $in_pipes, $in_pipes_ptr },"); + $self->pidl("\t\t{ $out_pipes, $out_pipes_ptr },"); $self->pidl("\t},"); return 1; } @@ -2303,12 +2553,16 @@ 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}}) { $count += $self->FunctionCallEntry($d); } - $self->pidl("\t{ NULL, 0, NULL, NULL, NULL, false }"); + $self->pidl("\t{ NULL, 0, NULL, NULL, NULL }"); $self->pidl("};"); $self->pidl(""); @@ -2556,6 +2810,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"); @@ -2575,10 +2843,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); @@ -2701,6 +2965,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}); @@ -2722,6 +2987,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/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm index bb0c18e13c..20c94c89e0 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm @@ -81,7 +81,7 @@ sub Boilerplate_Iface($) my $if_version = $interface->{PROPERTIES}->{version}; pidl " -static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) +static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version) { #ifdef DCESRV_INTERFACE_$uname\_BIND return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); diff --git a/pidl/lib/Parse/Pidl/Samba4/Python.pm b/pidl/lib/Parse/Pidl/Samba4/Python.pm index c785619adb..db2d79d2f6 100644 --- a/pidl/lib/Parse/Pidl/Samba4/Python.pm +++ b/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); @@ -24,8 +24,9 @@ sub new($) { my ($class) = @_; my $self = { res => "", res_hdr => "", tabs => "", constants => {}, module_methods => [], module_objects => [], ready_types => [], - module_imports => [], type_imports => {}, - patch_type_calls => [], readycode => [] }; + module_imports => {}, type_imports => {}, + patch_type_calls => [], prereadycode => [], + postreadycode => []}; bless($self, $class); } @@ -63,8 +64,11 @@ sub PrettifyTypeName($$) { my ($name, $basename) = @_; + $basename =~ s/^.*\.([^.]+)$/\1/; + $name =~ s/^$basename\_//; + return $name; } @@ -76,7 +80,7 @@ sub Import $_ = unmake_str($_); s/\.idl$//; $self->pidl_hdr("#include \"librpc/gen_ndr/$_\.h\"\n"); - $self->register_module_import($_); + $self->register_module_import("samba.dcerpc.$_"); } } @@ -126,6 +130,7 @@ sub FromUnionToPythonFunction($$$$) $self->ConvertObjectToPython($mem_ctx, {}, $e, "$name->$e->{NAME}", "ret", "return NULL;"); } else { $self->pidl("ret = Py_None;"); + $self->pidl("Py_INCREF(ret);"); } $self->pidl("return ret;"); @@ -213,7 +218,7 @@ sub PythonStruct($$$$$$) if ($l->{TYPE} eq "POINTER" and not ($nl->{TYPE} eq "ARRAY" and ($nl->{IS_FIXED} or is_charset_array($e, $nl))) and not ($nl->{TYPE} eq "DATA" and Parse::Pidl::Typelist::scalar_is_reference($nl->{DATA_TYPE}))) { - $self->pidl("talloc_free($varname);"); + $self->pidl("talloc_unlink(py_talloc_get_mem_ctx(py_obj), $varname);"); } $self->ConvertObjectFromPython($env, $mem_ctx, $e, "value", $varname, "return -1;"); $self->pidl("return 0;"); @@ -253,7 +258,7 @@ sub PythonStruct($$$$$$) $self->pidl("$cname *object = ($cname *)py_talloc_get_ptr(py_obj);"); $self->pidl("DATA_BLOB blob;"); $self->pidl("enum ndr_err_code err;"); - $self->pidl("err = ndr_push_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_push_flags_fn_t)ndr_push_$name);"); + $self->pidl("err = ndr_push_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), object, (ndr_push_flags_fn_t)ndr_push_$name);"); $self->pidl("if (err != NDR_ERR_SUCCESS) {"); $self->indent; $self->pidl("PyErr_SetNdrError(err);"); @@ -275,24 +280,7 @@ sub PythonStruct($$$$$$) $self->pidl("if (!PyArg_ParseTuple(args, \"s#:__ndr_unpack__\", &blob.data, &blob.length))"); $self->pidl("\treturn NULL;"); $self->pidl(""); - - # This disgusting hack works around the fact that ndr_pull_struct_blob_all will always fail on structures with relative pointers. - # So, map ndr_unpack to ndr_pull_struct_blob_all only if we don't have any relative pointers in this - my $got_relative = 0; - if ($#{$d->{ELEMENTS}} > -1) { - foreach my $e (@{$d->{ELEMENTS}}) { - my $l = $e->{LEVELS}[0]; - if ($l->{TYPE} eq "POINTER" and ($l->{POINTER_TYPE} eq "relative")) { - $got_relative = 1; - last; - } - } - } - if ($got_relative == 0) { - $self->pidl("err = ndr_pull_struct_blob_all(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);"); - } else { - $self->pidl("err = ndr_pull_struct_blob(&blob, py_talloc_get_mem_ctx(py_obj), NULL, object, (ndr_pull_flags_fn_t)ndr_pull_$name);"); - } + $self->pidl("err = ndr_pull_struct_blob_all(&blob, py_talloc_get_mem_ctx(py_obj), object, (ndr_pull_flags_fn_t)ndr_pull_$name);"); $self->pidl("if (err != NDR_ERR_SUCCESS) {"); $self->indent; $self->pidl("PyErr_SetNdrError(err);"); @@ -304,11 +292,29 @@ sub PythonStruct($$$$$$) $self->deindent; $self->pidl("}"); $self->pidl(""); + + $self->pidl("static PyObject *py_$name\_ndr_print(PyObject *py_obj)"); + $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("ret = PyString_FromString(retstr);"); + $self->pidl("talloc_free(retstr);"); + $self->pidl(""); + $self->pidl("return ret;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + $py_methods = "py_$name\_methods"; $self->pidl("static PyMethodDef $py_methods\[] = {"); $self->indent; - $self->pidl("{ \"__ndr_pack__\", (PyCFunction)py_$name\_ndr_pack, METH_NOARGS, \"S.pack() -> blob\\nNDR pack\" },"); - $self->pidl("{ \"__ndr_unpack__\", (PyCFunction)py_$name\_ndr_unpack, METH_VARARGS, \"S.unpack(blob) -> None\\nNDR unpack\" },"); + $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, \"S.ndr_unpack(class, blob) -> None\\nNDR unpack\" },"); + $self->pidl("{ \"__ndr_print__\", (PyCFunction)py_$name\_ndr_print, METH_VARARGS, \"S.ndr_print(object) -> None\\nNDR print\" },"); $self->pidl("{ NULL, NULL, 0, NULL }"); $self->deindent; $self->pidl("};"); @@ -323,21 +329,22 @@ sub PythonStruct($$$$$$) $self->indent; $self->pidl("PyObject_HEAD_INIT(NULL) 0,"); $self->pidl(".tp_name = \"$modulename.$prettyname\","); - $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),"); - $self->pidl(".tp_dealloc = py_talloc_dealloc,"); $self->pidl(".tp_getset = $getsetters,"); - $self->pidl(".tp_repr = py_talloc_default_repr,"); if ($docstring) { $self->pidl(".tp_doc = $docstring,"); } $self->pidl(".tp_methods = $py_methods,"); $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,"); + $self->pidl(".tp_basicsize = sizeof(py_talloc_Object),"); $self->pidl(".tp_new = py_$name\_new,"); $self->deindent; $self->pidl("};"); $self->pidl(""); + my $talloc_typename = $self->import_type_variable("talloc", "Object"); + $self->register_module_prereadycode(["$name\_Type.tp_base = $talloc_typename;", ""]); + return "&$typeobject"; } @@ -388,7 +395,7 @@ sub PythonFunctionUnpackOut($$$) $self->pidl("static PyObject *$outfnname(struct $fn->{NAME} *r)"); $self->pidl("{"); $self->indent; - $self->pidl("PyObject *result = Py_None;"); + $self->pidl("PyObject *result;"); foreach my $e (@{$fn->{ELEMENTS}}) { next unless (grep(/out/,@{$e->{DIRECTION}})); next if (($metadata_args->{in}->{$e->{NAME}} and grep(/in/, @{$e->{DIRECTION}})) or @@ -407,6 +414,8 @@ sub PythonFunctionUnpackOut($$$) $self->pidl("result = PyTuple_New($result_size);"); $signature .= "("; } elsif ($result_size == 0) { + $self->pidl("result = Py_None;"); + $self->pidl("Py_INCREF(result);"); $signature .= "None"; } @@ -505,7 +514,7 @@ sub PythonFunctionPackIn($$$) if ($metadata_args->{in}->{$e->{NAME}}) { my $py_var = "py_".$metadata_args->{in}->{$e->{NAME}}; $self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);"); - my $val = "PyList_Size($py_var)"; + my $val = "PyList_GET_SIZE($py_var)"; if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") { $self->pidl("r->in.$e->{NAME} = talloc_ptrtype(r, r->in.$e->{NAME});"); $self->pidl("*r->in.$e->{NAME} = $val;"); @@ -530,22 +539,13 @@ sub PythonFunction($$$) my $fnname = "py_$fn->{NAME}"; my $docstring = $self->DocString($fn, $fn->{NAME}); - my ($insignature, $outsignature); - my ($infn, $outfn); - - if (has_property($fn, "todo")) { - unless ($docstring) { $docstring = "NULL"; } - $infn = "NULL"; - $outfn = "NULL"; + my ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname); + my ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname); + my $signature = "S.$prettyname($insignature) -> $outsignature"; + if ($docstring) { + $docstring = "\"$signature\\n\\n\"$docstring"; } else { - ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname); - ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname); - my $signature = "S.$prettyname($insignature) -> $outsignature"; - if ($docstring) { - $docstring = "\"$signature\\n\\n\"$docstring"; - } else { - $docstring = "\"$signature\""; - } + $docstring = "\"$signature\""; } return ($infn, $outfn, $docstring); @@ -663,8 +663,18 @@ sub Interface($$$) my @fns = (); foreach my $d (@{$interface->{FUNCTIONS}}) { - next if not defined($d->{OPNUM}); + next if has_property($d, "noopnum"); 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}; @@ -673,14 +683,14 @@ sub Interface($$$) my ($infn, $outfn, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname); - push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}", $prettyname, $fndocstring, $d->{OPNUM}]); + push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}_r", $prettyname, $fndocstring, $d->{OPNUM}]); } $self->pidl("const struct PyNdrRpcMethodDef py_ndr_$interface->{NAME}\_methods[] = {"); $self->indent; foreach my $d (@fns) { my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d; - $self->pidl("{ \"$prettyname\", $docstring, (dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },"); + $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->deindent; @@ -711,12 +721,13 @@ sub Interface($$$) $docstring = $signature; } - $self->pidl("static PyTypeObject $interface->{NAME}_InterfaceType = {"); + my $if_typename = "$interface->{NAME}_InterfaceType"; + + $self->pidl("static PyTypeObject $if_typename = {"); $self->indent; $self->pidl("PyObject_HEAD_INIT(NULL) 0,"); $self->pidl(".tp_name = \"$basename.$interface->{NAME}\","); $self->pidl(".tp_basicsize = sizeof(dcerpc_InterfaceObject),"); - $self->pidl(".tp_base = &dcerpc_InterfaceType,"); $self->pidl(".tp_doc = $docstring,"); $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,"); $self->pidl(".tp_new = interface_$interface->{NAME}_new,"); @@ -725,8 +736,10 @@ sub Interface($$$) $self->pidl(""); - $self->register_module_typeobject($interface->{NAME}, "&$interface->{NAME}_InterfaceType"); - $self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, py_ndr_$interface->{NAME}\_methods))", "\treturn;", ""]); + $self->register_module_typeobject($interface->{NAME}, "&$if_typename"); + my $dcerpc_typename = $self->import_type_variable("samba.dcerpc.base", "ClientConnection"); + $self->register_module_prereadycode(["$if_typename.tp_base = $dcerpc_typename;", ""]); + $self->register_module_postreadycode(["if (!PyInterface_AddNdrRpcMethods(&$if_typename, py_ndr_$interface->{NAME}\_methods))", "\treturn;", ""]); } $self->pidl_hdr("\n"); @@ -743,7 +756,7 @@ sub register_module_typeobject($$$) { my ($self, $name, $py_name) = @_; - $self->register_module_object($name, "(PyObject *)$py_name"); + $self->register_module_object($name, "(PyObject *)(void *)$py_name"); $self->check_ready_type($py_name); @@ -758,9 +771,26 @@ sub check_ready_type($$) sub register_module_import($$) { - my ($self, $basename) = @_; + my ($self, $module_path) = @_; + + my $var_name = $module_path; + $var_name =~ s/\./_/g; + $var_name = "dep_$var_name"; + + $self->{module_imports}->{$var_name} = $module_path; + + return $var_name; +} + +sub import_type_variable($$$) +{ + my ($self, $module, $name) = @_; - push (@{$self->{module_imports}}, $basename) unless (grep(/^$basename$/,@{$self->{module_imports}})); + $self->register_module_import($module); + unless (defined($self->{type_imports}->{$name})) { + $self->{type_imports}->{$name} = $module; + } + return "$name\_Type"; } sub use_type_variable($$) @@ -768,7 +798,7 @@ sub use_type_variable($$) my ($self, $orig_ctype) = @_; # FIXME: Have a global lookup table for types that look different on the # wire than they are named in C? - if ($orig_ctype->{NAME} eq "dom_sid2") { + if ($orig_ctype->{NAME} eq "dom_sid2" or $orig_ctype->{NAME} eq "dom_sid28") { $orig_ctype->{NAME} = "dom_sid"; } my $ctype = resolveType($orig_ctype); @@ -777,11 +807,7 @@ sub use_type_variable($$) } # If this is an external type, make sure we do the right imports. if (($ctype->{BASEFILE} ne $self->{BASENAME})) { - $self->register_module_import($ctype->{BASEFILE}); - unless (defined($self->{type_imports}->{$ctype->{NAME}})) { - $self->{type_imports}->{$ctype->{NAME}} = $ctype->{BASEFILE}; - } - return "$ctype->{NAME}_Type"; + return $self->import_type_variable("samba.dcerpc.$ctype->{BASEFILE}", $ctype->{NAME}); } return "&$ctype->{NAME}_Type"; } @@ -794,11 +820,18 @@ sub register_patch_type_call($$$) } -sub register_module_readycode($$) +sub register_module_prereadycode($$) +{ + my ($self, $code) = @_; + + push (@{$self->{prereadycode}}, @$code); +} + +sub register_module_postreadycode($$) { my ($self, $code) = @_; - push (@{$self->{readycode}}, @$code); + push (@{$self->{postreadycode}}, @$code); } sub register_module_object($$$) @@ -814,7 +847,8 @@ sub assign($$$) if ($dest =~ /^\&/ and $src eq "NULL") { $self->pidl("memset($dest, 0, sizeof(" . get_value_of($dest) . "));"); } elsif ($dest =~ /^\&/) { - $self->pidl("memcpy($dest, $src, sizeof(" . get_value_of($dest) . "));"); + my $destvar = get_value_of($dest); + $self->pidl("$destvar = *$src;"); } else { $self->pidl("$dest = $src;"); } @@ -833,42 +867,103 @@ sub ConvertObjectFromPythonData($$$$$$;$) $actual_ctype = $actual_ctype->{DATA}; } - if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP" or - $actual_ctype->{TYPE} eq "SCALAR" and ( - expandAlias($actual_ctype->{NAME}) =~ /^(u?int[0-9]*|hyper|NTTIME|time_t|NTTIME_hyper|NTTIME_1sec|dlong|udlong|udlongr)$/)) { - $self->pidl("PY_CHECK_TYPE(&PyInt_Type, $cvar, $fail);"); + if ($actual_ctype->{TYPE} eq "ENUM" or $actual_ctype->{TYPE} eq "BITMAP") { + $self->pidl("if (PyLong_Check($cvar)) {"); + $self->indent; + $self->pidl("$target = PyLong_AsLongLong($cvar);"); + $self->deindent; + $self->pidl("} else if (PyInt_Check($cvar)) {"); + $self->indent; $self->pidl("$target = PyInt_AsLong($cvar);"); + $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($fail); + $self->deindent; + $self->pidl("}"); return; } + if ($actual_ctype->{TYPE} eq "SCALAR" ) { + if (expandAlias($actual_ctype->{NAME}) =~ /^(u?int64|hyper|dlong|udlong|udlongr|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) { + $self->pidl("if (PyLong_Check($cvar)) {"); + $self->indent; + $self->pidl("$target = PyLong_AsLongLong($cvar);"); + $self->deindent; + $self->pidl("} else if (PyInt_Check($cvar)) {"); + $self->indent; + $self->pidl("$target = PyInt_AsLong($cvar);"); + $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($fail); + $self->deindent; + $self->pidl("}"); + return; + } + 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; + } + } if ($actual_ctype->{TYPE} eq "STRUCT" or $actual_ctype->{TYPE} eq "INTERFACE") { 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) . " to Python\");"); + $self->pidl("PyErr_SetString(PyExc_TypeError, \"Can not convert C Type " . mapTypeName($ctype) . " from Python\");"); return; } $self->pidl("PY_CHECK_TYPE($ctype_name, $cvar, $fail);"); - $self->assign($target, "py_talloc_get_ptr($cvar)"); + $self->pidl("if (talloc_reference($mem_ctx, py_talloc_get_mem_ctx($cvar)) == NULL) {"); + $self->indent; + $self->pidl("PyErr_NoMemory();"); + $self->pidl("$fail"); + $self->deindent; + $self->pidl("}"); + $self->assign($target, "(".mapTypeName($ctype)." *)py_talloc_get_ptr($cvar)"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "DATA_BLOB") { - $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AsString($cvar), PyString_Size($cvar));"); + $self->pidl("$target = data_blob_talloc($mem_ctx, PyString_AS_STRING($cvar), PyString_GET_SIZE($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and ($actual_ctype->{NAME} eq "string" or $actual_ctype->{NAME} eq "nbt_string" or $actual_ctype->{NAME} eq "nbt_name" or $actual_ctype->{NAME} eq "wrepl_nbt_name")) { - $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AsString($cvar));"); + $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));"); + return; + } + + if ($actual_ctype->{TYPE} eq "SCALAR" and ($actual_ctype->{NAME} eq "dns_string" or $actual_ctype->{NAME} eq "dns_name")) { + $self->pidl("$target = talloc_strdup($mem_ctx, PyString_AS_STRING($cvar));"); return; } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv4address") { + $self->pidl("$target = PyString_AS_STRING($cvar);"); + return; + } + + if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "ipv6address") { $self->pidl("$target = PyString_AsString($cvar);"); return; - } + } + if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_name") { + $self->pidl("$target = PyString_AS_STRING($cvar);"); + return; + } + + if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "dnsp_string") { + $self->pidl("$target = PyString_AS_STRING($cvar);"); + return; + } if ($actual_ctype->{TYPE} eq "SCALAR" and $actual_ctype->{NAME} eq "NTSTATUS") { $self->pidl("$target = NT_STATUS(PyInt_AsLong($cvar));"); @@ -898,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; @@ -912,22 +1010,45 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) $self->pidl("} else {"); $self->indent; } - $self->pidl("$var_name = talloc_ptrtype($mem_ctx, $var_name);"); - $self->ConvertObjectFromPythonLevel($env, $mem_ctx, $py_var, $e, $nl, get_value_of($var_name), $fail); + # 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") { + $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;"); + } + 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); } if (is_charset_array($e, $l)) { - $self->pidl("PY_CHECK_TYPE(&PyUnicode_Type, $py_var, $fail);"); + $self->pidl("if (PyUnicode_Check($py_var)) {"); + $self->indent; # FIXME: Use Unix charset setting rather than utf-8 - $self->pidl($var_name . " = PyString_AsString(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));"); + $self->pidl($var_name . " = PyString_AS_STRING(PyUnicode_AsEncodedString($py_var, \"utf-8\", \"ignore\"));"); + $self->deindent; + $self->pidl("} else if (PyString_Check($py_var)) {"); + $self->indent; + $self->pidl($var_name . " = PyString_AS_STRING($py_var);"); + $self->deindent; + $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->deindent; + $self->pidl("}"); } else { my $counter = "$e->{NAME}_cntr_$l->{LEVEL_INDEX}"; $self->pidl("PY_CHECK_TYPE(&PyList_Type, $py_var, $fail);"); @@ -935,18 +1056,19 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) $self->indent; $self->pidl("int $counter;"); if (ArrayDynamicallyAllocated($e, $l)) { - $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_Size($py_var));"); + $self->pidl("$var_name = talloc_array_ptrtype($mem_ctx, $var_name, PyList_GET_SIZE($py_var));"); + $self->pidl("if (!$var_name) { $fail; }"); + $self->pidl("talloc_set_name_const($var_name, \"ARRAY: $var_name\");"); } - $self->pidl("for ($counter = 0; $counter < PyList_Size($py_var); $counter++) {"); + $self->pidl("for ($counter = 0; $counter < PyList_GET_SIZE($py_var); $counter++) {"); $self->indent; - $self->ConvertObjectFromPythonLevel($env, $var_name, "PyList_GetItem($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; $self->pidl("}"); } } elsif ($l->{TYPE} eq "DATA") { - if (not Parse::Pidl::Typelist::is_scalar($l->{DATA_TYPE})) { $var_name = get_pointer_to($var_name); } @@ -954,9 +1076,18 @@ sub ConvertObjectFromPythonLevel($$$$$$$$) } elsif ($l->{TYPE} eq "SWITCH") { $var_name = get_pointer_to($var_name); my $switch = ParseExpr($l->{SWITCH_IS}, $env, $e); - $self->assign($var_name, "py_export_" . GetNextLevel($e, $l)->{DATA_TYPE} . "($mem_ctx, $switch, $py_var)"); + my $switch_ptr = "$e->{NAME}_switch_$l->{LEVEL_INDEX}"; + $self->pidl("{"); + $self->indent; + my $union_type = mapTypeName($nl->{DATA_TYPE}); + $self->pidl("$union_type *$switch_ptr;"); + $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}"); } @@ -977,7 +1108,11 @@ sub ConvertScalarToPython($$$) $ctypename = expandAlias($ctypename); - if ($ctypename =~ /^(char|u?int[0-9]*|hyper|dlong|udlong|udlongr|time_t|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) { + if ($ctypename =~ /^(u?int64|hyper|dlong|udlong|udlongr|NTTIME_hyper|NTTIME|NTTIME_1sec)$/) { + return "PyLong_FromLongLong($cvar)"; + } + + if ($ctypename =~ /^(char|u?int[0-9]*|time_t|uid_t|gid_t)$/) { return "PyInt_FromLong($cvar)"; } @@ -994,12 +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($cvar)"; + return "PyString_FromStringOrNULL($cvar)"; + } + + if (($ctypename eq "dns_string" or $ctypename eq "dns_name")) { + return "PyString_FromStringOrNULL($cvar)"; } # Not yet supported if ($ctypename eq "string_array") { return "PyCObject_FromTallocPtr($cvar)"; } - if ($ctypename eq "ipv4address") { return "PyString_FromString($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)"; } @@ -1054,34 +1196,50 @@ 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; $self->pidl("$py_var = Py_None;"); + $self->pidl("Py_INCREF($py_var);"); $self->deindent; $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); } if (is_charset_array($e, $l)) { # FIXME: Use Unix charset setting rather than utf-8 + $self->pidl("if ($var_name == NULL) {"); + $self->indent; + $self->pidl("$py_var = Py_None;"); + $self->pidl("Py_INCREF($py_var);"); + $self->deindent; + $self->pidl("} else {"); + $self->indent; $self->pidl("$py_var = PyUnicode_Decode($var_name, strlen($var_name), \"utf-8\", \"ignore\");"); + $self->deindent; + $self->pidl("}"); } else { die("No SIZE_IS for array $var_name") unless (defined($l->{SIZE_IS})); my $length = $l->{SIZE_IS}; @@ -1100,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("}"); @@ -1110,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") { @@ -1120,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"); } @@ -1141,18 +1299,14 @@ sub Parse($$$$$) $self->pidl_hdr(" /* Python wrapper functions auto-generated by pidl */ -#include \"includes.h\" #include <Python.h> -#include \"librpc/rpc/dcerpc.h\" -#include \"lib/talloc/pytalloc.h\" +#include \"includes.h\" +#include <pytalloc.h> #include \"librpc/rpc/pyrpc.h\" +#include \"librpc/rpc/pyrpc_util.h\" #include \"$hdr\" #include \"$ndr_hdr\" -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None -#endif - "); foreach my $x (@$ndr) { @@ -1173,38 +1327,46 @@ sub Parse($$$$$) $self->pidl(""); + $self->pidl_hdr("void init$basename(void);"); $self->pidl("void init$basename(void)"); $self->pidl("{"); $self->indent; $self->pidl("PyObject *m;"); - foreach (@{$self->{module_imports}}) { - $self->pidl("PyObject *dep_$_;"); + foreach (keys %{$self->{module_imports}}) { + $self->pidl("PyObject *$_;"); } $self->pidl(""); - foreach (@{$self->{module_imports}}) { - $self->pidl("dep_$_ = PyImport_ImportModule(\"samba.dcerpc.$_\");"); - $self->pidl("if (dep_$_ == NULL)"); + foreach (keys %{$self->{module_imports}}) { + my $var_name = $_; + my $module_path = $self->{module_imports}->{$var_name}; + $self->pidl("$var_name = PyImport_ImportModule(\"$module_path\");"); + $self->pidl("if ($var_name == NULL)"); $self->pidl("\treturn;"); $self->pidl(""); } foreach (keys %{$self->{type_imports}}) { - my $basefile = $self->{type_imports}->{$_}; - $self->pidl_hdr("static PyTypeObject *$_\_Type;\n"); - my $pretty_name = PrettifyTypeName($_, $basefile); - $self->pidl("$_\_Type = (PyTypeObject *)PyObject_GetAttrString(dep_$basefile, \"$pretty_name\");"); - $self->pidl("if ($_\_Type == NULL)"); + my $type_var = "$_\_Type"; + my $module_path = $self->{type_imports}->{$_}; + $self->pidl_hdr("static PyTypeObject *$type_var;\n"); + my $pretty_name = PrettifyTypeName($_, $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;"); $self->pidl(""); } + $self->pidl($_) foreach (@{$self->{prereadycode}}); + foreach (@{$self->{ready_types}}) { $self->pidl("if (PyType_Ready($_) < 0)"); $self->pidl("\treturn;"); } - $self->pidl($_) foreach (@{$self->{readycode}}); + $self->pidl($_) foreach (@{$self->{postreadycode}}); foreach (@{$self->{patch_type_calls}}) { my ($typename, $cvar) = @$_; diff --git a/pidl/lib/Parse/Pidl/Typelist.pm b/pidl/lib/Parse/Pidl/Typelist.pm index ca5ea0cfd2..4f26a92ed2 100644 --- a/pidl/lib/Parse/Pidl/Typelist.pm +++ b/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'; @@ -20,8 +20,14 @@ use strict; my %types = (); my @reference_scalars = ( - "string", "string_array", "nbt_string", - "wrepl_nbt_name", "ipv4address" + "string", "string_array", "nbt_string", "dns_string", + "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 @@ -36,6 +42,8 @@ my %scalars = ( "uint1632" => "uint16_t", "int32" => "int32_t", "uint32" => "uint32_t", + "int3264" => "int32_t", + "uint3264" => "uint32_t", "hyper" => "uint64_t", "dlong" => "int64_t", "udlong" => "uint64_t", @@ -46,15 +54,21 @@ 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", "WERROR" => "WERROR", "NTSTATUS" => "NTSTATUS", "COMRESULT" => "COMRESULT", + "dns_string" => "const char *", "nbt_string" => "const char *", "wrepl_nbt_name"=> "struct nbt_name *", "ipv4address" => "const char *", + "ipv6address" => "const char *", + "dnsp_name" => "const char *", + "dnsp_string" => "const char *", ); my %aliases = ( @@ -122,16 +136,19 @@ sub getType($) return $types{$t}; } +sub typeIs($$); sub typeIs($$) { my ($t,$tt) = @_; - + if (ref($t) eq "HASH") { + return 1 if ($t->{TYPE} eq "TYPEDEF" and $t->{DATA}->{TYPE} eq $tt); return 1 if ($t->{TYPE} eq $tt); return 0; } - return 1 if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF" and - getType($t)->{DATA}->{TYPE} eq $tt); + if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF") { + return typeIs(getType($t)->{DATA}, $tt); + } return 0; } @@ -179,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; @@ -265,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}"); } @@ -303,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/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm b/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm index 5c37b4a0c4..1dec647d87 100644 --- a/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm +++ b/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm @@ -110,6 +110,7 @@ use strict; use Parse::Pidl qw(fatal warning error); use Parse::Pidl::Util qw(has_property); +use Parse::Pidl::Typelist qw(addType); sub handle_type($$$$$$$$$$) { @@ -149,6 +150,17 @@ sub handle_type($$$$$$$$$$) VALSSTRING => $valsstring, ALIGNMENT => $alignment }; + + addType({ + NAME => $name, + TYPE => "CONFORMANCE", + BASEFILE => "conformance file", + DATA => { + NAME => $name, + TYPE => "CONFORMANCE", + ALIGN => $alignment + } + }); } sub handle_tfs($$$$$) diff --git a/pidl/lib/Parse/Pidl/Wireshark/NDR.pm b/pidl/lib/Parse/Pidl/Wireshark/NDR.pm index a9ad555cca..64b8dcf18c 100644 --- a/pidl/lib/Parse/Pidl/Wireshark/NDR.pm +++ b/pidl/lib/Parse/Pidl/Wireshark/NDR.pm @@ -1,5 +1,5 @@ ################################################## -# Samba4 NDR parser generator for IDL structures +# Wireshark NDR parser generator for IDL structures # Copyright tridge@samba.org 2000-2003 # Copyright tpot@samba.org 2001,2005 # Copyright jelmer@samba.org 2004-2007 @@ -545,6 +545,9 @@ sub Struct($$$$) $self->indent; $self->pidl_code("proto_item *item = NULL;"); $self->pidl_code("proto_tree *tree = NULL;"); + if ($e->{ALIGN} > 1) { + $self->pidl_code("dcerpc_info *di = pinfo->private_data;"); + } $self->pidl_code("int old_offset;"); $self->pidl_code(""); @@ -565,6 +568,15 @@ sub Struct($$$$) $self->pidl_code("\n$res"); $self->pidl_code("proto_item_set_len(item, offset-old_offset);\n"); + if ($e->{ALIGN} > 1) { + $self->pidl_code(""); + $self->pidl_code("if (di->call_data->flags & DCERPC_IS_NDR64) {"); + $self->indent; + $self->pidl_code("ALIGN_TO_$e->{ALIGN}_BYTES;"); + $self->deindent; + $self->pidl_code("}"); + } + $self->pidl_code(""); $self->pidl_code("return offset;"); $self->deindent; $self->pidl_code("}\n"); @@ -634,6 +646,8 @@ sub Union($$$$) $self->pidl_code("switch(level) {$res\t}"); $self->pidl_code("proto_item_set_len(item, offset-old_offset);\n"); + $self->pidl_code(""); + $self->pidl_code("return offset;"); $self->deindent; $self->pidl_code("}"); @@ -872,10 +886,10 @@ sub Initialize($$) $self->register_type("dlong", "offset = dissect_ndr_duint32(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);","FT_INT64", "BASE_DEC", 0, "NULL", 8); $self->register_type("GUID", "offset = dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, \@HF\@, NULL);","FT_GUID", "BASE_NONE", 0, "NULL", 4); $self->register_type("policy_handle", "offset = PIDL_dissect_policy_hnd(tvb, offset, pinfo, tree, drep, \@HF\@, \@PARAM\@);","FT_BYTES", "BASE_NONE", 0, "NULL", 4); - $self->register_type("NTTIME", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);","FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4); - $self->register_type("NTTIME_hyper", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);","FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4); - $self->register_type("time_t", "offset = dissect_ndr_time_t(tvb, offset, pinfo,tree, drep, \@HF\@, NULL);","FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4); - $self->register_type("NTTIME_1sec", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, drep, \@HF\@);", "FT_ABSOLUTE_TIME", "BASE_NONE", 0, "NULL", 4); + $self->register_type("NTTIME", "offset = dissect_ndr_nt_NTTIME(tvb, offset, pinfo, tree, 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, 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, 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, drep, \@HF\@);", "FT_ABSOLUTE_TIME", "ABSOLUTE_TIME_LOCAL", 0, "NULL", 4); $self->register_type("SID", " dcerpc_info *di = (dcerpc_info *)pinfo->private_data; @@ -895,7 +909,7 @@ sub Initialize($$) sub Parse($$$$$) { my($self,$ndr,$idl_file,$h_filename,$cnf_file) = @_; - + $self->Initialize($cnf_file); return (undef, undef) if defined($self->{conformance}->{noemit_dissector}); diff --git a/pidl/lib/wscript_build b/pidl/lib/wscript_build new file mode 100644 index 0000000000..eb5f1e0c37 --- /dev/null +++ b/pidl/lib/wscript_build @@ -0,0 +1,4 @@ +#!/usr/bin/env python + +# install the pidl modules +bld.INSTALL_WILDCARD('${DATAROOTDIR}/perl5', '**/*.pm', flat=False) @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/env perl ################################################### # package to parse IDL files and generate code for @@ -653,7 +653,18 @@ sub process_file($) $pidl = Parse::Pidl::ODL::ODL2IDL($pidl, dirname($idl_file), \@opt_incdirs); - if (defined($opt_ws_parser) or + if (defined($opt_ws_parser)) { + require Parse::Pidl::Wireshark::NDR; + + my $cnffile = $idl_file; + $cnffile =~ s/\.idl$/\.cnf/; + + my $generator = new Parse::Pidl::Wireshark::NDR(); + $generator->Initialize($cnffile); + } + + + if (defined($opt_ws_parser) or defined($opt_client) or defined($opt_server) or defined($opt_header) or @@ -681,13 +692,15 @@ sub process_file($) } my $h_filename = "$outputdir/ndr_$basename.h"; - if (defined($opt_client)) { + my $c_header = "$outputdir/ndr_$basename\_c.h"; + if (defined($opt_client) or defined($opt_samba3_ndr_client)) { require Parse::Pidl::Samba4::NDR::Client; my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c"); - my ($c_header) = $c_client; + $c_header = $c_client; $c_header =~ s/\.c$/.h/; - my ($srcd,$hdrd) = Parse::Pidl::Samba4::NDR::Client::Parse( + my $generator = new Parse::Pidl::Samba4::NDR::Client(); + my ($srcd,$hdrd) = $generator->Parse( $ndr,$gen_header,$h_filename,$c_header); FileSave($c_client, $srcd); @@ -760,7 +773,7 @@ sub process_file($) my $header = $client; $header =~ s/\.c$/\.h/; require Parse::Pidl::Samba3::ClientNDR; my $generator = new Parse::Pidl::Samba3::ClientNDR(); - my ($c_code,$h_code) = $generator->Parse($ndr, $header, $h_filename); + my ($c_code,$h_code) = $generator->Parse($ndr, $header, $c_header); FileSave($client, $c_code); FileSave($header, $h_code); } diff --git a/pidl/tests/Util.pm b/pidl/tests/Util.pm index ff876ec039..63949eb5a3 100644 --- a/pidl/tests/Util.pm +++ b/pidl/tests/Util.pm @@ -76,7 +76,6 @@ SKIP: { } my $main = " -#define uint_t unsigned int #include <stdint.h> #include <stdlib.h> #include <stdio.h> diff --git a/pidl/tests/ndr.pl b/pidl/tests/ndr.pl index 53b8cb89e3..b6fd4899b0 100755 --- a/pidl/tests/ndr.pl +++ b/pidl/tests/ndr.pl @@ -22,7 +22,7 @@ my $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { 'IS_DEFERRED' => 0, 'LEVEL_INDEX' => 0, @@ -33,7 +33,7 @@ is_deeply(GetElementLevelTable($e, "unique"), [ } ]); -my $ne = ParseElement($e, "unique"); +my $ne = ParseElement($e, "unique", 0); is($ne->{ORIGINAL}, $e); is($ne->{NAME}, "v"); is($ne->{ALIGN}, 1); @@ -60,7 +60,7 @@ $e = { 'TYPE' => 'uint8', 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -90,7 +90,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -128,7 +128,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -158,7 +158,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -204,7 +204,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "ref"), [ +is_deeply(GetElementLevelTable($e, "ref", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -250,7 +250,7 @@ $e = { 'PARENT' => { TYPE => 'FUNCTION' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -280,7 +280,7 @@ $e = { 'PARENT' => { TYPE => 'FUNCTION' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -326,7 +326,7 @@ $e = { 'PARENT' => { TYPE => 'FUNCTION' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "unique"), [ +is_deeply(GetElementLevelTable($e, "unique", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -372,7 +372,7 @@ $e = { 'PARENT' => { TYPE => 'FUNCTION' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "ref"), [ +is_deeply(GetElementLevelTable($e, "ref", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -418,7 +418,7 @@ $e = { 'PARENT' => { TYPE => 'FUNCTION' }, 'LINE' => 42 }; -is_deeply(GetElementLevelTable($e, "ref"), [ +is_deeply(GetElementLevelTable($e, "ref", 0), [ { LEVEL_INDEX => 0, IS_DEFERRED => 0, @@ -463,7 +463,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -$ne = ParseElement($e, undef); +$ne = ParseElement($e, undef, 0); is($ne->{REPRESENTATION_TYPE}, "bar"); # representation_type @@ -476,7 +476,7 @@ $e = { 'PARENT' => { TYPE => 'STRUCT' }, 'LINE' => 42 }; -$ne = ParseElement($e, undef); +$ne = ParseElement($e, undef, 0); is($ne->{REPRESENTATION_TYPE}, "uint8"); is(align_type("hyper"), 8); @@ -521,7 +521,7 @@ $t = { }, ALIGN => undef }; -is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); +is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t); $t = { TYPE => "UNION", @@ -530,12 +530,14 @@ $t = { ELEMENTS => undef, PROPERTIES => undef, HAS_DEFAULT => 0, + IS_MS_UNION => 0, ORIGINAL => { TYPE => "UNION", NAME => "foo" - } + }, + ALIGN => undef }; -is_deeply(ParseType($t->{ORIGINAL}, "ref"), $t); +is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t); ok(not can_contain_deferred("uint32")); ok(can_contain_deferred("some_unknown_type")); @@ -552,8 +554,8 @@ ok(not can_contain_deferred({ TYPE => "TYPEDEF", ok(can_contain_deferred({ TYPE => "STRUCT", ELEMENTS => [ { TYPE => "someunknowntype" } ]})); # Make sure the elements for a enum without body aren't filled in -ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref")->{ELEMENTS})); +ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref", 0)->{ELEMENTS})); # Make sure the elements for a bitmap without body aren't filled in -ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref")->{ELEMENTS})); +ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref", 0)->{ELEMENTS})); # Make sure the elements for a union without body aren't filled in -ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref")->{ELEMENTS})); +ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref", 0)->{ELEMENTS})); diff --git a/pidl/tests/ndr_string.pl b/pidl/tests/ndr_string.pl index 7b76c7b295..8e8b8ecbad 100755 --- a/pidl/tests/ndr_string.pl +++ b/pidl/tests/ndr_string.pl @@ -14,8 +14,7 @@ test_samba4_ndr("string-pull-empty", ' uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 }; DATA_BLOB b = { data, 4 }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; r.in.data = NULL; @@ -37,8 +36,7 @@ test_samba4_ndr("string-ascii-pull", uint8_t data[] = { 0x03, 0x00, 0x00, 0x00, \'f\', \'o\', \'o\', 0 }; DATA_BLOB b = { data, 8 }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; r.in.data = NULL; @@ -74,8 +72,7 @@ test_samba4_ndr("string-wchar-fixed-array-01", 0x02, 0x00, 0x00, 0x00 }; DATA_BLOB b = { data, sizeof(data) }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; struct TestStringStruct str; r.in.str = &str; @@ -120,8 +117,7 @@ test_samba4_ndr("string-wchar-fixed-array-02", 0x02, 0x00, 0x00, 0x00 }; DATA_BLOB b = { data, sizeof(data) }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; struct TestStringStruct str; r.in.str = &str; @@ -152,8 +148,7 @@ test_samba4_ndr("string-wchar-fixed-array-03", 0x02, 0x00, 0x00, 0x00 }; DATA_BLOB b = { data, sizeof(data) }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; struct TestStringStruct str; r.in.str = &str; @@ -174,8 +169,7 @@ test_samba4_ndr("string-out", uint8_t data[] = { 0x03, 0x00, 0x00, 0x00, \'f\', \'o\', \'o\', 0 }; DATA_BLOB b = { data, 8 }; - struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, - smb_iconv_convenience_init(NULL, "ASCII", "UTF8", true)); + struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL); struct TestString r; char *str = NULL; r.out.data = &str; diff --git a/pidl/tests/parse_idl.pl b/pidl/tests/parse_idl.pl index e06526dd1e..14138a37b8 100755 --- a/pidl/tests/parse_idl.pl +++ b/pidl/tests/parse_idl.pl @@ -158,6 +158,7 @@ is_deeply($x, [ { 'DATA' => [ { 'TYPE' => 'TYPEDEF', 'NAME' => 'y', + 'POINTERS' => 0, 'DATA' => { 'TYPE' => 'STRUCT', 'NAME' => 'x', @@ -180,6 +181,7 @@ is_deeply($x, [ { 'DATA' => [ { 'TYPE' => 'TYPEDEF', 'NAME' => 'y', + 'POINTERS' => 0, 'DATA' => { 'TYPE' => 'STRUCT', 'ELEMENTS' => [], @@ -202,6 +204,7 @@ is_deeply($x, [ { 'DATA' => [ { 'TYPE' => 'TYPEDEF', 'NAME' => 'y', + 'POINTERS' => 0, 'DATA' => { 'TYPE' => 'BITMAP', 'NAME' => 'x', @@ -225,6 +228,7 @@ is_deeply($x, [ { 'DATA' => [ { 'TYPE' => 'TYPEDEF', 'NAME' => 'y', + 'POINTERS' => 0, 'DATA' => { 'TYPE' => 'UNION', 'NAME' => 'x', diff --git a/pidl/tests/samba-ndr.pl b/pidl/tests/samba-ndr.pl index 5c9c6afd85..e257817809 100755 --- a/pidl/tests/samba-ndr.pl +++ b/pidl/tests/samba-ndr.pl @@ -223,6 +223,7 @@ $generator->ParseStructPush({ ELEMENTS => [ ]}, "ndr", "x"); is($generator->{res}, "if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); } if (ndr_flags & NDR_BUFFERS) { } @@ -248,6 +249,7 @@ is($generator->{res}, "if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, ndr_string_array_size(ndr, x->el1))); NDR_CHECK(ndr_push_align(ndr, 4)); NDR_CHECK(ndr_push_mytype(ndr, NDR_SCALARS, &x->el1)); + NDR_CHECK(ndr_push_trailer_align(ndr, 4)); } if (ndr_flags & NDR_BUFFERS) { } diff --git a/pidl/tests/samba3-cli.pl b/pidl/tests/samba3-cli.pl index 0d283a2d5a..c758ef4542 100755 --- a/pidl/tests/samba3-cli.pl +++ b/pidl/tests/samba3-cli.pl @@ -4,12 +4,12 @@ use strict; use warnings; -use Test::More tests => 9; +use Test::More tests => 8; use FindBin qw($RealBin); use lib "$RealBin"; use Util; use Parse::Pidl::Util qw(MyDumper); -use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction ParseOutputArgument); +use Parse::Pidl::Samba3::ClientNDR qw(ParseFunction); use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv); # Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work @@ -31,10 +31,7 @@ $fn = { NAME => "bar", ELEMENTS => [ ] }; $x->ParseFunction("foo", $fn); is($x->{res}, "struct rpccli_bar_state { - struct bar orig; - struct bar tmp; TALLOC_CTX *out_mem_ctx; - NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx); }; static void rpccli_bar_done(struct tevent_req *subreq); @@ -53,23 +50,10 @@ struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx, return NULL; } state->out_mem_ctx = NULL; - state->dispatch_recv = cli->dispatch_recv; - /* In parameters */ - - /* Out parameters */ - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_IN_DEBUG(bar, &state->orig); - } - - /* make a temporary copy, that we pass to the dispatch function */ - state->tmp = state->orig; - - subreq = cli->dispatch_send(state, ev, cli, - &ndr_table_foo, - NDR_BAR, - &state->tmp); + subreq = dcerpc_bar_send(state, + ev, + cli->binding_handle); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -92,22 +76,14 @@ static void rpccli_bar_done(struct tevent_req *subreq) mem_ctx = state; } - status = state->dispatch_recv(subreq, mem_ctx); + status = dcerpc_bar_recv(subreq, + mem_ctx); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - /* Copy out parameters */ - - /* Reset temporary structure */ - ZERO_STRUCT(state->tmp); - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_OUT_DEBUG(bar, &state->orig); - } - tevent_req_done(req); } @@ -123,7 +99,7 @@ NTSTATUS rpccli_bar_recv(struct tevent_req *req, return status; } - /* Steal possbile out parameters to the callers context */ + /* Steal possible out parameters to the callers context */ talloc_steal(mem_ctx, state->out_mem_ctx); tevent_req_received(req); @@ -133,37 +109,16 @@ NTSTATUS rpccli_bar_recv(struct tevent_req *req, NTSTATUS rpccli_bar(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx) { -\tstruct bar r; -\tNTSTATUS status; - -\t/* In parameters */ - -\tif (DEBUGLEVEL >= 10) { -\t\tNDR_PRINT_IN_DEBUG(bar, &r); -\t} - - status = cli->dispatch(cli, - mem_ctx, - &ndr_table_foo, - NDR_BAR, - &r); - -\tif (!NT_STATUS_IS_OK(status)) { -\t\treturn status; -\t} - -\tif (DEBUGLEVEL >= 10) { -\t\tNDR_PRINT_OUT_DEBUG(bar, &r); -\t} - -\tif (NT_STATUS_IS_ERR(status)) { -\t\treturn status; -\t} + NTSTATUS status; -\t/* Return variables */ + status = dcerpc_bar(cli->binding_handle, + mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + return status; + } -\t/* Return result */ -\treturn NT_STATUS_OK; + /* Return result */ + return NT_STATUS_OK; } "); @@ -174,10 +129,8 @@ $fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" }; $x->ParseFunction("foo", $fn); is($x->{res}, "struct rpccli_bar_state { - struct bar orig; - struct bar tmp; TALLOC_CTX *out_mem_ctx; - NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx); + WERROR result; }; static void rpccli_bar_done(struct tevent_req *subreq); @@ -196,26 +149,10 @@ struct tevent_req *rpccli_bar_send(TALLOC_CTX *mem_ctx, return NULL; } state->out_mem_ctx = NULL; - state->dispatch_recv = cli->dispatch_recv; - - /* In parameters */ - - /* Out parameters */ - - /* Result */ - ZERO_STRUCT(state->orig.out.result); - if (DEBUGLEVEL >= 10) { - NDR_PRINT_IN_DEBUG(bar, &state->orig); - } - - /* make a temporary copy, that we pass to the dispatch function */ - state->tmp = state->orig; - - subreq = cli->dispatch_send(state, ev, cli, - &ndr_table_foo, - NDR_BAR, - &state->tmp); + subreq = dcerpc_bar_send(state, + ev, + cli->binding_handle); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -238,25 +175,15 @@ static void rpccli_bar_done(struct tevent_req *subreq) mem_ctx = state; } - status = state->dispatch_recv(subreq, mem_ctx); + status = dcerpc_bar_recv(subreq, + mem_ctx, + &state->result); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } - /* Copy out parameters */ - - /* Copy result */ - state->orig.out.result = state->tmp.out.result; - - /* Reset temporary structure */ - ZERO_STRUCT(state->tmp); - - if (DEBUGLEVEL >= 10) { - NDR_PRINT_OUT_DEBUG(bar, &state->orig); - } - tevent_req_done(req); } @@ -273,11 +200,11 @@ NTSTATUS rpccli_bar_recv(struct tevent_req *req, return status; } - /* Steal possbile out parameters to the callers context */ + /* Steal possible out parameters to the callers context */ talloc_steal(mem_ctx, state->out_mem_ctx); /* Return result */ - *result = state->orig.out.result; + *result = state->result; tevent_req_received(req); return NT_STATUS_OK; @@ -287,50 +214,23 @@ NTSTATUS rpccli_bar(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, WERROR *werror) { -\tstruct bar r; -\tNTSTATUS status; - -\t/* In parameters */ - -\tif (DEBUGLEVEL >= 10) { -\t\tNDR_PRINT_IN_DEBUG(bar, &r); -\t} - - status = cli->dispatch(cli, - mem_ctx, - &ndr_table_foo, - NDR_BAR, - &r); - -\tif (!NT_STATUS_IS_OK(status)) { -\t\treturn status; -\t} - -\tif (DEBUGLEVEL >= 10) { -\t\tNDR_PRINT_OUT_DEBUG(bar, &r); -\t} - -\tif (NT_STATUS_IS_ERR(status)) { -\t\treturn status; -\t} + WERROR result; + NTSTATUS status; -\t/* Return variables */ + status = dcerpc_bar(cli->binding_handle, + mem_ctx, + &result); + if (!NT_STATUS_IS_OK(status)) { + return status; + } -\t/* Return result */ -\tif (werror) { -\t\t*werror = r.out.result; -\t} + /* Return result */ + if (werror) { + *werror = result; + } -\treturn werror_to_ntstatus(r.out.result); + return werror_to_ntstatus(result); } "); -$x = new Parse::Pidl::Samba3::ClientNDR(); - -$fn = { NAME => "bar", ELEMENTS => [ ], RETURN_TYPE => "WERROR" }; -my $e = { NAME => "foo", ORIGINAL => { FILE => "f", LINE => -1 }, - LEVELS => [ { TYPE => "ARRAY", SIZE_IS => "mysize" }, { TYPE => "DATA", DATA_TYPE => "int" } ]}; - -$x->ParseOutputArgument($fn, $e); -is($x->{res}, "memcpy(foo, r.out.foo, (mysize) * sizeof(*foo));\n"); diff --git a/pidl/wscript b/pidl/wscript new file mode 100644 index 0000000000..e60ca202f5 --- /dev/null +++ b/pidl/wscript @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +import os, sys, Logs +from samba_utils import MODE_755 + +def set_options(opt): + opt.tool_options('perl') + +def configure(conf): + conf.check_tool('perl') + # 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) + + # yapp is used for building the parser + conf.find_program('yapp', var='YAPP') + conf.find_program('pod2man', var='POD2MAN') + +def build(bld): + bld.INSTALL_FILES('${BINDIR}', 'pidl', chmod=MODE_755) + + bld.RECURSE('lib') + + if not bld.CONFIG_SET('HAVE_PERL_MAKEMAKER'): + return + + pidl_src = ['pidl'] + pidl_src.extend(bld.path.ant_glob('lib/**/*.pm').split()) + + 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') + + blib_bld = os.path.join(bld.srcnode.abspath(bld.env), 'pidl/blib') + + bld.SET_BUILD_GROUP('final') + if 'POD2MAN' in bld.env and bld.env['POD2MAN'] != '': + for src, manpage in pidl_manpages.iteritems(): + bld(rule='${PERL} ${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 + # But we force the developer to use the pidl standalone build + # to regenerate the files. + # TODO: only warn in developer mode and if 'git diff HEAD' + # shows a difference + warn_about_grammar_changes = ('PIDL_BUILD_WARNINGS' in bld.env and ( + bld.IS_NEWER('idl.yp', 'lib/Parse/Pidl/IDL.pm') or + bld.IS_NEWER('expr.yp', 'lib/Parse/Pidl/Expr.pm'))) + + if warn_about_grammar_changes: + Logs.warn(''' +Pidl grammar files have changed. Please use the pidl standalone build +to regenerate them with yapp. + +$ cd ../pidl +$ perl Makefile.PL +$ make lib/Parse/Pidl/IDL.pm lib/Parse/Pidl/Expr.pm +$ 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 +try this to avoid this message: + +$ touch ../pidl/lib/Parse/Pidl/IDL.pm ../pidl/lib/Parse/Pidl/Expr.pm +''') + |