summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2008-05-07 16:04:21 +0200
committerJelmer Vernooij <jelmer@samba.org>2008-09-15 17:36:46 +0200
commitd106cb2ee59a6517d28660efeeb4f8f5a976f56b (patch)
tree4dd89b4e65e649bef1bd86c3b01c49ac3744fff6
parentb295dca7a04ca3cea7c7fc285b3e388b58e5c02d (diff)
downloadsamba-d106cb2ee59a6517d28660efeeb4f8f5a976f56b.tar.gz
samba-d106cb2ee59a6517d28660efeeb4f8f5a976f56b.tar.bz2
samba-d106cb2ee59a6517d28660efeeb4f8f5a976f56b.zip
Reimport COM and DCOM libraries.
-rw-r--r--source4/lib/com/README9
-rw-r--r--source4/lib/com/classes/simple.c122
-rw-r--r--source4/lib/com/com.h37
-rw-r--r--source4/lib/com/config.mk23
-rw-r--r--source4/lib/com/dcom/dcom.h41
-rw-r--r--source4/lib/com/dcom/main.c394
-rw-r--r--source4/lib/com/dcom/tables.c49
-rw-r--r--source4/lib/com/main.c111
-rw-r--r--source4/lib/com/rot.c34
-rw-r--r--source4/lib/com/tables.c109
10 files changed, 929 insertions, 0 deletions
diff --git a/source4/lib/com/README b/source4/lib/com/README
new file mode 100644
index 0000000000..361024e02c
--- /dev/null
+++ b/source4/lib/com/README
@@ -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
index 0000000000..295f113207
--- /dev/null
+++ b/source4/lib/com/classes/simple.c
@@ -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
index 0000000000..c4dd872ff7
--- /dev/null
+++ b/source4/lib/com/com.h
@@ -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
index 0000000000..08c459a5f6
--- /dev/null
+++ b/source4/lib/com/config.mk
@@ -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
index 0000000000..65a4d0f6e9
--- /dev/null
+++ b/source4/lib/com/dcom/dcom.h
@@ -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
index 0000000000..14a7287c59
--- /dev/null
+++ b/source4/lib/com/dcom/main.c
@@ -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
index 0000000000..ce4f672d37
--- /dev/null
+++ b/source4/lib/com/dcom/tables.c
@@ -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
index 0000000000..3e4127f246
--- /dev/null
+++ b/source4/lib/com/main.c
@@ -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
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..d9989ecdbe
--- /dev/null
+++ b/source4/lib/com/tables.c
@@ -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;
+}