pidl: handle hyper attribute for wireshark
[kai/samba-autobuild/.git] / pidl / lib / Parse / Pidl / Samba3 / ClientNDR.pm
index 68579d2c9a9be834a79ec441f5e1da553c21d730..8142b3569991ca84403e0605cfdcbc7dca6f8b0c 100644 (file)
@@ -9,13 +9,15 @@ 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);
+use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
 
 use vars qw($VERSION);
 $VERSION = '0.01';
@@ -71,54 +73,17 @@ sub HeaderProperties($$)
        }
 }
 
-sub ParseOutputArgument($$$;$$)
+sub ParseInvalidResponse($$)
 {
-       my ($self, $fn, $e, $r, $o) = @_;
-       my $level = 0;
-       $r = "r." unless defined($r);
-       $o = "" unless defined($o);
-
-       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;
-               }
-       }
+       my ($self, $type) = @_;
 
-       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 $env = GenerateFunctionInEnv($fn, $r);
-               my $l = $e->{LEVELS}[$level];
-               unless (defined($l->{SIZE_IS})) {
-                       error($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
-                       $self->pidl('#error No size known for [out] array `$e->{NAME}');
-               } else {
-                       my $size_is = ParseExpr($l->{SIZE_IS}, $env, $e->{ORIGINAL});
-                       if (has_property($e, "charset")) {
-                               $self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), ${r}out.$e->{NAME}, ($size_is) * sizeof(*$o$e->{NAME}));");
-                       } else {
-                               $self->pidl("memcpy($o$e->{NAME}, ${r}out.$e->{NAME}, ($size_is) * sizeof(*$o$e->{NAME}));");
-                       }
-               }
+       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 {
-               $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("}");
-               }
+               die("ParseInvalidResponse($type)");
        }
 }
 
@@ -131,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("");
@@ -180,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,");
@@ -218,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);");
@@ -267,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;
@@ -277,24 +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.");
-       }
-       $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("}");
@@ -331,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("");
        }
 
@@ -363,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")) {
@@ -373,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;");
@@ -457,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.");
@@ -475,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) {