diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2004-11-12 00:48:24 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:44 -0500 |
commit | 79c5d73a71c35f5b16232072a7b52033cb9364cb (patch) | |
tree | 62aec59516dd088a0b71b4f86119497b621acb16 | |
parent | c8b894b670a2e854c5a6af598ab1f02b142b3406 (diff) | |
download | samba-79c5d73a71c35f5b16232072a7b52033cb9364cb.tar.gz samba-79c5d73a71c35f5b16232072a7b52033cb9364cb.tar.bz2 samba-79c5d73a71c35f5b16232072a7b52033cb9364cb.zip |
r3689: Large number of COM updates:
- Work on server side and local COM support (should work, just no
example classes yet)
- Use vtables so that local and remote calls can be used transparently
- Generate 'proxies and stubs' rather then heavily modified code in client.pm and server.pm. proxies (client side code) are generated in proxy.pm, stubs (server side dispatchers) are generated in stubs.pm
- Support registering classes and interfaces
- DCOM interfaces no longer have to be in the same IDL file as their
base interface, which will allow us to split up dcom.idl
(This used to be commit 7466947a23985f9bb15209b67880f7b94dc515c8)
-rw-r--r-- | source4/build/pidl/README | 2 | ||||
-rw-r--r-- | source4/build/pidl/client.pm | 79 | ||||
-rw-r--r-- | source4/build/pidl/header.pm | 45 | ||||
-rw-r--r-- | source4/build/pidl/parser.pm | 9 | ||||
-rwxr-xr-x | source4/build/pidl/pidl.pl | 13 | ||||
-rw-r--r-- | source4/build/pidl/proxy.pm | 166 | ||||
-rw-r--r-- | source4/build/pidl/server.pm | 13 | ||||
-rw-r--r-- | source4/build/pidl/stub.pm | 221 | ||||
-rw-r--r-- | source4/lib/dcom/common/dcom.h | 36 | ||||
-rw-r--r-- | source4/lib/dcom/common/local.c | 82 | ||||
-rw-r--r-- | source4/lib/dcom/common/main.c | 243 | ||||
-rw-r--r-- | source4/lib/dcom/common/tables.c | 114 | ||||
-rw-r--r-- | source4/lib/dcom/config.mk | 4 | ||||
-rw-r--r-- | source4/librpc/idl/dcom.idl | 31 | ||||
-rw-r--r-- | source4/rpc_server/dcom/dcom.h | 54 | ||||
-rw-r--r-- | source4/rpc_server/dcom/remact.c | 11 | ||||
-rw-r--r-- | source4/rpc_server/dcom/rot.c | 13 | ||||
-rw-r--r-- | source4/torture/dcom/simple.c | 22 |
18 files changed, 799 insertions, 359 deletions
diff --git a/source4/build/pidl/README b/source4/build/pidl/README index 17a214cd58..c6432a8c0e 100644 --- a/source4/build/pidl/README +++ b/source4/build/pidl/README @@ -21,6 +21,8 @@ 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: tables.pl - Generates a table of available interfaces from a list of IDL files diff --git a/source4/build/pidl/client.pm b/source4/build/pidl/client.pm index 549a5d0dd3..015ac05223 100644 --- a/source4/build/pidl/client.pm +++ b/source4/build/pidl/client.pm @@ -11,82 +11,33 @@ my($res); ##################################################################### # parse a function -sub ParseFunction($) +sub ParseFunction($$) { + my $interface = shift; my $fn = shift; my $name = $fn->{NAME}; my $uname = uc $name; - return if (util::has_property($fn, "local")); - - my $objarg; - if (util::has_property($fn, "object")) { - $objarg = "&d->objref->u_objref.u_standard.std.ipid"; - # FIXME: Support custom marshalling - - $res .= " -struct rpc_request *dcerpc_$name\_send(struct dcom_interface *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; - -"; - } else { - $objarg = "NULL"; - $res .= " + $res .= " struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r) -{"; - } +{ - $res.=" if (p->flags & DCERPC_DEBUG_PRINT_IN) { NDR_PRINT_IN_DEBUG($name, r); } - return dcerpc_ndr_request_send(p, $objarg, DCERPC_$uname, mem_ctx, + return dcerpc_ndr_request_send(p, NULL, DCERPC_$uname, mem_ctx, (ndr_push_flags_fn_t) ndr_push_$name, (ndr_pull_flags_fn_t) ndr_pull_$name, r, sizeof(*r)); } -"; - - if (util::has_property($fn, "object")) { - $res .= -" -NTSTATUS dcerpc_$name(struct dcom_interface *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; - } - - "; - $objarg = "d"; - } else { - $res .= -" NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r) { struct rpc_request *req; NTSTATUS status; - "; - $objarg = "p"; - } - - $res .= " - req = dcerpc_$name\_send($objarg, mem_ctx, r); + + req = dcerpc_$name\_send(p, mem_ctx, r); if (req == NULL) return NT_STATUS_NO_MEMORY; status = dcerpc_ndr_request_recv(req); @@ -112,22 +63,10 @@ sub ParseInterface($) { my($interface) = shift; my($data) = $interface->{DATA}; + $res = "/* Client functions generated by pidl */\n\n"; foreach my $d (@{$data}) { ($d->{TYPE} eq "FUNCTION") && - ParseFunction($d); - } -} - - -##################################################################### -# parse a parsed IDL structure back into an IDL file -sub Parse($) -{ - my($idl) = shift; - $res = "/* dcerpc client calls generated by pidl */\n\n"; - foreach my $x (@{$idl}) { - ($x->{TYPE} eq "INTERFACE") && - ParseInterface($x); + ParseFunction($interface, $d); } return $res; } diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm index b981200781..188fdd4f72 100644 --- a/source4/build/pidl/header.pm +++ b/source4/build/pidl/header.pm @@ -298,22 +298,42 @@ sub HeaderFunction($) ##################################################################### # output prototypes for a IDL function -sub HeaderFnProto($) +sub HeaderFnProto($$) { + my $interface = shift; my $fn = shift; my $name = $fn->{NAME}; - my $firstarg = "dcerpc_pipe"; - if (util::has_property($fn, "object")) { - $firstarg = "dcom_interface"; - } - $res .= "void ndr_print_$name(struct ndr_print *, const char *, int, struct $name *);\n"; - $res .= "struct rpc_request *dcerpc_$name\_send(struct $firstarg *, TALLOC_CTX *, struct $name *);\n"; - $res .= "NTSTATUS dcerpc_$name(struct $firstarg *, TALLOC_CTX *, struct $name *);\n"; + + if (util::has_property($interface, "object")) { + $res .= "NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *, TALLOC_CTX *mem_ctx, struct $name *);\n"; + } else { + $res .= "NTSTATUS dcerpc_$name(struct dcerpc_pipe *, TALLOC_CTX *, struct $name *);\n"; + $res .= "struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *, TALLOC_CTX *, struct $name *);\n"; + } $res .= "\n"; } + +##################################################################### +# generate vtable structure for DCOM interface +sub HeaderVTable($) +{ + my $interface = shift; + $res .= "struct dcom_$interface->{NAME}_vtable {\n"; + if (defined($interface->{BASE})) { + $res .= "\tstruct dcom_$interface->{BASE}\_vtable base;\n"; + } + + my $data = $interface->{DATA}; + foreach my $d (@{$data}) { + $res .= "\tNTSTATUS (*$d->{NAME}) (struct dcom_interface_p *, TALLOC_CTX *mem_ctx, struct $d->{NAME} *);\n" if ($d->{TYPE} eq "FUNCTION"); + } + $res .= "};\n\n"; +} + + ##################################################################### # parse the interface definitions sub HeaderInterface($) @@ -379,11 +399,14 @@ sub HeaderInterface($) HeaderTypedef($d); ($d->{TYPE} eq "TYPEDEF") && HeaderTypedefProto($d); - ($d->{TYPE} eq "FUNCTION") && + ($d->{TYPE} eq "FUNCTION") && HeaderFunction($d); - ($d->{TYPE} eq "FUNCTION") && - HeaderFnProto($d); + ($d->{TYPE} eq "FUNCTION") && + HeaderFnProto($interface, $d); } + + (util::has_property($interface, "object")) && + HeaderVTable($interface); $res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; } diff --git a/source4/build/pidl/parser.pm b/source4/build/pidl/parser.pm index fd95f91665..e55e5ecd9c 100644 --- a/source4/build/pidl/parser.pm +++ b/source4/build/pidl/parser.pm @@ -9,6 +9,7 @@ package IdlParser; use strict; use client; +use proxy; use needed; # the list of needed functions @@ -1594,11 +1595,15 @@ sub Parse($$) if ($x->{TYPE} eq "INTERFACE") { needed::BuildNeeded($x); ParseInterface($x); + + if (util::has_property($x, "object")) { + pidl IdlProxy::ParseInterface($x); + } else { + pidl IdlClient::ParseInterface($x); + } } } - pidl IdlClient::Parse($idl); - close(OUT); } diff --git a/source4/build/pidl/pidl.pl b/source4/build/pidl/pidl.pl index fcd189d8cd..bb7f1f8ed6 100755 --- a/source4/build/pidl/pidl.pl +++ b/source4/build/pidl/pidl.pl @@ -17,6 +17,7 @@ use idl; use dump; use header; use server; +use stub; use parser; use eparser; use validator; @@ -139,7 +140,17 @@ sub process_file($) if ($opt_server) { my($server) = util::ChangeExtension($output, "_s.c"); - util::FileSave($server, IdlServer::Parse($pidl)); + my $res = ""; + foreach my $x (@{$pidl}) { + next if ($x->{TYPE} ne "INTERFACE"); + + if (util::has_property($x, "object")) { + $res .= IdlStub::ParseInterface($x); + } else { + $res .= IdlServer::ParseInterface($x); + } + } + util::FileSave($server, $res); } if ($opt_parser) { diff --git a/source4/build/pidl/proxy.pm b/source4/build/pidl/proxy.pm new file mode 100644 index 0000000000..b6d9733419 --- /dev/null +++ b/source4/build/pidl/proxy.pm @@ -0,0 +1,166 @@ +################################################### +# DCOM proxy generator +# Copyright jelmer@samba.org 2003 +# released under the GNU GPL + +package IdlProxy; + +use strict; + +my($res); + +sub ParseVTable($$) +{ + my $interface = shift; + my $name = shift; + + # Generate the vtable + $res .="\tstruct dcom_$interface->{NAME}_vtable $name = {"; + + if (defined($interface->{BASE})) { + $res .= "\n\t\t{},"; + } + + my $data = $interface->{DATA}; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { + $res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}"; + $res .= ","; + } + } + + $res .= "\n\t};\n\n"; +} + +sub ParseRegFunc($) +{ + my $interface = shift; + + $res .= "NTSTATUS dcom_$interface->{NAME}_init(void) +{ + struct dcom_interface iface; +"; + + ParseVTable($interface, "proxy"); + + if (defined($interface->{BASE})) { + $res.= " + const void *base_vtable; + + GUID_from_string(DCERPC_" . (uc $interface->{BASE}) . "_UUID, &iface.base_iid); + + base_vtable = dcom_proxy_vtable_by_iid(&iface.base_iid); + if (base_vtable == NULL) { + return NT_STATUS_FOOBAR; + } + + proxy.base = *((const struct dcom_$interface->{BASE}_vtable *)base_vtable); + "; + } else { + $res .= "\tZERO_STRUCT(iface.base_iid);\n"; + } + + $res.= " + iface.num_methods = DCERPC_" . (uc $interface->{NAME}) . "_CALL_COUNT; + GUID_from_string(DCERPC_" . (uc $interface->{NAME}) . "_UUID, &iface.iid); + iface.proxy_vtable = talloc_memdup(NULL, &proxy, sizeof(struct dcom_$interface->{NAME}_vtable)); + + return register_backend(\"dcom_interface\", &iface); +}\n\n"; +} + +##################################################################### +# parse a function +sub ParseFunction($$) +{ + my $interface = shift; + my $fn = shift; + my $name = $fn->{NAME}; + my $uname = uc $name; + + if (util::has_property($fn, "local")) { + $res .= " +static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + /* FIXME */ + return NT_STATUS_NOT_SUPPORTED; +}\n"; + } else { + $res .= " +static struct rpc_request *dcom_proxy_$interface->{NAME}_$name\_send(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + struct dcerpc_pipe *p; + NTSTATUS status = dcom_get_pipe(d, &p); + + if (NT_STATUS_IS_ERR(status)) { + return NULL; + } + + ZERO_STRUCT(r->in.ORPCthis); + r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION; + r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION; + + if (p->flags & DCERPC_DEBUG_PRINT_IN) { + NDR_PRINT_IN_DEBUG($name, r); + } + + return dcerpc_ndr_request_send(p, &d->ipid, DCERPC_$uname, mem_ctx, + (ndr_push_flags_fn_t) ndr_push_$name, + (ndr_pull_flags_fn_t) ndr_pull_$name, + r, sizeof(*r)); +} + +static NTSTATUS dcom_proxy_$interface->{NAME}_$name(struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + struct dcerpc_pipe *p; + NTSTATUS status = dcom_get_pipe(d, &p); + struct rpc_request *req; + + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + req = dcom_proxy_$interface->{NAME}_$name\_send(d, mem_ctx, r); + if (req == NULL) return NT_STATUS_NO_MEMORY; + + status = dcerpc_ndr_request_recv(req); + + if (NT_STATUS_IS_OK(status) && (p->flags & DCERPC_DEBUG_PRINT_OUT)) { + NDR_PRINT_OUT_DEBUG($name, r); + } + "; + if ($fn->{RETURN_TYPE} eq "NTSTATUS") { + $res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n"; + } + $res .= + " + return status; +}"; + } + + $res .=" +NTSTATUS dcom_$interface->{NAME}_$name (struct dcom_interface_p *d, TALLOC_CTX *mem_ctx, struct $name *r) +{ + return ((const struct dcom_$interface->{NAME}_vtable *)d->vtable)->$name (d, mem_ctx, r); +} +"; +} + + +##################################################################### +# parse the interface definitions +sub ParseInterface($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + $res = "/* DCOM stubs generated by pidl */\n\n"; + foreach my $d (@{$data}) { + ($d->{TYPE} eq "FUNCTION") && + ParseFunction($interface, $d); + } + + ParseRegFunc($interface); +} + +1; diff --git a/source4/build/pidl/server.pm b/source4/build/pidl/server.pm index 01c5adacb4..6a9ea157a9 100644 --- a/source4/build/pidl/server.pm +++ b/source4/build/pidl/server.pm @@ -203,19 +203,14 @@ NTSTATUS dcerpc_server_$name\_init(void) "; } - ##################################################################### # parse a parsed IDL structure back into an IDL file -sub Parse($) +sub ParseInterface($) { - my($idl) = shift; + my($interface) = shift; $res = "/* dcerpc server boilerplate generated by pidl */\n\n"; - foreach my $x (@{$idl}) { - if ($x->{TYPE} eq "INTERFACE") { - Boilerplate_Iface($x); - Boilerplate_Ep_Server($x); - } - } + Boilerplate_Iface($interface); + Boilerplate_Ep_Server($interface); return $res; } diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/stub.pm new file mode 100644 index 0000000000..1cfb3cb11e --- /dev/null +++ b/source4/build/pidl/stub.pm @@ -0,0 +1,221 @@ +################################################### +# stub boilerplate generator +# Copyright jelmer@samba.org 2004 +# Copyright tridge@samba.org 2003 +# 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"; + 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\tr2->out.result = vtable->$d->{NAME}(iface, mem_ctx, r2);\n"; + } else { + pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\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 0x%x in $d->{NAME}\\n\", 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 $count = 0; + my $name = $interface->{NAME}; + my $uname = uc $name; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + 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 *dce_conn, const struct dcesrv_interface *iface) +{ +#ifdef DCESRV_INTERFACE_$uname\_UNBIND + DCESRV_INTERFACE_$uname\_UNBIND(dce_conn,iface); +#else + return; +#endif +} + +static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16 opnum = dce_call->pkt.u.request.opnum; + struct GUID ipid = dce_call->pkt.u.request.object.object; + struct dcom_interface_p *iface = dcoms_get_ifacep(&ipid); + struct dcom_$name\_vtable *vtable = if->vtable; + + dce_call->fault_code = 0; + + switch (opnum) { +"; + gen_dispatch_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + return NT_STATUS_NET_WRITE_FAULT; + } + return NT_STATUS_OK; +} + +static const struct dcesrv_interface $name\_interface = { + &dcerpc_table_$name, + $name\__op_bind, + $name\__op_unbind, + $name\__op_dispatch +}; + +"; +} + +##################################################################### +# produce boilerplate code for an endpoint server +sub Boilerplate_Ep_Server($) +{ + my($interface) = shift; + my($data) = $interface->{DATA}; + my $count = 0; + my $name = $interface->{NAME}; + my $uname = uc $name; + + foreach my $d (@{$data}) { + if ($d->{TYPE} eq "FUNCTION") { $count++; } + } + + if ($count == 0) { + return; + } + + pidl " +static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server) +{ + int i; + + for (i=0;i<$name\_interface.ndr->endpoints->count;i++) { + NTSTATUS ret; + const char *name = $name\_interface.ndr->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 if_version) +{ + if ($name\_interface.ndr->if_version == if_version && + strcmp($name\_interface.ndr->uuid, uuid)==0) { + memcpy(iface,&$name\_interface, sizeof(*iface)); + return True; + } + + return False; +} + +static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name) +{ + if (strcmp($name\_interface.ndr->name, name)==0) { + memcpy(iface,&$name\_interface, 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 = register_backend(\"dcerpc\", &ep_server); + + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\")); + return ret; + } + + return ret; +} + +"; +} + +sub ParseInterface($) +{ + my($interface) = shift; + $res = "/* dcerpc server boilerplate generated by pidl */\n\n"; + + Boilerplate_Iface($interface); + Boilerplate_Ep_Server($interface); + + return $res; +} + +1; + diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 320b5a4a9f..9c09cc17d9 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -29,11 +29,18 @@ struct IUnknown_QueryInterface; struct dcom_context { - struct dcom_oxid_mapping { - struct dcom_oxid_mapping *prev, *next; + struct dcom_object_exporter { + struct dcom_object_exporter *prev, *next; + struct STRINGARRAY resolver_address; struct DUALSTRINGARRAY bindings; HYPER_T oxid; struct dcerpc_pipe *pipe; + struct dcom_object + { + struct dcom_object *prev, *next; + HYPER_T oid; + void *private_data; + } *objects; } *oxids; const char *domain; const char *user; @@ -41,11 +48,32 @@ struct dcom_context uint32_t dcerpc_flags; }; +/* Specific implementation of one or more interfaces */ +struct dcom_class +{ + const char *prog_id; + struct GUID clsid; + void (*get_class_object) (struct GUID *iid, void **vtable); +}; + 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; - struct dcerpc_pipe *pipe; - struct OBJREF *objref; + const struct dcom_interface *interface; + const void *vtable; /* Points to one of the available implementations */ + struct GUID ipid; + struct dcom_object *object; + int objref_flags; + int orpc_flags; + struct dcom_object_exporter *ox; uint32_t private_references; }; diff --git a/source4/lib/dcom/common/local.c b/source4/lib/dcom/common/local.c deleted file mode 100644 index a68f5f4593..0000000000 --- a/source4/lib/dcom/common/local.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Implementation of some of the local COM calls. Interfaces: - - IUnknown - - Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org> - - 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 "librpc/gen_ndr/ndr_dcom.h" - -NTSTATUS dcerpc_IUnknown_AddRef(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_AddRef *rr) -{ - struct RemAddRef r; - struct REMINTERFACEREF ref; - - /* This is rather inefficient, but we'll patch it up later */ - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - return dcerpc_RemAddRef(p, mem_ctx, &r); -} - -NTSTATUS dcerpc_IUnknown_Release(struct dcom_interface *p, TALLOC_CTX *mem_ctx, struct IUnknown_Release *rr) -{ - struct RemRelease r; - struct REMINTERFACEREF ref; - - return NT_STATUS_NOT_SUPPORTED; - - p->private_references--; - - /* Only do the remote version of this call when all local references have - * been released */ - if (p->private_references == 0) { - NTSTATUS status; - r.in.cInterfaceRefs = 1; - r.in.InterfaceRefs = &ref; - - status = dcerpc_RemRelease(p, mem_ctx, &r); - - if (NT_STATUS_IS_OK(status)) { - talloc_destroy(p); - } - - return status; - } - - return NT_STATUS_OK; -} - -NTSTATUS dcerpc_IUnknown_QueryInterface(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IUnknown_QueryInterface *rr) -{ - /* FIXME: Ask local server for interface pointer. Local server can then - * call RemQueryInterface if necessary */ - return NT_STATUS_NOT_SUPPORTED; -} - -NTSTATUS dcerpc_IClassFactory_CreateInstance(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_CreateInstance *rr) -{ - return NT_STATUS_NOT_SUPPORTED; -} - -NTSTATUS dcerpc_IClassFactory_LockServer(struct dcom_interface *o, TALLOC_CTX *mem_ctx, struct IClassFactory_LockServer *rr) -{ - return NT_STATUS_NOT_SUPPORTED; -} diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 996432181a..60f866aede 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -111,10 +111,31 @@ WERROR dcom_init(struct dcom_context **ctx, const char *domain, const char *user (*ctx)->domain = talloc_strdup(*ctx, domain); (*ctx)->user = talloc_strdup(*ctx, user); (*ctx)->password = talloc_strdup(*ctx, pass); + (*ctx)->dcerpc_flags = 0; return WERR_OK; } +static struct dcom_object_exporter *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +{ + struct dcom_object_exporter *m; + + for (m = ctx->oxids;m;m = m->next) { + if (m->oxid == oxid) { + break; + } + } + + /* Add oxid mapping if we couldn't find one */ + if (!m) { + m = talloc_zero_p(ctx, struct dcom_object_exporter); + m->oxid = oxid; + DLIST_ADD(ctx->oxids, m); + } + + return m; +} + WERROR dcom_ping(struct dcom_context *ctx) { /* FIXME: If OID's waiting in queue, do a ComplexPing call */ @@ -122,11 +143,12 @@ WERROR dcom_ping(struct dcom_context *ctx) 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 **ip, WERROR *results) +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_oxid_mapping *m; struct RemoteActivation r; + struct DUALSTRINGARRAY dualstring; int i; + struct dcom_object_exporter *m; struct dcerpc_pipe *p; NTSTATUS status; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; @@ -148,8 +170,7 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch r.in.Interfaces = num_ifaces; r.in.pIIDs = iid; r.out.ifaces = talloc_array_p(ctx, struct pMInterfacePointer, num_ifaces); - m = talloc_zero_p(ctx, struct dcom_oxid_mapping); - r.out.pdsaOxidBindings = &m->bindings; + r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -165,28 +186,33 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch return r.out.hr; } - *ip = talloc_array_p(ctx, struct dcom_interface, num_ifaces); + *ip = talloc_array_p(ctx, struct dcom_interface_p *, num_ifaces); for (i = 0; i < num_ifaces; i++) { results[i] = r.out.results[i]; - (*ip)[i].private_references = 1; - (*ip)[i].objref = &r.out.ifaces[i].p->obj; - (*ip)[i].pipe = NULL; - (*ip)[i].ctx = ctx; + (*ip)[i] = NULL; + if (W_ERROR_IS_OK(results[i])) { + status = dcom_ifacep_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i].p->obj); + if (NT_STATUS_IS_OK(status)) { + (*ip)[i]->private_references = 1; + } else { + results[i] = ntstatus_to_werror(status); + } + } } /* Add the OXID data for the returned oxid */ - m->oxid = r.out.pOxid; + m = oxid_mapping_by_oxid(ctx, r.out.pOxid); m->bindings = *r.out.pdsaOxidBindings; - DLIST_ADD(ctx->oxids, m); return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface *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_oxid_mapping *m; + struct dcom_object_exporter *m; struct RemoteActivation r; struct dcerpc_pipe *p; + struct DUALSTRINGARRAY dualstring; NTSTATUS status; struct pMInterfacePointer pm; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; @@ -209,8 +235,7 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const r.in.pIIDs = iid; r.in.Mode = MODE_GET_CLASS_OBJECT; r.out.ifaces = ± - m = talloc_zero_p(ctx, struct dcom_oxid_mapping); - r.out.pdsaOxidBindings = &m->bindings; + r.out.pdsaOxidBindings = &dualstring; status = dcerpc_RemoteActivation(p, ctx, &r); if(NT_STATUS_IS_ERR(status)) { @@ -223,74 +248,160 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; } /* Set up the interface data */ - ip->private_references = 1; - ip->pipe = NULL; - ip->objref = &pm.p->obj; - ip->ctx = ctx; + dcom_ifacep_from_OBJREF(ctx, ip, &pm.p->obj); + (*ip)->private_references = 1; /* Add the OXID data for the returned oxid */ - m->oxid = r.out.pOxid; + m = oxid_mapping_by_oxid(ctx, r.out.pOxid); m->bindings = *r.out.pdsaOxidBindings; - DLIST_ADD(ctx->oxids, m); return WERR_OK; } -static struct dcom_oxid_mapping *oxid_mapping_by_oxid (struct dcom_context *ctx, HYPER_T oxid) +NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) { - struct dcom_oxid_mapping *m; + struct dcerpc_binding binding; + struct GUID iid; + HYPER_T oxid; + NTSTATUS status; + int i; + + *p = NULL; - for (m = ctx->oxids;m;m = m->next) { - if (m->oxid == oxid) { - return m; + oxid = iface->ox->oxid; + iid = iface->interface->iid; + + if (iface->ox->pipe) { + if (!uuid_equal(&iface->ox->pipe->syntax.uuid, &iid)) { + iface->ox->pipe->syntax.uuid = iid; + status = dcerpc_alter(iface->ox->pipe, iface->ctx); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + } + *p = iface->ox->pipe; + return NT_STATUS_OK; + } + + i = 0; + do { + status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->ox->bindings.stringbindings[i]); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(1, ("Error parsing string binding")); + } else { + binding.flags = iface->ctx->dcerpc_flags; + status = dcerpc_pipe_connect_b(&iface->ox->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); } + + i++; + } while (NT_STATUS_IS_ERR(status) && iface->ox->bindings.stringbindings[i]); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); + return status; } - return NULL; + DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); + + *p = iface->ox->pipe; + return NT_STATUS_OK; } -NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) +struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T oid) { - struct dcom_oxid_mapping *m; - struct dcerpc_binding binding; - struct GUID iid; - HYPER_T oxid; - NTSTATUS status; - int i; + struct dcom_object *o; - *p = NULL; + for (o = ox->objects; o; o = o->next) { + if (o->oid == oid) { + break; + } + } + + if (o == NULL) { + o = talloc_zero_p(ox, struct dcom_object); + o->oid = oid; + DLIST_ADD(ox->objects, o); + } - SMB_ASSERT(iface->objref->signature == OBJREF_SIGNATURE); + return o; +} + +NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) +{ + struct dcom_interface_p *p = talloc_p(ctx, struct dcom_interface_p); - if (iface->objref->flags & OBJREF_HANDLER) { - DEBUG(0, ("dcom_get_pipe: OBJREF_HANDLER not supported!\n")); + p->ctx = ctx; + p->interface = dcom_interface_by_iid(&o->iid); + if (!p->interface) { + DEBUG(0, ("Unable to find interface with IID %s\n", GUID_string(ctx, &o->iid))); return NT_STATUS_NOT_SUPPORTED; } - if (iface->objref->flags & OBJREF_CUSTOM) { - DEBUG(0, ("dcom_get_pipe: OBJREF_CUSTOM not supported!\n")); + p->private_references = 0; + p->objref_flags = o->flags; + + switch(p->objref_flags) { + case OBJREF_NULL: + p->object = NULL; + p->ox = NULL; + p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); + ZERO_STRUCT(p->ipid); + *_p = p; + return NT_STATUS_OK; + + case OBJREF_STANDARD: + p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_standard.std.oxid); + p->ipid = o->u_objref.u_standard.std.ipid; + p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); + p->ox->resolver_address = o->u_objref.u_standard.saResAddr; + p->vtable = dcom_proxy_vtable_by_iid(&p->interface->iid); + *_p = p; + return NT_STATUS_OK; + + case OBJREF_HANDLER: + p->ox = oxid_mapping_by_oxid(ctx, o->u_objref.u_handler.std.oxid ); + p->ipid = o->u_objref.u_handler.std.ipid; + p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); + p->ox->resolver_address = o->u_objref.u_handler.saResAddr; + p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid); + /* FIXME: Do the custom unmarshaling call */ + + *_p = p; + return NT_STATUS_OK; + + case OBJREF_CUSTOM: + { + const struct dcom_interface *imarshal = dcom_vtable_by_clsid(&o->u_objref.u_custom.clsid); + p->vtable = NULL; + + /* FIXME: Do the actual custom unmarshaling call */ + p->ox = NULL; + p->object = NULL; + ZERO_STRUCT(p->ipid); + *_p = p; return NT_STATUS_NOT_SUPPORTED; + } } - oxid = iface->objref->u_objref.u_standard.std.oxid; - iid = iface->objref->iid; - - m = oxid_mapping_by_oxid(iface->ctx, oxid); + return NT_STATUS_NOT_SUPPORTED; + +#if 0 + struct dcom_oxid_mapping *m; /* Add OXID mapping if none present yet */ if (!m) { struct dcerpc_pipe *po; struct ResolveOxid r; uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; - DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", oxid)); + DEBUG(3, ("No binding data present yet, resolving OXID %llu\n", p->ox->oxid)); - m = talloc_zero_p(iface->ctx, struct dcom_oxid_mapping); + m = talloc_zero_p(p->ctx, struct dcom_oxid_mapping); m->oxid = oxid; i = 0; do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); + status = dcerpc_binding_from_STRINGBINDING(p->ctx, &binding, p->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_OK(status)) { binding.flags = iface->ctx->dcerpc_flags; @@ -300,7 +411,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) } i++; - } while (!NT_STATUS_IS_OK(status) && iface->objref->u_objref.u_standard.saResAddr.stringbindings[i]); + } while (!NT_STATUS_IS_OK(status) && iface->client.objref->u_objref.u_standard.saResAddr.stringbindings[i]); if (NT_STATUS_IS_ERR(status)) { DEBUG(1, ("Error while connecting to OXID Resolver : %s\n", nt_errstr(status))); @@ -322,39 +433,7 @@ NTSTATUS dcom_get_pipe (struct dcom_interface *iface, struct dcerpc_pipe **p) DLIST_ADD(iface->ctx->oxids, m); } +#endif - if (m->pipe) { - if (!uuid_equal(&m->pipe->syntax.uuid, &iid)) { - m->pipe->syntax.uuid = iid; - status = dcerpc_alter(m->pipe, iface->ctx); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - } - *p = m->pipe; - return NT_STATUS_OK; - } - - i = 0; - do { - status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, m->bindings.stringbindings[i]); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("Error parsing string binding")); - } else { - binding.flags = iface->ctx->dcerpc_flags; - status = dcerpc_pipe_connect_b(&m->pipe, &binding, GUID_string(iface->ctx, &iid) , 0.0, iface->ctx->domain, iface->ctx->user, iface->ctx->password); - } - - i++; - } while (NT_STATUS_IS_ERR(status) && m->bindings.stringbindings[i]); - - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status))); - return status; - } - - DEBUG(2, ("Successfully connected to OXID %llx\n", oxid)); - - *p = m->pipe; - return NT_STATUS_OK; + return NT_STATUS_NOT_SUPPORTED; } diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c new file mode 100644 index 0000000000..d6b7cfa78f --- /dev/null +++ b/source4/lib/dcom/common/tables.c @@ -0,0 +1,114 @@ +/* + Unix SMB/CIFS implementation. + DCOM interface and class tables + Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org> + + 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 (uuid_equal(iid, &l->interface.iid)) + return &l->interface; + + l = l->next; + } + + return NULL; +} + +const void *dcom_vtable_by_clsid(const struct GUID *clsid) +{ + struct class_list *c = classes; + + while(c) { + + if (uuid_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; +} + +static NTSTATUS dcom_register_interface(const void *_iface) +{ + const struct dcom_interface *iface = _iface; + struct interface_list *l = talloc_zero_p(interfaces, struct interface_list); + + l->interface = *iface; + + DLIST_ADD(interfaces, l); + + return NT_STATUS_OK; +} + +static NTSTATUS dcom_register_class(const void *_class) +{ + const struct dcom_class *class = _class; + struct class_list *l = talloc_zero_p(classes, struct class_list); + + l->class = *class; + + DLIST_ADD(classes, l); + + return NT_STATUS_OK; +} + +NTSTATUS libdcom_init(void) +{ + NTSTATUS status; + + status = register_subsystem("dcom_interface", dcom_register_interface); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + register_subsystem("dcom_class", dcom_register_class); + if (NT_STATUS_IS_ERR(status)) { + return status; + } + + return status; +} diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 39424e6b25..6ebf16324f 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -1,9 +1,11 @@ ################################################ # Start SUBSYSTEM LIBDCOM [SUBSYSTEM::LIBDCOM] +INIT_FUNCTION = libdcom_init INIT_OBJ_FILES = \ lib/dcom/common/main.o \ - lib/dcom/common/local.o + lib/dcom/common/tables.o +REQUIRED_SUBSYSTEMS = LIBRPC # # End SUBSYSTEM LIBDCOM ################################################ diff --git a/source4/librpc/idl/dcom.idl b/source4/librpc/idl/dcom.idl index b1295315d8..d9c5a72ab2 100644 --- a/source4/librpc/idl/dcom.idl +++ b/source4/librpc/idl/dcom.idl @@ -12,16 +12,13 @@ version(0.0) ] interface dcom_Unknown { - void dcomu_UseProtSeq(); - void dcomu_GetCustomProtseqInfo(); - void dcomu_UpdateResolverBindings(); + void UseProtSeq(); + void GetCustomProtseqInfo(); + void UpdateResolverBindings(); } interface ObjectRpcBaseTypes { - /*//////////////////////////////////////////////////////////////// */ - /* ORPC Call Packet Format */ - /*//////////////////////////////////////////////////////////////// */ /* COM_MINOR_VERSION = 1 (NT4.0, SP1, SP2, DCOM95). */ /* - Initial Release */ /* - Must be used when talking to downlevel machines, including */ @@ -71,7 +68,7 @@ interface ObjectRpcBaseTypes { GUID id; /* Extension identifier. */ uint32 size; /* Extension size. */ - /*FIXME[size_is((size+7)&~7)] uint8 data[]; // Extension data. */ + /*FIXME[size_is((size+7)&~7)] uint8 data[]; Extension data. */ [size_is(size)] uint8 data[]; } ORPC_EXTENT; @@ -81,7 +78,7 @@ interface ObjectRpcBaseTypes { uint32 size; /* Num extents. */ uint32 reserved; /* Must be zero. */ - /*FIXME[size_is((size+1)&~1,), unique] ORPC_EXTENT **extent; // extents */ + /*FIXME[size_is((size+1)&~1,), unique] ORPC_EXTENT **extent; extents */ [size_is(size),unique] ORPC_EXTENT extent[]; } ORPC_EXTENT_ARRAY; @@ -227,16 +224,16 @@ interface IUnknown /* Function 0x00 */ /* Returns the interface with the specified IID if implemented by this object */ - [local] WERROR IUnknown_QueryInterface([in] GUID *iid, + [local] WERROR QueryInterface([in] GUID *iid, [out,iid_is(riid)] MInterfacePointer *data); /*****************/ /* Function 0x01 */ - [local] uint32 IUnknown_AddRef(); + [local] uint32 AddRef(); /*****************/ /* Function 0x02 */ - [local] uint32 IUnknown_Release(); + [local] uint32 Release(); } @@ -246,7 +243,7 @@ interface IUnknown pointer_default(unique) ] interface IClassFactory : IUnknown { - [local] WERROR IClassFactory_CreateInstance([in] MInterfacePointer *pUnknown, + [local] WERROR CreateInstance([in] MInterfacePointer *pUnknown, [in] GUID *iid, [out, iid_is(riid)] MInterfacePointer *ppv); @@ -254,13 +251,11 @@ interface IUnknown /* Set lock to TRUE when you want to do a lock and set it to FALSE when you want to unlock */ - [local] WERROR IClassFactory_LockServer([in] uint8 lock); + [local] WERROR LockServer([in] uint8 lock); [call_as(LockServer)] WERROR RemoteLockServer(); } -/*//////////////////////////////////////////////////////////////// */ - /* The remote version of IUnknown. This interface exists on every */ /* OXID (whether an OXID represents either a thread or a process is */ /* implementation specific). It is used by clients to query for new */ @@ -286,7 +281,7 @@ interface IRemUnknown : IUnknown [in] GUID *ripid, /* interface to QI on */ [in] uint32 cRefs, /* count of AddRefs requested */ [in] uint16 cIids, /* count of IIDs that follow */ - [in, size_is(cIids)] GUID* iids, /*, // IIDs to QI for */ + [in, size_is(cIids)] GUID* iids, /* IIDs to QI for */ [out, size_is(cIids)] MInterfacePointer *ip ); @@ -463,14 +458,14 @@ uuid(DB7C21F8-FE33-4C11-AEA5-CEB56F076FBB), ] interface IStream : IUnknown { - WERROR IStream_Read( + WERROR Read( [out, size_is(num_requested), length_is(num_read)] uint8 pv[], [in] uint32 num_requested, [in] uint32 *num_readx, [out] uint32 num_read ); - WERROR IStream_Write( + WERROR Write( [in,size_is(num_requested)] uint8 *data, [in] uint32 num_requested, [out] uint32 num_written); diff --git a/source4/rpc_server/dcom/dcom.h b/source4/rpc_server/dcom/dcom.h deleted file mode 100644 index 2d4dc7d628..0000000000 --- a/source4/rpc_server/dcom/dcom.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DCOM standard objects - 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. -*/ - -#ifndef _DCOM_H /* _DCOM_H */ -#define _DCOM_H - -struct dcom_class -{ - const char *name; - const char *prog_id; - struct GUID CLSID; - - /* List of IID's implemented */ - uint32 num_iids; - struct GUID *IID; - - /* Pointers to functions this class implements */ - void **interfaces; -}; - -struct dcom_object -{ - struct dcom_class *class; - struct GUID oid; - HYPER_T OXID; - struct dcom_interface_pointer *interfaces; - void *private_data; -}; - -struct dcom_interface_pointer -{ - struct dcom_object *object; - struct dcerpc_interface_table *interface; - struct GUID ipid; -}; - -#endif /* _DCOM_H */ diff --git a/source4/rpc_server/dcom/remact.c b/source4/rpc_server/dcom/remact.c index 7a2b21a789..ce7c9c0c23 100644 --- a/source4/rpc_server/dcom/remact.c +++ b/source4/rpc_server/dcom/remact.c @@ -25,7 +25,6 @@ #include "rpc_server/common/common.h" #include "librpc/gen_ndr/ndr_remact.h" #include "librpc/gen_ndr/ndr_oxidresolver.h" -#include "rpc_server/dcom/dcom.h" struct dcom_interface_pointer *dcom_interface_pointer_by_ipid(struct GUID *ipid) { @@ -38,9 +37,9 @@ struct dcom_interface_pointer *dcom_interface_pointer_by_ipid(struct GUID *ipid) */ static WERROR RemoteActivation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct RemoteActivation *r) { - struct IClassFactory_CreateInstance *cr; - struct IUnknown_Release *ur; - struct dcom_interface *o; + struct CreateInstance *cr; + struct Release *ur; + struct dcom_interface_p *o; int i; /* FIXME: CoGetClassObject() */ @@ -61,9 +60,9 @@ static WERROR RemoteActivation(struct dcesrv_call_state *dce_call, TALLOC_CTX *m r->out.hr = cr->out.result; for (i = 0; i < r->in.Interfaces; i++) { - struct IUnknown_QueryInterface rr; + struct QueryInterface rr; rr.in.iid = &r->in.pIIDs[i]; - dcerpc_IUnknown_QueryInterface(o, mem_ctx, &rr); + dcom_IUnknown_QueryInterface(o, mem_ctx, &rr); ZERO_STRUCT(r->out.ifaces[i]); r->out.results[i] = rr.out.result; } diff --git a/source4/rpc_server/dcom/rot.c b/source4/rpc_server/dcom/rot.c index eb19aa0501..d639bd9bf3 100644 --- a/source4/rpc_server/dcom/rot.c +++ b/source4/rpc_server/dcom/rot.c @@ -23,19 +23,6 @@ #include "includes.h" #include "rpc_server/dcerpc_server.h" #include "rpc_server/common/common.h" -#include "rpc_server/dcom/dcom.h" - -struct dcom_object *dcom_object_by_oid(struct GUID *oid) -{ - /* FIXME */ - return NULL; -} - -struct dcom_class *dcom_class_by_clsid(struct GUID *clsid) -{ - /* FIXME */ - return NULL; -} struct dcom_object *dcom_call_get_object(struct dcesrv_call_state *call) { diff --git a/source4/torture/dcom/simple.c b/source4/torture/dcom/simple.c index 287e35142e..85bf194091 100644 --- a/source4/torture/dcom/simple.c +++ b/source4/torture/dcom/simple.c @@ -35,16 +35,21 @@ BOOL torture_dcom_simple(void) struct GUID IID[2]; struct GUID clsid; WERROR error; - struct dcom_interface *interfaces; - struct IStream_Read r_read; - struct IStream_Write r_write; + 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); mem_ctx = talloc_init("torture_dcom_simple"); + dcom_IUnknown_init(); + dcom_IStream_init(); + dcom_init(&ctx, lp_parm_string(-1, "torture", "userdomain"), lp_parm_string(-1, "torture", "username"), lp_parm_string(-1, "torture", "password")); @@ -62,10 +67,15 @@ BOOL torture_dcom_simple(void) 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 = dcerpc_IStream_Read(&interfaces[0], mem_ctx, &r_read); + 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; @@ -79,7 +89,7 @@ BOOL torture_dcom_simple(void) } r_write.in.num_requested = 5; r_write.in.data = (uint8_t *)&test_data; - status = dcerpc_IStream_Write(&interfaces[0], mem_ctx, &r_write); + 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; @@ -88,7 +98,7 @@ BOOL torture_dcom_simple(void) ret = False; } - status = dcerpc_IUnknown_Release(&interfaces[1], mem_ctx, NULL); + 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; |