pidl "";
}
+sub AsyncDispatchWithStruct($$$$$)
+{
+ my ($ev, $mem_ctx, $pipes_struct, $fn, $fail) = @_;
+ my $env = GenerateFunctionOutEnv($fn);
+ my $hasout = 0;
+ foreach (@{$fn->{ELEMENTS}}) {
+ if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
+ }
+
+ pidl "ZERO_STRUCT(r->out);" if ($hasout);
+
+ foreach (@{$fn->{ELEMENTS}}) {
+ my @dir = @{$_->{DIRECTION}};
+ if (grep(/in/, @dir) and grep(/out/, @dir)) {
+ pidl "r->out.$_->{NAME} = r->in.$_->{NAME};";
+ }
+ }
+
+ foreach (@{$fn->{ELEMENTS}}) {
+ my @dir = @{$_->{DIRECTION}};
+ if (grep(/in/, @dir) and grep(/out/, @dir)) {
+ # noop
+ } elsif (grep(/out/, @dir) and not
+ has_property($_, "represent_as")) {
+ AllocOutVar($_, $mem_ctx, "r->out.$_->{NAME}", $env, $fail);
+ }
+ }
+ pidl_hdr "struct tevent_req *_$fn->{NAME}_send(struct tevent_context *$ev, TALLOC_CTX *$mem_ctx, struct pipes_struct *$pipes_struct, struct $fn->{NAME} *r);";
+ pidl "subreq = _$fn->{NAME}_send($ev, $mem_ctx, $pipes_struct, r);";
+ pidl "if (subreq == NULL) {";
+ $fail->();
+ pidl "}";
+ pidl "tevent_req_set_callback(subreq, api_$fn->{NAME}_done, req);";
+}
+
sub CallWithStruct($$$$)
{
my ($pipes_struct, $mem_ctx, $fn, $fail) = @_;
pidl "struct api_$fn->{NAME}_state {";
pidl " struct $fn->{NAME} r;";
pidl " struct pipes_struct *p;";
+ pidl " uint32_t ptr_count;";
pidl " bool ret;";
pidl "};";
+ pidl "static void api_$fn->{NAME}_done(struct tevent_req *subreq);" if (has_property($fn, "async"));
pidl "";
}
pidl "{";
indent;
pidl "struct tevent_req *req;";
+ if (has_property($fn, "async")) {
+ pidl "struct tevent_req *subreq;"
+ } else {
+ pidl "struct ndr_push *push;";
+ }
pidl "struct api_$fn->{NAME}_state *state;";
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 "struct $fn->{NAME} *r;";
pidl "";
pidl "state->p = p;";
pidl "r = &state->r;";
pidl "";
- pidl "pull = ndr_pull_init_blob(&p->in_data.data, r);";
+ pidl "pull = ndr_pull_init_blob(&p->in_data.data, state);";
pidl "if (pull == NULL) {";
pidl " state->ret = false;";
pidl " tevent_req_done(req);";
pidl " tevent_req_done(req);";
pidl " return tevent_req_post(req, ev);";
pidl "}";
+ pidl "state->ptr_count = pull->ptr_count;";
pidl "";
pidl "if (DEBUGLEVEL >= 10) {";
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r);";
pidl "}";
pidl "";
+ if (has_property($fn, "async")) {
+ AsyncDispatchWithStruct("ev", "state", "p", $fn,
+ sub {
+ pidl " state->ret = false;";
+ pidl " tevent_req_done(req);";
+ pidl " return tevent_req_post(req, ev);";
+ }
+ );
+ pidl "return req;";
+ deindent;
+ pidl "}";
+ pidl "";
+ return;
+ }
+
CallWithStruct("p", "state", $fn,
sub {
pidl " state->ret = false;";
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r);";
pidl "}";
pidl "";
- pidl "push = ndr_push_init_ctx(r);";
+ pidl "push = ndr_push_init_ctx(state);";
pidl "if (push == NULL) {";
pidl " state->ret = false;";
pidl " tevent_req_done(req);";
pidl "";
}
+sub ParseFunctionAsyncDone($$)
+{
+ my ($if,$fn) = @_;
+ my $op = "NDR_".uc($fn->{NAME});
+
+ pidl "static void api_$fn->{NAME}_done(struct tevent_req *subreq)";
+ pidl "{";
+ indent;
+ pidl "struct tevent_req *req = tevent_req_callback_data(subreq,";
+ pidl " struct tevent_req);";
+ pidl "struct api_$fn->{NAME}_state *state";
+ pidl " = tevent_req_data(req, struct api_$fn->{NAME}_state);";
+ pidl "const struct ndr_interface_call *call;";
+ pidl "struct ndr_push *push;";
+ pidl "enum ndr_err_code ndr_err;";
+ pidl "";
+ pidl "call = &ndr_table_$if->{NAME}.calls[$op];";
+
+ if ($fn->{RETURN_TYPE}) {
+ pidl "state->r.out.result = _$fn->{NAME}_recv(subreq);";
+ pidl_hdr "$fn->{RETURN_TYPE} _$fn->{NAME}_recv(struct tevent_req *subreq);";
+ } else {
+ pidl "_$fn->{NAME}_recv(subreq);";
+ pidl_hdr "void _$fn->{NAME}_recv(struct tevent_req *subreq);";
+ }
+ pidl "";
+ pidl "if (state->p->fault_state) {";
+ pidl " /* Return true here, srv_pipe_hnd.c will take care */";
+ pidl " state->ret = true;";
+ pidl " tevent_req_done(req);";
+ pidl " return;";
+ pidl "}";
+ pidl "";
+ pidl "if (DEBUGLEVEL >= 10) {";
+ pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, &state->r);";
+ pidl "}";
+ pidl "";
+ pidl "push = ndr_push_init_ctx(state);";
+ pidl "if (push == NULL) {";
+ pidl " state->ret = false;";
+ pidl " tevent_req_done(req);";
+ pidl " return;";
+ 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 = state->ptr_count;";
+ pidl "";
+ pidl "ndr_err = call->ndr_push(push, NDR_OUT, &state->r);";
+ pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
+ pidl " state->ret = false;";
+ pidl " tevent_req_done(req);";
+ pidl " return;";
+ pidl "}";
+ pidl "";
+ pidl "state->p->out_data.rdata = ndr_push_blob(push);";
+ pidl "";
+ pidl "state->ret = true;";
+ pidl "tevent_req_done(req);";
+ pidl "return;";
+ deindent;
+ pidl "}";
+ pidl "";
+}
+
sub ParseFunctionAsyncRecv($$)
{
my ($if,$fn) = @_;
my ($if,$fn) = @_;
ParseFunctionAsyncState($if, $fn);
ParseFunctionAsyncSend($if, $fn);
+ if (has_property($fn, "async")) {
+ ParseFunctionAsyncDone($if, $fn);
+ }
ParseFunctionAsyncRecv($if, $fn);
}