6a9ea157a99096a4246b94da8086facdd1afac71
[jelmer/samba4-debian.git] / source / build / pidl / server.pm
1 ###################################################
2 # server boilerplate generator
3 # Copyright tridge@samba.org 2003
4 # Copyright metze@samba.org 2004
5 # released under the GNU GPL
6
7 package IdlServer;
8
9 use strict;
10
11 my($res);
12
13 sub pidl($)
14 {
15         $res .= shift;
16 }
17
18
19 #####################################################
20 # generate the switch statement for function dispatch
21 sub gen_dispatch_switch($)
22 {
23         my $data = shift;
24
25         my $count = 0;
26         foreach my $d (@{$data}) {
27                 next if ($d->{TYPE} ne "FUNCTION");
28
29                 pidl "\tcase $count: {\n";
30                 pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
31                 pidl "\t\tif (DEBUGLEVEL > 10) {\n";
32                 pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
33                 pidl "\t\t}\n";
34                 if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
35                         pidl "\t\tr2->out.result = $d->{NAME}(dce_call, mem_ctx, r2);\n";
36                 } else {
37                         pidl "\t\t$d->{NAME}(dce_call, mem_ctx, r2);\n";
38                 }
39                 pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
40                 pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
41                 pidl "\t\t}\n";
42                 pidl "\t\tif (dce_call->fault_code != 0) {\n";
43                 pidl "\t\t\tDEBUG(2,(\"dcerpc_fault 0x%x in $d->{NAME}\\n\", dce_call->fault_code));\n";
44                 pidl "\t\t}\n";
45                 pidl "\t\tbreak;\n\t}\n";
46                 $count++; 
47         }
48 }
49
50
51 #####################################################################
52 # produce boilerplate code for a interface
53 sub Boilerplate_Iface($)
54 {
55         my($interface) = shift;
56         my($data) = $interface->{DATA};
57         my $count = 0;
58         my $name = $interface->{NAME};
59         my $uname = uc $name;
60
61         foreach my $d (@{$data}) {
62                 if ($d->{TYPE} eq "FUNCTION") { $count++; }
63         }
64
65         if ($count == 0) {
66                 return;
67         }
68
69         pidl "
70 static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
71 {
72 #ifdef DCESRV_INTERFACE_$uname\_BIND
73         return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
74 #else
75         return NT_STATUS_OK;
76 #endif
77 }
78
79 static void $name\__op_unbind(struct dcesrv_connection *dce_conn, const struct dcesrv_interface *iface)
80 {
81 #ifdef DCESRV_INTERFACE_$uname\_UNBIND
82         DCESRV_INTERFACE_$uname\_UNBIND(dce_conn,iface);
83 #else
84         return;
85 #endif
86 }
87
88 static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
89 {
90         uint16 opnum = dce_call->pkt.u.request.opnum;
91
92         dce_call->fault_code = 0;
93
94         switch (opnum) {
95 ";
96         gen_dispatch_switch($data);
97
98 pidl "
99         default:
100                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
101                 break;
102         }
103
104         if (dce_call->fault_code != 0) {
105                 return NT_STATUS_NET_WRITE_FAULT;
106         }
107         return NT_STATUS_OK;
108 }
109
110 static const struct dcesrv_interface $name\_interface = {
111         &dcerpc_table_$name,
112         $name\__op_bind,
113         $name\__op_unbind,
114         $name\__op_dispatch
115 };
116
117 ";
118 }
119
120 #####################################################################
121 # produce boilerplate code for an endpoint server
122 sub Boilerplate_Ep_Server($)
123 {
124         my($interface) = shift;
125         my($data) = $interface->{DATA};
126         my $count = 0;
127         my $name = $interface->{NAME};
128         my $uname = uc $name;
129
130         foreach my $d (@{$data}) {
131                 if ($d->{TYPE} eq "FUNCTION") { $count++; }
132         }
133
134         if ($count == 0) {
135                 return;
136         }
137
138         pidl "
139 static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
140 {
141         int i;
142
143         for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
144                 NTSTATUS ret;
145                 const char *name = $name\_interface.ndr->endpoints->names[i];
146
147                 ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
148                 if (!NT_STATUS_IS_OK(ret)) {
149                         DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
150                         return ret;
151                 }
152         }
153
154         return NT_STATUS_OK;
155 }
156
157 static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
158 {
159         if ($name\_interface.ndr->if_version == if_version &&
160                 strcmp($name\_interface.ndr->uuid, uuid)==0) {
161                 memcpy(iface,&$name\_interface, sizeof(*iface));
162                 return True;
163         }
164
165         return False;
166 }
167
168 static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
169 {
170         if (strcmp($name\_interface.ndr->name, name)==0) {
171                 memcpy(iface,&$name\_interface, sizeof(*iface));
172                 return True;
173         }
174
175         return False;   
176 }
177         
178 NTSTATUS dcerpc_server_$name\_init(void)
179 {
180         NTSTATUS ret;
181         struct dcesrv_endpoint_server ep_server;
182
183         /* fill in our name */
184         ep_server.name = \"$name\";
185
186         /* fill in all the operations */
187         ep_server.init_server = $name\__op_init_server;
188
189         ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
190         ep_server.interface_by_name = $name\__op_interface_by_name;
191
192         /* register ourselves with the DCERPC subsystem. */
193         ret = register_backend(\"dcerpc\", &ep_server);
194
195         if (!NT_STATUS_IS_OK(ret)) {
196                 DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
197                 return ret;
198         }
199
200         return ret;
201 }
202
203 ";
204 }
205
206 #####################################################################
207 # parse a parsed IDL structure back into an IDL file
208 sub ParseInterface($)
209 {
210         my($interface) = shift;
211         $res = "/* dcerpc server boilerplate generated by pidl */\n\n";
212         Boilerplate_Iface($interface);
213         Boilerplate_Ep_Server($interface);
214
215         return $res;
216 }
217
218 1;
219