From cc368fa69e6a205516c64712aee701fe0cf6d20b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Nov 2004 17:47:09 +0000 Subject: r3898: Work towards local/server DCOM support, start working on Simple example server side implementation (This used to be commit 98afb504d95ccca4d6ec48273e10b52ccfa26ad0) --- source4/lib/dcom/classes/simple.c | 39 ++++++++++++ source4/lib/dcom/common/dcom.h | 5 +- source4/lib/dcom/common/main.c | 126 +++++++++++++++++++++++++++++++++++--- source4/lib/dcom/common/rot.c | 10 ++- source4/lib/dcom/common/tables.c | 5 +- source4/lib/dcom/config.mk | 6 ++ 6 files changed, 177 insertions(+), 14 deletions(-) create mode 100644 source4/lib/dcom/classes/simple.c (limited to 'source4/lib/dcom') diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c new file mode 100644 index 0000000000..e8b8730267 --- /dev/null +++ b/source4/lib/dcom/classes/simple.c @@ -0,0 +1,39 @@ +/* + 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" + +static struct dcom_IClassFactory_vtable simple_classobject; + +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(NULL, dcom_interface_by_iid(&iid), &simple_classobject, NULL); + + 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 9c09cc17d9..d8e3797c73 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -26,6 +26,7 @@ struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; +struct dcom_interface_p; struct dcom_context { @@ -53,7 +54,9 @@ struct dcom_class { const char *prog_id; struct GUID clsid; - void (*get_class_object) (struct GUID *iid, void **vtable); + + /* IUnknown */ + struct dcom_interface_p *class_object; }; struct dcom_interface diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 60f866aede..3730137268 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -143,15 +143,15 @@ 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_p ***ip, WERROR *results) +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) { + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + struct dcerpc_pipe *p; + struct dcom_object_exporter *m; + NTSTATUS status; struct RemoteActivation r; struct DUALSTRINGARRAY dualstring; int i; - struct dcom_object_exporter *m; - struct dcerpc_pipe *p; - NTSTATUS status; - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { @@ -207,7 +207,60 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch 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) +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; + 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) { struct dcom_object_exporter *m; struct RemoteActivation r; @@ -258,6 +311,36 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const 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 **p) { struct dcerpc_binding binding; @@ -326,6 +409,12 @@ struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T return o; } + +NTSTATUS dcom_OBJREF_from_ifacep(struct dcom_context *ctx, struct OBJREF *o, struct dcom_interface_p *_p) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + 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); @@ -363,7 +452,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface 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 p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/ /* FIXME: Do the custom unmarshaling call */ *_p = p; @@ -371,7 +460,6 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface 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 */ @@ -437,3 +525,25 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface return NT_STATUS_NOT_SUPPORTED; } + +HYPER_T dcom_get_current_oxid(void) +{ + return getpid(); +} + +struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct dcom_interface *iface, void *vtable, struct dcom_object *object) +{ + struct dcom_interface_p *ip = talloc_p(ctx, struct dcom_interface_p); + + ip->ctx = ctx; + ip->interface = iface; + ip->vtable = vtable; + uuid_generate_random(&ip->ipid); + 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 index 95f83d000c..7acdbe066e 100644 --- a/source4/lib/dcom/common/rot.c +++ b/source4/lib/dcom/common/rot.c @@ -22,9 +22,13 @@ #include "includes.h" - -struct dcom_interface_p *dcom_get_iface_p(struct GUID *ipid) +struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) { - /* FIXME */ + /* 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 index f9f1c49380..f615662b47 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -46,14 +46,15 @@ const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) return NULL; } -const void *dcom_vtable_by_clsid(const struct GUID *clsid) +const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) { struct class_list *c = classes; while(c) { - if (uuid_equal(clsid, &c->class.clsid)) + if (uuid_equal(clsid, &c->class.clsid)) { return &c->class; + } c = c->next; } diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 9fda924881..d599231525 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -7,6 +7,12 @@ INIT_OBJ_FILES = \ lib/dcom/common/rot.o REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ RPC_NDR_OXIDRESOLVER + +[MODULE::DCOM_SIMPLE] +SUBSYSTEM = LIBDCOM +INIT_FUNCTION = dcom_simple_init +INIT_OBJ_FILES = \ + lib/dcom/classes/simple.o # # End SUBSYSTEM LIBDCOM ################################################ -- cgit