From 80d3047333fceb3805ccd10a08cdf95021f57ff4 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Feb 2005 14:30:49 +0000 Subject: r5490: The big (D)COM commit! :-) Contains most of the changes described in the DCOM paper in lorikeet. This is the result of 1.5 months work (mainly figuring out how things *really* work) at the end of 2004. In general: - Clearer distinction between COM and DCOM. DCOM is now merely the glue between DCE/RPC+ORPC and COM. COM can also work without DCOM now. This makes the code a lot clearer. - Clearer distinction between NDR and DCOM. Before, NDR had a couple of "if"s to cope with DCOM, which are now gone. - Use "real" arguments rather then structures for function arguments in COM, mainly because most of these calls are local so packing/unpacking data for every call is too much overhead (both speed- and code-wise) - Support several mechanisms to load class objects: - from memory (e.g. part of the current executable, registered at start-up) - from shared object files - remotely - Most things are now also named COM rather then DCOM because that's what it really is. After an object is created, it no longer matters whether it was created locally or remotely. There is a very simple example class that contains both a class factory and a class that implements the IStream interface. It can be tested (locally only, remotely is broken at the moment) by running the COM-SIMPLE smbtorture test. Still to-do: - Autogenerate parts of the class implementation code (using the coclass definitions in IDL) - Test server-side - Implement some of the common classes, add definitions for common interfaces. (This used to be commit 71fd3e5c3aac5f0002001ab29d2248e6c6842d6f) --- source4/build/pidl/README | 24 +- source4/build/pidl/com_header.pm | 131 +++++++++++ source4/build/pidl/dcom_proxy.pm | 203 +++++++++++++++++ source4/build/pidl/dcom_stub.pm | 323 ++++++++++++++++++++++++++ source4/build/pidl/header.pm | 468 -------------------------------------- source4/build/pidl/ndr_header.pm | 445 ++++++++++++++++++++++++++++++++++++ source4/build/pidl/pidl.pl | 118 ++++++---- source4/build/pidl/proxy.pm | 201 ---------------- source4/build/pidl/stub.pm | 321 -------------------------- source4/build/smb_build/main.pm | 3 +- source4/include/includes.h | 4 +- source4/lib/com/classes/simple.c | 116 ++++++++++ source4/lib/com/com.h | 30 +++ source4/lib/com/config.mk | 10 + source4/lib/com/main.c | 85 +++++++ source4/lib/com/rot.c | 34 +++ source4/lib/com/tables.c | 107 +++++++++ source4/lib/dcom/classes/simple.c | 66 ------ source4/lib/dcom/common/dcom.h | 33 +-- source4/lib/dcom/common/main.c | 120 +--------- source4/lib/dcom/common/rot.c | 34 --- source4/lib/dcom/common/tables.c | 107 --------- source4/lib/dcom/config.mk | 26 +-- source4/librpc/idl/dcom.idl | 6 +- source4/librpc/idl/rot.idl | 14 +- source4/librpc/ndr/ndr_orpc.c | 1 + source4/rpc_server/config.mk | 2 +- source4/rpc_server/dcom/rodb.c | 2 +- source4/script/build_idl.sh | 4 +- source4/torture/com/simple.c | 93 ++++++++ source4/torture/config.mk | 7 +- source4/torture/dcom/simple.c | 114 ---------- source4/torture/torture.c | 3 + 33 files changed, 1713 insertions(+), 1542 deletions(-) create mode 100644 source4/build/pidl/com_header.pm create mode 100644 source4/build/pidl/dcom_proxy.pm create mode 100644 source4/build/pidl/dcom_stub.pm delete mode 100644 source4/build/pidl/header.pm create mode 100644 source4/build/pidl/ndr_header.pm delete mode 100644 source4/build/pidl/proxy.pm delete mode 100644 source4/build/pidl/stub.pm create mode 100644 source4/lib/com/classes/simple.c create mode 100644 source4/lib/com/com.h create mode 100644 source4/lib/com/config.mk create mode 100644 source4/lib/com/main.c create mode 100644 source4/lib/com/rot.c create mode 100644 source4/lib/com/tables.c delete mode 100644 source4/lib/dcom/classes/simple.c delete mode 100644 source4/lib/dcom/common/rot.c delete mode 100644 source4/lib/dcom/common/tables.c create mode 100644 source4/torture/com/simple.c delete mode 100644 source4/torture/dcom/simple.c (limited to 'source4') diff --git a/source4/build/pidl/README b/source4/build/pidl/README index c6432a8c0e..4b675ce210 100644 --- a/source4/build/pidl/README +++ b/source4/build/pidl/README @@ -13,20 +13,32 @@ After a parse tree is present, pidl will call one of it's backends (which one depends on the options given on the command-line). Here is a list of current backends: -client.pm - Generates client call functions in C +-- Generic -- dump.pm - Converts the parse tree back to an IDL file -eparser.pm - Generates a parser for the ethereal network sniffer +validator.pm - Validates the parse tree + +-- DCE/RPC+NDR -- +client.pm - Generates client call functions in C +eparser.pm - Generates a parser for the ethereal network sniffer by + applying regexes to the output of parser.pm +swig.pm - Generates SWIG interface files (.i) header.pm - Generates a header file with structures parser.pm - Generates pull/push functions for parsing server.pm - Generates server side implementation in C template.pm - Generates stubs in C for server implementation -validator.pm - Validates the parse tree -proxy.pm - Generates proxy object for DCOM (client-side) -stub.pm - Generates stub call handler for DCOM (server-side) -Other files in this directory are: +-- COM / DCOM -- +odl.pm - Generates IDL structures from ODL structures for use in + the NDR parser generator +dcom_proxy.pm - Generates proxy object for DCOM (client-side) +dcom_stub.pm - Generates stub call handler for DCOM (server-side) +com_header.pm - Generates header file for COM interface(s) + +-- Utility modules -- tables.pl - Generates a table of available interfaces from a list of IDL files util.pm - Misc utility functions used by *.pm and pidl.pl +typelist.pm - Utility functions for keeping track of known types and their + representation in C Tips for hacking on pidl: - Look at the pidl's parse tree by using the --keep option and looking diff --git a/source4/build/pidl/com_header.pm b/source4/build/pidl/com_header.pm new file mode 100644 index 0000000000..b0523c935a --- /dev/null +++ b/source4/build/pidl/com_header.pm @@ -0,0 +1,131 @@ +# COM Header generation +# (C) 2005 Jelmer Vernooij + +package COMHeader; + +use typelist; + +use strict; + +sub GetArgumentProtoList($) +{ + my $f = shift; + my $res = ""; + + foreach my $a (@{$f->{ELEMENTS}}) { + + $res .= ", " . typelist::mapType($a) . " "; + + my $l = $a->{POINTERS}; + $l-- if ($a->{TYPE} eq "string"); + foreach my $i (1..$l) { + $res .= "*"; + } + + if (defined $a->{ARRAY_LEN} && + !util::is_constant($a->{ARRAY_LEN}) && + !$a->{POINTERS}) { + $res .= "*"; + } + $res .= $a->{NAME}; + if (defined $a->{ARRAY_LEN} && util::is_constant($a->{ARRAY_LEN})) { + $res .= "[$a->{ARRAY_LEN}]"; + } + } + + return $res; +} + +sub GetArgumentList($) +{ + my $f = shift; + my $res = ""; + + foreach my $a (@{$f->{ELEMENTS}}) { + $res .= ", $a->{NAME}"; + } + + return $res; +} + +##################################################################### +# generate vtable structure for COM interface +sub HeaderVTable($) +{ + my $interface = shift; + my $res; + $res .= "#define " . uc($interface->{NAME}) . "_METHODS \\\n"; + if (defined($interface->{BASE})) { + $res .= "\t" . uc($interface->{BASE} . "_METHODS") . "\\\n"; + } + + my $data = $interface->{DATA}; + foreach my $d (@{$data}) { + $res .= "\t" . typelist::mapScalarType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION"); + } + $res .= "\n"; + $res .= "struct $interface->{NAME}_vtable {\n"; + $res .= "\t" . uc($interface->{NAME}) . "_METHODS\n"; + $res .= "};\n\n"; + + return $res; +} + +sub ParseInterface($) +{ + my $if = shift; + my $res; + + $res .="\n\n/* $if->{NAME} */\n"; + + $res .="#define COM_" . uc($if->{NAME}) . "_UUID $if->{PROPERTIES}->{uuid}\n\n"; + + $res .="struct $if->{NAME}_vtable;\n\n"; + + $res .="struct $if->{NAME} { + struct com_context *ctx; + struct $if->{NAME}_vtable *vtable; + void *object_data; +};\n\n"; + + $res.=HeaderVTable($if); + + foreach my $d (@{$if->{DATA}}) { + next if ($d->{TYPE} ne "FUNCTION"); + + $res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") "; + + $res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))"; + + $res .="\n"; + } + + return $res; +} + +sub ParseCoClass($) +{ + my $c = shift; + return "#define CLSID_$c->{NAME} $c->{PROPERTIES}->{uuid}\n\n"; +} + +sub Parse($) +{ + my $idl = shift; + my $res = ""; + + foreach my $x (@{$idl}) + { + if ($x->{TYPE} eq "INTERFACE" && util::has_property($x, "object")) { + $res.=ParseInterface($x); + } + + if ($x->{TYPE} eq "COCLASS") { + $res.=ParseCoClass($x); + } + } + + return $res; +} + +1; diff --git a/source4/build/pidl/dcom_proxy.pm b/source4/build/pidl/dcom_proxy.pm new file mode 100644 index 0000000000..1a1b8de064 --- /dev/null +++ b/source4/build/pidl/dcom_proxy.pm @@ -0,0 +1,203 @@ +################################################### +# DCOM parser for Samba +# Basically the glue between COM and DCE/RPC with NDR +# Copyright jelmer@samba.org 2003-2005 +# released under the GNU GPL + +package DCOMProxy; + +use com_header; + +use strict; + +my($res); + +sub ParseVTable($$) +{ + my $interface = shift; + my $name = shift; + + # Generate the vtable + $res .="\tstruct $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 .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void) +{ + struct GUID base_iid; + struct GUID iid; + struct $interface->{NAME}_vtable proxy_vtable;"; + + if (defined($interface->{BASE})) { + $res.= " + const void *base_vtable; + + GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &base_iid); + + base_vtable = dcom_proxy_vtable_by_iid(&base_iid); + if (base_vtable == NULL) { + DEBUG(0, (\"No proxy registered for base interface\n\")); + return NT_STATUS_FOOBAR; + } + + memcpy(&proxy_vtable, base_vtable, sizeof(struct $interface->{BASE}_vtable)); + +"; + } + foreach my $x (@{$interface->{DATA}}) { + next unless ($x->{TYPE} eq "FUNCTION"); + + $res .= "\tproxy_vtable.$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n"; + } + + $res.= " + GUID_from_string(DCERPC_" . (uc $interface->{NAME}) . "_UUID, &iid); + + return dcom_register_proxy(&iid, &proxy_vtable); +}\n\n"; +} + +##################################################################### +# parse a function +sub ParseFunction($$) +{ + my $interface = shift; + my $fn = shift; + my $name = $fn->{NAME}; + my $uname = uc $name; + + $res.=" +static $fn->{RETURN_TYPE} dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . COMHeader::GetArgumentProtoList($fn) . ") +{ + struct dcerpc_pipe *p; + NTSTATUS status = dcom_get_pipe(d, &p); + struct $name r; + struct rpc_request *req; + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + ZERO_STRUCT(r.in.ORPCthis); + r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; + r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; +"; + + # Put arguments into r + foreach my $a (@{$fn->{DATA}}) { + next if ($a->{NAME} eq "ORPCthis"); + next unless (util::has_property($a, "in")); + $res .= "\tr.in.$a->{NAME} = $a->{NAME};\n"; + } + + $res .=" + if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) { + NDR_PRINT_IN_DEBUG($name, &r); + } + + status = dcerpc_ndr_request(p, &d->ipid, &dcerpc_table_$interface->{NAME}, DCERPC_$uname, mem_ctx, &r); + + if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) { + NDR_PRINT_OUT_DEBUG($name, r); + } + +"; + + # Put r info back into arguments + foreach my $a (@{$fn->{DATA}}) { + next if ($a->{NAME} eq "ORPCthat"); + next unless (util::has_property($a, "out")); + $res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n"; + } + + if ($fn->{RETURN_TYPE} eq "NTSTATUS") { + $res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n"; + } + + $res .= + " + return r.out.result; +}\n\n"; +} + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + $res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n"; + foreach my $d (@{$data}) { + ($d->{TYPE} eq "FUNCTION") && + ParseFunction($interface, $d); + } + + ParseRegFunc($interface); +} + +sub RegistrationFunction($$) +{ + my $idl = shift; + my $basename = shift; + + my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n"; + $res .= "{\n"; + $res .="\tNTSTATUS status = NT_STATUS_OK;\n"; + foreach my $interface (@{$idl}) { + next if $interface->{TYPE} ne "INTERFACE"; + next if not util::has_property($interface, "object"); + + my $data = $interface->{INHERITED_DATA}; + my $count = 0; + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + next if ($count == 0); + + $res .= "\tstatus = dcom_$interface->{NAME}_init();\n"; + $res .= "\tif (NT_STATUS_IS_ERR(status)) {\n"; + $res .= "\t\treturn status;\n"; + $res .= "\t}\n\n"; + } + $res .= "\treturn status;\n"; + $res .= "}\n\n"; + + return $res; +} + +sub Parse($) +{ + my $pidl = shift; + my $res = ""; + + foreach my $x (@{$pidl}) { + next if ($x->{TYPE} ne "INTERFACE"); + next if util::has_property($x, "local"); + next unless util::has_property($x, "object"); + + $res .= ParseInterface($x); + } + + return $res; +} + +1; diff --git a/source4/build/pidl/dcom_stub.pm b/source4/build/pidl/dcom_stub.pm new file mode 100644 index 0000000000..024037e2e8 --- /dev/null +++ b/source4/build/pidl/dcom_stub.pm @@ -0,0 +1,323 @@ +################################################### +# DCOM stub boilerplate generator +# Copyright jelmer@samba.org 2004-2005 +# Copyright tridge@samba.org 2003 +# Copyright metze@samba.org 2004 +# released under the GNU GPL + +package DCOMStub; + +use strict; + +my($res); + +sub pidl($) +{ + $res .= shift; +} + +##################################################### +# generate the switch statement for function dispatch +sub gen_dispatch_switch($) +{ + my $data = shift; + + my $count = 0; + foreach my $d (@{$data}) { + next if ($d->{TYPE} ne "FUNCTION"); + + pidl "\tcase $count: {\n"; + if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") { + pidl "\t\tNTSTATUS result;\n"; + } + pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; + pidl "\t\tif (DEBUGLEVEL > 10) {\n"; + pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n"; + pidl "\t\t}\n"; + if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") { + pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n"; + } else { + pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n"; + } + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n"; + pidl "\t\t}\n"; + pidl "\t\tbreak;\n\t}\n"; + $count++; + } +} + +##################################################### +# generate the switch statement for function reply +sub gen_reply_switch($) +{ + my $data = shift; + + my $count = 0; + foreach my $d (@{$data}) { + next if ($d->{TYPE} ne "FUNCTION"); + + pidl "\tcase $count: {\n"; + pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n"; + pidl "\t\t}\n"; + pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n"; + pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n"; + pidl "\t\t}\n"; + pidl "\t\tif (dce_call->fault_code != 0) {\n"; + pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n"; + pidl "\t\t}\n"; + pidl "\t\tbreak;\n\t}\n"; + $count++; + } +} + +##################################################################### +# produce boilerplate code for a interface +sub Boilerplate_Iface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $name = $interface->{NAME}; + my $uname = uc $name; + my $uuid = util::make_str($interface->{PROPERTIES}->{uuid}); + my $if_version = $interface->{PROPERTIES}->{version}; + + pidl " +static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) +{ +#ifdef DCESRV_INTERFACE_$uname\_BIND + return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); +#else + return NT_STATUS_OK; +#endif +} + +static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface) +{ +#ifdef DCESRV_INTERFACE_$uname\_UNBIND + DCESRV_INTERFACE_$uname\_UNBIND(context, iface); +#else + return; +#endif +} + +static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r) +{ + NTSTATUS status; + uint16_t opnum = dce_call->pkt.u.request.opnum; + + dce_call->fault_code = 0; + + if (opnum >= dcerpc_table_$name.num_calls) { + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + return NT_STATUS_NET_WRITE_FAULT; + } + + *r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size); + NT_STATUS_HAVE_NO_MEMORY(*r); + + /* unravel the NDR for the packet */ + status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); + if (!NT_STATUS_IS_OK(status)) { + dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, + &dce_call->pkt.u.request.stub_and_verifier); + dce_call->fault_code = DCERPC_FAULT_NDR; + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + +static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16_t opnum = dce_call->pkt.u.request.opnum; + struct GUID ipid = dce_call->pkt.u.request.object.object; + struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid); + const struct dcom_$name\_vtable *vtable = iface->vtable; + + switch (opnum) { +"; + gen_dispatch_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, + &dce_call->pkt.u.request.stub_and_verifier); + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + +static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16_t opnum = dce_call->pkt.u.request.opnum; + + switch (opnum) { +"; + gen_reply_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, + &dce_call->pkt.u.request.stub_and_verifier); + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + +static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r) +{ + NTSTATUS status; + uint16_t opnum = dce_call->pkt.u.request.opnum; + + status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r); + if (!NT_STATUS_IS_OK(status)) { + dce_call->fault_code = DCERPC_FAULT_NDR; + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + +static const struct dcesrv_interface $name\_interface = { + .name = \"$name\", + .uuid = $uuid, + .if_version = $if_version, + .bind = $name\__op_bind, + .unbind = $name\__op_unbind, + .ndr_pull = $name\__op_ndr_pull, + .dispatch = $name\__op_dispatch, + .reply = $name\__op_reply, + .ndr_push = $name\__op_ndr_push +}; + +"; +} + +##################################################################### +# produce boilerplate code for an endpoint server +sub Boilerplate_Ep_Server($) +{ + my($interface) = shift; + my $name = $interface->{NAME}; + my $uname = uc $name; + + pidl " +static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) +{ + int i; + + for (i=0;icount;i++) { + NTSTATUS ret; + const char *name = dcerpc_table_$name.endpoints->names[i]; + + ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name)); + return ret; + } + } + + return NT_STATUS_OK; +} + +static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version) +{ + if (dcerpc_table_$name.if_version == if_version && + strcmp(dcerpc_table_$name.uuid, uuid)==0) { + memcpy(iface,&dcerpc_table_$name, sizeof(*iface)); + return True; + } + + return False; +} + +static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name) +{ + if (strcmp(dcerpc_table_$name.name, name)==0) { + memcpy(iface,&dcerpc_table_$name, sizeof(*iface)); + return True; + } + + return False; +} + +NTSTATUS dcerpc_server_$name\_init(void) +{ + NTSTATUS ret; + struct dcesrv_endpoint_server ep_server; + + /* fill in our name */ + ep_server.name = \"$name\"; + + /* fill in all the operations */ + ep_server.init_server = $name\__op_init_server; + + ep_server.interface_by_uuid = $name\__op_interface_by_uuid; + ep_server.interface_by_name = $name\__op_interface_by_name; + + /* register ourselves with the DCERPC subsystem. */ + ret = dcerpc_register_ep_server(&ep_server); + + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\")); + return ret; + } + + return ret; +} + +"; +} + +##################################################################### +# dcom interface stub from a parsed IDL structure +sub ParseInterface($) +{ + my($interface) = shift; + + return "" if util::has_property($interface, "local"); + + my($data) = $interface->{DATA}; + my $count = 0; + + $res = ""; + + if (!defined $interface->{PROPERTIES}->{uuid}) { + return $res; + } + + if (!defined $interface->{PROPERTIES}->{version}) { + $interface->{PROPERTIES}->{version} = "0.0"; + } + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return $res; + } + + $res = "/* dcom interface stub generated by pidl */\n\n"; + Boilerplate_Iface($interface); + Boilerplate_Ep_Server($interface); + + return $res; +} + +1; diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm deleted file mode 100644 index eeb2886bce..0000000000 --- a/source4/build/pidl/header.pm +++ /dev/null @@ -1,468 +0,0 @@ -################################################### -# create C header files for an IDL structure -# Copyright tridge@samba.org 2000 -# released under the GNU GPL - -package IdlHeader; - -use strict; -use needed; -use typelist; - -my($res); -my($tab_depth); - -sub pidl ($) -{ - $res .= shift; -} - -sub tabs() -{ - for (my($i)=0; $i < $tab_depth; $i++) { - pidl "\t"; - } -} - -##################################################################### -# parse a properties list -sub HeaderProperties($$) -{ - my($props) = shift; - my($ignores) = shift; - my $ret = ""; - - return; - - foreach my $d (keys %{$props}) { - next if ($ignores->{$d}); - if($props->{$d} ne "1") { - $ret.= "$d(" . $props->{$d} . "),"; - } else { - $ret.="$d,"; - } - } - - if ($ret) { - pidl "/* [" . substr($ret, 0, -1) . "] */"; - } -} - -##################################################################### -# parse a structure element -sub HeaderElement($) -{ - my($element) = shift; - - if (defined $element->{PROPERTIES}) { - HeaderProperties($element->{PROPERTIES}, {"in" => 1, "out" => 1}); - } - pidl tabs(); - HeaderType($element, $element->{TYPE}, ""); - pidl " "; - if ($element->{POINTERS} && $element->{TYPE} ne "string") { - my($n) = $element->{POINTERS}; - for (my($i)=$n; $i > 0; $i--) { - pidl "*"; - } - } - if (defined $element->{ARRAY_LEN} && - !util::is_constant($element->{ARRAY_LEN}) && - !$element->{POINTERS}) { - # conformant arrays are ugly! I choose to implement them with - # pointers instead of the [1] method - pidl "*"; - } - pidl "$element->{NAME}"; - if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) { - pidl "[$element->{ARRAY_LEN}]"; - } - pidl ";\n"; -} - -##################################################################### -# parse a struct -sub HeaderStruct($$) -{ - my($struct) = shift; - my($name) = shift; - pidl "\nstruct $name {\n"; - $tab_depth++; - my $el_count=0; - if (defined $struct->{ELEMENTS}) { - foreach my $e (@{$struct->{ELEMENTS}}) { - HeaderElement($e); - $el_count++; - } - } - if ($el_count == 0) { - # some compilers can't handle empty structures - pidl "\tchar _empty_;\n"; - } - $tab_depth--; - pidl "}"; -} - -##################################################################### -# parse a enum -sub HeaderEnum($$) -{ - my($enum) = shift; - my($name) = shift; - - pidl "\nenum $name {\n"; - $tab_depth++; - my $els = \@{$enum->{ELEMENTS}}; - foreach my $i (0 .. $#{$els}-1) { - my $e = ${$els}[$i]; - tabs(); - chomp $e; - pidl "$e,\n"; - } - - my $e = ${$els}[$#{$els}]; - tabs(); - chomp $e; - if ($e !~ /^(.*?)\s*$/) { - die "Bad enum $name\n"; - } - pidl "$1\n"; - $tab_depth--; - pidl "}"; -} - -##################################################################### -# parse a bitmap -sub HeaderBitmap($$) -{ - my($bitmap) = shift; - my($name) = shift; - - pidl "\n/* bitmap $name */\n"; - - my $els = \@{$bitmap->{ELEMENTS}}; - foreach my $i (0 .. $#{$els}) { - my $e = ${$els}[$i]; - chomp $e; - pidl "#define $e\n"; - } - - pidl "\n"; -} - -##################################################################### -# parse a union -sub HeaderUnion($$) -{ - my($union) = shift; - my($name) = shift; - my %done = (); - - if (defined $union->{PROPERTIES}) { - HeaderProperties($union->{PROPERTIES}, {}); - } - pidl "\nunion $name {\n"; - $tab_depth++; - foreach my $e (@{$union->{ELEMENTS}}) { - if ($e->{TYPE} ne "EMPTY") { - if (! defined $done{$e->{NAME}}) { - HeaderElement($e); - } - $done{$e->{NAME}} = 1; - } - } - $tab_depth--; - pidl "}"; -} - -##################################################################### -# parse a type -sub HeaderType($$$) -{ - my $e = shift; - my($data) = shift; - my($name) = shift; - if (ref($data) eq "HASH") { - ($data->{TYPE} eq "ENUM") && - HeaderEnum($data, $name); - ($data->{TYPE} eq "BITMAP") && - HeaderBitmap($data, $name); - ($data->{TYPE} eq "STRUCT") && - HeaderStruct($data, $name); - ($data->{TYPE} eq "UNION") && - HeaderUnion($data, $name); - return; - } - - pidl typelist::mapType($e); -} - -##################################################################### -# parse a typedef -sub HeaderTypedef($) -{ - my($typedef) = shift; - HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}); - pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP"); -} - -##################################################################### -# prototype a typedef -sub HeaderTypedefProto($) -{ - my($d) = shift; - - my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE}); - - if (needed::is_needed("ndr_size_$d->{NAME}")) { - my $size_args = $tf->{SIZE_FN_ARGS}->($d); - pidl "size_t ndr_size_$d->{NAME}($size_args);\n"; - } - - return unless util::has_property($d, "public"); - - my $pull_args = $tf->{PULL_FN_ARGS}->($d); - my $push_args = $tf->{PUSH_FN_ARGS}->($d); - my $print_args = $tf->{PRINT_FN_ARGS}->($d); - unless (util::has_property($d, "nopush")) { - pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n"; - } - unless (util::has_property($d, "nopull")) { - pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n"; - } - unless (util::has_property($d, "noprint")) { - pidl "void ndr_print_$d->{NAME}($print_args);\n"; - } -} - -##################################################################### -# parse a const -sub HeaderConst($) -{ - my($const) = shift; - if (!defined($const->{ARRAY_LEN})) { - pidl "#define $const->{NAME}\t( $const->{VALUE} )\n"; - } else { - pidl "#define $const->{NAME}\t $const->{VALUE}\n"; - } -} - -##################################################################### -# parse a function -sub HeaderFunctionInOut($$) -{ - my($fn) = shift; - my($prop) = shift; - - foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, $prop)) { - HeaderElement($e); - } - } -} - -##################################################################### -# determine if we need an "in" or "out" section -sub HeaderFunctionInOut_needed($$) -{ - my($fn) = shift; - my($prop) = shift; - - if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { - return 1; - } - - foreach my $e (@{$fn->{ELEMENTS}}) { - if (util::has_property($e, $prop)) { - return 1; - } - } - - return undef; -} - -##################################################################### -# parse a function -sub HeaderFunction($) -{ - my($fn) = shift; - - pidl "\nstruct $fn->{NAME} {\n"; - $tab_depth++; - my $needed = 0; - - if (HeaderFunctionInOut_needed($fn, "in")) { - tabs(); - pidl "struct {\n"; - $tab_depth++; - HeaderFunctionInOut($fn, "in"); - $tab_depth--; - tabs(); - pidl "} in;\n\n"; - $needed++; - } - - if (HeaderFunctionInOut_needed($fn, "out")) { - tabs(); - pidl "struct {\n"; - $tab_depth++; - HeaderFunctionInOut($fn, "out"); - if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { - tabs(); - pidl typelist::mapScalarType($fn->{RETURN_TYPE}) . " result;\n"; - } - $tab_depth--; - tabs(); - pidl "} out;\n\n"; - $needed++; - } - - if (! $needed) { - # sigh - some compilers don't like empty structures - tabs(); - pidl "int _dummy_element;\n"; - } - - $tab_depth--; - pidl "};\n\n"; -} - -##################################################################### -# output prototypes for a IDL function -sub HeaderFnProto($$) -{ - my $interface = shift; - my $fn = shift; - my $name = $fn->{NAME}; - - pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n"; - - if (util::has_property($interface, "object")) { - pidl "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - } else { - pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; - } - pidl "\n"; -} - -##################################################################### -# generate vtable structure for DCOM interface -sub HeaderVTable($) -{ - my $interface = shift; - pidl "struct dcom_$interface->{NAME}_vtable {\n"; - if (defined($interface->{BASE})) { - pidl "\tstruct dcom_$interface->{BASE}\_vtable base;\n"; - } - - my $data = $interface->{DATA}; - foreach my $d (@{$data}) { - pidl "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $d->{NAME} *r);\n" if ($d->{TYPE} eq "FUNCTION"); - } - pidl "};\n\n"; -} - -##################################################################### -# parse the interface definitions -sub HeaderInterface($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - - my $count = 0; - - pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n"; - pidl "#define _HEADER_NDR_$interface->{NAME}\n\n"; - - if (defined $interface->{PROPERTIES}->{depends}) { - my @d = split / /, $interface->{PROPERTIES}->{depends}; - foreach my $i (@d) { - pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n"; - } - } - - # Object interfaces use ORPC - if (util::has_property($interface, "object")) { - pidl "#include \"librpc/gen_ndr/ndr_orpc.h\"\n"; - } - - if (defined $interface->{PROPERTIES}->{uuid}) { - my $name = uc $interface->{NAME}; - pidl "#define DCERPC_$name\_UUID " . - util::make_str($interface->{PROPERTIES}->{uuid}) . "\n"; - - if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; } - pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n"; - - pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n"; - - if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; } - pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n"; - - pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n"; - pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n"; - } - - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { - my $u_name = uc $d->{NAME}; - pidl "#define DCERPC_$u_name ("; - - if (defined($interface->{BASE})) { - pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; - } - - pidl sprintf("0x%02x", $count) . ")\n"; - $count++; - } - } - - pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT ("; - - if (defined($interface->{BASE})) { - pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; - } - - pidl "$count)\n\n"; - - foreach my $d (@{$data}) { - ($d->{TYPE} eq "CONST") && - HeaderConst($d); - ($d->{TYPE} eq "TYPEDEF") && - HeaderTypedef($d); - ($d->{TYPE} eq "TYPEDEF") && - HeaderTypedefProto($d); - ($d->{TYPE} eq "FUNCTION") && - HeaderFunction($d); - ($d->{TYPE} eq "FUNCTION") && - HeaderFnProto($interface, $d); - } - - (util::has_property($interface, "object")) && - HeaderVTable($interface); - - pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; -} - -##################################################################### -# parse a parsed IDL into a C header -sub Parse($) -{ - my($idl) = shift; - $tab_depth = 0; - - NdrParser::Load($idl); - - $res = ""; - pidl "/* header auto-generated by pidl */\n\n"; - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - needed::BuildNeeded($x); - HeaderInterface($x); - } - } - return $res; -} - -1; diff --git a/source4/build/pidl/ndr_header.pm b/source4/build/pidl/ndr_header.pm new file mode 100644 index 0000000000..c928ee1db3 --- /dev/null +++ b/source4/build/pidl/ndr_header.pm @@ -0,0 +1,445 @@ +################################################### +# create C header files for an IDL structure +# Copyright tridge@samba.org 2000 +# released under the GNU GPL + +package NdrHeader; + +use strict; +use needed; +use typelist; + +my($res); +my($tab_depth); + +sub pidl ($) +{ + $res .= shift; +} + +sub tabs() +{ + for (my($i)=0; $i < $tab_depth; $i++) { + pidl "\t"; + } +} + +##################################################################### +# parse a properties list +sub HeaderProperties($$) +{ + my($props) = shift; + my($ignores) = shift; + my $ret = ""; + + return; + + foreach my $d (keys %{$props}) { + next if ($ignores->{$d}); + if($props->{$d} ne "1") { + $ret.= "$d(" . $props->{$d} . "),"; + } else { + $ret.="$d,"; + } + } + + if ($ret) { + pidl "/* [" . substr($ret, 0, -1) . "] */"; + } +} + +##################################################################### +# parse a structure element +sub HeaderElement($) +{ + my($element) = shift; + + if (defined $element->{PROPERTIES}) { + HeaderProperties($element->{PROPERTIES}, {"in" => 1, "out" => 1}); + } + pidl tabs(); + HeaderType($element, $element->{TYPE}, ""); + pidl " "; + if ($element->{POINTERS} && $element->{TYPE} ne "string") { + my($n) = $element->{POINTERS}; + for (my($i)=$n; $i > 0; $i--) { + pidl "*"; + } + } + if (defined $element->{ARRAY_LEN} && + !util::is_constant($element->{ARRAY_LEN}) && + !$element->{POINTERS}) { + # conformant arrays are ugly! I choose to implement them with + # pointers instead of the [1] method + pidl "*"; + } + pidl "$element->{NAME}"; + if (defined $element->{ARRAY_LEN} && util::is_constant($element->{ARRAY_LEN})) { + pidl "[$element->{ARRAY_LEN}]"; + } + pidl ";\n"; +} + +##################################################################### +# parse a struct +sub HeaderStruct($$) +{ + my($struct) = shift; + my($name) = shift; + pidl "\nstruct $name {\n"; + $tab_depth++; + my $el_count=0; + if (defined $struct->{ELEMENTS}) { + foreach my $e (@{$struct->{ELEMENTS}}) { + HeaderElement($e); + $el_count++; + } + } + if ($el_count == 0) { + # some compilers can't handle empty structures + pidl "\tchar _empty_;\n"; + } + $tab_depth--; + pidl "}"; +} + +##################################################################### +# parse a enum +sub HeaderEnum($$) +{ + my($enum) = shift; + my($name) = shift; + + pidl "\nenum $name {\n"; + $tab_depth++; + my $els = \@{$enum->{ELEMENTS}}; + foreach my $i (0 .. $#{$els}-1) { + my $e = ${$els}[$i]; + tabs(); + chomp $e; + pidl "$e,\n"; + } + + my $e = ${$els}[$#{$els}]; + tabs(); + chomp $e; + if ($e !~ /^(.*?)\s*$/) { + die "Bad enum $name\n"; + } + pidl "$1\n"; + $tab_depth--; + pidl "}"; +} + +##################################################################### +# parse a bitmap +sub HeaderBitmap($$) +{ + my($bitmap) = shift; + my($name) = shift; + + pidl "\n/* bitmap $name */\n"; + + my $els = \@{$bitmap->{ELEMENTS}}; + foreach my $i (0 .. $#{$els}) { + my $e = ${$els}[$i]; + chomp $e; + pidl "#define $e\n"; + } + + pidl "\n"; +} + +##################################################################### +# parse a union +sub HeaderUnion($$) +{ + my($union) = shift; + my($name) = shift; + my %done = (); + + if (defined $union->{PROPERTIES}) { + HeaderProperties($union->{PROPERTIES}, {}); + } + pidl "\nunion $name {\n"; + $tab_depth++; + foreach my $e (@{$union->{ELEMENTS}}) { + if ($e->{TYPE} ne "EMPTY") { + if (! defined $done{$e->{NAME}}) { + HeaderElement($e); + } + $done{$e->{NAME}} = 1; + } + } + $tab_depth--; + pidl "}"; +} + +##################################################################### +# parse a type +sub HeaderType($$$) +{ + my $e = shift; + my($data) = shift; + my($name) = shift; + if (ref($data) eq "HASH") { + ($data->{TYPE} eq "ENUM") && + HeaderEnum($data, $name); + ($data->{TYPE} eq "BITMAP") && + HeaderBitmap($data, $name); + ($data->{TYPE} eq "STRUCT") && + HeaderStruct($data, $name); + ($data->{TYPE} eq "UNION") && + HeaderUnion($data, $name); + return; + } + + pidl typelist::mapType($e); +} + +##################################################################### +# parse a typedef +sub HeaderTypedef($) +{ + my($typedef) = shift; + HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}); + pidl ";\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP"); +} + +##################################################################### +# prototype a typedef +sub HeaderTypedefProto($) +{ + my($d) = shift; + + my $tf = NdrParser::get_typefamily($d->{DATA}{TYPE}); + + if (needed::is_needed("ndr_size_$d->{NAME}")) { + my $size_args = $tf->{SIZE_FN_ARGS}->($d); + pidl "size_t ndr_size_$d->{NAME}($size_args);\n"; + } + + return unless util::has_property($d, "public"); + + my $pull_args = $tf->{PULL_FN_ARGS}->($d); + my $push_args = $tf->{PUSH_FN_ARGS}->($d); + my $print_args = $tf->{PRINT_FN_ARGS}->($d); + unless (util::has_property($d, "nopush")) { + pidl "NTSTATUS ndr_push_$d->{NAME}($push_args);\n"; + } + unless (util::has_property($d, "nopull")) { + pidl "NTSTATUS ndr_pull_$d->{NAME}($pull_args);\n"; + } + unless (util::has_property($d, "noprint")) { + pidl "void ndr_print_$d->{NAME}($print_args);\n"; + } +} + +##################################################################### +# parse a const +sub HeaderConst($) +{ + my($const) = shift; + if (!defined($const->{ARRAY_LEN})) { + pidl "#define $const->{NAME}\t( $const->{VALUE} )\n"; + } else { + pidl "#define $const->{NAME}\t $const->{VALUE}\n"; + } +} + +##################################################################### +# parse a function +sub HeaderFunctionInOut($$) +{ + my($fn) = shift; + my($prop) = shift; + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (util::has_property($e, $prop)) { + HeaderElement($e); + } + } +} + +##################################################################### +# determine if we need an "in" or "out" section +sub HeaderFunctionInOut_needed($$) +{ + my($fn) = shift; + my($prop) = shift; + + if ($prop eq "out" && $fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + return 1; + } + + foreach my $e (@{$fn->{ELEMENTS}}) { + if (util::has_property($e, $prop)) { + return 1; + } + } + + return undef; +} + +##################################################################### +# parse a function +sub HeaderFunction($) +{ + my($fn) = shift; + + pidl "\nstruct $fn->{NAME} {\n"; + $tab_depth++; + my $needed = 0; + + if (HeaderFunctionInOut_needed($fn, "in")) { + tabs(); + pidl "struct {\n"; + $tab_depth++; + HeaderFunctionInOut($fn, "in"); + $tab_depth--; + tabs(); + pidl "} in;\n\n"; + $needed++; + } + + if (HeaderFunctionInOut_needed($fn, "out")) { + tabs(); + pidl "struct {\n"; + $tab_depth++; + HeaderFunctionInOut($fn, "out"); + if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") { + tabs(); + pidl typelist::mapScalarType($fn->{RETURN_TYPE}) . " result;\n"; + } + $tab_depth--; + tabs(); + pidl "} out;\n\n"; + $needed++; + } + + if (! $needed) { + # sigh - some compilers don't like empty structures + tabs(); + pidl "int _dummy_element;\n"; + } + + $tab_depth--; + pidl "};\n\n"; +} + +##################################################################### +# output prototypes for a IDL function +sub HeaderFnProto($$) +{ + my $interface = shift; + my $fn = shift; + my $name = $fn->{NAME}; + + pidl "void ndr_print_$name(struct ndr_print *ndr, const char *name, int flags, struct $name *r);\n"; + + pidl "NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; + pidl "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);\n"; + + pidl "\n"; +} + +##################################################################### +# parse the interface definitions +sub HeaderInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + + my $count = 0; + + pidl "#ifndef _HEADER_NDR_$interface->{NAME}\n"; + pidl "#define _HEADER_NDR_$interface->{NAME}\n\n"; + + if (defined $interface->{PROPERTIES}->{depends}) { + my @d = split / /, $interface->{PROPERTIES}->{depends}; + foreach my $i (@d) { + pidl "#include \"librpc/gen_ndr/ndr_$i\.h\"\n"; + } + } + + # Object interfaces use ORPC + if (util::has_property($interface, "object")) { + pidl "#include \"librpc/gen_ndr/ndr_orpc.h\"\n"; + } + + if (defined $interface->{PROPERTIES}->{uuid}) { + my $name = uc $interface->{NAME}; + pidl "#define DCERPC_$name\_UUID " . + util::make_str($interface->{PROPERTIES}->{uuid}) . "\n"; + + if(!defined $interface->{PROPERTIES}->{version}) { $interface->{PROPERTIES}->{version} = "0.0"; } + pidl "#define DCERPC_$name\_VERSION $interface->{PROPERTIES}->{version}\n"; + + pidl "#define DCERPC_$name\_NAME \"$interface->{NAME}\"\n"; + + if(!defined $interface->{PROPERTIES}->{helpstring}) { $interface->{PROPERTIES}->{helpstring} = "NULL"; } + pidl "#define DCERPC_$name\_HELPSTRING $interface->{PROPERTIES}->{helpstring}\n"; + + pidl "\nextern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n"; + pidl "NTSTATUS dcerpc_server_$interface->{NAME}_init(void);\n\n"; + } + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + my $u_name = uc $d->{NAME}; + pidl "#define DCERPC_$u_name ("; + + if (defined($interface->{BASE})) { + pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; + } + + pidl sprintf("0x%02x", $count) . ")\n"; + $count++; + } + } + + pidl "\n#define DCERPC_" . uc $interface->{NAME} . "_CALL_COUNT ("; + + if (defined($interface->{BASE})) { + pidl "DCERPC_" . uc $interface->{BASE} . "_CALL_COUNT + "; + } + + pidl "$count)\n\n"; + + foreach my $d (@{$data}) { + ($d->{TYPE} eq "CONST") && + HeaderConst($d); + ($d->{TYPE} eq "TYPEDEF") && + HeaderTypedef($d); + ($d->{TYPE} eq "TYPEDEF") && + HeaderTypedefProto($d); + ($d->{TYPE} eq "FUNCTION") && + HeaderFunction($d); + ($d->{TYPE} eq "FUNCTION") && + HeaderFnProto($interface, $d); + } + + pidl "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; +} + +##################################################################### +# parse a parsed IDL into a C header +sub Parse($) +{ + my($idl) = shift; + $tab_depth = 0; + + NdrParser::Load($idl); + + $res = ""; + pidl "/* header auto-generated by pidl */\n\n"; + foreach my $x (@{$idl}) { + if ($x->{TYPE} eq "INTERFACE") { + needed::BuildNeeded($x); + HeaderInterface($x); + } + } + return $res; +} + +1; diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index b535215d03..f7b213dcb0 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -15,12 +15,13 @@ use Getopt::Long; use File::Basename; use idl; use dump; -use header; +use ndr_header; +use ndr; use server; use client; -use proxy; -use stub; -use ndr; +use dcom_proxy; +use dcom_stub; +use com_header; use odl; use eparser; use validator; @@ -41,6 +42,8 @@ my($opt_parser) = 0; my($opt_eparser) = 0; my($opt_keep) = 0; my($opt_swig) = 0; +my($opt_dcom_proxy) = 0; +my($opt_com_header) = 0; my($opt_odl) = 0; my($opt_output); @@ -62,27 +65,29 @@ sub IdlParse($) sub ShowHelp() { print " - perl IDL parser and code generator - Copyright (C) tridge\@samba.org - - Usage: pidl.pl [options] - - Options: - --help this help page - --output OUTNAME put output in OUTNAME.* - --parse parse a idl file to a .pidl file - --dump dump a pidl file back to idl - --header create a C header file - --parser create a C NDR parser - --client create a C client - --server create server boilerplate - --template print a template for a pipe - --eparser create an ethereal parser - --swig create swig wrapper file - --diff run diff on the idl and dumped output - --keep keep the .pidl file - --odl accept ODL input - \n"; + perl IDL parser and code generator + Copyright (C) tridge\@samba.org + + Usage: pidl.pl [options] + + Options: + --help this help page + --output OUTNAME put output in OUTNAME.* + --parse parse a idl file to a .pidl file + --dump dump a pidl file back to idl + --header create a C header file + --parser create a C NDR parser + --client create a C client + --server create server boilerplate + --template print a template for a pipe + --eparser create an ethereal parser + --swig create swig wrapper file + --diff run diff on the idl and dumped output + --keep keep the .pidl file + --odl accept ODL input + --dcom-proxy create DCOM proxy (implies --odl) + --com-header create header for COM interfaces (implies --odl) + \n"; exit(0); } @@ -101,7 +106,9 @@ GetOptions ( 'diff' => \$opt_diff, 'odl' => \$opt_odl, 'keep' => \$opt_keep, - 'swig' => \$opt_swig + 'swig' => \$opt_swig, + 'dcom-proxy' => \$opt_dcom_proxy, + 'com-header' => \$opt_com_header ); if ($opt_help) { @@ -113,7 +120,6 @@ sub process_file($) { my $idl_file = shift; my $output; - my $podl; my $pidl; my $basename = basename($idl_file, ".idl"); @@ -144,18 +150,48 @@ sub process_file($) print IdlDump::Dump($pidl); } - if ($opt_header || $opt_parser) { + if ($opt_diff) { + my($tempfile) = util::ChangeExtension($output, ".tmp"); + util::FileSave($tempfile, IdlDump::Dump($pidl)); + system("diff -wu $idl_file $tempfile"); + unlink($tempfile); + } + + if ($opt_header || $opt_parser || $opt_com_header || $opt_dcom_proxy) { typelist::LoadIdl($pidl); } + if ($opt_com_header) { + my $res = COMHeader::Parse($pidl); + if ($res) { + my $h_filename = dirname($output) . "/com_$basename.h"; + util::FileSave($h_filename, + "#include \"librpc/gen_ndr/ndr_orpc.h\"\n" . + "#include \"librpc/gen_ndr/ndr_$basename.h\"\n" . + $res); + } + $opt_odl = 1; + } + + if ($opt_dcom_proxy) { + my $res = DCOMProxy::Parse($pidl); + if ($res) { + my ($client) = util::ChangeExtension($output, "_p.c"); + util::FileSave($client, + "#include \"includes.h\"\n" . + "#include \"librpc/gen_ndr/com_$basename.h\"\n" . + "#include \"lib/dcom/common/orpc.h\"\n". $res); + } + $opt_odl = 1; + } + if ($opt_odl) { - $podl = $pidl; - $pidl = ODL::ODL2IDL($podl); + $pidl = ODL::ODL2IDL($pidl); } if ($opt_header) { my($header) = util::ChangeExtension($output, ".h"); - util::FileSave($header, IdlHeader::Parse($pidl)); + util::FileSave($header, NdrHeader::Parse($pidl)); if ($opt_eparser) { my($eparserhdr) = dirname($output) . "/packet-dcerpc-$basename.h"; IdlEParser::RewriteHeader($pidl, $header, $eparserhdr); @@ -172,23 +208,14 @@ sub process_file($) my ($client) = util::ChangeExtension($output, "_c.c"); my $res = ""; my $h_filename = util::ChangeExtension($output, ".h"); - my $need_dcom_register = 0; $res .= "#include \"includes.h\"\n"; $res .= "#include \"$h_filename\"\n\n"; foreach my $x (@{$pidl}) { - if (util::has_property($x, "object")) { - $res .= IdlProxy::ParseInterface($x); - $need_dcom_register = 1; - } else { - $res .= IdlClient::ParseInterface($x); - } + $res .= IdlClient::ParseInterface($x); } - if ($need_dcom_register) { - $res .= IdlProxy::RegistrationFunction($pidl, $basename); - } util::FileSave($client, $res); } @@ -201,7 +228,7 @@ sub process_file($) next if ($x->{TYPE} ne "INTERFACE"); if (util::has_property($x, "object")) { - $dcom .= IdlStub::ParseInterface($x); + $dcom .= DCOMStub::ParseInterface($x); } else { $plain .= IdlServer::ParseInterface($x); } @@ -233,13 +260,6 @@ $dcom } } - if ($opt_diff) { - my($tempfile) = util::ChangeExtension($output, ".tmp"); - util::FileSave($tempfile, IdlDump::Dump($pidl)); - system("diff -wu $idl_file $tempfile"); - unlink($tempfile); - } - if ($opt_template) { print IdlTemplate::Parse($pidl); } diff --git a/source4/build/pidl/proxy.pm b/source4/build/pidl/proxy.pm deleted file mode 100644 index 1eef131a6c..0000000000 --- a/source4/build/pidl/proxy.pm +++ /dev/null @@ -1,201 +0,0 @@ -################################################### -# 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 .= "static 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(talloc_autofree_context(), &proxy, sizeof(struct dcom_$interface->{NAME}_vtable)); - - return dcom_register_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->conn->flags & DCERPC_DEBUG_PRINT_IN) { - NDR_PRINT_IN_DEBUG($name, r); - } - - return dcerpc_ndr_request_send(p, &d->ipid, &dcerpc_table_$interface->{NAME}, DCERPC_$uname, mem_ctx, 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->conn->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) -{ - const struct dcom_$interface->{NAME}_vtable *table = d->vtable; - - if (table->$name == NULL) { - DEBUG(0, (\"Object does not implement $name of interface $interface->{NAME}\\n\")); - return NT_STATUS_NOT_IMPLEMENTED; - } - - return table->$name (d, mem_ctx, r); -} -"; -} - - -##################################################################### -# parse the interface definitions -sub ParseInterface($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - $res = "/* DCOM proxy generated by pidl */\n\n"; - foreach my $d (@{$data}) { - ($d->{TYPE} eq "FUNCTION") && - ParseFunction($interface, $d); - } - - ParseRegFunc($interface); -} - -sub RegistrationFunction($$) -{ - my $idl = shift; - my $basename = shift; - - my $res = "NTSTATUS dcom_$basename\_init(void)\n"; - $res .= "{\n"; - $res .="\tNTSTATUS status = NT_STATUS_OK;\n"; - foreach my $interface (@{$idl}) { - next if $interface->{TYPE} ne "INTERFACE"; - next if not util::has_property($interface, "object"); - - my $data = $interface->{INHERITED_DATA}; - my $count = 0; - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { $count++; } - } - - next if ($count == 0); - - $res .= "\tstatus = dcom_$interface->{NAME}_init();\n"; - $res .= "\tif (NT_STATUS_IS_ERR(status)) {\n"; - $res .= "\t\treturn status;\n"; - $res .= "\t}\n\n"; - } - $res .= "\treturn status;\n"; - $res .= "}\n\n"; - - return $res; -} - -1; diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/stub.pm deleted file mode 100644 index 53be35b216..0000000000 --- a/source4/build/pidl/stub.pm +++ /dev/null @@ -1,321 +0,0 @@ -################################################### -# stub boilerplate generator -# Copyright jelmer@samba.org 2004 -# Copyright tridge@samba.org 2003 -# Copyright metze@samba.org 2004 -# released under the GNU GPL - -package IdlStub; - -use strict; - -my($res); - -sub pidl($) -{ - $res .= shift; -} - - -##################################################### -# generate the switch statement for function dispatch -sub gen_dispatch_switch($) -{ - my $data = shift; - - my $count = 0; - foreach my $d (@{$data}) { - next if ($d->{TYPE} ne "FUNCTION"); - - pidl "\tcase $count: {\n"; - if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") { - pidl "\t\tNTSTATUS result;\n"; - } - pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; - pidl "\t\tif (DEBUGLEVEL > 10) {\n"; - pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n"; - pidl "\t\t}\n"; - if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") { - pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n"; - } else { - pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n"; - } - pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; - pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n"; - pidl "\t\t}\n"; - pidl "\t\tbreak;\n\t}\n"; - $count++; - } -} - -##################################################### -# generate the switch statement for function reply -sub gen_reply_switch($) -{ - my $data = shift; - - my $count = 0; - foreach my $d (@{$data}) { - next if ($d->{TYPE} ne "FUNCTION"); - - pidl "\tcase $count: {\n"; - pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; - pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; - pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n"; - pidl "\t\t}\n"; - pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n"; - pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n"; - pidl "\t\t}\n"; - pidl "\t\tif (dce_call->fault_code != 0) {\n"; - pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n"; - pidl "\t\t}\n"; - pidl "\t\tbreak;\n\t}\n"; - $count++; - } -} - -##################################################################### -# produce boilerplate code for a interface -sub Boilerplate_Iface($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - my $name = $interface->{NAME}; - my $uname = uc $name; - my $uuid = util::make_str($interface->{PROPERTIES}->{uuid}); - my $if_version = $interface->{PROPERTIES}->{version}; - - pidl " -static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface) -{ -#ifdef DCESRV_INTERFACE_$uname\_BIND - return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface); -#else - return NT_STATUS_OK; -#endif -} - -static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface) -{ -#ifdef DCESRV_INTERFACE_$uname\_UNBIND - DCESRV_INTERFACE_$uname\_UNBIND(context, iface); -#else - return; -#endif -} - -static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r) -{ - NTSTATUS status; - uint16_t opnum = dce_call->pkt.u.request.opnum; - - dce_call->fault_code = 0; - - if (opnum >= dcerpc_table_$name.num_calls) { - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - return NT_STATUS_NET_WRITE_FAULT; - } - - *r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size); - NT_STATUS_HAVE_NO_MEMORY(*r); - - /* unravel the NDR for the packet */ - status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); - if (!NT_STATUS_IS_OK(status)) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - dce_call->fault_code = DCERPC_FAULT_NDR; - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) -{ - uint16_t opnum = dce_call->pkt.u.request.opnum; - struct GUID ipid = dce_call->pkt.u.request.object.object; - struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid); - const struct dcom_$name\_vtable *vtable = iface->vtable; - - switch (opnum) { -"; - gen_dispatch_switch($data); - -pidl " - default: - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - break; - } - - if (dce_call->fault_code != 0) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) -{ - uint16_t opnum = dce_call->pkt.u.request.opnum; - - switch (opnum) { -"; - gen_reply_switch($data); - -pidl " - default: - dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; - break; - } - - if (dce_call->fault_code != 0) { - dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, - &dce_call->pkt.u.request.stub_and_verifier); - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r) -{ - NTSTATUS status; - uint16_t opnum = dce_call->pkt.u.request.opnum; - - status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r); - if (!NT_STATUS_IS_OK(status)) { - dce_call->fault_code = DCERPC_FAULT_NDR; - return NT_STATUS_NET_WRITE_FAULT; - } - - return NT_STATUS_OK; -} - -static const struct dcesrv_interface $name\_interface = { - .name = \"$name\", - .uuid = $uuid, - .if_version = $if_version, - .bind = $name\__op_bind, - .unbind = $name\__op_unbind, - .ndr_pull = $name\__op_ndr_pull, - .dispatch = $name\__op_dispatch, - .reply = $name\__op_reply, - .ndr_push = $name\__op_ndr_push -}; - -"; -} - -##################################################################### -# produce boilerplate code for an endpoint server -sub Boilerplate_Ep_Server($) -{ - my($interface) = shift; - my $name = $interface->{NAME}; - my $uname = uc $name; - - pidl " -static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) -{ - int i; - - for (i=0;icount;i++) { - NTSTATUS ret; - const char *name = dcerpc_table_$name.endpoints->names[i]; - - ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name)); - return ret; - } - } - - return NT_STATUS_OK; -} - -static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version) -{ - if (dcerpc_table_$name.if_version == if_version && - strcmp(dcerpc_table_$name.uuid, uuid)==0) { - memcpy(iface,&dcerpc_table_$name, sizeof(*iface)); - return True; - } - - return False; -} - -static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name) -{ - if (strcmp(dcerpc_table_$name.name, name)==0) { - memcpy(iface,&dcerpc_table_$name, sizeof(*iface)); - return True; - } - - return False; -} - -NTSTATUS dcerpc_server_$name\_init(void) -{ - NTSTATUS ret; - struct dcesrv_endpoint_server ep_server; - - /* fill in our name */ - ep_server.name = \"$name\"; - - /* fill in all the operations */ - ep_server.init_server = $name\__op_init_server; - - ep_server.interface_by_uuid = $name\__op_interface_by_uuid; - ep_server.interface_by_name = $name\__op_interface_by_name; - - /* register ourselves with the DCERPC subsystem. */ - ret = dcerpc_register_ep_server(&ep_server); - - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\")); - return ret; - } - - return ret; -} - -"; -} - -##################################################################### -# dcom interface stub from a parsed IDL structure -sub ParseInterface($) -{ - my($interface) = shift; - my($data) = $interface->{DATA}; - my $count = 0; - - $res = ""; - - if (!defined $interface->{PROPERTIES}->{uuid}) { - return $res; - } - - if (!defined $interface->{PROPERTIES}->{version}) { - $interface->{PROPERTIES}->{version} = "0.0"; - } - - foreach my $d (@{$data}) { - if ($d->{TYPE} eq "FUNCTION") { $count++; } - } - - if ($count == 0) { - return $res; - } - - $res = "/* dcom interface stub generated by pidl */\n\n"; - Boilerplate_Iface($interface); - Boilerplate_Ep_Server($interface); - - return $res; -} - -1; diff --git a/source4/build/smb_build/main.pm b/source4/build/smb_build/main.pm index 76b7b3d210..c401bc8de6 100644 --- a/source4/build/smb_build/main.pm +++ b/source4/build/smb_build/main.pm @@ -30,7 +30,6 @@ sub smb_build_main($) "auth/config.mk", "nsswitch/config.mk", "lib/basic.mk", - "lib/dcom/config.mk", "lib/socket/config.mk", "lib/ldb/config.mk", "lib/talloc/config.mk", @@ -58,6 +57,8 @@ sub smb_build_main($) "libcli/libsmb.mk", "libcli/config.mk", "libcli/security/config.mk", + "lib/dcom/config.mk", + "lib/com/config.mk", "scripting/swig/config.mk", ); diff --git a/source4/include/includes.h b/source4/include/includes.h index 2e04e365eb..be100c6390 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -127,11 +127,11 @@ extern int errno; #include "librpc/gen_ndr/ndr_misc.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "librpc/rpc/dcerpc.h" -#include "lib/dcom/common/dcom.h" -#include "librpc/gen_ndr/ndr_dcom.h" #include "smb_interfaces.h" #include "ntvfs/ntvfs.h" #include "cli_context.h" +#include "lib/com/com.h" +#include "lib/dcom/common/dcom.h" #define malloc_p(type) (type *)malloc(sizeof(type)) #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count) diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c new file mode 100644 index 0000000000..2c72d56f94 --- /dev/null +++ b/source4/lib/com/classes/simple.c @@ -0,0 +1,116 @@ +/* + Unix SMB/CIFS implementation. + Simple class + Copyright (C) 2004-2005 Jelmer Vernooij + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/com/com.h" +#include "librpc/gen_ndr/com_dcom.h" + + +static WERROR simple_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +{ + *iun = d; + return WERR_OK; +} + +static uint32_t simple_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static uint32_t simple_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static WERROR simple_Read (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *pv, uint32_t num_requested, uint32_t *num_readx, uint32_t num_read) +{ + printf("%d bytes are being read\n", num_read); + return WERR_OK; +} + +static WERROR simple_Write (struct IStream *d, TALLOC_CTX *mem_ctx, uint8_t *data, uint32_t num_requested, uint32_t num_written) +{ + printf("%d bytes are being written\n", num_requested); + return WERR_OK; +} + +static struct IStream_vtable simple_istream_vtable = { + simple_QueryInterface, + simple_AddRef, + simple_Release, + simple_Read, + simple_Write +}; + +static WERROR simpleclass_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun) +{ + /* FIXME: Return WERR_IFACE_NOT_SUPPORTED if IID != IID_IUNKNOWN and IID != IID_CLASSFACTORY */ + *iun = d; + return WERR_OK; +} + +static WERROR simpleclass_CreateInstance (struct IClassFactory *d, TALLOC_CTX *mem_ctx, struct IUnknown *iunk, struct GUID *iid, struct IUnknown **ppv) +{ + struct IStream *ret; + /* FIXME: Check whether IID == ISTREAM_IID */ + ret = talloc(mem_ctx, struct IStream); + ret->ctx = NULL; + ret->vtable = &simple_istream_vtable; + ret->object_data = NULL; + + *ppv = ret; + + return WERR_OK; +} + +static uint32_t simpleclass_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +static uint32_t simpleclass_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx) +{ + return 1; +} + +/* Everything below this line should be autogenerated later on */ +static struct IClassFactory_vtable simple_classobject_vtable = { + simpleclass_QueryInterface, + simpleclass_AddRef, + simpleclass_Release, + simpleclass_CreateInstance, + NULL, + NULL, + NULL +}; + +NTSTATUS com_simple_init(void) +{ + struct GUID clsid; + struct IUnknown *class_object = talloc(talloc_autofree_context(), struct IUnknown); + + class_object->ctx = NULL; + class_object->object_data = NULL; + class_object->vtable = (struct IUnknown_vtable *)&simple_classobject_vtable; + + GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &clsid); + + return com_register_running_class(&clsid, "Samba.Simple", class_object); +} diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h new file mode 100644 index 0000000000..be7dcde5b5 --- /dev/null +++ b/source4/lib/com/com.h @@ -0,0 +1,30 @@ +/* + Unix SMB/CIFS implementation. + COM standard objects + Copyright (C) Jelmer Vernooij 2004-2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _COM_H /* _COM_H */ +#define _COM_H + +struct com_context +{ +}; + +typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid); + +#endif /* _COM_H */ diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk new file mode 100644 index 0000000000..006ea212c1 --- /dev/null +++ b/source4/lib/com/config.mk @@ -0,0 +1,10 @@ +[SUBSYSTEM::LIBCOM] +INIT_OBJ_FILES = \ + lib/com/tables.o \ + lib/com/rot.o \ + lib/com/main.o + +[MODULE::com_simple] +SUBSYSTEM = LIBCOM +INIT_OBJ_FILES = lib/com/classes/simple.o +INIT_FUNCTION = com_simple_init diff --git a/source4/lib/com/main.c b/source4/lib/com/main.c new file mode 100644 index 0000000000..378c3738b9 --- /dev/null +++ b/source4/lib/com/main.c @@ -0,0 +1,85 @@ +/* + Unix SMB/CIFS implementation. + Main COM functionality + Copyright (C) 2004 Jelmer Vernooij + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" +#include "lib/com/com.h" +#include "librpc/gen_ndr/com_dcom.h" + +WERROR com_init(struct com_context **ctx) +{ + *ctx = talloc(NULL, struct com_context); + return WERR_OK; +} + +WERROR com_create_object(struct com_context *ctx, struct GUID *clsid, int num_ifaces, struct GUID *iid, struct IUnknown **ip, WERROR *results) +{ + struct IUnknown *iunk = NULL; + struct IClassFactory *factory; + WERROR error; + int i; + struct GUID classfact_iid; + + GUID_from_string(DCERPC_ICLASSFACTORY_UUID, &classfact_iid); + + /* Obtain class object */ + error = com_get_class_object(ctx, clsid, &classfact_iid, (struct IUnknown **)&factory); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); + return error; + } + + /* Run IClassFactory::CreateInstance() */ + error = IClassFactory_CreateInstance(factory, ctx, NULL, &classfact_iid, &iunk); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", win_errstr(error))); + return error; + } + + if (!iunk) { + DEBUG(0, ("IClassFactory_CreateInstance returned success but result pointer is still NULL!\n")); + return WERR_GENERAL_FAILURE; + } + + /* Release class object */ + IUnknown_Release(factory, ctx); + + error = WERR_OK; + + /* Do one or more QueryInterface calls */ + for (i = 0; i < num_ifaces; i++) { + results[i] = IUnknown_QueryInterface(iunk, ctx, &iid[i], &ip[i]); + if (!W_ERROR_IS_OK(results[i])) error = results[i]; + } + + return error; +} + +WERROR com_get_class_object(struct com_context *ctx, struct GUID *clsid, struct GUID *iid, struct IUnknown **ip) +{ + struct IUnknown *iu; + + iu = com_class_by_clsid(ctx, clsid); + if (!iu) { + return WERR_CLASS_NOT_REGISTERED; + } + + return IUnknown_QueryInterface(iu, ctx, iid, ip); +} diff --git a/source4/lib/com/rot.c b/source4/lib/com/rot.c new file mode 100644 index 0000000000..34a5671f5b --- /dev/null +++ b/source4/lib/com/rot.c @@ -0,0 +1,34 @@ +/* + Unix SMB/CIFS implementation. + + Running object table functions + + Copyright (C) Jelmer Vernooij 2004-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) +{ + /* FIXME: Call the local ROT and do a + * rot_get_interface_pointer call */ + + /* FIXME: Perhaps have a local (thread-local) table with + * local DCOM objects so that not every DCOM call requires a lookup + * to the ROT? */ + return NULL; +} diff --git a/source4/lib/com/tables.c b/source4/lib/com/tables.c new file mode 100644 index 0000000000..cf63e7e9a2 --- /dev/null +++ b/source4/lib/com/tables.c @@ -0,0 +1,107 @@ +/* + Unix SMB/CIFS implementation. + COM class tables + Copyright (C) 2004 Jelmer Vernooij + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "dlinklist.h" + +/* Specific implementation of one or more interfaces */ +struct com_class +{ + const char *progid; + struct GUID clsid; + + struct IUnknown *class_object; + struct com_class *prev, *next; +} * running_classes = NULL; + +static struct IUnknown *get_com_class_running(const struct GUID *clsid) +{ + struct com_class *c = running_classes; + + while(c) { + + if (GUID_equal(clsid, &c->clsid)) { + return c->class_object; + } + + c = c->next; + } + + return NULL; +} + +static struct IUnknown *get_com_class_so(TALLOC_CTX *mem_ctx, const struct GUID *clsid) +{ + char *mod_name; + char *clsid_str; + void *mod; + get_class_object_function f; + + clsid_str = GUID_string(mem_ctx, clsid); + mod_name = talloc_asprintf(mem_ctx, "%s.so", clsid_str); + talloc_free(clsid_str); + + mod = sys_dlopen(mod_name, 0); + + if (!mod) { + return NULL; + } + + f = sys_dlsym(mod, "get_class_object"); + + if (!f) { + return NULL; + } + + return f(clsid); +} + +struct IUnknown *com_class_by_clsid(struct com_context *ctx, const struct GUID *clsid) +{ + struct IUnknown *c; + + /* Check list of running COM classes first */ + c = get_com_class_running(clsid); + + if (c != NULL) { + return c; + } + + c = get_com_class_so(ctx, clsid); + + if (c != NULL) { + return c; + } + + return NULL; +} + +NTSTATUS com_register_running_class(struct GUID *clsid, const char *progid, struct IUnknown *p) +{ + struct com_class *l = talloc_zero(running_classes?running_classes:talloc_autofree_context(), struct com_class); + + l->clsid = *clsid; + l->progid = talloc_strdup(l, progid); + l->class_object = p; + + DLIST_ADD(running_classes, l); + + return NT_STATUS_OK; +} diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c deleted file mode 100644 index 13cf4616b2..0000000000 --- a/source4/lib/dcom/classes/simple.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Simple class - Copyright (C) 2004 Jelmer Vernooij - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "lib/dcom/common/dcom.h" - -NTSTATUS simple_QueryInterface (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct QueryInterface *r) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -static NTSTATUS simple_CreateInstance (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct CreateInstance *r) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -/* Everything below this line should be autogenerated later on */ - -static struct dcom_IClassFactory_vtable simple_classobject = { - { simple_QueryInterface, NULL, NULL }, - simple_CreateInstance, - NULL, - NULL, - NULL -}; - -NTSTATUS dcom_simple_init(void) -{ - struct GUID iid; - struct dcom_class simple_class = { - "Samba.Simple", - }; - - GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); - - simple_class.class_object = dcom_new_local_ifacep( - talloc_autofree_context(), - &iid, - &simple_classobject, NULL); - - if (!simple_class.class_object) { - DEBUG(1, ("Unable to create class object for simple class\n")); - return NT_STATUS_OK; - } - - GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); - - return dcom_register_class(&simple_class); -} diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 0bc4a256f1..dd21bb9d29 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. DCOM standard objects - Copyright (C) Jelmer Vernooij 2004. + Copyright (C) Jelmer Vernooij 2004-2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,11 +23,6 @@ #include "librpc/ndr/ndr_dcom.h" -struct IUnknown_AddRef; -struct IUnknown_Release; -struct IUnknown_QueryInterface; -struct dcom_interface_p; - struct dcom_context { struct dcom_object_exporter { @@ -49,34 +44,16 @@ struct dcom_context uint32_t dcerpc_flags; }; -/* Specific implementation of one or more interfaces */ -struct dcom_class -{ - const char *prog_id; - struct GUID clsid; - - /* IUnknown */ - struct dcom_interface_p *class_object; -}; - -struct dcom_interface -{ - struct GUID iid; - int num_methods; - struct GUID base_iid; - const void *proxy_vtable; -}; - struct dcom_interface_p { - struct dcom_context *ctx; - const struct dcom_interface *interface; + struct com_context *ctx; + const struct com_interface *interface; const void *vtable; /* Points to one of the available implementations */ struct GUID ipid; - struct dcom_object *object; + struct com_object *object; int objref_flags; int orpc_flags; - struct dcom_object_exporter *ox; + struct com_object_exporter *ox; uint32_t private_references; }; diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index a8324606f1..315912ba3c 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -117,7 +117,7 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user return WERR_OK; } -static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) +struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, uint64_t oxid) { struct dcom_object_exporter *m; @@ -144,7 +144,7 @@ WERROR dcom_ping(struct dcom_context *ctx) return WERR_OK; } -static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +static WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; struct dcerpc_pipe *p; @@ -154,6 +154,10 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c struct DUALSTRINGARRAY dualstring; int i; + if (!server) { + return com_create_object(ctx, clsid, num_ifaces, iid, ip, results); + } + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); @@ -208,60 +212,7 @@ static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *c return WERR_OK; } -WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) -{ - struct dcom_interface_p *factory, *iunk = NULL; - struct QueryInterface qr; - struct Release rr; - struct CreateInstance cr; - WERROR error; - int i; - NTSTATUS status; - - if (server != NULL) { - return dcom_create_object_remote(ctx, clsid, server, num_ifaces, iid, ip, results); - } - - /* Obtain class object */ - error = dcom_get_class_object(ctx, clsid, server, iid, &factory); - if (!W_ERROR_IS_OK(error)) { - DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); - return error; - } - - dcom_OBJREF_from_ifacep(ctx, &cr.in.pUnknown->obj, factory); - - GUID_from_string(DCERPC_ICLASSFACTORY_UUID, cr.in.iid); - - /* Run IClassFactory::CreateInstance() */ - status = dcom_IClassFactory_CreateInstance(factory, ctx, &cr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - /* Release class object */ - status = dcom_IUnknown_Release(factory, ctx, &rr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(3, ("Error freeing class factory: %s\n", nt_errstr(status))); - return ntstatus_to_werror(status); - } - - /* Do one or more QueryInterface calls */ - for (i = 0; i < num_ifaces; i++) { - qr.in.iid = &iid[i]; - status = dcom_IUnknown_QueryInterface(iunk, ctx, &qr); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(4, ("Error obtaining interface %s : %s\n", GUID_string(NULL, &iid[i]), nt_errstr(status))); - return ntstatus_to_werror(status); - } - results[i] = qr.out.result; - } - - return WERR_OK; -} - -WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) { struct dcom_object_exporter *m; struct RemoteActivation r; @@ -271,6 +222,10 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid struct pMInterfacePointer pm; uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + if (!server) { + return com_get_class_object(ctx, clsid, iid, ip); + } + status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Unable to connect to %s - %s\n", server, nt_errstr(status))); @@ -312,36 +267,6 @@ WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) -{ - const struct dcom_class *c; - struct QueryInterface qi; - NTSTATUS status; - - if (server != NULL) { - return dcom_get_class_object_remote(ctx, clsid, server, iid, ip); - } - - c = dcom_class_by_clsid(clsid); - if (!c) { - /* FIXME: Better error code.. */ - return WERR_DEST_NOT_FOUND; - } - - qi.in.iid = iid; - - status = dcom_IUnknown_QueryInterface(c->class_object, ctx, &qi ); - if (NT_STATUS_IS_ERR(status)) { - return ntstatus_to_werror(status); - } - - if (!W_ERROR_IS_OK(qi.out.result)) { return qi.out.result; } - - dcom_ifacep_from_OBJREF(ctx, ip, &qi.out.data->obj); - - return WERR_OK; -} - NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **pp) { struct dcerpc_binding binding; @@ -549,26 +474,3 @@ uint64_t dcom_get_current_oxid(void) { return getpid(); } - -struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct GUID *iid, void *vtable, struct dcom_object *object) -{ - struct dcom_interface_p *ip = talloc(ctx, struct dcom_interface_p); - const struct dcom_interface *iface = dcom_interface_by_iid(iid); - - if (!iface) { - DEBUG (1, ("Unable to find interface with IID %s\n", GUID_string(ctx, iid))); - return NULL; - } - - ip->ctx = ctx; - ip->interface = iface; - ip->vtable = vtable; - ip->ipid = GUID_random(); - ip->object = object; - ip->objref_flags = 0; - ip->orpc_flags = 0; - ip->ox = NULL; - ip->private_references = 1; - - return ip; -} diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c deleted file mode 100644 index 7acdbe066e..0000000000 --- a/source4/lib/dcom/common/rot.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Running object table functions - - Copyright (C) Jelmer Vernooij 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) -{ - /* FIXME: Call the local ROT and do a - * rot_get_interface_pointer call */ - - /* FIXME: Perhaps have a local (thread-local) table with - * local DCOM objects so that not every DCOM call requires a lookup - * to the ROT? */ - return NULL; -} diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c deleted file mode 100644 index cd7e0867ee..0000000000 --- a/source4/lib/dcom/common/tables.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DCOM interface and class tables - Copyright (C) 2004 Jelmer Vernooij - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "dlinklist.h" - -static struct class_list { - struct class_list *prev, *next; - struct dcom_class class; -} *classes = NULL; - -static struct interface_list { - struct interface_list *prev, *next; - struct dcom_interface interface; -} *interfaces = NULL; - -const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) -{ - struct interface_list *l = interfaces; - - while(l) { - - if (GUID_equal(iid, &l->interface.iid)) - return &l->interface; - - l = l->next; - } - - return NULL; -} - -const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) -{ - struct class_list *c = classes; - - while(c) { - - if (GUID_equal(clsid, &c->class.clsid)) { - return &c->class; - } - - c = c->next; - } - - return NULL; -} - -const void *dcom_proxy_vtable_by_iid(const struct GUID *iid) -{ - const struct dcom_interface *iface = dcom_interface_by_iid(iid); - - if (!iface) { - return NULL; - } - - return iface->proxy_vtable; -} - -NTSTATUS dcom_register_interface(const void *_iface) -{ - const struct dcom_interface *iface = _iface; - struct interface_list *l; - TALLOC_CTX *lcl_ctx = talloc_init("dcom_register_interface"); - - DEBUG(5, ("Adding DCOM interface %s\n", GUID_string(lcl_ctx, &iface->iid))); - - talloc_free(lcl_ctx); - - l = talloc_zero(interfaces?interfaces:talloc_autofree_context(), - struct interface_list); - - l->interface = *iface; - - DLIST_ADD(interfaces, l); - - return NT_STATUS_OK; -} - -NTSTATUS dcom_register_class(const void *_class) -{ - const struct dcom_class *class = _class; - struct class_list *l = talloc_zero(classes?classes:talloc_autofree_context(), - struct class_list); - - l->class = *class; - - DLIST_ADD(classes, l); - - return NT_STATUS_OK; -} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index ca280884ea..ae8fe9c4b0 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -1,19 +1,19 @@ ################################################ # Start SUBSYSTEM LIBDCOM -[SUBSYSTEM::LIBDCOM] -INIT_OBJ_FILES = \ - lib/dcom/common/main.o \ - lib/dcom/common/tables.o \ - lib/dcom/common/rot.o -REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ - RPC_NDR_OXIDRESOLVER +#[SUBSYSTEM::LIBDCOM] +#ENABLE = NO +#INIT_OBJ_FILES = \ +# lib/dcom/common/main.o +#REQUIRED_SUBSYSTEMS = LIBCOM DCOM_PROXY_DCOM RPC_NDR_REMACT \ +# RPC_NDR_OXIDRESOLVER -[MODULE::DCOM_SIMPLE] -SUBSYSTEM = LIBDCOM -REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM -INIT_FUNCTION = dcom_simple_init -INIT_OBJ_FILES = \ - lib/dcom/classes/simple.o +#[MODULE::DCOM_SIMPLE] +#ENABLE = NO +#SUBSYSTEM = LIBDCOM +#REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM +#INIT_FUNCTION = dcom_simple_init +#INIT_OBJ_FILES = \ +# lib/dcom/classes/simple.o # # End SUBSYSTEM LIBDCOM ################################################ diff --git a/source4/librpc/idl/dcom.idl b/source4/librpc/idl/dcom.idl index 855fbfce8f..b4ce03e5aa 100644 --- a/source4/librpc/idl/dcom.idl +++ b/source4/librpc/idl/dcom.idl @@ -159,10 +159,10 @@ interface IRemUnknown : IUnknown interface ISystemActivator : IClassActivator { WERROR ISystemActivatorRemoteCreateInstance([in] hyper unknown1, /* OXID ? */ - [in] MInterfacePointer iface, + [in] MInterfacePointer iface1, [in] hyper unknown2, [out] uint32 unknown3, - [out] MInterfacePointer iface); + [out] MInterfacePointer iface2); } @@ -270,7 +270,7 @@ object, object ] interface ICoffeeMachine : IUnknown { - [helpstring("method MakeCoffee")] WERROR MakeCoffee(BSTR *flavor); + [helpstring("method MakeCoffee")] WERROR MakeCoffee(unistr *flavor); } [ diff --git a/source4/librpc/idl/rot.idl b/source4/librpc/idl/rot.idl index 28aae60036..aa257dcf2f 100644 --- a/source4/librpc/idl/rot.idl +++ b/source4/librpc/idl/rot.idl @@ -4,6 +4,7 @@ uuid("b9e79e60-3d52-11ce-aaa1-00006901293f"), version(0.2), pointer_default(unique), + depends(orpc), endpoint("ncacn_np:[\\pipe\\epmapper]", "ncacn_ip_tcp:[135]", "ncalrpc:[EPMAPPER]", "ncacn_unix_stream:[/tmp/epmapper]") ] interface rot @@ -42,16 +43,3 @@ [out] MInterfacePointer *EnumMoniker ); } - -/* -[ - object, -] interface IRotData : IUnknown -{ - WERROR irotdata_getdata( - [out,size_is(max),length_is(ret)] uint8 *data, - [in] uint32 max, - [out] uint32 ret - ); -} -*/ diff --git a/source4/librpc/ndr/ndr_orpc.c b/source4/librpc/ndr/ndr_orpc.c index 2a28db4178..ccfd48e099 100644 --- a/source4/librpc/ndr/ndr_orpc.c +++ b/source4/librpc/ndr/ndr_orpc.c @@ -22,6 +22,7 @@ #include "includes.h" +#include "librpc/gen_ndr/ndr_orpc.h" NTSTATUS ndr_pull_DUALSTRINGARRAY(struct ndr_pull *ndr, int ndr_flags, struct DUALSTRINGARRAY *ar) { diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index f58cbd0ac3..e50aa58c35 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -27,7 +27,7 @@ REQUIRED_SUBSYSTEMS = \ DCERPC_COMMON \ NDR_OXIDRESOLVER \ NDR_REMACT \ - LIBDCOM + LIBCOM # End MODULE dcerpc_dcom ################################################ diff --git a/source4/rpc_server/dcom/rodb.c b/source4/rpc_server/dcom/rodb.c index 5008e105ba..76f3d2da80 100644 --- a/source4/rpc_server/dcom/rodb.c +++ b/source4/rpc_server/dcom/rodb.c @@ -31,7 +31,7 @@ struct tdb_wrap *openrodb(TALLOC_CTX *mem_ctx) struct tdb_wrap *wrap; char *rodb_name = NULL; - asprintf(&rodb_name, "%s/rot.tdb", lp_lockdir()); + rodb_name = smbd_tmp_path(mem_ctx, "rot.tdb"); wrap = tdb_wrap_open(mem_ctx, rodb_name, 0, 0, O_RDWR|O_CREAT, 0600); SAFE_FREE(rodb_name); diff --git a/source4/script/build_idl.sh b/source4/script/build_idl.sh index 7b49721a5c..d15a9add31 100755 --- a/source4/script/build_idl.sh +++ b/source4/script/build_idl.sh @@ -4,7 +4,7 @@ FULLBUILD=$1 [ -d librpc/gen_ndr ] || mkdir -p librpc/gen_ndr || exit 1 -PIDL="$PERL ./build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser --server --client --swig --odl" +PIDL="$PERL ./build/pidl/pidl.pl --output librpc/gen_ndr/ndr_ --parse --header --parser --server --client --dcom-proxy --com-header --swig --odl" if [ x$FULLBUILD = xFULL ]; then echo Rebuilding all idl files in librpc/idl @@ -14,7 +14,7 @@ fi list="" -for f in librpc/idl/*.idl; do +for f in librpc/idl/*.idl ; do basename=`basename $f .idl` ndr="librpc/gen_ndr/ndr_$basename.c" # blergh - most shells don't have the -nt function diff --git a/source4/torture/com/simple.c b/source4/torture/com/simple.c new file mode 100644 index 0000000000..369b03f151 --- /dev/null +++ b/source4/torture/com/simple.c @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + run the "simple" example (D)COM program + + Copyright (C) Jelmer Vernooij 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/com/com.h" +#include "librpc/gen_ndr/com_dcom.h" + +#define CLSID_SIMPLE "5e9ddec7-5767-11cf-beab-00aa006c3606" +#define DEFAULT_TRANS 4096 + +static BOOL test_readwrite(TALLOC_CTX *mem_ctx, const char *host) +{ + struct dcerpc_pipe *p = NULL; + BOOL ret = True; + struct GUID IID[2]; + struct GUID clsid; + WERROR error; + struct IUnknown *interfaces[3]; + WERROR results[2]; + struct com_context *ctx; + char test_data[5]; + int i; + + com_init(&ctx); + + GUID_from_string(COM_ISTREAM_UUID, &IID[0]); + GUID_from_string(COM_IUNKNOWN_UUID, &IID[1]); + GUID_from_string(CLSID_SIMPLE, &clsid); +/* error = dcom_create_object(ctx, &clsid, + host, 2, IID, + &interfaces, + results);*/ + + error = com_create_object(ctx, &clsid, 2, IID, interfaces, results); + + if (!W_ERROR_IS_OK(error)) { + printf("(d)com_create_object failed - %s\n", win_errstr(error)); + return False; + } + + error = IStream_Read((struct IStream *)interfaces[0], mem_ctx, NULL, 20, 20, 30); + if (!W_ERROR_IS_OK(error)) { + printf("IStream::Read() failed - %s\n", win_errstr(error)); + ret = False; + } + + for (i = 0; i < 5; i++) { + test_data[i] = i+1; + } + + error = IStream_Write((struct IStream *)interfaces[0], mem_ctx, &test_data, 5, NULL); + if (!W_ERROR_IS_OK(error)) { + printf("IStream::Write() failed - %s\n", win_errstr(error)); + ret = False; + } + + IUnknown_Release((struct IUnknown *)interfaces[1], mem_ctx); + + torture_rpc_close(p); + + return True; +} + +BOOL torture_com_simple(void) +{ + BOOL ret = True; + TALLOC_CTX *mem_ctx = talloc_init("torture_dcom_simple"); + + ret &= test_readwrite(mem_ctx, NULL); + ret &= test_readwrite(mem_ctx, lp_parm_string(-1, "torture", "dcomhost")); + + talloc_free(mem_ctx); + + return ret; +} diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 2a81ac1c7c..5ac33bb556 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -59,11 +59,11 @@ REQUIRED_SUBSYSTEMS = \ ################################# # Start SUBSYSTEM TORTURE_DCOM -[SUBSYSTEM::TORTURE_DCOM] +[SUBSYSTEM::TORTURE_COM] ADD_OBJ_FILES = \ - torture/dcom/simple.o + torture/com/simple.o REQUIRED_SUBSYSTEMS = \ - LIBDCOM + LIBCOM # End SUBSYSTEM TORTURE_DCOM ################################# @@ -196,6 +196,7 @@ REQUIRED_SUBSYSTEMS = \ TORTURE_LOCAL \ TORTURE_NBENCH \ TORTURE_LDAP \ + TORTURE_COM \ TORTURE_NBT \ CONFIG \ LIBCMDLINE \ diff --git a/source4/torture/dcom/simple.c b/source4/torture/dcom/simple.c deleted file mode 100644 index 4e9ae1be28..0000000000 --- a/source4/torture/dcom/simple.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - Unix SMB/CIFS implementation. - run the "simple" example DCOM program - - Copyright (C) Jelmer Vernooij 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "librpc/gen_ndr/ndr_dcom.h" -#include "librpc/gen_ndr/ndr_oxidresolver.h" - -#define CLSID_SIMPLE "5e9ddec7-5767-11cf-beab-00aa006c3606" -#define DEFAULT_TRANS 4096 - -static BOOL test_readwrite(TALLOC_CTX *mem_ctx, const char *host) -{ - NTSTATUS status; - struct dcerpc_pipe *p = NULL; - BOOL ret = True; - struct GUID IID[2]; - struct GUID clsid; - WERROR error; - struct dcom_interface_p **interfaces; - struct Read r_read; - struct Write r_write; - WERROR results[2]; - struct dcom_context *ctx; - char test_data[5]; - int i; - extern NTSTATUS dcom_IUnknown_init(void); - extern NTSTATUS dcom_IStream_init(void); - - torture_dcom_init(&ctx); - - GUID_from_string(DCERPC_ISTREAM_UUID, &IID[0]); - GUID_from_string(DCERPC_IUNKNOWN_UUID, &IID[1]); - GUID_from_string(CLSID_SIMPLE, &clsid); - error = dcom_create_object(ctx, &clsid, - host, 2, IID, - &interfaces, - results); - - if (!W_ERROR_IS_OK(error)) { - printf("dcom_create_object failed - %s\n", win_errstr(error)); - return False; - } - - if (!W_ERROR_IS_OK(results[0])) { - printf("dcom_create_object didn't return IStream interface - %s\n", win_errstr(results[0])); - return False; - } - - ZERO_STRUCT(r_read); - r_read.in.num_requested = 20; /* Give me 20 0xFF bytes... */ - status = dcom_IStream_Read(interfaces[0], mem_ctx, &r_read); - if (NT_STATUS_IS_ERR(status)) { - printf("IStream::Read() failed - %s\n", nt_errstr(status)); - ret = False; - } else if (!W_ERROR_IS_OK(r_read.out.result)) { - printf("IStream::Read() failed - %s\n", win_errstr(r_read.out.result)); - ret = False; - } - - for (i = 0; i < 5; i++) { - test_data[i] = i+1; - } - r_write.in.num_requested = 5; - r_write.in.data = (uint8_t *)&test_data; - status = dcom_IStream_Write(interfaces[0], mem_ctx, &r_write); - if (NT_STATUS_IS_ERR(status)) { - printf("IStream::Write() failed - %s\n", nt_errstr(status)); - ret = False; - } else if (!W_ERROR_IS_OK(r_write.out.result)) { - printf("IStream::Write() failed - %s\n", win_errstr(r_write.out.result)); - ret = False; - } - - status = dcom_IUnknown_Release(interfaces[1], mem_ctx, NULL); - if (NT_STATUS_IS_ERR(status)) { - printf("IUnknown::Release() failed - %s\n", nt_errstr(status)); - return False; - } - - talloc_free(mem_ctx); - - torture_rpc_close(p); - - return True; -} - -BOOL torture_dcom_simple(void) -{ - BOOL ret = True; - TALLOC_CTX *mem_ctx = talloc_init("torture_dcom_simple"); - - ret &= test_readwrite(mem_ctx, NULL); - ret &= test_readwrite(mem_ctx, lp_parm_string(-1, "torture", "dcomhost")); - - return ret; -} diff --git a/source4/torture/torture.c b/source4/torture/torture.c index ac9af7ed4b..b589902b66 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -2416,6 +2416,9 @@ static struct { {"LOCAL-IDTREE", torture_local_idtree, 0}, {"LOCAL-SOCKET", torture_local_socket, 0}, + /* COM (Component Object Model) testers */ + {"COM-SIMPLE", torture_com_simple, 0 }, + /* ldap testers */ {"LDAP-BASIC", torture_ldap_basic, 0}, -- cgit