s4:dcom: add a comment about unused code.
[Samba/gebeck_regimport.git] / source4 / lib / com / dcom / main.c
blob261dac05c67f8b4c8e0f959fa5d96166fb582d4e
1 /*
2 Unix SMB/CIFS implementation.
3 Main DCOM functionality
4 Copyright (C) 2004 Jelmer Vernooij <jelmer@samba.org>
5 Copyright (C) 2006 Andrzej Hajda <andrzej.hajda@wp.pl>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "librpc/gen_ndr/epmapper.h"
25 #include "librpc/gen_ndr/ndr_remact_c.h"
26 #include "librpc/gen_ndr/com_dcom.h"
27 #include "librpc/gen_ndr/dcom.h"
28 #include "librpc/rpc/dcerpc.h"
29 #include "lib/com/dcom/dcom.h"
30 #include "librpc/ndr/ndr_table.h"
31 #include "../lib/util/dlinklist.h"
32 #include "auth/credentials/credentials.h"
33 #include "libcli/composite/composite.h"
35 #define DCOM_NEGOTIATED_PROTOCOLS { EPM_PROTOCOL_TCP, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NCALRPC }
37 static NTSTATUS dcerpc_binding_from_STRINGBINDING(TALLOC_CTX *mem_ctx, struct dcerpc_binding **b_out, struct STRINGBINDING *bd)
39 char *host, *endpoint;
40 struct dcerpc_binding *b;
42 b = talloc_zero(mem_ctx, struct dcerpc_binding);
43 if (!b) {
44 return NT_STATUS_NO_MEMORY;
47 b->transport = dcerpc_transport_by_endpoint_protocol(bd->wTowerId);
49 if (b->transport == -1) {
50 DEBUG(1, ("Can't find transport match endpoint protocol %d\n", bd->wTowerId));
51 talloc_free(b);
52 return NT_STATUS_NOT_SUPPORTED;
55 host = talloc_strdup(b, bd->NetworkAddr);
56 endpoint = strchr(host, '[');
58 if (endpoint) {
59 *endpoint = '\0';
60 endpoint++;
62 endpoint[strlen(endpoint)-1] = '\0';
65 b->host = host;
66 b->endpoint = talloc_strdup(b, endpoint);
68 *b_out = b;
69 return NT_STATUS_OK;
72 struct cli_credentials *dcom_get_server_credentials(struct com_context *ctx, const char *server)
74 struct dcom_server_credentials *c;
75 struct cli_credentials *d;
77 d = NULL;
78 for (c = ctx->dcom->credentials; c; c = c->next) {
79 if (c->server == NULL) {
80 d = c->credentials;
81 continue;
83 if (server && !strcmp(c->server, server)) return c->credentials;
85 return d;
88 /**
89 * Register credentials for a specific server.
91 * @param ctx COM context
92 * @param server Name of server, can be NULL
93 * @param credentials Credentials object
95 void dcom_add_server_credentials(struct com_context *ctx, const char *server,
96 struct cli_credentials *credentials)
98 struct dcom_server_credentials *c;
100 /* FIXME: Don't use talloc_find_parent_bytype */
101 for (c = ctx->dcom->credentials; c; c = c->next) {
102 if ((server == NULL && c->server == NULL) ||
103 (server != NULL && c->server != NULL &&
104 !strcmp(c->server, server))) {
105 if (c->credentials && c->credentials != credentials) {
106 talloc_unlink(c, c->credentials);
107 c->credentials = credentials;
108 if (talloc_find_parent_bytype(c->credentials, struct dcom_server_credentials))
109 (void)talloc_reference(c, c->credentials);
110 else
111 talloc_steal(c, c->credentials);
114 return;
118 c = talloc(ctx->event_ctx, struct dcom_server_credentials);
119 c->server = talloc_strdup(c, server);
120 c->credentials = credentials;
121 if (talloc_find_parent_bytype(c->credentials, struct dcom_server_credentials))
122 (void)talloc_reference(c, c->credentials);
123 else
124 talloc_steal(c, c->credentials);
126 DLIST_ADD(ctx->dcom->credentials, c);
129 void dcom_update_credentials_for_aliases(struct com_context *ctx,
130 const char *server,
131 struct DUALSTRINGARRAY *pds)
133 struct cli_credentials *cc;
134 struct dcerpc_binding *b;
135 uint32_t i;
136 NTSTATUS status;
138 cc = dcom_get_server_credentials(ctx, server);
139 for (i = 0; pds->stringbindings[i]; ++i) {
140 if (pds->stringbindings[i]->wTowerId != EPM_PROTOCOL_TCP)
141 continue;
142 status = dcerpc_binding_from_STRINGBINDING(ctx, &b, pds->stringbindings[i]);
143 if (!NT_STATUS_IS_OK(status))
144 continue;
145 dcom_add_server_credentials(ctx, b->host, cc);
146 talloc_free(b);
150 struct dcom_client_context *dcom_client_init(struct com_context *ctx, struct cli_credentials *credentials)
152 ctx->dcom = talloc_zero(ctx, struct dcom_client_context);
153 if (!credentials) {
154 credentials = cli_credentials_init(ctx);
155 cli_credentials_set_conf(credentials, ctx->lp_ctx);
156 cli_credentials_parse_string(credentials, "%", CRED_SPECIFIED);
158 dcom_add_server_credentials(ctx, NULL, credentials);
159 return ctx->dcom;
162 static NTSTATUS dcom_connect_host(struct com_context *ctx,
163 struct dcerpc_pipe **p, const char *server)
165 struct dcerpc_binding *bd;
166 const char * available_transports[] = { "ncacn_ip_tcp", "ncacn_np" };
167 int i;
168 NTSTATUS status;
169 TALLOC_CTX *loc_ctx;
171 if (server == NULL) {
172 return dcerpc_pipe_connect(ctx->event_ctx, p, "ncalrpc",
173 &ndr_table_IRemoteActivation,
174 dcom_get_server_credentials(ctx, NULL), ctx->event_ctx, ctx->lp_ctx);
176 loc_ctx = talloc_new(ctx);
178 /* Allow server name to contain a binding string */
179 if (strchr(server, ':') &&
180 NT_STATUS_IS_OK(dcerpc_parse_binding(loc_ctx, server, &bd))) {
181 if (DEBUGLVL(11))
182 bd->flags |= DCERPC_DEBUG_PRINT_BOTH;
183 status = dcerpc_pipe_connect_b(ctx->event_ctx, p, bd,
184 &ndr_table_IRemoteActivation,
185 dcom_get_server_credentials(ctx, bd->host), ctx->event_ctx, ctx->lp_ctx);
186 goto end;
189 for (i = 0; i < ARRAY_SIZE(available_transports); i++)
191 char *binding = talloc_asprintf(loc_ctx, "%s:%s", available_transports[i], server);
192 if (!binding) {
193 status = NT_STATUS_NO_MEMORY;
194 goto end;
196 status = dcerpc_pipe_connect(ctx->event_ctx, p, binding,
197 &ndr_table_IRemoteActivation,
198 dcom_get_server_credentials(ctx, server),
199 ctx->event_ctx, ctx->lp_ctx);
201 if (NT_STATUS_IS_OK(status)) {
202 if (DEBUGLVL(11))
203 (*p)->conn->flags |= DCERPC_DEBUG_PRINT_BOTH;
204 goto end;
205 } else {
206 DEBUG(1,(__location__": dcom_connect_host : %s\n", get_friendly_nt_error_msg(status)));
210 end:
211 talloc_free(loc_ctx);
212 return status;
215 struct dcom_object_exporter *object_exporter_by_oxid(struct com_context *ctx,
216 uint64_t oxid)
218 struct dcom_object_exporter *ox;
219 for (ox = ctx->dcom->object_exporters; ox; ox = ox->next) {
220 if (ox->oxid == oxid) {
221 return ox;
225 return NULL;
228 struct dcom_object_exporter *object_exporter_update_oxid(struct com_context *ctx, uint64_t oxid, struct DUALSTRINGARRAY *bindings)
230 struct dcom_object_exporter *ox;
231 ox = object_exporter_by_oxid(ctx, oxid);
232 if (!ox) {
233 ox = talloc_zero(ctx, struct dcom_object_exporter);
234 DLIST_ADD(ctx->dcom->object_exporters, ox);
235 ox->oxid = oxid;
236 } else {
237 talloc_free(ox->bindings);
239 ox->bindings = bindings;
240 talloc_steal(ox, bindings);
241 return ox;
244 struct dcom_object_exporter *object_exporter_by_ip(struct com_context *ctx, struct IUnknown *ip)
246 return object_exporter_by_oxid(ctx, ip->obj.u_objref.u_standard.std.oxid);
249 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)
251 uint16_t protseq[] = DCOM_NEGOTIATED_PROTOCOLS;
252 struct dcerpc_pipe *p;
253 struct dcom_object_exporter *m;
254 NTSTATUS status;
255 struct RemoteActivation r;
256 struct DUALSTRINGARRAY *pds;
257 int i;
258 WERROR hr;
259 uint64_t oxid;
260 struct GUID ipidRemUnknown;
261 struct IUnknown *ru_template;
262 struct ORPCTHAT that;
263 uint32_t AuthnHint;
264 struct COMVERSION ServerVersion;
265 struct MInterfacePointer **ifaces;
266 TALLOC_CTX *loc_ctx;
268 status = dcom_connect_host(ctx, &p, server);
269 if (NT_STATUS_IS_ERR(status)) {
270 DEBUG(1, ("Unable to connect to %s - %s\n", server, get_friendly_nt_error_msg(status)));
271 return ntstatus_to_werror(status);
273 loc_ctx = talloc_new(ctx);
275 ifaces = talloc_array(loc_ctx, struct MInterfacePointer *, num_ifaces);
277 ZERO_STRUCT(r.in);
278 r.in.this.version.MajorVersion = COM_MAJOR_VERSION;
279 r.in.this.version.MinorVersion = COM_MINOR_VERSION;
280 r.in.this.cid = GUID_random();
281 r.in.Clsid = *clsid;
282 r.in.ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
283 r.in.num_protseqs = ARRAY_SIZE(protseq);
284 r.in.protseq = protseq;
285 r.in.Interfaces = num_ifaces;
286 r.in.pIIDs = iid;
287 r.out.that = &that;
288 r.out.pOxid = &oxid;
289 r.out.pdsaOxidBindings = &pds;
290 r.out.ipidRemUnknown = &ipidRemUnknown;
291 r.out.AuthnHint = &AuthnHint;
292 r.out.ServerVersion = &ServerVersion;
293 r.out.hr = &hr;
294 r.out.ifaces = ifaces;
295 r.out.results = results;
297 status = dcerpc_RemoteActivation(p, loc_ctx, &r);
298 talloc_free(p);
300 if(NT_STATUS_IS_ERR(status)) {
301 DEBUG(1, ("Error while running RemoteActivation %s\n", nt_errstr(status)));
302 hr = ntstatus_to_werror(status);
303 goto end;
306 if(!W_ERROR_IS_OK(r.out.result)) {
307 hr = r.out.result;
308 goto end;
311 if(!W_ERROR_IS_OK(hr)) {
312 goto end;
315 m = object_exporter_update_oxid(ctx, oxid, pds);
317 ru_template = NULL;
318 *ip = talloc_array(ctx, struct IUnknown *, num_ifaces);
319 for (i = 0; i < num_ifaces; i++) {
320 (*ip)[i] = NULL;
321 if (W_ERROR_IS_OK(results[i])) {
322 status = dcom_IUnknown_from_OBJREF(ctx, &(*ip)[i], &r.out.ifaces[i]->obj);
323 if (!NT_STATUS_IS_OK(status)) {
324 results[i] = ntstatus_to_werror(status);
325 } else if (!ru_template)
326 ru_template = (*ip)[i];
330 /* TODO:avg check when exactly oxid should be updated,its lifetime etc */
331 if (m->rem_unknown && memcmp(&m->rem_unknown->obj.u_objref.u_standard.std.ipid, &ipidRemUnknown, sizeof(ipidRemUnknown))) {
332 talloc_free(m->rem_unknown);
333 m->rem_unknown = NULL;
335 if (!m->rem_unknown) {
336 if (!ru_template) {
337 DEBUG(1,("dcom_create_object: Cannot Create IRemUnknown - template interface not available\n"));
338 hr = WERR_GENERAL_FAILURE;
340 m->rem_unknown = talloc_zero(m, struct IRemUnknown);
341 memcpy(m->rem_unknown, ru_template, sizeof(struct IUnknown));
342 GUID_from_string(COM_IREMUNKNOWN_UUID, &m->rem_unknown->obj.iid);
343 m->rem_unknown->obj.u_objref.u_standard.std.ipid = ipidRemUnknown;
344 m->rem_unknown->vtable = (struct IRemUnknown_vtable *)dcom_proxy_vtable_by_iid(&m->rem_unknown->obj.iid);
345 /* TODO:avg copy stringbindigs?? */
348 dcom_update_credentials_for_aliases(ctx, server, pds);
350 char *c;
351 c = strchr(server, '[');
352 if (m->host) talloc_free(m->host);
353 m->host = c ? talloc_strndup(m, server, c - server) : talloc_strdup(m, server);
355 hr = WERR_OK;
356 end:
357 talloc_free(loc_ctx);
358 return hr;
361 int find_similar_binding(struct STRINGBINDING **sb, const char *host)
363 int i, l;
364 l = strlen(host);
365 for (i = 0; sb[i]; ++i) {
366 if ((sb[i]->wTowerId == EPM_PROTOCOL_TCP) && !strncasecmp(host, sb[i]->NetworkAddr, l) && (sb[i]->NetworkAddr[l] == '['))
367 break;
369 return i;
372 WERROR dcom_query_interface(struct IUnknown *d, uint32_t cRefs, uint16_t cIids, struct GUID *iids, struct IUnknown **ip, WERROR *results)
374 struct dcom_object_exporter *ox;
375 struct REMQIRESULT *rqir;
376 WERROR result;
377 NTSTATUS status;
378 int i;
379 TALLOC_CTX *loc_ctx;
380 struct IUnknown ru;
382 loc_ctx = talloc_new(d);
383 ox = object_exporter_by_ip(d->ctx, d);
385 result = IRemUnknown_RemQueryInterface(ox->rem_unknown, loc_ctx, &IUnknown_ipid(d), cRefs, cIids, iids, &rqir);
386 if (!W_ERROR_IS_OK(result)) {
387 DEBUG(1, ("dcom_query_interface failed: %08X\n", W_ERROR_V(result)));
388 talloc_free(loc_ctx);
389 return result;
391 ru = *(struct IUnknown *)ox->rem_unknown;
392 for (i = 0; i < cIids; ++i) {
393 ip[i] = NULL;
394 results[i] = rqir[i].hResult;
395 if (W_ERROR_IS_OK(results[i])) {
396 ru.obj.iid = iids[i];
397 ru.obj.u_objref.u_standard.std = rqir[i].std;
398 status = dcom_IUnknown_from_OBJREF(d->ctx, &ip[i], &ru.obj);
399 if (!NT_STATUS_IS_OK(status)) {
400 results[i] = ntstatus_to_werror(status);
405 talloc_free(loc_ctx);
406 return WERR_OK;
409 int is_ip_binding(const char* s)
411 while (*s && (*s != '[')) {
412 if (((*s >= '0') && (*s <= '9')) || *s == '.')
413 ++s;
414 else
415 return 0;
417 return 1;
420 NTSTATUS dcom_get_pipe(struct IUnknown *iface, struct dcerpc_pipe **pp)
422 struct dcerpc_binding *binding;
423 struct GUID iid;
424 uint64_t oxid;
425 NTSTATUS status;
426 int i, j, isimilar;
427 struct dcerpc_pipe *p;
428 struct dcom_object_exporter *ox;
429 const struct ndr_interface_table *table;
431 ox = object_exporter_by_oxid(iface->ctx, iface->obj.u_objref.u_standard.std.oxid);
432 if (!ox) {
433 DEBUG(0, ("dcom_get_pipe: OXID not found\n"));
434 return NT_STATUS_NOT_SUPPORTED;
437 p = ox->pipe;
439 iid = iface->vtable->iid;
440 table = ndr_table_by_uuid(&iid);
441 if (table == NULL) {
442 char *guid_str;
443 guid_str = GUID_string(NULL, &iid);
444 DEBUG(0,(__location__": dcom_get_pipe - unrecognized interface{%s}\n", guid_str));
445 talloc_free(guid_str);
446 return NT_STATUS_NOT_SUPPORTED;
449 if (p && p->last_fault_code) {
450 talloc_free(p);
451 ox->pipe = p = NULL;
454 if (p) {
455 if (!GUID_equal(&p->syntax.uuid, &iid)) {
456 ox->pipe->syntax.uuid = iid;
458 /* interface will always be present, so
459 * idl_iface_by_uuid can't return NULL */
460 /* status = dcerpc_secondary_context(p, &p2, idl_iface_by_uuid(&iid)); */
461 status = dcerpc_alter_context(p, p, &ndr_table_by_uuid(&iid)->syntax_id, &p->transfer_syntax);
462 } else
463 status = NT_STATUS_OK;
464 *pp = p;
465 return status;
468 status = NT_STATUS_NO_MORE_ENTRIES;
470 /* To avoid delays whe connecting nonroutable bindings we 1st check binding starting with hostname */
471 /* FIX:low create concurrent connections to all bindings, fastest wins - Win2k and newer does this way???? */
472 isimilar = find_similar_binding(ox->bindings->stringbindings, ox->host);
473 DEBUG(1, (__location__": dcom_get_pipe: host=%s, similar=%s\n", ox->host, ox->bindings->stringbindings[isimilar] ? ox->bindings->stringbindings[isimilar]->NetworkAddr : "None"));
474 j = isimilar - 1;
475 for (i = 0; ox->bindings->stringbindings[i]; ++i) {
476 if (!ox->bindings->stringbindings[++j]) j = 0;
477 /* FIXME:LOW Use also other transports if possible */
478 if ((j != isimilar) && (ox->bindings->stringbindings[j]->wTowerId != EPM_PROTOCOL_TCP || !is_ip_binding(ox->bindings->stringbindings[j]->NetworkAddr))) {
479 DEBUG(9, ("dcom_get_pipe: Skipping stringbinding %24.24s\n", ox->bindings->stringbindings[j]->NetworkAddr));
480 continue;
482 DEBUG(9, ("dcom_get_pipe: Trying stringbinding %s\n", ox->bindings->stringbindings[j]->NetworkAddr));
483 status = dcerpc_binding_from_STRINGBINDING(iface->ctx, &binding,
484 ox->bindings->stringbindings[j]);
485 if (!NT_STATUS_IS_OK(status)) {
486 DEBUG(1, ("Error parsing string binding"));
487 } else {
488 /* FIXME:LOW Make flags more flexible */
489 binding->flags |= DCERPC_AUTH_NTLM | DCERPC_SIGN;
490 if (DEBUGLVL(11))
491 binding->flags |= DCERPC_DEBUG_PRINT_BOTH;
492 status = dcerpc_pipe_connect_b(iface->ctx->event_ctx, &p, binding,
493 ndr_table_by_uuid(&iid),
494 dcom_get_server_credentials(iface->ctx, binding->host),
495 iface->ctx->event_ctx, iface->ctx->lp_ctx);
496 talloc_unlink(iface->ctx, binding);
498 if (NT_STATUS_IS_OK(status)) break;
501 if (NT_STATUS_IS_ERR(status)) {
502 DEBUG(0, ("Unable to connect to remote host - %s\n", nt_errstr(status)));
503 return status;
506 DEBUG(2, ("Successfully connected to OXID %llx\n", (long long)oxid));
508 ox->pipe = *pp = p;
510 return NT_STATUS_OK;
513 NTSTATUS dcom_OBJREF_from_IUnknown(TALLLOC_CTX *mem_ctx, struct OBJREF *o, struct IUnknown *p)
515 /* FIXME: Cache generated objref objects? */
516 ZERO_STRUCTP(o);
518 if (!p) {
519 o->signature = OBJREF_SIGNATURE;
520 o->flags = OBJREF_NULL;
521 } else {
522 *o = p->obj;
523 switch(o->flags) {
524 case OBJREF_CUSTOM: {
525 marshal_fn marshal;
527 marshal = dcom_marshal_by_clsid(&o->u_objref.u_custom.clsid);
528 if (marshal) {
529 return marshal(mem_ctx, p, o);
530 } else {
531 return NT_STATUS_NOT_SUPPORTED;
537 return NT_STATUS_OK;
540 enum ndr_err_code dcom_IUnknown_from_OBJREF(struct com_context *ctx, struct IUnknown **_p, struct OBJREF *o)
542 struct IUnknown *p;
543 struct dcom_object_exporter *ox;
544 unmarshal_fn unmarshal;
546 switch(o->flags) {
547 case OBJREF_NULL:
548 *_p = NULL;
549 return NDR_ERR_SUCCESS;
551 case OBJREF_STANDARD:
552 p = talloc_zero(ctx, struct IUnknown);
553 p->ctx = ctx;
554 p->obj = *o;
555 p->vtable = dcom_proxy_vtable_by_iid(&o->iid);
557 if (!p->vtable) {
558 DEBUG(0, ("Unable to find proxy class for interface with IID %s\n", GUID_string(ctx, &o->iid)));
559 return NDR_ERR_INVALID_POINTER;
562 p->vtable->Release_send = dcom_release_send;
564 ox = object_exporter_by_oxid(ctx, o->u_objref.u_standard.std.oxid);
565 /* FIXME: Add object to list of objects to ping */
566 *_p = p;
567 return NDR_ERR_SUCCESS;
569 case OBJREF_HANDLER:
570 p = talloc_zero(ctx, struct IUnknown);
571 p->ctx = ctx;
572 p->obj = *o;
573 ox = object_exporter_by_oxid(ctx, o->u_objref.u_handler.std.oxid );
574 /* FIXME: Add object to list of objects to ping */
575 /*FIXME p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/
576 /* FIXME: Do the custom unmarshaling call */
578 *_p = p;
579 return NDR_ERR_BAD_SWITCH;
581 case OBJREF_CUSTOM:
582 p = talloc_zero(ctx, struct IUnknown);
583 p->ctx = ctx;
584 p->vtable = NULL;
585 p->obj = *o;
586 unmarshal = dcom_unmarshal_by_clsid(&o->u_objref.u_custom.clsid);
587 *_p = p;
588 if (unmarshal) {
589 return unmarshal(ctx, o, _p);
590 } else {
591 return NDR_ERR_BAD_SWITCH;
595 return NDR_ERR_BAD_SWITCH;
598 uint64_t dcom_get_current_oxid(void)
600 return getpid();
603 /* FIXME:Fake async dcom_get_pipe_* */
604 struct composite_context *dcom_get_pipe_send(struct IUnknown *d, TALLOC_CTX *mem_ctx)
606 struct composite_context *c;
608 c = composite_create(0, d->ctx->event_ctx);
609 if (c == NULL) return NULL;
610 c->private_data = d;
611 /* composite_done(c); bugged - callback is triggered twice by composite_continue and composite_done */
612 c->state = COMPOSITE_STATE_DONE; /* this is workaround */
614 return c;
617 NTSTATUS dcom_get_pipe_recv(struct composite_context *c, struct dcerpc_pipe **pp)
619 NTSTATUS status;
621 status = dcom_get_pipe((struct IUnknown *)c->private_data, pp);
622 talloc_free(c);
624 return status;
627 /* FIXME:avg put IUnknown_Release_out into header */
628 struct IUnknown_Release_out {
629 uint32_t result;
632 void dcom_release_continue(struct composite_context *cr)
634 struct composite_context *c;
635 struct IUnknown *d;
636 struct IUnknown_Release_out *out;
637 WERROR r;
639 c = talloc_get_type(cr->async.private_data, struct composite_context);
640 d = c->private_data;
641 r = IRemUnknown_RemRelease_recv(cr);
642 talloc_free(d);
643 out = talloc_zero(c, struct IUnknown_Release_out);
644 out->result = W_ERROR_V(r);
645 c->private_data = out;
646 composite_done(c);
649 struct composite_context *dcom_release_send(struct IUnknown *d, TALLOC_CTX *mem_ctx)
651 struct composite_context *c, *cr;
652 struct REMINTERFACEREF iref;
653 struct dcom_object_exporter *ox;
655 c = composite_create(d->ctx, d->ctx->event_ctx);
656 if (c == NULL) return NULL;
657 c->private_data = d;
659 ox = object_exporter_by_ip(d->ctx, d);
660 iref.ipid = IUnknown_ipid(d);
661 iref.cPublicRefs = 5;
662 iref.cPrivateRefs = 0;
663 cr = IRemUnknown_RemRelease_send(ox->rem_unknown, mem_ctx, 1, &iref);
665 composite_continue(c, cr, dcom_release_continue, c);
666 return c;
669 uint32_t dcom_release_recv(struct composite_context *c)
671 NTSTATUS status;
672 WERROR r;
674 status = composite_wait(c);
675 if (!NT_STATUS_IS_OK(status))
676 r = ntstatus_to_werror(status);
677 else
678 W_ERROR_V(r) = ((struct IUnknown_Release_out *)c->private_data)->result;
679 talloc_free(c);
680 return W_ERROR_IS_OK(r) ? 0 : W_ERROR_V(r);
683 uint32_t dcom_release(void *interface, TALLOC_CTX *mem_ctx)
685 struct composite_context *c;
687 c = dcom_release_send(interface, mem_ctx);
688 return dcom_release_recv(c);
691 void dcom_proxy_async_call_recv_pipe_send_rpc(struct composite_context *c_pipe)
693 struct composite_context *c;
694 struct dcom_proxy_async_call_state *s;
695 struct dcerpc_pipe *p;
696 struct rpc_request *req;
697 NTSTATUS status;
699 c = c_pipe->async.private_data;
700 s = talloc_get_type(c->private_data, struct dcom_proxy_async_call_state);
702 status = dcom_get_pipe_recv(c_pipe, &p);
703 if (!NT_STATUS_IS_OK(status)) {
704 composite_error(c, NT_STATUS_RPC_NT_CALL_FAILED);
705 return;
707 /*TODO: FIXME - for now this unused anyway */
708 req = dcerpc_ndr_request_send(p, &s->d->obj.u_objref.u_standard.std.ipid, s->table, s->opnum, s, s->r);
709 composite_continue_rpc(c, req, s->continuation, c);