pidl: Add simple test for ServerNDR.
[ira/wip.git] / source / pidl / lib / Parse / Pidl / Samba3 / ServerNDR.pm
index 02fd1884a240e88c44e060ee968528ded8410025..ca9e7d15db019f0ef8c3ddb2d27f155fdf39260d 100644 (file)
@@ -6,11 +6,17 @@
 
 package Parse::Pidl::Samba3::ServerNDR;
 
+use Exporter;
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(DeclLevel);
+
 use strict;
-use Parse::Pidl::Typelist qw(hasType getType mapType scalar_is_reference);
-use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
-use Parse::Pidl::NDR qw(GetPrevLevel GetNextLevel ContainsDeferred);
-use Parse::Pidl::Samba4 qw(DeclLong);
+use Parse::Pidl qw(warning fatal);
+use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
+use Parse::Pidl::Util qw(ParseExpr has_property is_constant);
+use Parse::Pidl::NDR qw(GetNextLevel);
+use Parse::Pidl::Samba4 qw(ElementStars DeclLong);
+use Parse::Pidl::Samba4::Header qw(GenerateFunctionOutEnv);
 
 use vars qw($VERSION);
 $VERSION = '0.01';
@@ -20,32 +26,58 @@ my $res_hdr;
 my $tabs = "";
 sub indent() { $tabs.="\t"; }
 sub deindent() { $tabs = substr($tabs, 1); }
-sub pidl($) { $res .= $tabs.(shift)."\n"; }
+sub pidl($) { my ($txt) = @_; $res .= $txt?$tabs.(shift)."\n":"\n"; }
 sub pidl_hdr($) { $res_hdr .= (shift)."\n"; }
-sub fatal($$) { my ($e,$s) = @_; die("$e->{ORIGINAL}->{FILE}:$e->{ORIGINAL}->{LINE}: $s\n"); }
-sub warning($$) { my ($e,$s) = @_; warn("$e->{ORIGINAL}->{FILE}:$e->{ORIGINAL}->{LINE}: $s\n"); }
 sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; }
 
+sub DeclLevel($$)
+{
+       my ($e, $l) = @_;
+       my $res = "";
+
+       if (has_property($e, "charset")) {
+               $res .= "const char";
+       } else {
+               $res .= mapTypeName($e->{TYPE});
+       }
+
+       my $stars = ElementStars($e, $l);
+
+       $res .= " ".$stars unless ($stars eq "");
+
+       return $res;
+}
+
 sub AllocOutVar($$$$)
 {
        my ($e, $mem_ctx, $name, $env) = @_;
 
        my $l = $e->{LEVELS}[0];
 
+       # we skip pointer to arrays
        if ($l->{TYPE} eq "POINTER") {
-               $l = GetNextLevel($e, $l);
+               my $nl = GetNextLevel($e, $l);
+               $l = $nl if ($nl->{TYPE} eq "ARRAY");
        }
 
+       # we don't support multi-dimentional arrays yet
        if ($l->{TYPE} eq "ARRAY") {
-               my $size = ParseExpr($l->{SIZE_IS}, $env);
-               pidl "$name = talloc_zero_size($mem_ctx, sizeof(*$name) * $size);";
+               my $nl = GetNextLevel($e, $l);
+               if ($nl->{TYPE} eq "ARRAY") {
+                       fatal($e->{ORIGINAL},"multi-dimentional [out] arrays are not supported!");
+               }
+       }
+
+       if ($l->{TYPE} eq "ARRAY") {
+               my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
+               pidl "$name = talloc_zero_array($mem_ctx, " . DeclLevel($e, 1) . ", $size);";
        } else {
-               pidl "$name = talloc_zero_size($mem_ctx, sizeof(*$name));";
+               pidl "$name = talloc_zero($mem_ctx, " . DeclLevel($e, 1) . ");";
        }
 
        pidl "if ($name == NULL) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       pidl "\ttalloc_free($mem_ctx);";
+       pidl "\treturn false;";
        pidl "}";
        pidl "";
 }
@@ -54,65 +86,72 @@ sub ParseFunction($$)
 {
        my ($if,$fn) = @_;
 
-       pidl "static BOOL api_$fn->{NAME}(pipes_struct *p)";
+       my $op = "NDR_".uc($fn->{NAME});
+
+       pidl "static bool api_$fn->{NAME}(pipes_struct *p)";
        pidl "{";
        indent;
+       pidl "const struct ndr_interface_call *call;";
        pidl "struct ndr_pull *pull;";
        pidl "struct ndr_push *push;";
-       pidl "NTSTATUS status;";
+       pidl "enum ndr_err_code ndr_err;";
        pidl "DATA_BLOB blob;";
-       pidl "struct $fn->{NAME} r;";
-       pidl "TALLOC_CTX *mem_ctx = talloc_init(\"api_$fn->{NAME}\");";
+       pidl "struct $fn->{NAME} *r;";
+       pidl "";
+       pidl "call = &ndr_table_$if->{NAME}.calls[$op];";
        pidl "";
-       pidl "if (!prs_data_blob(&p->in_data.data, &blob, mem_ctx)) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       pidl "r = talloc(NULL, struct $fn->{NAME});";
+       pidl "if (r == NULL) {";
+       pidl "\treturn false;";
        pidl "}";
        pidl "";
-       pidl "pull = ndr_pull_init_blob(&blob, mem_ctx);";
-       pidl "if (pull == NULL)";
-       pidl "\treturn False;";
+       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);";
+       pidl "if (pull == NULL) {";
+       pidl "\ttalloc_free(r);";
+       pidl "\treturn false;";
+       pidl "}";
        pidl "";
        pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;";
