r3689: Large number of COM updates:
[samba.git] / source4 / build / pidl / stub.pm
1 ###################################################
2 # stub boilerplate generator
3 # Copyright jelmer@samba.org 2004
4 # Copyright tridge@samba.org 2003
5 # released under the GNU GPL
6
7 package IdlStub;
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 = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
36                 } else {
37                         pidl "\t\tvtable->$d->{NAME}(iface, 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         struct GUID ipid = dce_call->pkt.u.request.object.object;
92         struct dcom_interface_p *iface = dcoms_get_ifacep(&ipid);
93         struct dcom_$name\_vtable *vtable = if->vtable;
94
95         dce_call->fault_code = 0;
96
97         switch (opnum) {
98 ";
99         gen_dispatch_switch($data);
100
101 pidl "
102         default:
103                 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
104                 break;
105         }
106
107         if (dce_call->fault_code != 0) {
108                 return NT_STATUS_NET_WRITE_FAULT;
109         }
110         return NT_STATUS_OK;
111 }
112
113 static const struct dcesrv_interface $name\_interface = {
114         &dcerpc_table_$name,
115         $name\__op_bind,
116         $name\__op_unbind,
117         $name\__op_dispatch
118 };
119
120 ";
121 }
122
123 #####################################################################
124 # produce boilerplate code for an endpoint server
125 sub Boilerplate_Ep_Server($)
126 {
127         my($interface) = shift;
128         my($data) = $interface->{DATA};
129         my $count = 0;
130         my $name = $interface->{NAME};
131         my $uname = uc $name;
132
133         foreach my $d (@{$data}) {
134                 if ($d->{TYPE} eq "FUNCTION") { $count++; }
135         }
136
137         if ($count == 0) {
138                 return;
139         }
140
141         pidl "
142 static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
143 {
144         int i;
145
146         for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
147                 NTSTATUS ret;
148                 const char *name = $name\_interface.ndr->endpoints->names[i];
149
150                 ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
151                 if (!NT_STATUS_IS_OK(ret)) {
152                         DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
153                         return ret;
154                 }
155         }
156
157         return NT_STATUS_OK;
158 }
159
160 static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
161 {
162         if ($name\_interface.ndr->if_version == if_version &&
163                 strcmp($name\_interface.ndr->uuid, uuid)==0) {
164                 memcpy(iface,&$name\_interface, sizeof(*iface));
165                 return True;
166         }
167
168         return False;
169 }
170
171 static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
172 {
173         if (strcmp($name\_interface.ndr->name, name)==0) {
174                 memcpy(iface,&$name\_interface, sizeof(*iface));
175                 return True;
176         }
177
178         return False;   
179 }
180         
181 NTSTATUS dcerpc_server_$name\_init(void)
182 {
183         NTSTATUS ret;
184         struct dcesrv_endpoint_server ep_server;
185
186         /* fill in our name */
187         ep_server.name = \"$name\";
188
189         /* fill in all the operations */
190         ep_server.init_server = $name\__op_init_server;
191
192         ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
193         ep_server.interface_by_name = $name\__op_interface_by_name;
194
195         /* register ourselves with the DCERPC subsystem. */
196         ret = register_backend(\"dcerpc\", &ep_server);
197
198         if (!NT_STATUS_IS_OK(ret)) {
199                 DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
200                 return ret;
201         }
202
203         return ret;
204 }
205
206 ";
207 }
208
209 sub ParseInterface($)
210 {
211         my($interface) = shift;
212         $res = "/* dcerpc server boilerplate generated by pidl */\n\n";
213
214         Boilerplate_Iface($interface);
215         Boilerplate_Ep_Server($interface);
216
217         return $res;
218 }
219
220 1;
221