diff options
Diffstat (limited to 'source4/build/pidl/proxy.pm')
-rw-r--r-- | source4/build/pidl/proxy.pm | 166 |
1 files changed, 166 insertions, 0 deletions
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; |