Reimport COM and DCOM libraries.
authorJelmer Vernooij <jelmer@samba.org>
Wed, 7 May 2008 14:04:21 +0000 (16:04 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Mon, 15 Sep 2008 15:36:46 +0000 (17:36 +0200)
source4/lib/com/README [new file with mode: 0644]
source4/lib/com/classes/simple.c [new file with mode: 0644]
source4/lib/com/com.h [new file with mode: 0644]
source4/lib/com/config.mk [new file with mode: 0644]
source4/lib/com/dcom/dcom.h [new file with mode: 0644]
source4/lib/com/dcom/main.c [new file with mode: 0644]
source4/lib/com/dcom/tables.c [new file with mode: 0644]
source4/lib/com/main.c [new file with mode: 0644]
source4/lib/com/rot.c [new file with mode: 0644]
source4/lib/com/tables.c [new file with mode: 0644]

diff --git a/source4/lib/com/README b/source4/lib/com/README
new file mode 100644 (file)
index 0000000..361024e
--- /dev/null
@@ -0,0 +1,9 @@
+This directory contains Samba's very simple COM implementation. 
+It is by no means finished yet. 
+
+The main aim of this implementation is for use by our DCOM implementation, 
+which lives in the dcom subdirectory. The local version is used mostly for
+testing.
+
+More information on this effort can be found in the DCOM whitepaper in 
+the lorikeet repository.
diff --git a/source4/lib/com/classes/simple.c b/source4/lib/com/classes/simple.c
new file mode 100644 (file)
index 0000000..295f113
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   Unix SMB/CIFS implementation.
+   Simple class
+   Copyright (C) 2004-2005 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 "lib/com/com.h"
+#include "librpc/gen_ndr/com_dcom.h"
+
+static struct IClassFactory_vtable simple_classobject_vtable;
+static struct IStream_vtable simple_IStream_vtable;
+
+static WERROR simple_IUnknown_QueryInterface (struct IUnknown *d, TALLOC_CTX *mem_ctx, struct GUID *iid, struct IUnknown **iun)
+{
+       *iun = d;
+       return WERR_OK;
+}
+
+static uint32_t simple_IUnknown_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx)
+{
+       return 1;
+}
+
+static uint32_t simple_IUnknown_Release (struct IUnknown *d, TALLOC_CTX *mem_ctx)
+{
+       return 1;
+}
+
+static WERROR simple_IStream_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_IStream_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 WERROR simpleclass_IUnknown_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_IClassFactory_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 = (struct IUnknown *)ret;
+       
+       return WERR_OK;
+}
+
+static uint32_t simpleclass_IUnknown_AddRef (struct IUnknown *d, TALLOC_CTX *mem_ctx)
+{
+       return 1;
+}
+
+static uint32_t simpleclass_IUnknown_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 = {
+        { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
+       simpleclass_IUnknown_QueryInterface, 
+       simpleclass_IUnknown_AddRef, 
+       simpleclass_IUnknown_Release,
+       simpleclass_IClassFactory_CreateInstance,
+       NULL,
+       NULL,
+       NULL
+};
+
+static struct IStream_vtable simple_IStream_vtable = {
+        { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
+       simple_IUnknown_QueryInterface,
+       simple_IUnknown_AddRef, 
+       simple_IUnknown_Release,
+       simple_IStream_Read,
+       simple_IStream_Write
+};
+
+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(CLSID_SIMPLE, &clsid);
+       GUID_from_string(COM_ICLASSFACTORY_UUID, &simple_classobject_vtable.iid);
+       GUID_from_string(COM_ISTREAM_UUID, &simple_IStream_vtable.iid);
+
+       return com_register_running_class(&clsid, PROGID_SIMPLE, class_object);
+}
diff --git a/source4/lib/com/com.h b/source4/lib/com/com.h
new file mode 100644 (file)
index 0000000..c4dd872
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   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 IUnknown_vtable;
+
+struct com_context 
+{
+       struct dcom_client_context *dcom;
+       struct event_context *event_ctx;
+};
+
+typedef struct IUnknown *(*get_class_object_function) (const struct GUID *clsid);
+
+
+#include "lib/com/proto.h"
+
+#endif /* _COM_H */
diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk
new file mode 100644 (file)
index 0000000..08c459a
--- /dev/null
@@ -0,0 +1,23 @@
+[LIBRARY::com]
+VERSION = 0.0.1
+SO_VERSION = 0
+PRIVATE_PROTO_HEADER = proto.h
+OBJ_FILES = \
+               tables.o \
+               rot.o \
+               main.o
+
+[LIBRARY::dcom]
+VERSION = 0.0.1
+SO_VERSION = 0
+PRIVATE_PROTO_HEADER = dcom/proto.h
+OBJ_FILES = \
+               dcom/main.o \
+               dcom/tables.o
+PUBLIC_DEPENDENCIES = com DCOM_PROXY_DCOM RPC_NDR_REMACT \
+                                         RPC_NDR_OXIDRESOLVER
+
+[MODULE::com_simple]
+SUBSYSTEM = com
+OBJ_FILES = classes/simple.o
+INIT_FUNCTION = com_simple_init
diff --git a/source4/lib/com/dcom/dcom.h b/source4/lib/com/dcom/dcom.h
new file mode 100644 (file)
index 0000000..65a4d0f
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+   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 _DCOM_H /* _DCOM_H */
+#define _DCOM_H 
+
+struct cli_credentials;
+struct dcerpc_pipe;
+
+#include "lib/com/com.h"
+#include "librpc/gen_ndr/orpc.h"
+#include "lib/com/dcom/proto.h"
+
+struct dcom_client_context {
+       struct cli_credentials *credentials;
+       struct dcom_object_exporter {
+               uint64_t oxid;  
+               struct DUALSTRINGARRAY bindings;
+               struct dcerpc_pipe *pipe;
+               struct dcom_object_exporter *prev, *next;
+       } *object_exporters;
+};
+
+#endif /* _DCOM_H */
diff --git a/source4/lib/com/dcom/main.c b/source4/lib/com/dcom/main.c
new file mode 100644 (file)
index 0000000..14a7287
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+   Unix SMB/CIFS implementation.
+   Main DCOM functionality
+   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 "system/filesys.h"
+#include "librpc/gen_ndr/epmapper.h"
+#include "librpc/gen_ndr/ndr_remact_c.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "lib/com/dcom/dcom.h"
+#include "librpc/rpc/dcerpc_table.h"
+
+#define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC }
+
+struct dcom_client_context *dcom_client_init(struct com_context *ctx, struct cli_credentials *credentials)
+{
+       ctx->dcom = talloc(ctx, struct dcom_client_context);
+       ctx->dcom->credentials = credentials;
+
+       return ctx->dcom;
+}
+
+static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding **b_out, struct STRINGBINDING *bd)
+{
+       char *host, *endpoint;
+       struct dcerpc_binding *b;
+
+       b = talloc_zero(mem_ctx, struct dcerpc_binding);
+       if (!b) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId);
+
+       if (b->transport == -1) {
+               DEBUG(1, ("Can't find transport match endpoint protocol %d\n", bd->wTowerId));
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       host = talloc_strdup(b, bd->NetworkAddr);
+       endpoint = strchr(host, '[');
+
+       if (endpoint) {
+               *endpoint = '\0';
+               endpoint++;
+
+               endpoint[strlen(endpoint)-1] = '\0';
+       }
+
+       b->host = host;
+       b->endpoint = talloc_strdup(b, endpoint);
+
+       *b_out = b;
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS dcom_connect_host(struct com_context *ctx, struct dcerpc_pipe **p, const char *server)
+{
+       struct dcerpc_binding *bd;
+       const char * available_transports[] = { "ncacn_ip_tcp", "ncacn_np" };
+       int i;
+       NTSTATUS status;
+       TALLOC_CTX *mem_ctx = talloc_init("dcom_connect");
+
+       if (server == NULL) { 
+               return dcerpc_pipe_connect(ctx, p, "ncalrpc", 
+                                                                  &dcerpc_table_IRemoteActivation,
+                                                                  ctx->dcom->credentials, ctx->event_ctx);
+       }
+
+       /* Allow server name to contain a binding string */
+       if (NT_STATUS_IS_OK(dcerpc_parse_binding(mem_ctx, server, &bd))) {
+               status = dcerpc_pipe_connect_b(ctx, p, bd, 
+                                                                          &dcerpc_table_IRemoteActivation,
+                                                                  ctx->dcom->credentials, ctx->event_ctx);
+
+               talloc_free(mem_ctx);
+               return status;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(available_transports); i++)
+       {
+               char *binding = talloc_asprintf(mem_ctx, "%s:%s", available_transports[i], server);
+               if (!binding) {
+                       talloc_free(mem_ctx);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               
+               status = dcerpc_pipe_connect(ctx, p, binding, 
+                                                                        &dcerpc_table_IRemoteActivation,
+                                            ctx->dcom->credentials, ctx->event_ctx);
+
+               if (NT_STATUS_IS_OK(status)) {
+                       talloc_free(mem_ctx);
+                       return status;
+               }
+       }
+       
+       talloc_free(mem_ctx);
+       return status;
+}
+
+struct dcom_object_exporter *object_exporter_by_oxid(struct com_context *ctx, uint64_t oxid)
+{
+       struct dcom_object_exporter *ox;
+       for (ox = ctx->dcom->object_exporters; ox; ox = ox->next) {
+               if (ox->oxid == oxid) {
+                       return ox;
+               }
+       }
+
+       return NULL; 
+}
+
+struct dcom_object_exporter *object_exporter_by_ip(struct com_context *ctx, struct IUnknown *ip)
+{
+       return NULL; /* FIXME */
+}
+
+WERROR dcom_create_object(struct com_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct IUnknown ***ip, WERROR *results)
+{
+       uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS;
+       struct dcerpc_pipe *p;
+       struct dcom_object_exporter *m;
+       NTSTATUS status;
+       struct RemoteActivation r;
+       struct DUALSTRINGARRAY dualstring;
+       int i;
+
+       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)));
+               return ntstatus_to_werror(status);
+       }
+
+       ZERO_STRUCT(r.in);
+       r.in.this.version.MajorVersion = COM_MAJOR_VERSION;
+       r.in.this.version.MinorVersion = COM_MINOR_VERSION;
+       r.in.this.cid = GUID_random();
+       r.in.Clsid = *clsid;
+       r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
+       r.in.num_protseqs = ARRAY_SIZE(protseq);
+       r.in.protseq = protseq;
+       r.in.Interfaces = num_ifaces;
+       r.in.pIIDs = iid;
+       r.out.ifaces = talloc_array(ctx, struct MInterfacePointer *, num_ifaces);
+       r.out.pdsaOxidBindings = &dualstring;
+       
+       status = dcerpc_RemoteActivation(p, ctx, &r);
+       if(NT_STATUS_IS_ERR(status)) {
+               DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status)));
+               return ntstatus_to_werror(status);
+       }
+
+       if(!W_ERROR_IS_OK(r.out.result)) {
+               return r.out.result; 
+       }
+       
+       if(!W_ERROR_IS_OK(r.out.hr)) { 
+               return r.out.hr; 
+       }
+
+       *ip = talloc_array(ctx, struct IUnknown *, num_ifaces);
+       for (i = 0; i < num_ifaces; i++) {
+               results[i] = r.out.results[i];
+               (*ip)[i] = NULL;
+               if (W_ERROR_IS_OK(results[i])) {
+                       status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i]->obj);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               results[i] = ntstatus_to_werror(status);
+                       }
+               }
+       }
+
+       /* Add the OXID data for the returned oxid */
+       m = object_exporter_by_oxid(ctx, r.out.pOxid);
+       m->bindings = *r.out.pdsaOxidBindings;
+       
+       return WERR_OK;
+}
+
+WERROR dcom_get_class_object(struct com_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct IUnknown **ip)
+{
+       struct dcom_object_exporter *m;
+       struct RemoteActivation r;
+       struct dcerpc_pipe *p;
+       struct DUALSTRINGARRAY dualstring;
+       NTSTATUS status;
+       struct MInterfacePointer pm;
+       struct MInterfacePointer *ifaces[1];
+       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)));
+               return ntstatus_to_werror(status);
+       }
+
+       ZERO_STRUCT(r.in);
+       r.in.this.version.MajorVersion = COM_MAJOR_VERSION;
+       r.in.this.version.MinorVersion = COM_MINOR_VERSION;
+       r.in.this.cid = GUID_random();
+       r.in.Clsid = *clsid;
+       r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
+       r.in.num_protseqs = ARRAY_SIZE(protseq);
+       r.in.protseq = protseq;
+       r.in.Interfaces = 1;
+       r.in.pIIDs = iid;
+       r.in.Mode = MODE_GET_CLASS_OBJECT;
+       r.out.ifaces = ifaces;
+       ifaces[0] = &pm;
+       r.out.pdsaOxidBindings = &dualstring;
+
+       status = dcerpc_RemoteActivation(p, ctx, &r);
+       if(NT_STATUS_IS_ERR(status)) {
+               DEBUG(1, ("Error while running RemoteActivation - %s\n", nt_errstr(status)));
+               return ntstatus_to_werror(status);
+       }
+
+       if(!W_ERROR_IS_OK(r.out.result)) { return r.out.result; }
+       if(!W_ERROR_IS_OK(r.out.hr)) { return r.out.hr; }
+       if(!W_ERROR_IS_OK(r.out.results[0])) { return r.out.results[0]; }
+       
+       /* Set up the interface data */
+       dcom_IUnknown_from_OBJREF(ctx, ip, &pm.obj);
+       
+       /* Add the OXID data for the returned oxid */
+       m = object_exporter_by_oxid(ctx, r.out.pOxid);
+       m->bindings = *r.out.pdsaOxidBindings;
+
+       return WERR_OK;
+}
+
+NTSTATUS dcom_get_pipe(struct IUnknown *iface, struct dcerpc_pipe **pp)
+{
+       struct dcerpc_binding *binding;
+       struct GUID iid;
+       uint64_t oxid;
+       NTSTATUS status;
+       int i;
+       struct dcerpc_pipe *p;
+       TALLOC_CTX *tmp_ctx;
+       struct dcom_object_exporter *ox;
+
+       ox = object_exporter_by_ip(iface->ctx, iface);
+
+       tmp_ctx = talloc_new(NULL);
+
+       p = ox->pipe;
+       
+       iid = iface->vtable->iid;
+
+       if (p) {
+               if (!GUID_equal(&p->syntax.uuid, &iid)) {
+                       struct dcerpc_pipe *p2;
+                       ox->pipe->syntax.uuid = iid;
+
+                       /* interface will always be present, so 
+                        * idl_iface_by_uuid can't return NULL */
+                       status = dcerpc_secondary_context(p, &p2, idl_iface_by_uuid(&iid));
+
+                       if (NT_STATUS_IS_OK(status)) {
+                               p = p2;
+                       }
+               } else {
+                       p = talloc_reference(NULL, p);
+               }
+               *pp = p;
+               talloc_free(tmp_ctx);
+               return status;
+       }
+
+       i = 0;
+       do {
+               status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding, 
+                                                          ox->bindings.stringbindings[i]);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(1, ("Error parsing string binding"));
+               } else {
+                       status = dcerpc_pipe_connect_b(NULL, &p, binding, 
+                                                      idl_iface_by_uuid(&iid),
+                                                      iface->ctx->dcom->credentials,
+                                                          iface->ctx->event_ctx);
+               }
+               talloc_free(binding);
+               i++;
+       } while (!NT_STATUS_IS_OK(status) && ox->bindings.stringbindings[i]);
+
+       if (NT_STATUS_IS_ERR(status)) {
+               DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status)));
+               talloc_free(tmp_ctx);
+               return status;
+       }
+
+       DEBUG(2, ("Successfully connected to OXID %llx\n", (long long)oxid));
+       
+       *pp = p;
+       talloc_free(tmp_ctx);
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS dcom_OBJREF_from_IUnknown(struct OBJREF *o, struct IUnknown *p)
+{
+       /* FIXME: Cache generated objref objects? */
+       ZERO_STRUCTP(o);
+       
+       o->signature = OBJREF_SIGNATURE;
+       
+       if (!p) {
+               o->flags = OBJREF_NULL;
+       } else {
+               o->iid = p->vtable->iid;
+               /* 
+               OBJREF_STANDARD
+               OBJREF_CUSTOM
+               OBJREF_HANDLER
+               */
+       }
+
+       return NT_STATUS_NOT_IMPLEMENTED;       
+}
+
+NTSTATUS dcom_IUnknown_from_OBJREF(struct com_context *ctx, struct IUnknown **_p, struct OBJREF *o)
+{
+       struct IUnknown *p;
+       struct dcom_object_exporter *ox;
+
+       switch(o->flags) {
+       case OBJREF_NULL: 
+               *_p = NULL;
+               return NT_STATUS_OK;
+               
+       case OBJREF_STANDARD:
+               p = talloc(ctx, struct IUnknown);
+               p->ctx = ctx;   
+               p->vtable = dcom_proxy_vtable_by_iid(&o->iid);
+               if (!p->vtable) {
+                       DEBUG(0, ("Unable to find proxy class for interface with IID %s\n", GUID_string(ctx, &o->iid)));
+                       return NT_STATUS_NOT_SUPPORTED;
+               }
+
+               ox = object_exporter_by_oxid(ctx, o->u_objref.u_standard.std.oxid);
+               /* FIXME: Add object to list of objects to ping */
+               *_p = p;
+               return NT_STATUS_OK;
+               
+       case OBJREF_HANDLER:
+               p = talloc(ctx, struct IUnknown);
+               p->ctx = ctx;   
+               ox = object_exporter_by_oxid(ctx, o->u_objref.u_handler.std.oxid );
+               /* FIXME: Add object to list of objects to ping */
+/*FIXME                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:
+               p = talloc(ctx, struct IUnknown);
+               p->ctx = ctx;   
+               p->vtable = NULL;
+               /* FIXME: Do the actual custom unmarshaling call */
+               *_p = p;
+               return NT_STATUS_NOT_SUPPORTED;
+       }
+
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+uint64_t dcom_get_current_oxid(void)
+{
+       return getpid();
+}
diff --git a/source4/lib/com/dcom/tables.c b/source4/lib/com/dcom/tables.c
new file mode 100644 (file)
index 0000000..ce4f672
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+   Unix SMB/CIFS implementation.
+   DCOM proxy tables functionality
+   Copyright (C) 2005 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/com_dcom.h"
+
+static struct dcom_proxy {
+       struct IUnknown_vtable *vtable;
+       struct dcom_proxy *prev, *next;
+}  *proxies = NULL;
+
+NTSTATUS dcom_register_proxy(struct IUnknown_vtable *proxy_vtable)
+{
+       struct dcom_proxy *proxy = talloc(talloc_autofree_context(), struct dcom_proxy);
+
+       proxy->vtable = proxy_vtable;
+       DLIST_ADD(proxies, proxy);
+
+       return NT_STATUS_OK;
+}
+
+struct IUnknown_vtable *dcom_proxy_vtable_by_iid(struct GUID *iid)
+{
+       struct dcom_proxy *p;
+       for (p = proxies; p; p = p->next) {
+               if (GUID_equal(&p->vtable->iid, iid)) {
+                       return p->vtable;
+               }
+       }
+       return NULL;
+}
diff --git a/source4/lib/com/main.c b/source4/lib/com/main.c
new file mode 100644 (file)
index 0000000..3e4127f
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+   Unix SMB/CIFS implementation.
+   Main COM functionality
+   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 "lib/com/com.h"
+#include "lib/events/events.h"
+#include "librpc/gen_ndr/com_dcom.h"
+#include "build.h"
+
+WERROR com_init_ctx(struct com_context **ctx, struct event_context *event_ctx)
+{
+       *ctx = talloc(NULL, struct com_context);
+       if (event_ctx == NULL) {
+               event_ctx = event_context_init(*ctx);
+       }
+       (*ctx)->event_ctx = event_ctx;
+       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);
+}
+
+NTSTATUS com_init(void)
+{
+       static BOOL initialized = False;
+       
+       init_module_fn static_init[] = STATIC_com_MODULES; 
+       init_module_fn *shared_init;
+
+       if (initialized) return NT_STATUS_OK;
+       initialized = True;
+
+       shared_init = load_samba_modules(NULL, "com");
+
+       run_init_functions(static_init);
+       run_init_functions(shared_init);
+
+       talloc_free(shared_init);
+       
+       return NT_STATUS_OK;    
+}
diff --git a/source4/lib/com/rot.c b/source4/lib/com/rot.c
new file mode 100644 (file)
index 0000000..34a5671
--- /dev/null
@@ -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 (file)
index 0000000..d9989ec
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+   Unix SMB/CIFS implementation.
+   COM 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"
+#include "lib/com/com.h"
+#include "librpc/gen_ndr/ndr_misc.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 = dlopen(mod_name, 0);
+
+       if (!mod) {
+               return NULL;
+       }
+       
+       f = 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;
+}