11
11
@ISA = qw(Exporter);
12
@EXPORT_OK = qw(ParseFunction $res $res_hdr ParseOutputArgument);
12
@EXPORT_OK = qw(ParseFunction $res $res_hdr);
15
15
use Parse::Pidl qw(fatal warning error);
16
16
use Parse::Pidl::Util qw(has_property ParseExpr);
17
use Parse::Pidl::NDR qw(ContainsPipe);
18
use Parse::Pidl::Typelist qw(mapTypeName);
17
19
use Parse::Pidl::Samba4 qw(DeclLong);
18
20
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
88
sub ParseOutputArgument($$$;$$$)
90
my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_;
92
$r = "r." unless defined($r);
93
$o = "" unless defined($o);
94
$invalid_response_type = "sync" unless defined($invalid_response_type);
96
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") {
97
$self->pidl("return NT_STATUS_NOT_SUPPORTED;");
98
error($e->{ORIGINAL}, "[out] argument is not a pointer or array");
102
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
104
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
105
$self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {");
110
if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") {
111
# This is a call to GenerateFunctionInEnv intentionally.
112
# Since the data is being copied into a user-provided data
113
# structure, the user should be able to know the size beforehand
114
# to allocate a structure of the right size.
115
my $in_env = GenerateFunctionInEnv($fn, $r);
116
my $out_env = GenerateFunctionOutEnv($fn, $r);
117
my $l = $e->{LEVELS}[$level];
118
unless (defined($l->{SIZE_IS})) {
119
$self->pidl('#error No size known for [out] array `$e->{NAME}');
120
error($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
122
my $in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
123
my $out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
124
my $out_length_is = $out_size_is;
125
if (defined($l->{LENGTH_IS})) {
126
$out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
128
if ($out_size_is ne $in_size_is) {
129
$self->pidl("if (($out_size_is) > ($in_size_is)) {");
131
$self->ParseInvalidResponse($invalid_response_type);
135
if ($out_length_is ne $out_size_is) {
136
$self->pidl("if (($out_length_is) > ($out_size_is)) {");
138
$self->ParseInvalidResponse($invalid_response_type);
142
if (has_property($e, "charset")) {
143
$self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));");
145
$self->pidl("memcpy($o$e->{NAME}, ${r}out.$e->{NAME}, ($out_length_is) * sizeof(*$o$e->{NAME}));");
149
$self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};");
152
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
153
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
160
90
sub ParseFunctionAsyncState($$$)
162
92
my ($self, $if, $fn) = @_;
167
97
$self->pidl("$state_str {");
169
$self->pidl("struct $fn->{NAME} orig;");
170
$self->pidl("struct $fn->{NAME} tmp;");
171
99
$self->pidl("TALLOC_CTX *out_mem_ctx;");
172
$self->pidl("NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx);");
100
if (defined($fn->{RETURN_TYPE})) {
101
$self->pidl(mapTypeName($fn->{RETURN_TYPE}). " result;");
174
104
$self->pidl("};");
216
146
$self->pidl("}");
217
147
$self->pidl("state->out_mem_ctx = NULL;");
218
$self->pidl("state->dispatch_recv = cli->dispatch_recv;");
221
$self->pidl("/* In parameters */");
222
foreach (@{$fn->{ELEMENTS}}) {
223
if (grep(/in/, @{$_->{DIRECTION}})) {
224
$self->pidl("state->orig.in.$_->{NAME} = _$_->{NAME};");
229
150
my $out_params = 0;
230
$self->pidl("/* Out parameters */");
231
151
foreach (@{$fn->{ELEMENTS}}) {
232
152
if (grep(/out/, @{$_->{DIRECTION}})) {
233
$self->pidl("state->orig.out.$_->{NAME} = _$_->{NAME};");
239
if (defined($fn->{RETURN_TYPE})) {
240
$self->pidl("/* Result */");
241
$self->pidl("ZERO_STRUCT(state->orig.out.result);");
245
157
if ($out_params > 0) {
246
158
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
256
$self->pidl("/* make a temporary copy, that we pass to the dispatch function */");
257
$self->pidl("state->tmp = state->orig;");
168
$fn_str = "subreq = dcerpc_$fn->{NAME}_send";
169
$pad = "\t" . genpad($fn_str);
170
$fn_args = "state,\n" . $pad . "ev,\n" . $pad . "cli->binding_handle";
171
foreach (@{$fn->{ELEMENTS}}) {
172
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
260
$self->pidl("subreq = cli->dispatch_send(state, ev, cli,");
261
$self->pidl("\t\t\t &ndr_table_$if,");
262
$self->pidl("\t\t\t $ufn,");
263
$self->pidl("\t\t\t &state->tmp);");
175
$self->pidl("$fn_str($fn_args);");
264
176
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
266
178
$self->pidl("return tevent_req_post(req, ev);");
302
214
$self->pidl("}");
305
$self->pidl("status = state->dispatch_recv(subreq, mem_ctx);");
217
my $fn_str = "status = dcerpc_$fn->{NAME}_recv";
218
my $pad = "\t" . genpad($fn_str);
219
my $fn_args = "subreq,\n" . $pad . "mem_ctx";
220
if (defined($fn->{RETURN_TYPE})) {
221
$fn_args .= ",\n" . $pad . "&state->result";
224
$self->pidl("$fn_str($fn_args);");
306
225
$self->pidl("TALLOC_FREE(subreq);");
307
226
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
312
231
$self->pidl("}");
315
$self->pidl("/* Copy out parameters */");
316
foreach my $e (@{$fn->{ELEMENTS}}) {
317
next unless (grep(/out/, @{$e->{DIRECTION}}));
319
$self->ParseOutputArgument($fn, $e,
326
if (defined($fn->{RETURN_TYPE})) {
327
$self->pidl("/* Copy result */");
328
$self->pidl("state->orig.out.result = state->tmp.out.result;");
332
$self->pidl("/* Reset temporary structure */");
333
$self->pidl("ZERO_STRUCT(state->tmp);");
336
234
$self->pidl("tevent_req_done(req);");
338
236
$self->pidl("}");
369
267
$self->pidl("}");
372
$self->pidl("/* Steal possbile out parameters to the callers context */");
270
$self->pidl("/* Steal possible out parameters to the callers context */");
373
271
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
376
274
if (defined($fn->{RETURN_TYPE})) {
377
275
$self->pidl("/* Return result */");
378
$self->pidl("*result = state->orig.out.result;");
276
$self->pidl("*result = state->result;");
401
299
foreach (@{$fn->{ELEMENTS}}) {
402
300
my $dir = ElementDirection($_);
403
301
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
404
$fn_args .= ",\n" . $pad . DeclLong($_) . " /* $dir $prop */";
302
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
407
305
if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) {
411
309
$self->fn_declare("$fn_str($fn_args)");
412
310
$self->pidl("{");
414
$self->pidl("struct $fn->{NAME} r;");
312
if (defined($fn->{RETURN_TYPE})) {
313
$self->pidl(mapTypeName($fn->{RETURN_TYPE})." result;");
415
315
$self->pidl("NTSTATUS status;");
417
$self->pidl("/* In parameters */");
318
$fn_str = "status = dcerpc_$fn->{NAME}";
319
$pad = "\t" . genpad($fn_str);
320
$fn_args = "cli->binding_handle,\n" . $pad . "mem_ctx";
419
321
foreach (@{$fn->{ELEMENTS}}) {
420
if (grep(/in/, @{$_->{DIRECTION}})) {
421
$self->pidl("r.in.$_->{NAME} = $_->{NAME};");
426
$self->pidl("status = cli->dispatch(cli,");
427
$self->pidl("\t\t\tmem_ctx,");
428
$self->pidl("\t\t\t&ndr_table_$if,");
429
$self->pidl("\t\t\t$ufn,");
430
$self->pidl("\t\t\t&r);");
322
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
324
if (defined($fn->{RETURN_TYPE})) {
325
$fn_args .= ",\n" . $pad . "&result";
328
$self->pidl("$fn_str($fn_args);");
433
329
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
435
331
$self->pidl("return status;");
437
333
$self->pidl("}");
440
$self->pidl("if (NT_STATUS_IS_ERR(status)) {");
442
$self->pidl("return status;");
446
$self->pidl("/* Return variables */");
447
foreach my $e (@{$fn->{ELEMENTS}}) {
448
next unless (grep(/out/, @{$e->{DIRECTION}}));
450
$self->ParseOutputArgument($fn, $e);
455
336
$self->pidl("/* Return result */");
456
337
if (not $fn->{RETURN_TYPE}) {
457
338
$self->pidl("return NT_STATUS_OK;");
458
339
} elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") {
459
$self->pidl("return r.out.result;");
340
$self->pidl("return result;");
460
341
} elsif ($fn->{RETURN_TYPE} eq "WERROR") {
461
342
$self->pidl("if (werror) {");
463
$self->pidl("*werror = r.out.result;");
344
$self->pidl("*werror = result;");
465
346
$self->pidl("}");
467
$self->pidl("return werror_to_ntstatus(r.out.result);");
348
$self->pidl("return werror_to_ntstatus(result);");
469
350
warning($fn->{ORIGINAL}, "Unable to convert $fn->{RETURN_TYPE} to NTSTATUS");
470
351
$self->pidl("return NT_STATUS_OK;");
496
377
$self->pidl_hdr("#ifndef __CLI_$uif\__");
497
378
$self->pidl_hdr("#define __CLI_$uif\__");
498
foreach (@{$if->{FUNCTIONS}}) {
499
next if ($_->{PROPERTIES}{noopnum});
500
$self->ParseFunction($if->{NAME}, $_);
379
foreach my $fn (@{$if->{FUNCTIONS}}) {
380
next if has_property($fn, "noopnum");
381
next if has_property($fn, "todo");
384
foreach my $e (@{$fn->{ELEMENTS}}) {
385
if (ContainsPipe($e, $e->{LEVELS}[0])) {
392
$self->ParseFunction($if->{NAME}, $fn);
502
394
$self->pidl_hdr("#endif /* __CLI_$uif\__ */");
507
my($self,$ndr,$header,$ndr_header) = @_;
399
my($self,$ndr,$header,$c_header) = @_;
509
401
$self->pidl("/*");
510
402
$self->pidl(" * Unix SMB/CIFS implementation.");