From 79c5d73a71c35f5b16232072a7b52033cb9364cb Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 12 Nov 2004 00:48:24 +0000 Subject: r3689: Large number of COM updates: - Work on server side and local COM support (should work, just no example classes yet) - Use vtables so that local and remote calls can be used transparently - Generate 'proxies and stubs' rather then heavily modified code in client.pm and server.pm. proxies (client side code) are generated in proxy.pm, stubs (server side dispatchers) are generated in stubs.pm - Support registering classes and interfaces - DCOM interfaces no longer have to be in the same IDL file as their base interface, which will allow us to split up dcom.idl (This used to be commit 7466947a23985f9bb15209b67880f7b94dc515c8) --- source4/build/pidl/proxy.pm | 166 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 source4/build/pidl/proxy.pm (limited to 'source4/build/pidl/proxy.pm') diff --git a/source4/build/pidl/proxy.pm b/source4/build/pidl/proxy.pm new file mode 100644 index 0000000000..b6d9733419 --- /dev/null +++ b/source4/build/pidl/proxy.pm @@ -0,0 +1,166 @@ +################################################### +# DCOM proxy generator +# Copyright jelmer@samba.org 2003 +# released under the GNU GPL + +package IdlProxy; + +use strict; + +my($res); + +sub ParseVTable($$) +{ + my $interface = shift; + my $name = shift; + + # Generate the vtable + $res .="\tstruct dcom_$interface->{NAME}_vtable $name = {"; + + if (defined($interface->{BASE})) { + $res .= "\n\t\t{},"; + } + + my $data = $interface->{DATA}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + $res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}"; + $res .= ","; + } + } + + $res .= "\n\t};\n\n"; +} + +sub ParseRegFunc($) +{ + my $interface = shift; + + $res .= "NTSTATUS dcom_$interface->{NAME}_init(void) +{ + struct dcom_interface iface; +"; + + ParseVTable($interface, "proxy"); + + if (defined($interface->{BASE})) { + $res.= " + const void *base_vtable; + + GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &iface.base_iid); + + base_vtable = dcom_proxy_vtable_by_iid(&iface.base_iid); + if (base_vtable == NULL) { + return NT_STATUS_FOOBAR; + } + + proxy.base = *((const struct dcom_$interface->{BASE}_vtable *)base_vtable); + "; + } else { + $res .= "\tZERO_STRUCT(iface.base_iid);\n"; + } + + $res.= " + iface.num_methods = DCERPC_" . (uc $interface->{NAME}) . "_CALL_COUNT; + GUID_from_string(DCERPC_" . (uc $interface->{NAME}) . "_UUID, &iface.iid); + iface.proxy_vtable = talloc_memdup(NULL, &proxy, sizeof(struct dcom_$interface->{NAME}_vtable)); + + return register_backend(\"dcom_interface\", &iface); +}\n\n"; +} + +##################################################################### +# parse a function +sub ParseFunction($$) +{ + my $interface = shift; + my $fn = shift; + my $name = $fn->{NAME}; + my $uname = uc $name; + + if (util::has_property($fn, "local")) { + $res .= " +static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + /* FIXME */ + return NT_STATUS_NOT_SUPPORTED; +}\n"; + } else { + $res .= " +static struct rpc_request *dcom_proxy_$interface->{NAME}_$name\_send(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + struct dcerpc_pipe *p; + NTSTATUS status = dcom_get_pipe(d, &p); + + if (NT_STATUS_IS_ERR(status)) { + return NULL; + } + + ZERO_STRUCT(r->in.ORPCthis); + r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; + r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; + + if (p->flags & DCERPC_DEBUG_PRINT_IN) { + NDR_PRINT_IN_DEBUG($name, r); + } + + return dcerpc_ndr_request_send(p, &d->ipid, DCERPC_$uname, mem_ctx, + (ndr_push_flags_fn_t) ndr_push_$name, + (ndr_pull_flags_fn_t) ndr_pull_$name, + r, sizeof(*r)); +} + +static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + struct dcerpc_pipe *p; + NTSTATUS status = dcom_get_pipe(d, &p); + struct rpc_request *req; + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + req = dcom_proxy_$interface->{NAME}_$name\_send(d, mem_ctx, r); + if (req == NULL) return NT_STATUS_NO_MEMORY; + + status = dcerpc_ndr_request_recv(req); + + if (NT_STATUS_IS_OK(status) && (p->flags & DCERPC_DEBUG_PRINT_OUT)) { + NDR_PRINT_OUT_DEBUG($name, r); + } + "; + if ($fn->{RETURN_TYPE} eq "NTSTATUS") { + $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; + } + $res .= + " + return status; +}"; + } + + $res .=" +NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + return ((const struct dcom_$interface->{NAME}_vtable *)d->vtable)->$name (d, mem_ctx, r); +} +"; +} + + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + $res = "/* DCOM stubs generated by pidl */\n\n"; + foreach my $d (@{$data}) { + ($d->{TYPE} eq "FUNCTION") && + ParseFunction($interface, $d); + } + + ParseRegFunc($interface); +} + +1; -- cgit