From: Stefan Metzmacher Date: Tue, 5 Oct 2010 18:58:15 +0000 (+0200) Subject: pidl:NDR/Client.pm: generate pipe pull/push functions X-Git-Url: http://git.samba.org/?p=metze%2Fsamba%2Fwip.git;a=commitdiff_plain;h=dea7a94624d3d52985365fe133bfaada559b924f pidl:NDR/Client.pm: generate pipe pull/push functions Signed-off-by: Stefan Metzmacher --- diff --git a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm index 734e86dd1833..8e2e0656f5c2 100644 --- a/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm +++ b/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm @@ -813,6 +813,379 @@ sub ParseFunction($$$) $self->pidl_hdr(""); } +sub ParsePipeCreate($$$) +{ + my ($self, $t, $cname) = @_; + + $self->pidl_both("/* $t->{NAME} */"); + + $self->pidl_hdr("struct $t->{NAME};"); + $self->pidl("struct $t->{NAME} {"); + $self->indent; + $self->pidl("struct dcerpc_pipe_handle_connection *pc;"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + + my $proto = "struct $t->{NAME} *dcerpc_$t->{NAME}\_create(TALLOC_CTX *mem_ctx)"; + + $self->pidl_hdr("$proto;"); + $self->pidl("$proto"); + $self->pidl("{"); + $self->indent; + + $self->pidl("struct $t->{NAME} *p;"); + $self->pidl(""); + + $self->pidl("p = talloc_zero(mem_ctx, struct $t->{NAME});"); + $self->pidl("if (p == NULL) {"); + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + my $cname = "$t->{NAME}_chunk"; + + $self->pidl("/* the pipe is disconnected by default */"); + $self->pidl("p->pc = dcerpc_pipe_handle_connection_create(p,"); + $self->pidl("\t\t\t\"$cname\","); + $self->pidl("\t\t\tsizeof(struct $cname));"); + $self->pidl("if (p->pc == NULL) {"); + $self->indent; + $self->pidl("TALLOC_FREE(p);"); + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("return p;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPush_State($$$) +{ + my ($self, $t, $cname) = @_; + + my $state_str = "struct dcerpc_$cname\_push_state"; + my $done_fn = "dcerpc_$cname\_push_done"; + + $self->pidl("$state_str {"); + $self->indent; + $self->pidl("uint8_t dummy;"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + + $self->pidl("static void $done_fn(struct tevent_req *subreq);"); + $self->pidl(""); +} + +sub ParsePipeChunkPush_Send($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_push_state"; + my $done_fn = "dcerpc_$cname\_push_done"; + my $fn_str = "struct tevent_req *dcerpc_$cname\_push_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 $t->{NAME} *p"; + $fn_args .= ",\n" . $pad . "const struct $cname *chunk"; + + $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(""); + + $self->pidl("subreq = dcerpc_pipe_handle_push_send(state, ev,"); + $self->pidl("\t\t\tp->pc, chunk);"); + $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(""); + + $self->pidl("return req;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPush_Done($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_push_state"; + my $fn_str = "static void dcerpc_$cname\_push_done"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *subreq"; + + $self->pidl("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req ="); + $self->pidl("\ttevent_req_callback_data(subreq,"); + $self->pidl("\tstruct tevent_req);"); + # unused + #$self->pidl("$state_str *state ="); + #$self->pidl("\ttevent_req_data(req,"); + #$self->pidl("\t$state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("status = dcerpc_pipe_handle_push_recv(subreq);"); + $self->pidl("TALLOC_FREE(subreq);"); + $self->pidl("if (tevent_req_nterror(req, status)) {"); + $self->indent; + $self->pidl("return;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("tevent_req_done(req);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPush_Recv($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_push_state"; + my $fn_str = "NTSTATUS dcerpc_$cname\_push_recv"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *req"; + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$state_str *state ="); + $self->pidl("\ttevent_req_data(req,"); + $self->pidl("\t$state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("if (tevent_req_is_nterror(req, &status)) {"); + $self->indent; + $self->pidl("/*"); + $self->pidl(" * We want the tevent_req_data() protection,"); + $self->pidl(" * but don't need 'state', so just pretend we use it"); + $self->pidl(" * in order to avoid compiler warnings."); + $self->pidl(" */"); + $self->pidl("state->dummy = 0;"); + $self->pidl("tevent_req_received(req);"); + $self->pidl("return status;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("tevent_req_received(req);"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPull_State($$$) +{ + my ($self, $t, $cname) = @_; + + my $state_str = "struct dcerpc_$cname\_pull_state"; + my $done_fn = "dcerpc_$cname\_pull_done"; + + $self->pidl("$state_str {"); + $self->indent; + $self->pidl("struct $cname *chunk;"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + + $self->pidl("static void $done_fn(struct tevent_req *subreq);"); + $self->pidl(""); +} + +sub ParsePipeChunkPull_Send($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_pull_state"; + my $done_fn = "dcerpc_$cname\_pull_done"; + my $fn_str = "struct tevent_req *dcerpc_$cname\_pull_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 $t->{NAME} *p"; + + $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->chunk = talloc_zero(state, struct $cname);"); + $self->pidl("if (tevent_req_nomem(state->chunk, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("subreq = dcerpc_pipe_handle_pull_send(state, ev,"); + $self->pidl("\t\t\tp->pc, state->chunk, state->chunk);"); + $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(""); + + $self->pidl("return req;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPull_Done($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_pull_state"; + my $fn_str = "static void dcerpc_$cname\_pull_done"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *subreq"; + + $self->pidl("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req ="); + $self->pidl("\ttevent_req_callback_data(subreq,"); + $self->pidl("\tstruct tevent_req);"); + # unused + #$self->pidl("$state_str *state ="); + #$self->pidl("\ttevent_req_data(req,"); + #$self->pidl("\t$state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + + $self->pidl("status = dcerpc_pipe_handle_pull_recv(subreq);"); + $self->pidl("TALLOC_FREE(subreq);"); + $self->pidl("if (tevent_req_nterror(req, status)) {"); + $self->indent; + $self->pidl("return;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("tevent_req_done(req);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipeChunkPull_Recv($$$) +{ + my ($self, $t, $cname) = @_; + + my $fn_args = ""; + my $state_str = "struct dcerpc_$cname\_pull_state"; + my $fn_str = "NTSTATUS dcerpc_$cname\_pull_recv"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *req"; + $fn_args .= ",\n" . $pad . "TALLOC_CTX *mem_ctx"; + $fn_args .= ",\n" . $pad . "struct $cname **chunk"; + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$state_str *state ="); + $self->pidl("\ttevent_req_data(req,"); + $self->pidl("\t$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("*chunk = talloc_move(mem_ctx, &state->chunk);"); + $self->pidl(""); + + $self->pidl("tevent_req_received(req);"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParsePipe($$) +{ + my ($self, $t) = @_; + + my $pipe = $t; + $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF"); + my $struct = $pipe->{DATA}; + + my $name = "$struct->{NAME}"; + + $self->ParsePipeCreate($t, $name); + + $self->ParsePipeChunkPush_State($t, $name); + $self->ParsePipeChunkPush_Send($t, $name); + $self->ParsePipeChunkPush_Done($t, $name); + $self->ParsePipeChunkPush_Recv($t, $name); + + $self->ParsePipeChunkPull_State($t, $name); + $self->ParsePipeChunkPull_Send($t, $name); + $self->ParsePipeChunkPull_Done($t, $name); + $self->ParsePipeChunkPull_Recv($t, $name); + $self->pidl_both(""); +} + my %done; ##################################################################### @@ -834,6 +1207,13 @@ sub ParseInterface($$) $self->pidl("/* $if->{NAME} - client functions generated by pidl */"); $self->pidl(""); + foreach my $t (reverse @{$if->{TYPES}}) { + next unless Parse::Pidl::Typelist::typeIs($t, "PIPE"); + + $self->ParsePipe($t); + $done{$t->{NAME}} = 1; + } + foreach my $fn (@{$if->{FUNCTIONS}}) { next if defined($done{$fn->{NAME}}); next if has_property($fn, "noopnum");