vfs_ceph_new: handle errno properly for 'readdir'
[Samba.git] / pidl / lib / Parse / Pidl / Samba4 / COM / Stub.pm
blob7198038357246121dc229240550da44d54cfd15a
1 ###################################################
2 # DCOM stub boilerplate generator
3 # Copyright jelmer@samba.org 2004-2005
4 # Copyright tridge@samba.org 2003
5 # Copyright metze@samba.org 2004
6 # released under the GNU GPL
8 package Parse::Pidl::Samba4::COM::Stub;
10 use Parse::Pidl::Util qw(has_property);
11 use strict;
12 use warnings;
14 use vars qw($VERSION);
15 $VERSION = '0.01';
17 my($res);
19 sub pidl($)
21 $res .= shift;
24 #####################################################
25 # generate the switch statement for function dispatch
26 sub gen_dispatch_switch($)
28 my $data = shift;
30 my $count = 0;
31 foreach my $d (@{$data}) {
32 next if ($d->{TYPE} ne "FUNCTION");
34 pidl "\tcase $count: {\n";
35 if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
36 pidl "\t\tNTSTATUS result;\n";
38 pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
39 pidl "\t\tif (DEBUGLEVEL > 10) {\n";
40 pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
41 pidl "\t\t}\n";
42 if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
43 pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
44 } else {
45 pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
47 pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
48 pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n";
49 pidl "\t\t}\n";
50 pidl "\t\tbreak;\n\t}\n";
51 $count++;
55 #####################################################
56 # generate the switch statement for function reply
57 sub gen_reply_switch($)
59 my $data = shift;
61 my $count = 0;
62 foreach my $d (@{$data}) {
63 next if ($d->{TYPE} ne "FUNCTION");
65 pidl "\tcase $count: {\n";
66 pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
67 pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
68 pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n";
69 pidl "\t\t}\n";
70 pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
71 pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
72 pidl "\t\t}\n";
73 pidl "\t\tif (dce_call->fault_code != 0) {\n";
74 pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
75 pidl "\t\t}\n";
76 pidl "\t\tbreak;\n\t}\n";
77 $count++;
81 #####################################################################
82 # produce boilerplate code for a interface
83 sub Boilerplate_Iface($)
85 my($interface) = shift;
86 my($data) = $interface->{DATA};
87 my $name = $interface->{NAME};
88 my $uname = uc $name;
89 my $uuid = Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid});
90 my $if_version = $interface->{PROPERTIES}->{version};
92 pidl "
93 static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
95 #ifdef DCESRV_INTERFACE_$uname\_BIND
96 return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
97 #else
98 return NT_STATUS_OK;
99 #endif
102 static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
104 #ifdef DCESRV_INTERFACE_$uname\_UNBIND
105 DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
106 #else
107 return;
108 #endif
111 static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
113 NTSTATUS status;
114 uint16_t opnum = dce_call->pkt.u.request.opnum;
116 dce_call->fault_code = 0;
118 if (opnum >= dcerpc_table_$name.num_calls) {
119 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
120 return NT_STATUS_NET_WRITE_FAULT;
123 *r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
124 NT_STATUS_HAVE_NO_MEMORY(*r);
126 /* unravel the NDR for the packet */
127 status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
128 if (!NT_STATUS_IS_OK(status)) {
129 dce_call->fault_code = DCERPC_FAULT_NDR;
130 return NT_STATUS_NET_WRITE_FAULT;
133 return NT_STATUS_OK;
136 static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
138 uint16_t opnum = dce_call->pkt.u.request.opnum;
139 struct GUID ipid = dce_call->pkt.u.request.object.object;
140 struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
141 const struct dcom_$name\_vtable *vtable = iface->vtable;
143 switch (opnum) {
145 gen_dispatch_switch($data);
147 pidl "
148 default:
149 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
150 break;
153 if (dce_call->fault_code != 0) {
154 return NT_STATUS_NET_WRITE_FAULT;
157 return NT_STATUS_OK;
160 static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
162 uint16_t opnum = dce_call->pkt.u.request.opnum;
164 switch (opnum) {
166 gen_reply_switch($data);
168 pidl "
169 default:
170 dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
171 break;
174 if (dce_call->fault_code != 0) {
175 return NT_STATUS_NET_WRITE_FAULT;
178 return NT_STATUS_OK;
181 static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
183 NTSTATUS status;
184 uint16_t opnum = dce_call->pkt.u.request.opnum;
186 status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
187 if (!NT_STATUS_IS_OK(status)) {
188 dce_call->fault_code = DCERPC_FAULT_NDR;
189 return NT_STATUS_NET_WRITE_FAULT;
192 return NT_STATUS_OK;
195 static const struct dcesrv_interface $name\_interface = {
196 .name = \"$name\",
197 .uuid = $uuid,
198 .if_version = $if_version,
199 .bind = $name\__op_bind,
200 .unbind = $name\__op_unbind,
201 .ndr_pull = $name\__op_ndr_pull,
202 .dispatch = $name\__op_dispatch,
203 .reply = $name\__op_reply,
204 .ndr_push = $name\__op_ndr_push
210 #####################################################################
211 # produce boilerplate code for an endpoint server
212 sub Boilerplate_Ep_Server($)
214 my($interface) = shift;
215 my $name = $interface->{NAME};
216 my $uname = uc $name;
218 pidl "
219 static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
221 int i;
223 for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
224 NTSTATUS ret;
225 const char *name = dcerpc_table_$name.endpoints->names[i];
227 ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
228 if (!NT_STATUS_IS_OK(ret)) {
229 DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
230 return ret;
234 return NT_STATUS_OK;
237 static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
239 if (dcerpc_table_$name.if_version == if_version &&
240 strcmp(dcerpc_table_$name.uuid, uuid)==0) {
241 memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
242 return True;
245 return False;
248 static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
250 if (strcmp(dcerpc_table_$name.name, name)==0) {
251 memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
252 return True;
255 return False;
258 NTSTATUS dcerpc_server_$name\_init(void)
260 NTSTATUS ret;
261 struct dcesrv_endpoint_server ep_server;
263 /* fill in our name */
264 ep_server.name = \"$name\";
266 /* fill in all the operations */
267 ep_server.init_server = $name\__op_init_server;
269 ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
270 ep_server.interface_by_name = $name\__op_interface_by_name;
272 /* register ourselves with the DCERPC subsystem. */
273 ret = dcerpc_register_ep_server(&ep_server);
275 if (!NT_STATUS_IS_OK(ret)) {
276 DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
277 return ret;
280 return ret;
286 #####################################################################
287 # dcom interface stub from a parsed IDL structure
288 sub ParseInterface($)
290 my($interface) = shift;
292 return "" if has_property($interface, "local");
294 my($data) = $interface->{DATA};
295 my $count = 0;
297 $res = "";
299 if (!defined $interface->{PROPERTIES}->{uuid}) {
300 return $res;
303 if (!defined $interface->{PROPERTIES}->{version}) {
304 $interface->{PROPERTIES}->{version} = "0.0";
307 foreach my $d (@{$data}) {
308 if ($d->{TYPE} eq "FUNCTION") { $count++; }
311 if ($count == 0) {
312 return $res;
315 $res = "/* dcom interface stub generated by pidl */\n\n";
316 Boilerplate_Iface($interface);
317 Boilerplate_Ep_Server($interface);
319 return $res;