fa5292e5aa921344bb978aad59197537dac7784c
[vlendec/samba-autobuild/.git] / pidl / lib / Parse / Pidl / Samba4 / NDR / ServerCompat.pm
1 ###################################################
2 # server boilerplate generator
3 # Copyright tridge@samba.org 2003
4 # Copyright metze@samba.org 2004
5 # Copyright scabrero@samba.org 2019
6 # released under the GNU GPL
7
8 package Parse::Pidl::Samba4::NDR::ServerCompat;
9
10 use Exporter;
11 @ISA = qw(Exporter);
12 @EXPORT_OK = qw(Parse);
13
14 use Parse::Pidl::Util qw(print_uuid);
15 use Parse::Pidl::Typelist qw(mapTypeName);
16
17 use vars qw($VERSION);
18 $VERSION = '1.0';
19
20 use strict;
21
22 sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
23 sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
24 sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
25 sub pidlnoindent($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$txt\n" : "\n"; }
26 sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
27 sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; }
28
29 sub new($)
30 {
31         my ($class) = shift;
32         my $self = { res => "", res_hdr => "", tabs => "" };
33         bless($self, $class);
34 }
35
36 #####################################################
37 # generate the switch statement for function dispatch
38 sub gen_dispatch_switch($)
39 {
40         my ($self, $interface) = @_;
41
42         foreach my $fn (@{$interface->{FUNCTIONS}}) {
43                 next if not defined($fn->{OPNUM});
44
45                 my $fname = $fn->{NAME};
46                 my $ufname = uc($fname);
47
48                 $self->pidl("case $fn->{OPNUM}: { /* $fn->{NAME} */");
49                 $self->indent();
50                 $self->pidl("struct $fname *r2 = (struct $fname *)r;");
51                 $self->pidl("if (DEBUGLEVEL >= 10) {");
52                 $self->indent();
53                 $self->pidl("NDR_PRINT_FUNCTION_DEBUG($fname, NDR_IN, r2);");
54                 $self->deindent();
55                 $self->pidl("}");
56
57                 $self->pidl_hdr("struct $fname;");
58
59                 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
60                         $self->pidl_hdr(mapTypeName($fn->{RETURN_TYPE}) . " _$fname(struct pipes_struct *p, struct $fname *r);");
61                         $self->pidl("r2->out.result = _$fname(p, r2);");
62                 } else {
63                         $self->pidl_hdr("void _$fname(struct pipes_struct *p, struct $fname *r);");
64                         $self->pidl("_$fname(p, r2);");
65                 }
66
67                 $self->pidl("break;");
68                 $self->deindent();
69                 $self->pidl("}");
70         }
71 }
72
73 #####################################################
74 # generate the switch statement for function reply
75 sub gen_reply_switch($)
76 {
77         my ($self, $interface) = @_;
78
79         foreach my $fn (@{$interface->{FUNCTIONS}}) {
80                 next if not defined($fn->{OPNUM});
81
82                 $self->pidl("case $fn->{OPNUM}: { /* $fn->{NAME} */");
83                 $self->indent();
84                 $self->pidl("struct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;");
85                 $self->pidl("if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {");
86                 $self->indent();
87                 $self->pidl("DEBUG(5,(\"function $fn->{NAME} replied async\\n\"));");
88                 $self->deindent();
89                 $self->pidl("}");
90                 $self->pidl("if (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {");
91                 $self->indent();
92                 $self->pidl("NDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);");
93                 $self->deindent();
94                 $self->pidl("}");
95                 $self->pidl("if (dce_call->fault_code != 0) {");
96                 $self->indent();
97                 $self->pidl("DBG_WARNING(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code));");
98                 $self->deindent();
99                 $self->pidl("}");
100                 $self->pidl("break;");
101                 $self->deindent();
102                 $self->pidl("}");
103         }
104 }
105
106 #####################################################################
107 # produce boilerplate code for a interface
108 sub boilerplate_iface($)
109 {
110         my ($self, $interface) = @_;
111
112         my $name = $interface->{NAME};
113         my $uname = uc $name;
114         my $uuid = lc($interface->{UUID});
115         my $if_version = $interface->{VERSION};
116
117         $self->pidl("static NTSTATUS $name\__op_bind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)");
118         $self->pidl("{");
119         $self->indent();
120         $self->pidl("struct pipes_struct *p = NULL;");
121         $self->pidl("struct pipe_rpc_fns *context_fns = NULL;");
122         $self->pidl("bool ok = false;");
123         $self->pidl("");
124         $self->pidl("/* Retrieve pipes struct */");
125         $self->pidl("p = dcesrv_get_pipes_struct(context->conn);");
126         $self->pidl("/* Init pipe handles */");
127         $self->pidl("ok = init_pipe_handles(p, &iface->syntax_id);");
128         $self->pidl("if (!ok) {");
129         $self->indent();
130         $self->pidl("DBG_ERR(\"Failed to init pipe handles\\n\");");
131         $self->pidl("return NT_STATUS_UNSUCCESSFUL;");
132         $self->deindent();
133         $self->pidl("}");
134         $self->pidl("");
135
136         $self->pidl("/* TODO check loop */");
137
138         $self->pidl("/* Init pipe context */");
139         $self->pidl("p->pipe_bound = true;");
140         $self->pidl("for (context_fns = p->contexts; context_fns != NULL; context_fns = context_fns->next) {");
141         $self->indent();
142         $self->pidl("if (context_fns->context_id != context->context_id) {");
143         $self->indent();
144         $self->pidl("continue;");
145         $self->deindent();
146         $self->pidl("}");
147         $self->pidl("ok = ndr_syntax_id_equal(&context_fns->syntax, &iface->syntax_id);");
148         $self->pidl("if (ok) {");
149         $self->indent();
150         $self->pidl("break;");
151         $self->deindent();
152         $self->pidl("}");
153         $self->pidl("return NT_STATUS_UNSUCCESSFUL;");
154         $self->deindent();
155         $self->pidl("}");
156         $self->pidl("if (context_fns == NULL) {");
157         $self->indent();
158         $self->pidl("context_fns = talloc_zero(p, struct pipe_rpc_fns);");
159         $self->pidl("if (context_fns == NULL) {");
160         $self->indent();
161         $self->pidl("return NT_STATUS_NO_MEMORY;");
162         $self->deindent();
163         $self->pidl("}");
164         $self->pidl("");
165         $self->pidl("context_fns->next = context_fns->prev = NULL;");
166         $self->pidl("context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(&iface->syntax_id);");
167         $self->pidl("context_fns->cmds = rpc_srv_get_pipe_cmds(&iface->syntax_id);");
168         $self->pidl("context_fns->context_id = context->context_id;");
169         $self->pidl("context_fns->syntax = iface->syntax_id;");
170         $self->pidl("DLIST_ADD( p->contexts, context_fns);");
171         $self->deindent();
172         $self->pidl("}");
173         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_BIND");
174         $self->pidl("return DCESRV_INTERFACE_$uname\_BIND(context,iface);");
175         $self->pidlnoindent("#else");
176         $self->pidl("return NT_STATUS_OK;");
177         $self->deindent();
178         $self->pidl("#endif");
179         $self->pidl("}");
180         $self->pidl("");
181
182         $self->pidl("static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)");
183         $self->pidl("{");
184         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_UNBIND");
185         $self->indent();
186         $self->pidl("DCESRV_INTERFACE_$uname\_UNBIND(context, iface);");
187         $self->pidlnoindent("#else");
188         $self->pidl("return;");
189         $self->pidlnoindent("#endif");
190         $self->deindent();
191         $self->pidl("}");
192         $self->pidl("");
193
194         $self->pidl_hdr("NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r);");
195         $self->pidl("NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)");
196         $self->pidl("{");
197         $self->indent();
198         $self->pidl("enum ndr_err_code ndr_err;");
199         $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;");
200         $self->pidl("");
201         $self->pidl("dce_call->fault_code = 0;");
202         $self->pidl("");
203         $self->pidl("if (opnum >= ndr_table_$name.num_calls) {");
204         $self->indent();
205         $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;");
206         $self->pidl("return NT_STATUS_NET_WRITE_FAULT;");
207         $self->deindent();
208         $self->pidl("}");
209         $self->pidl("");
210         $self->pidl("*r = talloc_named(mem_ctx, ndr_table_$name.calls[opnum].struct_size, \"struct %s\", ndr_table_$name.calls[opnum].name);");
211         $self->pidl("NT_STATUS_HAVE_NO_MEMORY(*r);");
212         $self->pidl("");
213         $self->pidl("/* unravel the NDR for the packet */");
214         $self->pidl("ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);");
215         $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {");
216         $self->indent();
217         $self->pidl("dce_call->fault_code = DCERPC_FAULT_NDR;");
218         $self->pidl("return NT_STATUS_NET_WRITE_FAULT;");
219         $self->deindent();
220         $self->pidl("}");
221         $self->pidl("");
222         $self->pidl("return NT_STATUS_OK;");
223         $self->deindent();
224         $self->pidl("}");
225         $self->pidl("");
226
227         $self->pidl_hdr("NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r);");
228         $self->pidl("NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)");
229         $self->pidl("{");
230         $self->indent();
231         $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;");
232         $self->pidl("struct pipes_struct *p = NULL;");
233         $self->pidl("struct auth_session_info *pipe_session_info = NULL;");
234         $self->pidl("NTSTATUS status = NT_STATUS_OK;");
235         $self->pidl("bool impersonated;");
236         $self->pidl("");
237         $self->pidl("/* Retrieve pipes struct */");
238         $self->pidl("p = dcesrv_get_pipes_struct(dce_call->conn);");
239         $self->pidl("/* Update pipes struct opnum */");
240         $self->pidl("p->opnum = opnum;");
241         $self->pidl("/* Update pipes struct session info */");
242         $self->pidl("pipe_session_info = p->session_info;");
243         $self->pidl("p->session_info = dce_call->auth_state->session_info;");
244         $self->pidl("p->auth.auth_type = dce_call->auth_state->auth_type;");
245         $self->pidl("p->auth.auth_level = dce_call->auth_state->auth_level;");
246         $self->pidl("p->auth.auth_context_id = dce_call->auth_state->auth_context_id;");
247         $self->pidl("/* Reset pipes struct fault state */");
248         $self->pidl("p->fault_state = 0;");
249         $self->pidl("");
250
251         $self->pidl("/* Impersonate */");
252         $self->pidl("impersonated = become_authenticated_pipe_user(p->session_info);");
253         $self->pidl("if (!impersonated) {");
254         $self->indent();
255         $self->pidl("dce_call->fault_code = DCERPC_FAULT_ACCESS_DENIED;");
256         $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;");
257         $self->pidl("goto fail;");
258         $self->deindent();
259         $self->pidl("}");
260         $self->pidl("");
261
262         $self->pidl("switch (opnum) {");
263         $self->gen_dispatch_switch($interface);
264         $self->pidl("default:");
265         $self->indent();
266         $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;");
267         $self->pidl("break;");
268         $self->deindent();
269         $self->pidl("}");
270         $self->pidl("");
271
272         $self->pidlnoindent("fail:");
273         $self->pidl("/* Unimpersonate */");
274         $self->pidl("if (impersonated) {");
275         $self->indent();
276         $self->pidl("unbecome_authenticated_pipe_user();");
277         $self->deindent();
278         $self->pidl("}");
279         $self->pidl("");
280
281         $self->pidl("/* Restore session info */");
282         $self->pidl("p->session_info = pipe_session_info;");
283         $self->pidl("p->auth.auth_type = 0;");
284         $self->pidl("p->auth.auth_level = 0;");
285         $self->pidl("p->auth.auth_context_id = 0;");
286         $self->pidl("/* Check pipes struct fault state */");
287         $self->pidl("if (p->fault_state != 0) {");
288         $self->indent();
289         $self->pidl("dce_call->fault_code = p->fault_state;");
290         $self->deindent();
291         $self->pidl("}");
292         $self->pidl("if (dce_call->fault_code != 0) {");
293         $self->indent();
294         $self->pidl("status = NT_STATUS_NET_WRITE_FAULT;");
295         $self->deindent();
296         $self->pidl("}");
297         $self->pidl("");
298
299         $self->pidl("return status;");
300         $self->deindent();
301         $self->pidl("}");
302         $self->pidl("");
303
304         $self->pidl_hdr("NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r);");
305         $self->pidl("NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)");
306         $self->pidl("{");
307         $self->indent();
308         $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;");
309         $self->pidl("");
310         $self->pidl("switch (opnum) {");
311         $self->gen_reply_switch($interface);
312         $self->pidl("default:");
313         $self->indent();
314         $self->pidl("dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;");
315         $self->pidl("break;");
316         $self->deindent();
317         $self->pidl("}");
318         $self->pidl("");
319
320         $self->pidl("if (dce_call->fault_code != 0) {");
321         $self->indent();
322         $self->pidl("return NT_STATUS_NET_WRITE_FAULT;");
323         $self->deindent();
324         $self->pidl("}");
325         $self->pidl("");
326         $self->pidl("return NT_STATUS_OK;");
327         $self->deindent();
328         $self->pidl("}");
329         $self->pidl("");
330
331         $self->pidl_hdr("NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r);");
332         $self->pidl("NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)");
333         $self->pidl("{");
334         $self->indent();
335         $self->pidl("enum ndr_err_code ndr_err;");
336         $self->pidl("uint16_t opnum = dce_call->pkt.u.request.opnum;");
337         $self->pidl("");
338         $self->pidl("ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);");
339         $self->pidl("if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {");
340         $self->indent();
341         $self->pidl("dce_call->fault_code = DCERPC_FAULT_NDR;");
342         $self->pidl("return NT_STATUS_NET_WRITE_FAULT;");
343         $self->deindent();
344         $self->pidl("}");
345         $self->pidl("");
346         $self->pidl("return NT_STATUS_OK;");
347         $self->deindent();
348         $self->pidl("}");
349         $self->pidl("");
350
351         $self->pidl("static const struct dcesrv_interface dcesrv\_$name\_interface = {");
352         $self->indent();
353         $self->pidl(".name      = \"$name\",");
354         $self->pidl(".syntax_id = {".print_uuid($uuid).",$if_version},");
355         $self->pidl(".bind      = $name\__op_bind,");
356         $self->pidl(".unbind    = $name\__op_unbind,");
357         $self->pidl(".ndr_pull  = $name\__op_ndr_pull,");
358         $self->pidl(".dispatch  = $name\__op_dispatch,");
359         $self->pidl(".reply     = $name\__op_reply,");
360         $self->pidl(".ndr_push  = $name\__op_ndr_push,");
361         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_FLAGS");
362         $self->pidl(".flags     = DCESRV_INTERFACE_$uname\_FLAGS");
363         $self->pidlnoindent("#else");
364         $self->pidl(".flags     = 0");
365         $self->pidlnoindent("#endif");
366         $self->deindent();
367         $self->pidl("};");
368         $self->pidl("");
369 }
370
371 #####################################################################
372 # produce boilerplate code for an endpoint server
373 sub boilerplate_ep_server($)
374 {
375         my ($self, $interface) = @_;
376         my $name = $interface->{NAME};
377         my $uname = uc $name;
378
379         $self->pidl("static NTSTATUS $name\__check_register_in_endpoint(const char *name, struct dcerpc_binding *binding) {");
380         $self->indent();
381         $self->pidl("enum dcerpc_transport_t transport = dcerpc_binding_get_transport(binding);");
382         $self->pidl("");
383         $self->pidl("/* If service is embedded, register only for ncacn_np");
384         $self->pidl(" * see 8466b3c85e4b835e57e41776853093f4a0edc8b8");
385         $self->pidl(" */");
386         $self->pidl("if (rpc_service_mode(name) == RPC_SERVICE_MODE_EMBEDDED && transport != NCACN_NP) {");
387         $self->indent();
388         $self->pidl("DBG_INFO(\"Interface \'$name\' not registered in endpoint \'%s\' as service is embedded\\n\", name);");
389         $self->pidl("return NT_STATUS_NOT_SUPPORTED;");
390         $self->deindent();
391         $self->pidl("}");
392         $self->pidl("");
393         $self->pidl("return NT_STATUS_OK;");
394         $self->deindent();
395         $self->pidl("}");
396         $self->pidl("");
397
398         $self->pidl("static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)");
399         $self->pidl("{");
400         $self->indent();
401         $self->pidl("int i;");
402         $self->pidl("NTSTATUS ret;");
403         $self->pidl("struct dcerpc_binding *binding;");
404         $self->pidl("const struct api_struct *legacy_cmds = NULL;");
405         $self->pidl("int n_fns = 0;");
406         $self->pidl("");
407         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT");
408         $self->pidl("const char *ncacn_np_secondary_endpoint = DCESRV_INTERFACE_$uname\_NCACN_NP_SECONDARY_ENDPOINT;");
409         $self->pidlnoindent("#else");
410         $self->pidl("const char *ncacn_np_secondary_endpoint = NULL;");
411         $self->pidlnoindent("#endif");
412         $self->pidl("");
413         $self->pidl("for (i=0;i<ndr_table_$name.endpoints->count;i++) {");
414         $self->indent();
415         $self->pidl("const char *name = ndr_table_$name.endpoints->names[i];");
416         $self->pidl("");
417         $self->pidl("/* Register the interface for local dispatching */");
418         $self->pidl("legacy_cmds = $name\_get_pipe_fns(&n_fns);");
419         $self->pidl("if (legacy_cmds == NULL) {");
420         $self->indent();
421         $self->pidl("DBG_ERR(\"Failed to get legacy \'$name\' API cmds\\n\");");
422         $self->pidl("return NT_STATUS_UNSUCCESSFUL;");
423         $self->deindent();
424         $self->pidl("}");
425         $self->pidl("");
426         $self->pidl("ret = rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$name\", \"$name\", &ndr_table_$name, legacy_cmds, n_fns, NULL);");
427         $self->pidl("if (!NT_STATUS_IS_OK(ret)) {");
428         $self->indent();
429         $self->pidl("DBG_ERR(\"Failed to register legacy \'$name\' API cmds\\n\");");
430         $self->pidl("return ret;");
431         $self->deindent();
432         $self->pidl("}");
433         $self->pidl("");
434         $self->pidl("ret = dcerpc_parse_binding(dce_ctx, name, &binding);");
435         $self->pidl("if (NT_STATUS_IS_ERR(ret)) {");
436         $self->indent();
437         $self->pidl("DBG_ERR(\"Failed to parse binding string \'%s\'\\n\", name);");
438         $self->pidl("return ret;");
439         $self->deindent();
440         $self->pidl("}");
441         $self->pidl("");
442         $self->pidl("ret = $name\__check_register_in_endpoint(\"$name\", binding);");
443         $self->pidl("if (NT_STATUS_IS_ERR(ret)) {");
444         $self->indent();
445         $self->pidl("talloc_free(binding);");
446         $self->pidl("continue;");
447         $self->deindent();
448         $self->pidl("}");
449         $self->pidl("talloc_free(binding);");
450         $self->pidl("");
451         $self->pidl("ret = dcesrv_interface_register(dce_ctx, name, ncacn_np_secondary_endpoint, &dcesrv_$name\_interface, NULL);");
452         $self->pidl("if (!NT_STATUS_IS_OK(ret)) {");
453         $self->indent();
454         $self->pidl("DBG_ERR(\"Failed to register endpoint \'%s\'\\n\",name);");
455         $self->pidl("return ret;");
456         $self->deindent();
457         $self->pidl("}");
458         $self->deindent();
459         $self->pidl("}");
460         $self->pidl("");
461         $self->pidl("return NT_STATUS_OK;");
462         $self->deindent();
463         $self->pidl("}");
464         $self->pidl("");
465
466         $self->pidl("static NTSTATUS $name\__op_shutdown_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)");
467         $self->pidl("{");
468         $self->indent();
469         $self->pidl("NTSTATUS status;");
470         $self->pidl("");
471         $self->pidl("/* Unregister the interface from local dispatching table */");
472         $self->pidl("status = rpc_srv_unregister(&ndr_table_$name);");
473         $self->pidl("if (!NT_STATUS_IS_OK(status)) {");
474         $self->indent();
475         $self->pidl("DBG_ERR(\"Failed to unregister legacy \'$name\' API cmds\\n\");");
476         $self->pidl("return status;");
477         $self->deindent();
478         $self->pidl("}");
479         $self->pidl("");
480         $self->pidl("return NT_STATUS_OK;");
481         $self->deindent();
482         $self->pidl("}");
483         $self->pidl("");
484
485         $self->pidl("static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)");
486         $self->pidl("{");
487         $self->indent();
488         $self->pidl("if (dcesrv_$name\_interface.syntax_id.if_version == if_version && GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {");
489         $self->indent();
490         $self->pidl("memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));");
491         $self->pidl("return true;");
492         $self->deindent();
493         $self->pidl("}");
494         $self->pidl("");
495         $self->pidl("return false;");
496         $self->deindent();
497         $self->pidl("}");
498         $self->pidl("");
499
500         $self->pidl("static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)");
501         $self->pidl("{");
502         $self->indent();
503         $self->pidl("if (strcmp(dcesrv_$name\_interface.name, name)==0) {");
504         $self->indent();
505         $self->pidl("memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface));");
506         $self->pidl("return true;");
507         $self->deindent();
508         $self->pidl("}");
509         $self->pidl("");
510         $self->pidl("return false;");
511         $self->deindent();
512         $self->pidl("}");
513         $self->pidl("");
514
515         $self->pidl("static const struct dcesrv_endpoint_server $name\_ep_server = {");
516         $self->indent();
517         $self->pidl("/* fill in our name */");
518         $self->pidl(".name = \"$name\",");
519         $self->pidl("");
520         $self->pidl("/* Initialization flag */");
521         $self->pidl(".initialized = false,");
522         $self->pidl("");
523         $self->pidl("/* fill in all the operations */");
524         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_INIT_SERVER");
525         $self->pidl(".init_server = DCESRV_INTERFACE_$uname\_INIT_SERVER,");
526         $self->pidlnoindent("#else");
527         $self->pidl(".init_server = $name\__op_init_server,");
528         $self->pidlnoindent("#endif");
529         $self->pidlnoindent("#ifdef DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER");
530         $self->pidl(".shutdown_server = DCESRV_INTERFACE_$uname\_SHUTDOWN_SERVER,");
531         $self->pidlnoindent("#else");
532         $self->pidl(".shutdown_server = $name\__op_shutdown_server,");
533         $self->pidlnoindent("#endif");
534         $self->pidl(".interface_by_uuid = $name\__op_interface_by_uuid,");
535         $self->pidl(".interface_by_name = $name\__op_interface_by_name");
536         $self->deindent();
537         $self->pidl("};");
538         $self->pidl("");
539
540         $self->pidl("const struct dcesrv_endpoint_server *$name\_get_ep_server(void)");
541         $self->pidl("{");
542         $self->indent();
543         $self->pidl("return &$name\_ep_server;");
544         $self->deindent();
545         $self->pidl("}");
546 }
547
548 #####################################################################
549 # dcerpc server boilerplate from a parsed IDL structure
550 sub parse_interface($)
551 {
552         my ($self, $interface) = @_;
553         my $count = 0;
554         my $uif = uc($interface->{NAME});
555
556
557         $self->pidl_hdr("#ifndef __NDR_${uif}_SCOMPAT_H__");
558         $self->pidl_hdr("#define __NDR_${uif}_SCOMPAT_H__");
559         $self->pidl_hdr("");
560         $self->pidl_hdr("struct pipes_struct;");
561         $self->pidl_hdr("struct dcesrv_endpoint_server;");
562         $self->pidl_hdr("struct dcesrv_call_state;");
563         $self->pidl_hdr("");
564         $self->pidl_hdr("const struct dcesrv_endpoint_server *$interface->{NAME}\_get_ep_server(void);");
565         $self->pidl_hdr("");
566
567         if (!defined $interface->{PROPERTIES}->{uuid}) {
568                 $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */");
569                 return;
570         }
571
572         if (!defined $interface->{PROPERTIES}->{version}) {
573                 $interface->{PROPERTIES}->{version} = "0.0";
574         }
575
576         foreach my $fn (@{$interface->{FUNCTIONS}}) {
577                 if (defined($fn->{OPNUM})) { $count++; }
578         }
579
580         if ($count == 0) {
581                 $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */");
582                 return;
583         }
584
585         $self->pidl("/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */");
586         $self->boilerplate_iface($interface);
587         $self->boilerplate_ep_server($interface);
588
589         $self->pidl_hdr("#endif /* __NDR_${uif}_SCOMPAT_H__ */");
590 }
591
592 sub Parse($$)
593 {
594         my ($self, $ndr, $h_scompat, $header) = @_;
595
596         $self->pidl("/* s3 compat server functions auto-generated by pidl */");
597         $self->pidl("#include \"$header\"");
598         $self->pidl("#include \"$h_scompat\"");
599         $self->pidl("#include <rpc_server/srv_pipe_register.h>");
600         $self->pidl("#include <rpc_server/srv_pipe_internal.h>");
601
602         $self->pidl("#include <librpc/rpc/dcesrv_core.h>");
603         $self->pidl("#include <rpc_server/rpc_config.h>");
604         $self->pidl("#include <rpc_server/rpc_server.h>");
605         $self->pidl("#include <util/debug.h>");
606         $self->pidl("");
607
608         foreach my $x (@{$ndr}) {
609                 $self->parse_interface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object}));
610         }
611
612         return ($self->{res}, $self->{res_hdr});
613 }
614
615 1;