From a7fa0d7063dd8abe5d9cdb3721fe0733983f5310 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 14 Feb 2007 14:23:59 +0000 Subject: r21338: Fix handling of top-level arrays for the Samba 3 client code. This doesn't fix the winreg code yet (as that's an array on top of a pointer), but at least it gets us closer. Also added a couple of tests for the Samba 3 client code. (This used to be commit 4a5b62ad622d7be08591e19bc2e89f665fff445a) --- source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 54 ++++++++++++++++++------ source4/pidl/tests/samba3-cli.pl | 56 +++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 12 deletions(-) create mode 100755 source4/pidl/tests/samba3-cli.pl (limited to 'source4/pidl') diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index ade2711d85..3b596aba65 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -6,18 +6,22 @@ package Parse::Pidl::Samba3::ClientNDR; +use Exporter; +@ISA = qw(Exporter); +@EXPORT_OK = qw(GenerateFunctionInEnv ParseFunction $res $res_hdr); + use strict; use Parse::Pidl qw(fatal warning); use Parse::Pidl::Typelist qw(hasType getType mapType scalar_is_reference); -use Parse::Pidl::Util qw(has_property is_constant); +use Parse::Pidl::Util qw(has_property is_constant ParseExpr); use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred); use Parse::Pidl::Samba4 qw(DeclLong); use vars qw($VERSION); $VERSION = '0.01'; -my $res; -my $res_hdr; +our $res; +our $res_hdr; my $tabs = ""; sub indent() { $tabs.="\t"; } sub deindent() { $tabs = substr($tabs, 1); } @@ -25,13 +29,26 @@ sub pidl($) { $res .= $tabs.(shift)."\n"; } sub pidl_hdr($) { $res_hdr .= (shift)."\n"; } sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; } +sub GenerateFunctionInEnv($) +{ + my $fn = shift; + my %env; + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (grep (/in/, @{$e->{DIRECTION}})) { + $env{$e->{NAME}} = "r.in.$e->{NAME}"; + } + } + + return \%env; +} + sub ParseFunction($$) { - my ($if,$fn) = @_; + my ($uif, $fn) = @_; my $inargs = ""; my $defargs = ""; - my $uif = uc($if->{NAME}); my $ufn = "DCERPC_".uc($fn->{NAME}); foreach (@{$fn->{ELEMENTS}}) { @@ -58,7 +75,7 @@ sub ParseFunction($$) pidl "status = cli_do_rpc_ndr(cli, mem_ctx, PI_$uif, $ufn, &r, (ndr_pull_flags_fn_t)ndr_pull_$fn->{NAME}, (ndr_push_flags_fn_t)ndr_push_$fn->{NAME});"; pidl ""; - pidl "if ( !NT_STATUS_IS_OK(status) ) {"; + pidl "if (!NT_STATUS_IS_OK(status)) {"; indent; pidl "return status;"; deindent; @@ -78,16 +95,29 @@ sub ParseFunction($$) fatal($e, "[out] argument is not a pointer or array") if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY"); - if ( ($e->{LEVELS}[0]->{TYPE} eq "POINTER") && ($e->{LEVELS}[0]->{POINTER_TYPE} eq "unique") ) { + if ( ($e->{LEVELS}[0]->{TYPE} eq "POINTER") and + ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") ) { pidl "if ( $e->{NAME} ) {"; indent; + } + + if ($e->{LEVELS}[0]->{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 $env = GenerateFunctionInEnv($fn); + my $size_is = ParseExpr($e->{LEVELS}[0]->{SIZE_IS}, $env, $e); + pidl "memcpy($e->{NAME}, r.out.$e->{NAME}, $size_is);"; + } else { pidl "*$e->{NAME} = *r.out.$e->{NAME};"; + } + + if ( ($e->{LEVELS}[0]->{TYPE} eq "POINTER") and + ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") ) { deindent; pidl "}"; - } else { - pidl "*$e->{NAME} = *r.out.$e->{NAME};"; } - } pidl""; @@ -99,7 +129,7 @@ sub ParseFunction($$) } elsif ($fn->{RETURN_TYPE} eq "WERROR") { pidl "return werror_to_ntstatus(r.out.result);"; } else { - pidl "/* Sorry, don't know how to convert $fn->{RETURN_TYPE} to NTSTATUS */"; + pidl "#warning Sorry, don't know how to convert $fn->{RETURN_TYPE} to NTSTATUS"; pidl "return NT_STATUS_OK;"; } @@ -116,7 +146,7 @@ sub ParseInterface($) pidl_hdr "#ifndef __CLI_$uif\__"; pidl_hdr "#define __CLI_$uif\__"; - ParseFunction($if, $_) foreach (@{$if->{FUNCTIONS}}); + ParseFunction($if->{NAME}, $_) foreach (@{$if->{FUNCTIONS}}); pidl_hdr "#endif /* __CLI_$uif\__ */"; } diff --git a/source4/pidl/tests/samba3-cli.pl b/source4/pidl/tests/samba3-cli.pl new file mode 100755 index 0000000000..1d1bae8550 --- /dev/null +++ b/source4/pidl/tests/samba3-cli.pl @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# (C) 2007 Jelmer Vernooij +# Published under the GNU General Public License +use strict; +use warnings; + +use Test::More tests => 4; +use FindBin qw($RealBin); +use lib "$RealBin"; +use Util; +use Parse::Pidl::Util qw(MyDumper); +use Parse::Pidl::Samba3::ClientNDR qw(GenerateFunctionInEnv ParseFunction $res + $res_hdr); + +# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work +my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] }; +is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn)); + +$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] }; +is_deeply({ "foo" => "r.in.foo" }, GenerateFunctionInEnv($fn)); + +$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] }; +is_deeply({ }, GenerateFunctionInEnv($fn)); + +$fn = { NAME => "bar", ELEMENTS => [ ] }; +ParseFunction("foo", $fn); +is($res, "NTSTATUS rpccli_bar(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx) +{ +\tstruct bar r; +\tNTSTATUS status; +\t +\t/* In parameters */ +\t +\tif (DEBUGLEVEL >= 10) +\t\tNDR_PRINT_IN_DEBUG(bar, &r); +\t +\tstatus = cli_do_rpc_ndr(cli, mem_ctx, PI_foo, DCERPC_BAR, &r, (ndr_pull_flags_fn_t)ndr_pull_bar, (ndr_push_flags_fn_t)ndr_push_bar); +\t +\tif (!NT_STATUS_IS_OK(status)) { +\t\treturn status; +\t} +\t +\tif (DEBUGLEVEL >= 10) +\t\tNDR_PRINT_OUT_DEBUG(bar, &r); +\t +\tif (NT_STATUS_IS_ERR(status)) { +\t\treturn status; +\t} +\t +\t/* Return variables */ +\t +\t/* Return result */ +\treturn NT_STATUS_OK; +} + +"); -- cgit