-       pidl "status = ndr_pull_$fn->{NAME}(pull, NDR_IN, &r);";
-       pidl "if (NT_STATUS_IS_ERR(status)) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       pidl "ndr_err = call->ndr_pull(pull, NDR_IN, r);";
+       pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
+       pidl "\ttalloc_free(r);";
+       pidl "\treturn false;";
        pidl "}";
        pidl "";
-       pidl "if (DEBUGLEVEL >= 10)";
-       pidl "\tNDR_PRINT_IN_DEBUG($fn->{NAME}, &r);";
+       pidl "if (DEBUGLEVEL >= 10) {";
+       pidl "\tNDR_PRINT_IN_DEBUG($fn->{NAME}, r);";
+       pidl "}";
        pidl "";
 
-       my %env = ();
+       my $env = GenerateFunctionOutEnv($fn);
        my $hasout = 0;
        foreach (@{$fn->{ELEMENTS}}) {
                if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
-               next unless (grep (/in/, @{$_->{DIRECTION}}));
-               $env{$_->{NAME}} = "r.in.$_->{NAME}";
        }
 
-       pidl "ZERO_STRUCT(r.out);" if ($hasout);
+       pidl "ZERO_STRUCT(r->out);" if ($hasout);
 
-       my $proto = "_$fn->{NAME}(pipes_struct *p";
-       my $ret = "_$fn->{NAME}(p";
+       my $proto = "_$fn->{NAME}(pipes_struct *p, struct $fn->{NAME} *r";
+       my $ret = "_$fn->{NAME}(p, r";
        foreach (@{$fn->{ELEMENTS}}) {
                my @dir = @{$_->{DIRECTION}};
                if (grep(/in/, @dir) and grep(/out/, @dir)) {
-                       pidl "r.out.$_->{NAME} = r.in.$_->{NAME};";
-               } elsif (grep(/out/, @dir)) {
-                       AllocOutVar($_, "mem_ctx", "r.out.$_->{NAME}", \%env);
+                       pidl "r->out.$_->{NAME} = r->in.$_->{NAME};";
+               } elsif (grep(/out/, @dir) and not
+                                has_property($_, "represent_as")) {
+                       AllocOutVar($_, "r", "r->out.$_->{NAME}", $env);
                }
-               if (grep(/in/, @dir)) { $ret .= ", r.in.$_->{NAME}"; }
-               else { $ret .= ", r.out.$_->{NAME}"; }
-
-               $proto .= ", " . DeclLong($_);
        }
        $ret .= ")";
        $proto .= ");";
 
        if ($fn->{RETURN_TYPE}) {
-               $ret = "r.out.result = $ret";
+               $ret = "r->out.result = $ret";
                $proto = "$fn->{RETURN_TYPE} $proto";
        } else {
                $proto = "void $proto";
@@ -122,30 +161,37 @@ sub ParseFunction($$)
        pidl "$ret;";
 
        pidl "";
-       pidl "if (DEBUGLEVEL >= 10)";
-       pidl "\tNDR_PRINT_OUT_DEBUG($fn->{NAME}, &r);";
+       pidl "if (p->rng_fault_state) {";
+       pidl "\ttalloc_free(r);";
+       pidl "\t/* Return true here, srv_pipe_hnd.c will take care */";
+       pidl "\treturn true;";
+       pidl "}";
+       pidl "";
+       pidl "if (DEBUGLEVEL >= 10) {";
+       pidl "\tNDR_PRINT_OUT_DEBUG($fn->{NAME}, r);";
+       pidl "}";
        pidl "";
-       pidl "push = ndr_push_init_ctx(mem_ctx);";
+       pidl "push = ndr_push_init_ctx(r);";
        pidl "if (push == NULL) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       pidl "\ttalloc_free(r);";
+       pidl "\treturn false;";
        pidl "}";
        pidl "";
-       pidl "status = ndr_push_$fn->{NAME}(push, NDR_OUT, &r);";
-       pidl "if (NT_STATUS_IS_ERR(status)) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       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, blob.data, (uint32)blob.length)) {";
-       pidl "\ttalloc_free(mem_ctx);";
-       pidl "\treturn False;";
+       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 "";
-       pidl "talloc_free(mem_ctx);";
+       pidl "talloc_free(r);";
        pidl "";
-       pidl "return True;";
+       pidl "return true;";
        deindent;
        pidl "}";
        pidl "";
@@ -168,7 +214,7 @@ sub ParseInterface($)
        indent;
 
        foreach (@{$if->{FUNCTIONS}}) {
-               pidl "{\"" . uc($_->{NAME}) . "\", DCERPC_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
+               pidl "{\"" . uc($_->{NAME}) . "\", NDR_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
        }
 
        deindent;
@@ -211,7 +257,7 @@ sub Parse($$$)
        pidl "#include \"$header\"";
        pidl_hdr "#include \"$ndr_header\"";
        pidl "";
-       
+
        foreach (@$ndr) {
                ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
        }